Packages
grizzly
8.2.2
9.1.4
9.1.2
9.1.1
9.1.0
9.0.0
8.15.3
8.15.2
8.15.1
8.15.0
8.14.0
8.13.0
8.12.0
8.11.3
8.11.2
8.11.1
8.11.0
8.10.0
8.9.0
8.8.1
8.8.0
8.7.1
8.7.0
8.6.12
8.6.11
8.6.10
8.6.9
8.6.8
8.6.7
retired
8.6.6
8.6.5
8.6.4
8.6.3
8.6.2
8.6.1
8.6.0
8.5.3
8.5.2
8.5.1
8.5.0
8.4.0
8.3.0
8.2.3
8.2.2
8.2.1
8.2.0
8.1.0
8.0.1
8.0.0
7.4.3
7.4.2
7.4.1
7.4.0
7.3.0
7.2.0
7.1.4
7.1.3
7.1.2
7.1.1
7.1.0
7.0.4
7.0.3
7.0.2
7.0.1
7.0.0
6.8.8
6.8.7
6.8.6
6.8.5
6.8.4
6.8.3
6.8.2
6.8.1
6.8.0
6.7.1
6.7.0
6.6.1
6.6.0
6.5.1
6.5.0
6.4.0
6.3.0
6.2.0
6.1.1
6.1.0
6.0.1
6.0.0
5.4.1
5.4.0
5.3.0
5.2.8
5.2.7
5.2.6
5.2.5
5.2.4
5.2.3
5.2.2
5.2.1
5.2.0
5.1.2
5.1.1
5.1.0
5.0.2
5.0.1
5.0.0
4.0.1
4.0.0
3.0.0
2.1.0
2.0.0
1.0.1
1.0.0
0.22.7
0.22.6
0.22.5
0.22.4
0.22.3
0.22.2
0.22.1
0.22.0
0.21.1
0.21.0
0.20.2
0.20.1
0.20.0
0.19.1
0.19.0
0.18.3
0.18.2
0.18.1
0.18.0
0.17.7
0.17.6
0.17.5
0.17.4
0.17.3
0.17.2
0.17.1
0.17.0
0.16.2
0.16.1
0.16.0
0.15.11
0.15.10
0.15.9
0.15.8
0.15.7
0.15.6
0.15.5
0.15.4
0.15.3
0.15.2
0.15.1
0.15.0
0.14.8
0.14.7
0.14.6
0.14.5
0.14.4
0.14.3
0.14.2
0.14.1
0.14.0
0.13.0
0.12.3
0.12.2
0.12.1
0.12.0
0.11.0
0.10.3
0.10.2
0.10.1
0.10.0
0.9.0
0.9.0-rc.4
0.9.0-rc.3
0.9.0-rc.2
0.9.0-rc.1
0.9.0-rc.0
0.8.8
0.8.7
0.8.6
0.8.5
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.7.0
0.6.6
0.6.5
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
0.5.0
0.4.3
0.4.2
Elixir Z-Wave library
Current section
Files
Jump to
Current section
Files
lib/grizzly/zipgateway/supervisor.ex
defmodule Grizzly.ZIPGateway.Supervisor do
@moduledoc """
Supervisor for the Z/IP Gateway process.
"""
# Supervisor for the `zipgateway` system process
use Supervisor
alias Grizzly.{Indicator, Options}
alias Grizzly.ZIPGateway.{Config, ExitMonitor, LogMonitor, SAPIMonitor}
require Logger
@zgw_eeprom_to_sqlite "/usr/bin/zgw_eeprom_to_sqlite"
@doc """
Restarts the Z/IP Gateway process. An error will be raised if `Grizzly.ZIPGateway.Supervisor`
is not running.
"""
@spec restart_zipgateway() :: :ok
def restart_zipgateway() do
_ = Supervisor.terminate_child(__MODULE__, Grizzly.ZIPGateway.ProcessSupervisor)
{:ok, _} = Supervisor.restart_child(__MODULE__, Grizzly.ZIPGateway.ProcessSupervisor)
:ok
end
@doc "Stops the Z/IP Gateway process if it is running."
@spec stop_zipgateway() :: :ok
def stop_zipgateway() do
_ = Supervisor.terminate_child(__MODULE__, Grizzly.ZIPGateway.ProcessSupervisor)
:ok
end
@spec start_link(Options.t()) :: Supervisor.on_start()
def start_link(options) do
Supervisor.start_link(__MODULE__, options, name: __MODULE__)
end
@impl Supervisor
def init(options) do
Supervisor.init(child_specs(options), strategy: :rest_for_one)
end
defp child_specs(options) do
if options.run_zipgateway do
zipgateway_child_specs(options)
else
[]
end
end
defp zipgateway_child_specs(options) do
try_migrate_eeprom_to_sql(options)
:ok = system_checks(options)
:ok =
options
|> Options.to_zipgateway_config(use_database?())
|> Config.ensure_files()
|> Config.write(options.zipgateway_config_path)
_ = System.cmd("modprobe", ["tun"])
beam_notify_options = [
name: "grizzly indicator",
path: "/tmp/grizzly_beam_notify_socket",
dispatcher: &Indicator.handle_event(&1, &2, options.indicator_handler)
]
[
{SAPIMonitor, [status_reporter: options.status_reporter]},
LogMonitor,
{BEAMNotify, beam_notify_options},
zipgateway_process_supervisor_spec(options)
]
end
# Run MuonTrap.Daemon and ZIPGateway.ExitMonitor under a supervisor using the
# `:rest_for_one` strategy. This isolates the Z/IP Gateway process from exits
# in LogMonitor or BEAMNotify while allowing ExitMonitor to do cleanup when
# Z/IP Gateway exits (chiefly, this means closing all DTLS connections).
defp zipgateway_process_supervisor_spec(options) do
priv = Application.app_dir(:grizzly, "priv")
children = [
{MuonTrap.Daemon,
[
options.zipgateway_binary,
["-c", options.zipgateway_config_path, "-s", options.serial_port],
[
name: Grizzly.ZIPGateway.Daemon,
cd: priv,
log_output: :debug,
log_transform: &zipgateway_log_transform/1,
exit_status_to_reason: &zipgateway_exit_status/1
]
]},
ExitMonitor
]
%{
id: Grizzly.ZIPGateway.ProcessSupervisor,
type: :supervisor,
start:
{Supervisor, :start_link,
[children, [name: Grizzly.ZIPGateway.ProcessSupervisor, strategy: :rest_for_one]]}
}
end
defp try_migrate_eeprom_to_sql(%{eeprom_file: eeprom_file, database_file: database_file}) do
if use_database?() and
eeprom_file != nil and
database_file != nil and
not File.exists?(database_file) and
File.exists?(eeprom_file) do
run_eeprom_to_sql_prog(eeprom_file, database_file)
end
:ok
end
defp use_database?() do
File.exists?(@zgw_eeprom_to_sqlite)
end
defp run_eeprom_to_sql_prog(eeprom_file, database_file) do
Logger.info("Running #{@zgw_eeprom_to_sqlite} -e #{eeprom_file} -d #{database_file}")
case System.cmd(@zgw_eeprom_to_sqlite, ["-e", eeprom_file, "-d", database_file]) do
{message, 0} ->
Logger.info("Successfully migrated EEPROM to DB: #{inspect(message)}")
:ok
{message, _error_no} ->
Logger.error("EEPROM to DB migration failed: #{inspect(message)}")
end
:ok
end
defp system_checks(options) do
:ok = check_serial_port(options.serial_port)
:ok = find_zipgateway_bin(options.zipgateway_binary)
:ok
end
defp check_serial_port(serial_port) do
if File.exists?(serial_port) do
:ok
else
raise ArgumentError, """
It looks like the serial port: #{inspect(serial_port)} is not available
If you are using an USB dongle ensure that you have plugged it in and that
you have configured the correct serial port.
If you are using a Z-Wave controller embedded onto your system make sure you
are using the correct serial port in the configuration.
"""
end
end
defp find_zipgateway_bin(zipgateway_path) do
case File.stat(zipgateway_path) do
{:error, _posix} ->
raise ArgumentError, """
Cannot find the zipgateway executable (looked for it in #{inspect(zipgateway_path)})
If it is located somewhere else, please pass the path to Grizzly.Supervisor
```
Grizzly.Supervisor.start_link(zipgateway_path: <path>)
```
```
{Grizzly.Supervisor, [zipgateway_path: <path>]}
```
"""
{:ok, _stat} ->
:ok
end
end
@spec zipgateway_log_transform(binary()) :: binary()
defp zipgateway_log_transform(message) do
case GenServer.whereis(Grizzly.ZIPGateway.LogMonitor) do
nil -> :ok
pid -> send(pid, {:message, message})
end
message
end
defp zipgateway_exit_status(status) do
:telemetry.execute(
[:grizzly, :zipgateway, :crash],
%{exit_status: status}
)
grizzly_opts = Grizzly.options()
reset_zwave_module(grizzly_opts)
:error_exit_status
end
@spec reset_zwave_module(Options.t()) :: :ok
defp reset_zwave_module(%Options{zwave_firmware: opts}) do
if is_function(opts[:module_reset_fun], 0), do: opts.module_reset_fun.()
:ok
end
end