Start implementing firmware startup

Misc other cleanup
pull/974/head
Connor Rigby 2018-12-03 12:21:41 -08:00
parent 7cde2b2390
commit cf5077e2a9
No known key found for this signature in database
GPG Key ID: 29A88B24B70456E0
35 changed files with 237 additions and 234 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -141,11 +141,9 @@ defmodule Farmbot.Asset do
fwe =
if params["key"] || params[:key] do
Repo.get_by(FarmwareEnv, key: params["key"] || params[:key])
else
%FarmwareEnv{}
end
FarmwareEnv.changeset(fwe, params)
FarmwareEnv.changeset(fwe || %FarmwareEnv{}, params)
|> Repo.insert_or_update()
end

View File

@ -1,7 +1,6 @@
defimpl Farmbot.AssetWorker, for: Farmbot.Asset.Device do
alias Farmbot.Asset.Device
use GenServer
import Farmbot.Config, only: [update_config_value: 4]
def preload(%Device{}), do: []
@ -14,7 +13,6 @@ defimpl Farmbot.AssetWorker, for: Farmbot.Asset.Device do
end
def handle_info(:timeout, %Device{} = device) do
update_config_value(:string, "settings", "timezone", device.timezone)
{:noreply, device}
end
end

View File

@ -3,7 +3,7 @@ defimpl Farmbot.AssetWorker, for: Farmbot.Asset.FbosConfig do
require Logger
alias Farmbot.Asset.FbosConfig
import Farmbot.Config, only: [update_config_value: 4]
alias Farmbot.BotState
def preload(%FbosConfig{}), do: []
@ -16,37 +16,18 @@ defimpl Farmbot.AssetWorker, for: Farmbot.Asset.FbosConfig do
end
def handle_info(:timeout, %FbosConfig{} = fbos_config) do
bool("arduino_debug_messages", fbos_config.arduino_debug_messages)
bool("auto_sync", fbos_config.auto_sync)
bool("beta_opt_in", fbos_config.beta_opt_in)
bool("disable_factory_reset", fbos_config.disable_factory_reset)
string("firmware_hardware", fbos_config.firmware_hardware)
bool("firmware_input_log", fbos_config.firmware_input_log)
bool("firmware_output_log", fbos_config.firmware_output_log)
float("network_not_found_timer", fbos_config.network_not_found_timer)
bool("os_auto_update", fbos_config.os_auto_update)
bool("sequence_body_log", fbos_config.sequence_body_log)
bool("sequence_complete_log", fbos_config.sequence_complete_log)
bool("sequence_init_log", fbos_config.sequence_init_log)
:ok = BotState.set_config_value(:arduino_debug_messages, fbos_config.arduino_debug_messages)
:ok = BotState.set_config_value(:auto_sync, fbos_config.auto_sync)
:ok = BotState.set_config_value(:beta_opt_in, fbos_config.beta_opt_in)
:ok = BotState.set_config_value(:disable_factory_reset, fbos_config.disable_factory_reset)
:ok = BotState.set_config_value(:firmware_hardware, fbos_config.firmware_hardware)
:ok = BotState.set_config_value(:firmware_input_log, fbos_config.firmware_input_log)
:ok = BotState.set_config_value(:firmware_output_log, fbos_config.firmware_output_log)
:ok = BotState.set_config_value(:network_not_found_timer, fbos_config.network_not_found_timer)
:ok = BotState.set_config_value(:os_auto_update, fbos_config.os_auto_update)
:ok = BotState.set_config_value(:sequence_body_log, fbos_config.sequence_body_log)
:ok = BotState.set_config_value(:sequence_complete_log, fbos_config.sequence_complete_log)
:ok = BotState.set_config_value(:sequence_init_log, fbos_config.sequence_init_log)
{:noreply, fbos_config}
end
defp bool(key, val) do
update_config_value(:bool, "settings", key, val)
:ok = Farmbot.BotState.set_config_value(key, val)
end
defp string(key, val) do
update_config_value(:string, "settings", key, val)
:ok = Farmbot.BotState.set_config_value(key, val)
end
defp float(_key, nil) do
:ok
end
defp float(key, val) do
update_config_value(:float, "settings", key, val / 1)
:ok = Farmbot.BotState.set_config_value(key, val)
end
end

