Allow to use non-standard MQTT ports

This commit is contained in:
Adrian Kumpf
2021-01-03 22:24:59 +01:00
parent b27276b7db
commit ab7556e8af
5 changed files with 54 additions and 61 deletions

View File

@@ -5,6 +5,9 @@ defmodule Util do
:crypto.strong_rand_bytes(length) |> Base.encode64() |> binary_part(0, length)
end
def to_integer(nil), do: nil
def to_integer(str), do: String.to_integer(str)
def validate_namespace!(nil), do: nil
def validate_namespace!(""), do: nil
@@ -96,10 +99,11 @@ config :teslamate, TeslaMateWeb.Endpoint,
if System.get_env("DISABLE_MQTT") != "true" or config_env() == :test do
config :teslamate, :mqtt,
host: Util.fetch_env!("MQTT_HOST", all: "localhost"),
port: System.get_env("MQTT_PORT") |> Util.to_integer(),
username: System.get_env("MQTT_USERNAME"),
password: System.get_env("MQTT_PASSWORD"),
tls: System.get_env("MQTT_TLS"),
accept_invalid_certs: System.get_env("MQTT_TLS_ACCEPT_INVALID_CERTS"),
tls: System.get_env("MQTT_TLS") == "true",
accept_invalid_certs: System.get_env("MQTT_TLS_ACCEPT_INVALID_CERTS") == "true",
namespace: System.get_env("MQTT_NAMESPACE") |> Util.validate_namespace!(),
ipv6: System.get_env("MQTT_IPV6") == "true"
end

View File

@@ -14,7 +14,7 @@ defmodule TeslaMate.Application do
end
defp children do
mqtt_enabled? = !is_nil(Application.get_env(:teslamate, :mqtt))
mqtt_config = Application.get_env(:teslamate, :mqtt)
case Application.get_env(:teslamate, :import_directory) do
nil ->
@@ -27,7 +27,7 @@ defmodule TeslaMate.Application do
TeslaMateWeb.Endpoint,
TeslaMate.Terrain,
TeslaMate.Vehicles,
if(mqtt_enabled?, do: TeslaMate.Mqtt),
if(mqtt_config != nil, do: {TeslaMate.Mqtt, mqtt_config}),
TeslaMate.Repair
]
|> Enum.reject(&is_nil/1)

View File

@@ -10,13 +10,13 @@ defmodule TeslaMate.Mqtt do
end
@impl true
def init(_opts) do
def init(opts) do
client_id = generate_client_id()
children = [
{Tortoise.Connection, connection_config() ++ [client_id: client_id]},
{Tortoise.Connection, connection_config(opts) ++ [client_id: client_id]},
{Publisher, client_id: client_id},
{PubSub, namespace: namespace()}
{PubSub, namespace: opts[:namespace]}
]
Supervisor.init(children, strategy: :one_for_one)
@@ -26,49 +26,38 @@ defmodule TeslaMate.Mqtt do
alias Tortoise.Transport
defp connection_config do
opts = Application.get_env(:teslamate, :mqtt)
host = Keyword.get(opts, :host)
defp connection_config(opts) do
socket_opts =
if opts[:ipv6] do
[:inet6]
else
[]
end
if opts[:ipv6],
do: [:inet6],
else: []
server =
if Keyword.get(opts, :tls) == "true" do
if opts[:tls] do
verify =
if Keyword.get(opts, :accept_invalid_certs) == "true" do
:verify_none
else
:verify_peer
end
if opts[:accept_invalid_certs],
do: :verify_none,
else: :verify_peer
{Transport.SSL,
host: host,
port: 8883,
host: opts[:host],
port: opts[:port] || 8883,
cacertfile: CAStore.file_path(),
verify: verify,
opts: socket_opts}
else
{Transport.Tcp, host: host, port: 1883, opts: socket_opts}
{Transport.Tcp, host: opts[:host], port: opts[:port] || 1883, opts: socket_opts}
end
[
user_name: Keyword.get(opts, :username),
password: Keyword.get(opts, :password),
user_name: opts[:username],
password: opts[:password],
server: server,
handler: {Handler, []},
subscriptions: []
]
end
defp namespace do
Application.get_env(:teslamate, :mqtt) |> Keyword.get(:namespace)
end
defp generate_client_id do
"TESLAMATE_" <> (:rand.uniform() |> to_string() |> Base.encode16() |> String.slice(0..10))
end

View File

@@ -30,16 +30,15 @@ defmodule TeslaMate.Mqtt.Publisher do
@impl true
def handle_call({:publish, topic, msg, opts}, from, %State{client_id: id, refs: refs} = state) do
opts = Keyword.put_new(opts, :timeout, round(@timeout * 0.95))
case Keyword.get(opts, :qos, 0) do
0 ->
:ok = Tortoise.publish(id, topic, msg, Keyword.put_new(opts, :timeout, @timeout * 0.95))
:ok = Tortoise.publish(id, topic, msg, opts)
{:reply, :ok, state}
_ ->
{:ok, ref} =
Tortoise.publish(id, topic, msg, Keyword.put_new(opts, :timeout, @timeout * 0.95))
{:ok, ref} = Tortoise.publish(id, topic, msg, opts)
{:noreply, %State{state | refs: Map.put(refs, ref, from)}}
end
end

