Network updates
* Add handler for network not found. * if never connected - reset * if no delay configured - reset * if delay configured, start timer. reset if timer completes before connection. * Update facotry reset message display. * Allow manual input for wireless ssid.
This commit is contained in:
parent
a2da261066
commit
6b3cdcb612
|
@ -43,8 +43,12 @@ defmodule Farmbot.Logger.Console do
|
|||
end
|
||||
|
||||
defp maybe_log(%Farmbot.Log{module: module} = log) do
|
||||
# should_log = List.first(Module.split(module)) == "Farmbot"
|
||||
should_log = List.first(Module.split(module)) == "Farmbot"
|
||||
if should_log do
|
||||
IO.inspect log
|
||||
else
|
||||
:ok
|
||||
end
|
||||
end
|
||||
|
||||
def handle_call({:set_verbosity_level, num}, _from, state) do
|
||||
|
|
|
@ -56,6 +56,11 @@ defmodule Farmbot.System do
|
|||
@system_tasks.shutdown(formatted)
|
||||
end
|
||||
|
||||
defp write_file(nil) do
|
||||
file = Path.join(@data_path, "last_shutdown_reason")
|
||||
File.rm_rf(file)
|
||||
end
|
||||
|
||||
defp write_file(reason) do
|
||||
file = Path.join(@data_path, "last_shutdown_reason")
|
||||
File.write!(file, reason)
|
||||
|
@ -71,18 +76,27 @@ defmodule Farmbot.System do
|
|||
rescue
|
||||
_ ->
|
||||
[_ | [_ | stack]] = System.stacktrace()
|
||||
stack = Enum.map(stack, fn er -> "\t#{inspect(er)}" end) |> Enum.join("\r\n")
|
||||
|
||||
do_format_reason(reason) <> """
|
||||
|
||||
environment: #{@env}
|
||||
source_ref: #{@ref}
|
||||
target: #{@target}
|
||||
stack = Enum.map(stack, fn er -> "\t#{inspect(er)}" end) |> Enum.join(",\r\n <p>")
|
||||
formated = do_format_reason(reason)
|
||||
footer = """
|
||||
<hr>
|
||||
<p>
|
||||
<p>
|
||||
<p> <strong> environment: </strong> #{@env}
|
||||
<p> <strong> source_ref: </strong> #{@ref}
|
||||
<p> <strong> target: </strong> #{@target}
|
||||
<p>
|
||||
<p>
|
||||
Stacktrace:
|
||||
[
|
||||
#{stack}
|
||||
]
|
||||
<p> [#{stack}]
|
||||
<hr>
|
||||
"""
|
||||
if formated do
|
||||
formated <> footer
|
||||
else
|
||||
nil
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# This mess of pattern matches cleans up erlang startup errors. It's very
|
||||
|
@ -98,7 +112,7 @@ defmodule Farmbot.System do
|
|||
|
||||
defp do_format_reason({:error, {:shutdown, {:failed_to_start_child, child, rest}}}) do
|
||||
{failed_child, failed_reason} = enumerate_ftsc_error(child, rest)
|
||||
|
||||
if failed_reason do
|
||||
"""
|
||||
Failed to start child: #{failed_child}
|
||||
reason: #{do_format_reason(failed_reason)}
|
||||
|
@ -106,6 +120,9 @@ defmodule Farmbot.System do
|
|||
This is likely a bug. Please copy or screenshot this error and send it to
|
||||
the Farmbot developers.
|
||||
"""
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
defp do_format_reason({:bad_return, {Farmbot.Bootstrap.Supervisor, :init, error}}) do
|
||||
|
@ -130,6 +147,13 @@ defmodule Farmbot.System do
|
|||
"""
|
||||
end
|
||||
|
||||
defp do_format_reason({:badarg, [{:ets, :lookup_element, _, _} | _]}) do
|
||||
"""
|
||||
Bad Ecto call. This usually is a result of an over the air update and can
|
||||
likely be ignored.
|
||||
"""
|
||||
end
|
||||
|
||||
defp do_format_reason(reason), do: do_format_reason({:error, reason})
|
||||
|
||||
# This cleans up nested supervisors/workers.
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
defmodule Farmbot.Target.Network.Manager do
|
||||
use GenServer
|
||||
use Farmbot.Logger
|
||||
alias Farmbot.System.ConfigStorage
|
||||
alias Nerves.Network
|
||||
alias Farmbot.Target.Network.Ntp
|
||||
import Farmbot.Target.Network, only: [test_dns: 0]
|
||||
|
@ -10,6 +11,7 @@ defmodule Farmbot.Target.Network.Manager do
|
|||
end
|
||||
|
||||
def init({interface, opts} = args) do
|
||||
Elixir.Logger.remove_backend Elixir.Logger.Backends.Console
|
||||
Logger.busy(3, "Waiting for interface up.")
|
||||
unless interface in Nerves.NetworkInterface.interfaces() do
|
||||
Process.sleep(1000)
|
||||
|
@ -20,7 +22,7 @@ defmodule Farmbot.Target.Network.Manager do
|
|||
{:ok, _} = Registry.register(Nerves.Udhcpc, interface, [])
|
||||
{:ok, _} = Registry.register(Nerves.WpaSupplicant, interface, [])
|
||||
Network.setup(interface, opts)
|
||||
{:ok, %{interface: interface, ip_address: nil, connected: false}}
|
||||
{:ok, %{interface: interface, ip_address: nil, connected: false, not_found_timer: nil}}
|
||||
end
|
||||
|
||||
def handle_info({:system_registry, :global, registry}, state) do
|
||||
|
@ -32,7 +34,14 @@ defmodule Farmbot.Target.Network.Manager do
|
|||
end
|
||||
|
||||
connected = match?({:ok, {:hostent, 'nerves-project.org', [], :inet, 4, _}}, test_dns())
|
||||
{:noreply, %{state | ip_address: ip, connected: connected || false}}
|
||||
if connected do
|
||||
if state.not_found_timer do
|
||||
Process.cancel_timer(state.not_found_timer)
|
||||
end
|
||||
{:noreply, %{state | ip_address: ip, connected: true, not_found_timer: nil}}
|
||||
else
|
||||
{:noreply, %{state | connected: false}}
|
||||
end
|
||||
end
|
||||
|
||||
def handle_info({Nerves.WpaSupplicant, {:INFO, "WPA: 4-Way Handshake failed - pre-shared key may be incorrect"}, _}, state) do
|
||||
|
@ -41,6 +50,40 @@ defmodule Farmbot.Target.Network.Manager do
|
|||
{:stop, :normal, state}
|
||||
end
|
||||
|
||||
def handle_info({Nerves.WpaSupplicant, :"CTRL-EVENT-NETWORK-NOT-FOUND", _}, %{not_found_timer: nil} = state) do
|
||||
first_boot = ConfigStorage.get_config_value(:bool, "settings", "first_boot")
|
||||
delay_timer = ConfigStorage.get_config_value(:float, "settings", "network_not_found_timer")
|
||||
cond do
|
||||
first_boot ->
|
||||
Logger.error 1, "Network not found"
|
||||
Farmbot.System.factory_reset("WIFI Authentication failed. (network not found)")
|
||||
{:stop, :normal, state}
|
||||
delay_timer > 0 ->
|
||||
Logger.warn 1, "Network not found. Starting timer."
|
||||
timer = Process.send_after(self(), :network_not_found_timer, round(delay_timer))
|
||||
{:noreply, %{state | not_found_timer: timer}}
|
||||
delay_timer == -1 -> {:noreply, state}
|
||||
is_nil(delay_timer) ->
|
||||
Logger.error 1, "Network not found"
|
||||
Farmbot.System.factory_reset("WIFI Authentication failed. (network not found)")
|
||||
{:stop, :normal, state}
|
||||
end
|
||||
end
|
||||
|
||||
def handle_info({Nerves.WpaSupplicant, :"CTRL-EVENT-NETWORK-NOT-FOUND"}, state) do
|
||||
{:noreply, state}
|
||||
end
|
||||
|
||||
def handle_info(:network_not_found_timer, state) do
|
||||
if state.connected do
|
||||
{:noreply, %{state | not_found_timer: nil}}
|
||||
else
|
||||
Logger.error 1, "Network not found"
|
||||
Farmbot.System.factory_reset("WIFI Authentication failed. (network not found after timer)")
|
||||
{:stop, :normal, state}
|
||||
end
|
||||
end
|
||||
|
||||
def handle_info(_event, state) do
|
||||
# Logger.warn 3, "unhandled network event: #{inspect event}"
|
||||
{:noreply, state}
|
||||
|
|
|
@ -138,6 +138,7 @@ defmodule Farmbot.System.ConfigStorage.Migrations.SeedGroups do
|
|||
create_value(BoolValue, false) |> create_config(group_id, "auto_sync")
|
||||
create_value(StringValue, nil) |> create_config(group_id, "firmware_hardware")
|
||||
create_value(StringValue, nil) |> create_config(group_id, "timezone")
|
||||
create_value(FloatValue, nil) |> create_config(group_id, "network_not_found_timer")
|
||||
fpf_url = Application.get_env(:farmbot, :farmware)[:first_part_farmware_manifest_url]
|
||||
create_value(StringValue, fpf_url) |> create_config(group_id, "first_party_farmware_url")
|
||||
end
|
||||
|
|
|
@ -3,8 +3,29 @@
|
|||
<head>
|
||||
<title> Configure Farmbot's Network </title>
|
||||
<link rel="stylesheet" href="/styles.css">
|
||||
<script type="text/javascript">
|
||||
function ssidSelectOnChange(iface) {
|
||||
var elem = document.getElementById(iface + "_ssid_select");
|
||||
var selected = elem.options[elem.selectedIndex];
|
||||
expected_id = iface + "_ssid_manual_input";
|
||||
if(selected.id == expected_id) {
|
||||
replaceSelect(iface);
|
||||
}
|
||||
}
|
||||
function replaceSelect(iface) {
|
||||
console.log("Replaceing select element with input element")
|
||||
var elem = document.getElementById(iface + "_ssid_select");
|
||||
var inputNode = document.createElement("input");
|
||||
inputNode.setAttribute("name", iface + "_ssid");
|
||||
inputNode.setAttribute("type", "text");
|
||||
elem.parentNode.insertBefore(inputNode, elem.nextSibling);
|
||||
elem.outerHTML = "";
|
||||
delete elem;
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
||||
|
||||
<body>
|
||||
<h1>Configure your FarmBot</h1>
|
||||
<div class="widget">
|
||||
|
@ -13,34 +34,32 @@
|
|||
</div>
|
||||
<div class="widget-content">
|
||||
<form action="configure_network" method="post">
|
||||
<%= for {interface, settings} <- interfaces do
|
||||
case settings do
|
||||
%{type: :wired} ->
|
||||
"""
|
||||
<%= for {interface, settings} <- interfaces do %>
|
||||
<%= case settings do %>
|
||||
<% %{type: :wired} -> %>
|
||||
<fieldset>
|
||||
<label>Enable Ethernet ( #{interface} )</label>
|
||||
<input type=checkbox name=#{interface}_enable>
|
||||
<input hidden=true name=#{interface}_type value=wired>
|
||||
<label>Enable Ethernet (<%= interface %>)</label>
|
||||
<input type=checkbox name="<%= interface %>_enable">
|
||||
<input hidden=true name="<%= interface %>_type" value=wired>
|
||||
</fieldset>
|
||||
"""
|
||||
%{type: :wireless, ssids: ssids} ->
|
||||
"""
|
||||
|
||||
<% %{type: :wireless, ssids: ssids} -> %>
|
||||
<fieldset>
|
||||
<label>Enable Wireless ( #{interface} )</label>
|
||||
<input type=checkbox name=#{interface}_enable>
|
||||
<label>Enable Wireless (<%= interface %>) </label>
|
||||
<input type=checkbox name="<%= interface %>_enable">
|
||||
<label>Network Name/SSID</label>
|
||||
<select name=#{interface}_ssid>
|
||||
#{Enum.reduce(ssids, "", fn(ssid, acc) ->
|
||||
<select name="<%= interface %>_ssid" id="<%= interface %>_ssid_select" onchange="ssidSelectOnChange('<%= interface %>');">
|
||||
<%= Enum.reduce(ssids, "", fn(ssid, acc) ->
|
||||
acc <> "<option value=#{ssid}> #{ssid} </option>"
|
||||
end)}
|
||||
end) %>
|
||||
<option id="<%= interface %>_ssid_manual_input"> <bold> Manual Input </bold> </option>
|
||||
</select>
|
||||
<label>Password</label>
|
||||
<input type=password name=#{interface}_psk>
|
||||
<input hidden=true name=#{interface}_type value=wireless>
|
||||
<input type=password name="<%= interface %>_psk">
|
||||
<input hidden=true name="<%= interface %>_type" value=wireless>
|
||||
</fieldset>
|
||||
"""
|
||||
end
|
||||
end %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="button">
|
||||
|
@ -48,6 +67,6 @@
|
|||
</div>
|
||||
</form>
|
||||
|
||||
</boty>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
|
Loading…
Reference in a new issue