View File

@ -58,6 +58,16 @@ defmodule Farmbot.BotState do
GenServer.call(bot_state_server, {:set_firmware_locked, false})
end
@doc "Sets informational_settings.firmware_version"
def set_firmware_version(bot_state_server \\ __MODULE__, version) do
GenServer.call(bot_state_server, {:set_firmware_version, version})
end
@doc "Sets informational_settings.busy"
def set_firmware_busy(bot_state_server \\ __MODULE__, busy) do
GenServer.call(bot_state_server, {:set_firmware_busy, busy})
end
@doc "Sets informational_settings.status"
def set_sync_status(bot_state_server \\ __MODULE__, s)
when s in ["syncing", "synced", "error"] do
@ -212,6 +222,26 @@ defmodule Farmbot.BotState do
{:reply, reply, state}
end
def handle_call({:set_firmware_version, version}, _from, state) do
change = %{informational_settings: %{firmware_version: version}}
{reply, state} =
BotStateNG.changeset(state.tree, change)
|> dispatch_and_apply(state)
{:reply, reply, state}
end
def handle_call({:set_firmware_busy, busy}, _from, state) do
change = %{informational_settings: %{busy: busy}}
{reply, state} =
BotStateNG.changeset(state.tree, change)
|> dispatch_and_apply(state)
{:reply, reply, state}
end
def handle_call({:set_sync_status, status}, _from, state) do
change = %{informational_settings: %{sync_status: status}}

View File

@ -5,6 +5,7 @@ defmodule Farmbot.Config.MigrationHelpers do
alias Farmbot.Config
alias Config.{Repo, Config, StringValue, BoolValue, FloatValue}
import Ecto.Query
@auth_group_id 1
@hw_param_group_id 2
@ -20,6 +21,16 @@ defmodule Farmbot.Config.MigrationHelpers do
|> create_config(@settings_group_id, key)
end
def delete_settings_config(key, type) when type in [:string, :float, :bool] do
IO.puts "deleting #{key} #{type}"
conf = Repo.one!(from c in Config, where: c.group_id == @settings_group_id and c.key == ^key)
val_id = Map.fetch!(conf, :"#{type}_value_id")
val = Repo.one!(from t in type_to_mod(type), where: t.id == ^val_id)
Repo.delete!(conf)
Repo.delete!(val)
:ok
end
def create_hw_param(key) when is_binary(key) do
create_value(FloatValue, nil) |> create_config(@hw_param_group_id, key)
end

View File

@ -37,14 +37,18 @@ defmodule Farmbot.Core.FirmwareSideEffects do
:ok = Farmbot.BotState.set_pin_value(pin, value)
end
def handle_software_version([_version]) do
:noop
def handle_software_version([version]) do
:ok = Farmbot.BotState.set_firmware_version(version)
end
def handle_end_stops(_) do
:noop
end
def handle_busy(busy) do
:ok = Farmbot.BotState.set_firmware_busy(busy)
end
def handle_emergency_lock() do
_ = FirmwareEstopTimer.start_timer()
:ok = Farmbot.BotState.set_firmware_locked()

View File