View File

@@ -6,28 +6,29 @@ sidebar_label: Environment Variables
TeslaMate accepts the following environment variables for runtime configuration:
| Variable Name | Description | Default Value |
| --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- |
| **DATABASE_USER** | Username (**required**) | |
| **DATABASE_PASS** | User password (**required**) | |
| **DATABASE_NAME** | The database to connect to (**required**) | |
| **DATABASE_HOST** | Hostname of the database server (**required**) | |
| **DATABASE_PORT** | Port of the database server | 5432 |
| **DATABASE_POOL_SIZE** | Size of the database connection pool | 10 |
| **DATABASE_TIMEOUT** | The time in milliseconds to wait for database query calls to finish | 60000 |
| **DATABASE_SSL** | Set to `true` if SSL should be used | false |
| **DATABASE_IPV6** | Set to `true` if IPv6 should be used | false |
| **VIRTUAL_HOST** | Host part used for generating URLs throughout the app | localhost |
| **CHECK_ORIGIN** | Configures whether to check the origin header or not. May be `true` (**recommended**), `false` (_default_) or a comma-separated list of hosts that are allowed (e.g. `https://example.com,//another.com:8080`). Hosts also support wildcards. If `true`, it will check against the host value in `VIRTUAL_HOST`. | false |
| **PORT** | Port where the web interface is exposed | 4000 |
| **HTTP_BINDING_ADDRESS** | IP address where the web interface is exposed, or blank (_default_) meaning all addresses. | |
| **DISABLE_MQTT** | Disables the MQTT feature if `true` | false |
| **MQTT_HOST** | Hostname of the broker (**required** unless DISABLE_MQTT is `true`) | |
| **MQTT_USERNAME** | Username | |
| **MQTT_PASSWORD** | Password | |
| **MQTT_TLS** | Enables TLS if `true` | false |
| **MQTT_TLS_ACCEPT_INVALID_CERTS** | Accepts invalid certificates if `true` | false |
| **MQTT_IPV6** | Set to `true` if IPv6 should be used | false |
| **MQTT_NAMESPACE** | Inserts a custom namespace into the MQTT topic . For example, with `MQTT_NAMESPACE=account_0`: `teslamate/account_0/cars/$car_id/state`. | |
| **IMPORT_DIR** | The path of the directory for the import of data (e.g. TeslaFi) | ./import |
| **TZ** | Used to establish the local time zone, e.g. to use the local time in logs. See [List of tz database time zones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). | |
| Variable Name | Description | Default Value |
| --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------ |
| **DATABASE_USER** | Username (**required**) | |
| **DATABASE_PASS** | User password (**required**) | |
| **DATABASE_NAME** | The database to connect to (**required**) | |
| **DATABASE_HOST** | Hostname of the database server (**required**) | |
| **DATABASE_PORT** | Port of the database server | 5432 |
| **DATABASE_POOL_SIZE** | Size of the database connection pool | 10 |
| **DATABASE_TIMEOUT** | The time in milliseconds to wait for database query calls to finish | 60000 |
| **DATABASE_SSL** | Set to `true` if SSL should be used | false |
| **DATABASE_IPV6** | Set to `true` if IPv6 should be used | false |
| **VIRTUAL_HOST** | Host part used for generating URLs throughout the app | localhost |
| **CHECK_ORIGIN** | Configures whether to check the origin header or not. May be `true` (**recommended**), `false` (_default_) or a comma-separated list of hosts that are allowed (e.g. `https://example.com,//another.com:8080`). Hosts also support wildcards. If `true`, it will check against the host value in `VIRTUAL_HOST`. | false |
| **PORT** | Port where the web interface is exposed | 4000 |
| **HTTP_BINDING_ADDRESS** | IP address where the web interface is exposed, or blank (_default_) meaning all addresses. | |
| **DISABLE_MQTT** | Disables the MQTT feature if `true` | false |
| **MQTT_HOST** | Hostname of the broker (**required** unless DISABLE_MQTT is `true`) | |
| **MQTT_PORT** | Port of the broker | 1883 (8883 for MQTT ovoer TLS) |
| **MQTT_USERNAME** | Username | |
| **MQTT_PASSWORD** | Password | |
| **MQTT_TLS** | Enables TLS if `true` | false |
| **MQTT_TLS_ACCEPT_INVALID_CERTS** | Accepts invalid certificates if `true` | false |
| **MQTT_IPV6** | Set to `true` if IPv6 should be used | false |
| **MQTT_NAMESPACE** | Inserts a custom namespace into the MQTT topic . For example, with `MQTT_NAMESPACE=account_0`: `teslamate/account_0/cars/$car_id/state`. | |
| **IMPORT_DIR** | The path of the directory for the import of data (e.g. TeslaFi) | ./import |
| **TZ** | Used to establish the local time zone, e.g. to use the local time in logs. See [List of tz database time zones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). | |