@ -6,40 +6,14 @@ defmodule Farmbot.Core.FirmwareSupervisor do
Supervisor.start_link(__MODULE__, args, name: __MODULE__)
end
def reinitialize do
_ = Supervisor.terminate_child(Farmbot.Core, __MODULE__)
Supervisor.restart_child(Farmbot.Core, __MODULE__)
end
def stub do
Asset.fbos_config()
|> Asset.FbosConfig.changeset(%{firmware_path: "stub"})
|> Asset.Repo.insert_or_update()
end
def init([]) do
fbos_config = Asset.fbos_config()
children =
firmware_children(fbos_config) ++
[
Farmbot.Core.FirmwareEstopTimer
]
children = [
Farmbot.Core.FirmwareEstopTimer
]
Supervisor.init(children, strategy: :one_for_all)
end
def firmware_children(%Asset.FbosConfig{firmware_hardware: nil}), do: []
def firmware_children(%Asset.FbosConfig{firmware_path: "stub"}) do
[
{Farmbot.Firmware,
transport: Farmbot.Firmware.StubTransport, side_effects: Farmbot.Core.FirmwareSideEffects}
]
end
def firmware_children(%Asset.FbosConfig{firmware_path: nil}), do: []
def firmware_children(%Asset.FbosConfig{} = fbos_config) do
[
{Farmbot.Firmware,

View File

@ -11,8 +11,7 @@ defmodule Farmbot.TimeUtils do
# returns midnight of today
@spec build_epoch(DateTime.t) :: DateTime.t
def build_epoch(time) do
import Farmbot.Config, only: [get_config_value: 3]
tz = get_config_value(:string, "settings", "timezone")
tz = Farmbot.Asset.fbos_config().timezone
n = Timex.Timezone.convert(time, tz)
Timex.shift(n, hours: -n.hour, seconds: -n.second, minutes: -n.minute)
end

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,34 @@
defmodule Farmbot.Config.Repo.Migrations.MigrateSettings do
use Ecto.Migration
import Farmbot.Config.MigrationHelpers
def change do
delete_settings_config("auto_sync", :bool)
delete_settings_config("firmware_needs_migration", :bool)
delete_settings_config("email_on_estop", :bool)
delete_settings_config("disable_factory_reset", :bool)
delete_settings_config("ignore_fbos_config", :bool)
delete_settings_config("os_update_server_overwrite", :string)
delete_settings_config("network_not_found_timer", :float)
delete_settings_config("timezone", :string)
delete_settings_config("first_party_farmware_url", :string)
delete_settings_config("sync_timeout_ms", :float)
delete_settings_config("ignore_external_logs", :bool)
delete_settings_config("needs_http_sync", :bool)
delete_settings_config("currently_on_beta", :bool)
delete_settings_config("arduino_debug_messages", :bool)
delete_settings_config("firmware_output_log", :bool)
delete_settings_config("firmware_input_log", :bool)
delete_settings_config("beta_opt_in", :bool)
delete_settings_config("log_amqp_connected", :bool)
delete_settings_config("current_repo", :string)
delete_settings_config("user_env", :string)
delete_settings_config("sequence_complete_log", :bool)
delete_settings_config("sequence_init_log", :bool)
delete_settings_config("sequence_body_log", :bool)
delete_settings_config("ignore_fw_config", :bool)
delete_settings_config("api_migrated", :bool)
delete_settings_config("firmware_needs_first_sync", :bool)
delete_settings_config("first_boot", :bool)
end
end

Binary file not shown.

Binary file not shown.

View File

@ -11,7 +11,6 @@ defmodule Farmbot.AMQP.AutoSyncTransport do
require Logger
require Farmbot.Logger
import Farmbot.Config, only: [get_config_value: 3]
alias Farmbot.{
API.EagerLoader,
@ -98,7 +97,7 @@ defmodule Farmbot.AMQP.AutoSyncTransport do
end
def handle_asset(asset_kind, label, id, params, state) do
auto_sync? = get_config_value(:bool, "settings", "auto_sync")
auto_sync? = Farmbot.Asset.fbos_config().auto_sync
cond do
# TODO(Connor) no way to cache a deletion yet
@ -109,7 +108,6 @@ defmodule Farmbot.AMQP.AutoSyncTransport do
Repo.get_by!(Device, id: id)
|> Device.changeset(params)
|> Repo.update!()
|> Farmbot.Bootstrap.APITask.device_to_config_storage()
:ok
@ -117,7 +115,6 @@ defmodule Farmbot.AMQP.AutoSyncTransport do
Repo.get_by!(FbosConfig, id: id)
|> FbosConfig.changeset(params)
|> Repo.update!()
|> Farmbot.Bootstrap.APITask.fbos_config_to_config_storage()
:ok
@ -153,7 +150,7 @@ defmodule Farmbot.AMQP.AutoSyncTransport do
end
end
device = state.bot
device = state.jwt.bot
json = JSON.encode!(%{args: %{label: label}, kind: "rpc_ok"})
:ok = Basic.publish(state.chan, @exchange, "bot.#{device}.from_device", json)
{:noreply, state}

View File

@ -12,8 +12,6 @@ defmodule Farmbot.AMQP.CeleryScriptTransport do
alias Farmbot.AMQP.ConnectionWorker
import Farmbot.Config, only: [get_config_value: 3, update_config_value: 4]
@exchange "amq.topic"
defstruct [:conn, :chan, :jwt]
@ -61,11 +59,7 @@ defmodule Farmbot.AMQP.CeleryScriptTransport do
# Confirmation sent by the broker after registering this process as a consumer
def handle_info({:basic_consume_ok, _}, state) do
if get_config_value(:bool, "settings", "log_amqp_connected") do
Farmbot.Logger.success(1, "Farmbot is up and running!")
update_config_value(:bool, "settings", "log_amqp_connected", false)
end
Farmbot.Logger.success(1, "Farmbot is up and running!")
{:noreply, state}
end
@ -101,7 +95,8 @@ defmodule Farmbot.AMQP.CeleryScriptTransport do
if results_ast.kind == :rpc_error do
[%{args: %{message: message}}] = results_ast.body
Logger.error(message)
msg = ["CeleryScript Error\n", message, "\n", inspect(json)]
Logger.error(msg)
end
AMQP.Basic.publish(state.chan, @exchange, "bot.#{state.jwt.bot}.from_device", reply)

View File

@ -10,7 +10,6 @@ defmodule Farmbot.Bootstrap do
end
def init([]) do
update_config_value(:bool, "settings", "log_amqp_connected", true)
{:ok, nil, 0}
end
@ -45,14 +44,15 @@ defmodule Farmbot.Bootstrap do
# TODO(Connor) - drop password and save secret here somehow.
def try_auth(email, server, password, _secret) do
Logger.debug("using password to auth")
# require IEx; IEx.pry
with {:ok, tkn} <- Authorization.authorize_with_password(email, password, server),
_ <- update_config_value(:string, "authorization", "token", tkn),
{:ok, pid} <- Supervisor.start_child(Farmbot.Ext, Farmbot.Bootstrap.Supervisor) do
{:noreply, pid}
else
_ -> {:noreply, nil, 5000}
er ->
Logger.error("password auth failed: #{inspect(er)} ")
{:noreply, nil, 5000}
end
end
end

View File

@ -8,16 +8,12 @@ defmodule Farmbot.Bootstrap.APITask do
alias Ecto.{Changeset, Multi}
require Farmbot.Logger
import Farmbot.Config, only: [get_config_value: 3, update_config_value: 4]
alias Farmbot.API
alias API.{Reconciler, SyncGroup, EagerLoader}
alias Farmbot.Asset.{
Repo,
Sync,
Device,
FbosConfig
# FirmwareConfig
Sync
}
def child_spec(_) do
@ -38,16 +34,16 @@ defmodule Farmbot.Bootstrap.APITask do
multi = Multi.new()
with {:ok, multi} <- Reconciler.sync_group(multi, sync, SyncGroup.group_0()),
{:ok, r} <- Repo.transaction(multi) do
[%{id: device_id}] = sync.devices
[%{id: fbos_config_id}] = sync.fbos_configs
# [%{id: firmware_config_id}] = sync.firmware_configs
:ok = device_to_config_storage(r[{:devices, device_id}])
:ok = fbos_config_to_config_storage(r[{:fbos_configs, fbos_config_id}])
# :ok = firmware_config_to_config_storage(r[{:firmware_configs, firmware_config_id}])
{:ok, _} <- Repo.transaction(multi) do
auto_sync_change =
Enum.find_value(multi.operations, fn {{key, _id}, {:changeset, change, []}} ->
key == :fbos_configs && Changeset.get_change(change, :auto_sync)
end)
Farmbot.Logger.success(3, "Successfully synced bootup resources.")
:ok = maybe_auto_sync(sync_changeset, get_config_value(:bool, "settings", "auto_sync"))
:ok =
maybe_auto_sync(sync_changeset, auto_sync_change || Farmbot.Asset.fbos_config().auto_sync)
end
:ignore
@ -82,42 +78,4 @@ defmodule Farmbot.Bootstrap.APITask do
Farmbot.Logger.success(3, "preloaded sync ok")
:ok
end
def device_to_config_storage(nil), do: :ok
def device_to_config_storage(%Device{timezone: tz} = _device) do
update_config_value(:string, "settings", "timezone", tz)
:ok
end
def fbos_config_to_config_storage(nil), do: :ok
def fbos_config_to_config_storage(%FbosConfig{} = config) do
update_config_value(
:bool,
"settings",
"arduino_debug_messages",
config.arduino_debug_messages
)
update_config_value(:bool, "settings", "auto_sync", config.auto_sync)
update_config_value(:bool, "settings", "beta_opt_in", config.beta_opt_in)
update_config_value(:bool, "settings", "disable_factory_reset", config.disable_factory_reset)
update_config_value(:string, "settings", "firmware_hardware", config.firmware_hardware)
update_config_value(:bool, "settings", "firmware_input_log", config.firmware_input_log)
update_config_value(:bool, "settings", "firmware_output_log", config.firmware_output_log)
update_config_value(
:float,
"settings",
"network_not_found_timer",
config.network_not_found_timer && config.network_not_found_timer / 1
)
update_config_value(:bool, "settings", "os_auto_update", config.os_auto_update)
update_config_value(:bool, "settings", "sequence_body_log", config.sequence_body_log)
update_config_value(:bool, "settings", "sequence_complete_log", config.sequence_complete_log)
update_config_value(:bool, "settings", "sequence_init_log", config.sequence_init_log)
:ok
end
end

Binary file not shown.

View File

@ -282,6 +282,7 @@ defmodule Farmbot.Firmware do
# report_idle => goto(_, :idle)
def handle_report({:report_idle, []}, %{status: _} = state) do
side_effects(state, :handle_busy, [false])
{:noreply, goto(%{state | caller_pid: nil, current: nil}, :idle), 0}
end
@ -293,6 +294,7 @@ defmodule Farmbot.Firmware do
def handle_report({:report_success, []} = code, state) do
if state.caller_pid, do: send(state.caller_pid, {state.tag, code})
new_state = %{state | current: nil, caller_pid: nil}
side_effects(state, :handle_busy, [false])
if new_state.status == :emergency_lock do
{:noreply, goto(new_state, :idle), 0}
@ -303,16 +305,19 @@ defmodule Farmbot.Firmware do
def handle_report({:report_busy, []} = code, state) do
if state.caller_pid, do: send(state.caller_pid, {state.tag, code})
side_effects(state, :handle_busy, [true])
{:noreply, state}
end
def handle_report({:report_error, []} = code, %{status: :configuration} = state) do
if state.caller_pid, do: send(state.caller_pid, {state.tag, code})
side_effects(state, :handle_busy, [false])
{:stop, {:error, state.current}, state}
end
def handle_report({:report_error, []} = code, state) do
if state.caller_pid, do: send(state.caller_pid, {state.tag, code})
side_effects(state, :handle_busy, [false])
{:noreply, %{state | caller_pid: nil, current: nil}, 0}
end
@ -351,6 +356,7 @@ defmodule Farmbot.Firmware do
# report_no_config => goto(_, :no_config)
def handle_report({:report_no_config, []}, %{status: _} = state) do
Logger.debug("REPORT_NO_CONFIG")
tag = state.tag || "0"
loaded_params = side_effects(state, :load_params, []) || []
@ -368,15 +374,18 @@ defmodule Farmbot.Firmware do
to_process =
if loaded_params[:movement_home_at_boot_x] == 1,
do: to_process ++ [{:command_movement_find_home, [:x]}]
do: to_process ++ [{:command_movement_find_home, [:x]}],
else: to_process
to_process =
if loaded_params[:movement_home_at_boot_y] == 1,
do: to_process ++ [{:command_movement_find_home, [:y]}]
do: to_process ++ [{:command_movement_find_home, [:y]}],
else: to_process
to_process =
if loaded_params[:movement_home_at_boot_z] == 1,
do: to_process ++ [{:command_movement_find_home, [:z]}]
do: to_process ++ [{:command_movement_find_home, [:z]}],
else: to_process
{:noreply, goto(%{state | tag: tag, configuration_queue: to_process}, :configuration), 0}
end

View File

@ -17,6 +17,7 @@ defmodule Farmbot.Firmware.SideEffects do
@callback handle_emergency_unlock() :: any()
@callback handle_pin_value(p: integer(), v: integer()) :: any()
@callback handle_software_version([String.t()]) :: any()
@callback handle_busy(boolean()) :: any()
@type axis_state :: :stop | :idle | :begin | :crawl | :decelerate | :accelerate
@callback handle_axis_state([{axis(), axis_state}]) :: any()

View File

@ -118,6 +118,8 @@ defmodule Farmbot.Firmware.StubSideEffects do
def handle_software_version(_), do: :noop
def handle_busy(_), do: :noop
def handle_input_gcode(_), do: :noop
def handle_output_gcode(_), do: :noop

View File

@ -28,11 +28,11 @@ defmodule Farmbot.Firmware.UARTTransport do
end
end
def handle_info({:nerves_uart, _, {:error, reason}}, state) do
def handle_info({:circuits_uart, _, {:error, reason}}, state) do
{:stop, {:uart_error, reason}, state}
end
def handle_info({:nerves_uart, _, data}, state) when is_binary(data) do
def handle_info({:circuits_uart, _, data}, state) when is_binary(data) do
code = GCODE.decode(String.trim(data))
state.handle_gcode.(code)
{:noreply, state}

View File

@ -46,6 +46,8 @@ config :farmbot, Farmbot.Platform.Supervisor,
]
import_config("lagger.exs")
config :logger, backends: [:console]
config :logger, :console, metadata: [:changeset, :module]
if Mix.Project.config()[:target] == "host" do
if File.exists?("config/host/#{Mix.env()}.exs") do

View File

@ -1,6 +1,7 @@
use Mix.Config
data_path = Path.join(["/", "tmp", "farmbot"])
File.mkdir_p(data_path)
config :farmbot_ext,
data_path: data_path
@ -24,19 +25,16 @@ config :farmbot_core, Farmbot.Asset.Repo,
loggers: [],
database: Path.join(data_path, "asset-#{Mix.env()}.sqlite3")
config :farmbot,
ecto_repos: [Farmbot.Config.Repo, Farmbot.Logger.Repo, Farmbot.Asset.Repo],
platform_children: [
{Farmbot.Host.Configurator, []}
config :farmbot, Farmbot.System.Init.Supervisor,
init_children: [
Farmbot.TTYDetector,
Farmbot.Host.Configurator
]
config :farmbot, :behaviour, system_tasks: Farmbot.Host.SystemTasks
config :farmbot,
ecto_repos: [Farmbot.Config.Repo, Farmbot.Logger.Repo, Farmbot.Asset.Repo]
config :farmbot, Farmbot.System.NervesHub,
farmbot_nerves_hub_handler: Farmbot.Host.NervesHubHandler
config :farmbot_core, :behaviour,
leds_handler: Farmbot.Leds.StubHandler,
pin_binding_handler: Farmbot.PinBinding.StubHandler,
celery_script_io_layer: Farmbot.OS.IOLayer,
firmware_handler: Farmbot.Firmware.UartHandler

View File

@ -44,10 +44,8 @@ defmodule Farmbot.System do
# credo:disable-for-next-line
require IEx; IEx.pry()
end
alias Farmbot.Config
import Config, only: [get_config_value: 3]
if Process.whereis Farmbot.Core do
if get_config_value(:bool, "settings", "disable_factory_reset") do
if Farmbot.Asset.fbos_config().disable_factory_reset do
reboot(reason)
else
do_reset(reason)

View File

@ -0,0 +1,87 @@
defmodule Farmbot.TTYDetector do
use GenServer
require Logger
alias Circuits.UART
import Farmbot.Config, only: [get_config_value: 3]
@expected_names ["ttyACM0"]
@error_ms 5000
def start_link(args) do
GenServer.start_link(__MODULE__, args, name: __MODULE__)
end
def init([]) do
{:ok, %{device: nil, needs_flash: false, open: false}, 0}
end
def handle_info(:timeout, %{device: nil} = state) do
case get_config_value(:string, "settings", "firmware_hardware") do
nil -> {:noreply, state, @error_ms}
_hw ->
available = UART.enumerate() |> Map.to_list()
{:noreply, state, {:continue, available}}
end
end
def handle_info(:timeout, %{device: device, needs_flash: true} = state) do
dir = Application.app_dir(:farmbot_core, ["priv"])
case get_config_value(:string, "settings", "firmware_hardware") do
"arduino" -> flash_fw(Path.join(dir, "arduino_firmware.hex"), state)
"farmduino" -> flash_fw(Path.join(dir, "farmduino.hex"), state)
"farmduino_k14" -> flash_fw(Path.join(dir, "farmduino_k14.hex"), state)
nil -> {:noreply, state, @error_ms}
other ->
Logger.error "Unknown arduino firmware #{other}"
{:stop, {:unknown_firmware, other}, state}
end
end
def handle_info(:timeout, %{device: device, needs_flash: false, open: false} = state) do
opts = [
device: device,
transport: Farmbot.Firmware.UARTTransport,
side_effects: Farmbot.Core.FirmwareSideEffects
]
case Farmbot.Firmware.start_link(opts) do
{:ok, pid} ->
Process.monitor(pid)
{:noreply, %{state | open: true}}
error ->
{:stop, error, state}
end
end
def handle_info({:DOWN, _ref, :process, _pid, reason}, state) do
{:stop, reason, state}
end
def handle_continue([{name, _} | rest], %{device: nil} = state)
when name in @expected_names do
{:noreply, %{state | device: name}, 0}
end
def handle_continue([_ | rest], %{device: nil} = state) do
{:noreply, state, {:continue, rest}}
end
def handle_continue([], %{device: nil} = state) do
{:noreply, state, @error_ms}
end
defp flash_fw(fw_file, state) do
args = ~w"-q -q -patmega2560 -cwiring -P#{dev(state.device)} -b115200 -D -V -Uflash:w:#{fw_file}:i"
opts = [stderr_to_stdout: true, into: IO.stream(:stdio, :line)]
res = System.cmd("avrdude", args, opts)
case res do
{_, 0} -> {:noreply, %{state | needs_flash: false}, 0}
_ ->
Logger.error("firmware flash failed")
{:noreply, state, @error_ms}
end
end
defp dev("/dev/" <> _ = device), do: IO.inspect(device, label: "DEVICE")
defp dev("tty" <> _ = dev), do: IO.inspect(Path.join("/dev", dev), label: "DEVICE")
end

View File

@ -3,7 +3,7 @@ defmodule Farmbot.Host.Configurator do
use Supervisor
import Farmbot.Config,
only: [update_config_value: 4, get_config_value: 3]
only: [update_config_value: 4]
@doc false
def start_link(args) do
@ -26,16 +26,7 @@ defmodule Farmbot.Host.Configurator do
pass = System.get_env("FARMBOT_PASSWORD") || raise error("password")
server = System.get_env("FARMBOT_SERVER") || raise error("server")
update_config_value(:string, "authorization", "email", email)
# if there is no firmware hardware, default ot farmduino
unless get_config_value(:string, "settings", "firmware_hardware") do
update_config_value(:string, "settings", "firmware_hardware", "farmduino")
end
if get_config_value(:bool, "settings", "first_boot") do
update_config_value(:string, "authorization", "password", pass)
end
update_config_value(:string, "authorization", "password", pass)
update_config_value(:string, "authorization", "server", server)
update_config_value(:string, "authorization", "token", nil)
:ignore

View File

@ -11,7 +11,7 @@ defmodule Farmbot.System.NervesHubClient do
@behaviour Farmbot.System.NervesHub
@current_version Farmbot.Project.version()
@data_path Application.get_env(:farmbot, :data_path)
@data_path Farmbot.OS.FileSystem.data_path()
@data_path || Mix.raise("Please configure data_path in application env")
import Farmbot.Config, only: [get_config_value: 3]
@ -196,7 +196,7 @@ defmodule Farmbot.System.NervesHubClient do
Farmbot.BotState.set_update_available(true)
end
case get_config_value(:bool, "settings", "os_auto_update") do
case Farmbot.Asset.fbos_config(:os_auto_update) do
true ->
Logger.success(1, "Applying OTA update")
{:reply, :apply, {:apply, url}}

View File

@ -1,64 +0,0 @@
defmodule Farmbot.Target.Network.DnsTask do
require Farmbot.Logger
use GenServer
import Farmbot.Target.Network, only: [test_dns: 0]
import Farmbot.Config, only: [get_config_value: 3]
@default_timeout_ms 45_000
def start_link(args) do
GenServer.start_link(__MODULE__, args, name: __MODULE__)
end
def init([]) do
# Block and reset if after 10 tries
# resolution doesn't work.
block_check(true)
{:ok, nil, @default_timeout_ms}
end
def handle_info(:timeout, state) do
# Block and don't reset if after 10 tries
# resolution doesn't work.
block_check()
{:noreply, state, @default_timeout_ms}
end
defp block_check(last_result, reset \\ false, tries \\ 10)
defp block_check(last_result, false, 0) do
server = get_config_value(:string, "authorization", "server")
Farmbot.Logger.error(1, "Could not resolve #{server} after 10 tries.")
end
defp block_check(_last_result, true, 0) do
server = get_config_value(:string, "authorization", "server")
Farmbot.Logger.error(1, "Tried 10 times to resolve DNS requests.")
msg = """
FarmBot is unable to make DNS requests to #{server} after
10 tries. It is possible your network has a firewall blocking this
url, or your FarmBot is configured incorrectly.
"""
Farmbot.System.factory_reset(msg)
:error
end
defp block_check(last_result, reset, tries) do
server = get_config_value(:string, "authorization", "server")
case test_dns() do
{:ok, _} ->
:ok
{:error, :nxdomain} ->
Process.sleep(10_000)
Farmbot.Logger.error(1, "Trying to resolve #{server} #{tries - 1} more times.")
block_check(reset, tries - 1)
err ->
Farmbot.Logger.error(1, "Failed to resolve #{server}: #{inspect(err)}")
block_check(reset, tries)
end
end
end

View File

@ -9,4 +9,4 @@ if [ -z $2 ]; then
exit 1
fi
avrdude -v -p atmega2560 -c wiring -P$2 -b 115200 -D -V -Uflash:w:./priv/$1.hex:i
avrdude -v -p atmega2560 -c wiring -P$2 -b 115200 -D -V -Uflash:w:./farmbot_core/priv/$1.hex:i

View File

@ -1,5 +1,5 @@
#!/bin/bash
AVAILABLE=$(ls priv/*.hex | grep -v "eeprom_clear" | tr '\n' ' ')
AVAILABLE=$(ls ./farmbot_core/priv/*.hex | grep -v "eeprom_clear" | tr '\n' ' ')
if [ -z $1 ]; then
echo "usage: scripts/reset_fw.sh [$AVAILABLE] /dev/ttyACM0"
exit 1