Update fbos_config and peripherals to coordinate with firmware status
parent
12049e04ba
commit
1a1bcb49bc
|
@ -8,7 +8,7 @@ defimpl FarmbotCore.AssetWorker, for: FarmbotCore.Asset.FbosConfig do
|
|||
require Logger
|
||||
require FarmbotCore.Logger
|
||||
alias FarmbotCeleryScript.AST
|
||||
alias FarmbotCore.{Asset.FbosConfig, BotState, Config}
|
||||
alias FarmbotCore.{Asset.FbosConfig, BotState, Config, DepTracker}
|
||||
import FarmbotFirmware.PackageUtils, only: [package_to_string: 1]
|
||||
|
||||
@firmware_flash_attempt_threshold Application.get_env(:farmbot_core, __MODULE__)[:firmware_flash_attempt_threshold]
|
||||
|
@ -35,6 +35,7 @@ defimpl FarmbotCore.AssetWorker, for: FarmbotCore.Asset.FbosConfig do
|
|||
|
||||
@impl GenServer
|
||||
def init(%FbosConfig{} = fbos_config) do
|
||||
:ok = DepTracker.register_asset(fbos_config, :init)
|
||||
if Config.get_config_value(:bool, "settings", "firmware_needs_flash") do
|
||||
Config.update_config_value(:bool, "settings", "firmware_needs_open", false)
|
||||
end
|
||||
|
@ -51,6 +52,7 @@ defimpl FarmbotCore.AssetWorker, for: FarmbotCore.Asset.FbosConfig do
|
|||
|
||||
@impl GenServer
|
||||
def handle_info({:step_complete, _, :ok}, state) do
|
||||
DepTracker.register_asset(state.fbos_config, :idle)
|
||||
Config.update_config_value(:bool, "settings", "firmware_needs_flash", false)
|
||||
Config.update_config_value(:bool, "settings", "firmware_needs_open", true)
|
||||
{:noreply, %{state | firmware_flash_in_progress: false}}
|
||||
|
@ -58,6 +60,7 @@ defimpl FarmbotCore.AssetWorker, for: FarmbotCore.Asset.FbosConfig do
|
|||
|
||||
def handle_info({:step_complete, _, {:error, reason}}, %{firmware_flash_attempts: tries, firmware_flash_attempt_threshold: thresh} = state)
|
||||
when tries >= thresh do
|
||||
DepTracker.register_asset(state.fbos_config, :idle)
|
||||
FarmbotCore.Logger.error 1, """
|
||||
Failed flashing firmware: #{reason}
|
||||
Tried #{tries} times. Not retrying
|
||||
|
@ -68,6 +71,7 @@ defimpl FarmbotCore.AssetWorker, for: FarmbotCore.Asset.FbosConfig do
|
|||
end
|
||||
|
||||
def handle_info({:step_complete, _, {:error, reason}}, %{fbos_config: %FbosConfig{} = fbos_config} = state) do
|
||||
DepTracker.register_asset(fbos_config, :flash_firmware)
|
||||
Config.update_config_value(:bool, "settings", "firmware_needs_flash", true)
|
||||
Config.update_config_value(:bool, "settings", "firmware_needs_open", false)
|
||||
|
||||
|
@ -138,6 +142,11 @@ defimpl FarmbotCore.AssetWorker, for: FarmbotCore.Asset.FbosConfig do
|
|||
{:noreply, %{state | fbos_config: new_fbos_config, firmware_io_timer: nil}}
|
||||
end
|
||||
|
||||
def handle_info(:bootup_sequence, state) do
|
||||
DepTracker.register_asset(state.fbos_config, :idle)
|
||||
{:noreply, state}
|
||||
end
|
||||
|
||||
@impl GenServer
|
||||
def handle_cast({:new_data, new_fbos_config}, %{fbos_config: %FbosConfig{} = old_fbos_config} = state) do
|
||||
_ = set_config_to_state(new_fbos_config, old_fbos_config)
|
||||
|
@ -157,10 +166,11 @@ defimpl FarmbotCore.AssetWorker, for: FarmbotCore.Asset.FbosConfig do
|
|||
:ok
|
||||
end
|
||||
|
||||
def maybe_flash_firmware(_state, new_hardware, old_hardware) do
|
||||
def maybe_flash_firmware(state, new_hardware, old_hardware) do
|
||||
force? = Config.get_config_value(:bool, "settings", "firmware_needs_flash")
|
||||
cond do
|
||||
force? ->
|
||||
DepTracker.register_asset(state.fbos_config, :firmware_flash)
|
||||
FarmbotCore.Logger.warn 1, "Firmware hardware forced flash"
|
||||
Config.update_config_value(:bool, "settings", "firmware_needs_flash", false)
|
||||
new_hardware
|
||||
|
@ -168,6 +178,7 @@ defimpl FarmbotCore.AssetWorker, for: FarmbotCore.Asset.FbosConfig do
|
|||
|> FarmbotCeleryScript.execute(make_ref())
|
||||
|
||||
new_hardware != old_hardware ->
|
||||
DepTracker.register_asset(state.fbos_config, :firmware_flash)
|
||||
FarmbotCore.Logger.warn 1, "Firmware hardware change from #{package_to_string(old_hardware)} to #{package_to_string(new_hardware)}"
|
||||
new_hardware
|
||||
|> fbos_config_to_flash_firmware_rpc()
|
||||
|
@ -175,6 +186,7 @@ defimpl FarmbotCore.AssetWorker, for: FarmbotCore.Asset.FbosConfig do
|
|||
|
||||
true ->
|
||||
# Config.update_config_value(:bool, "settings", "firmware_needs_open", true)
|
||||
send self(), :bootup_sequence
|
||||
:ok
|
||||
end
|
||||
end
|
||||
|
@ -270,7 +282,7 @@ defimpl FarmbotCore.AssetWorker, for: FarmbotCore.Asset.FbosConfig do
|
|||
|
||||
def fbos_config_to_flash_firmware_rpc(firmware_hardware) do
|
||||
AST.Factory.new()
|
||||
|> AST.Factory.rpc_request("FbosConfig")
|
||||
|> AST.Factory.rpc_request("fbos_config.flash_firmware")
|
||||
|> AST.Factory.flash_firmware(firmware_hardware)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,12 +1,20 @@
|
|||
defimpl FarmbotCore.AssetWorker, for: FarmbotCore.Asset.Peripheral do
|
||||
use GenServer
|
||||
require Logger
|
||||
require FarmbotCore.Logger
|
||||
|
||||
alias FarmbotCore.{Asset.Peripheral, BotState}
|
||||
alias FarmbotCore.{Asset.FbosConfig, Asset.Peripheral, BotState, DepTracker}
|
||||
alias FarmbotCeleryScript.AST
|
||||
|
||||
@retry_ms 1_000
|
||||
|
||||
@unacceptable_fbos_config_statuses [
|
||||
nil,
|
||||
:init,
|
||||
:firmware_flash,
|
||||
:bootup_sequence,
|
||||
]
|
||||
|
||||
@impl true
|
||||
def preload(%Peripheral{}), do: []
|
||||
|
||||
|
@ -20,30 +28,69 @@ defimpl FarmbotCore.AssetWorker, for: FarmbotCore.Asset.Peripheral do
|
|||
|
||||
@impl true
|
||||
def init(peripheral) do
|
||||
%{informational_settings: %{idle: idle, firmware_version: fw_version}} = BotState.subscribe()
|
||||
state = %{peripheral: peripheral, errors: 0, fw_idle: idle || false, fw_version: fw_version}
|
||||
send self(), :timeout
|
||||
%{
|
||||
informational_settings: %{
|
||||
idle: idle,
|
||||
firmware_version: fw_version,
|
||||
firmware_configured: fw_configured
|
||||
}
|
||||
} = BotState.subscribe()
|
||||
state = %{
|
||||
peripheral: peripheral,
|
||||
errors: 0,
|
||||
fw_idle: idle || false,
|
||||
fw_version: fw_version,
|
||||
fw_configured: fw_configured || false,
|
||||
fbos_config_status: nil
|
||||
}
|
||||
:ok = DepTracker.subscribe_asset(FbosConfig)
|
||||
send self(), :try_read_peripheral
|
||||
{:ok, state}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_info(:timeout, %{fw_version: nil} = state) do
|
||||
# Logger.debug("Not reading peripheral. Firmware not started.")
|
||||
Process.send_after(self(), :timeout, @retry_ms)
|
||||
def handle_info({DepTracker, {FbosConfig, _}, _old, status}, state) do
|
||||
{:noreply, %{state | fbos_config_status: status}}
|
||||
end
|
||||
|
||||
def handle_info(:try_read_peripheral, %{fbos_config_status: fbos_config_status} = state)
|
||||
when fbos_config_status in @unacceptable_fbos_config_statuses do
|
||||
# Logger.debug("Not reading peripheral. fbos_config not in acceptable state: #{fbos_config_status}")
|
||||
Process.send_after(self(), :try_read_peripheral, @retry_ms)
|
||||
{:noreply, state}
|
||||
end
|
||||
|
||||
def handle_info(:timeout, %{fw_version: "8.0.0.S"} = state) do
|
||||
def handle_info(:try_read_peripheral, %{fbos_config_status: :bootup_sequence} = state) do
|
||||
# Logger.debug("Not reading peripheral. Bootup sequence not complete")
|
||||
Process.send_after(self(), :try_read_peripheral, @retry_ms)
|
||||
{:noreply, state}
|
||||
end
|
||||
|
||||
def handle_info(:timeout, %{fw_idle: false} = state) do
|
||||
def handle_info(:try_read_peripheral, %{fw_version: nil} = state) do
|
||||
# Logger.debug("Not reading peripheral. Firmware not booted.")
|
||||
Process.send_after(self(), :try_read_peripheral, @retry_ms)
|
||||
{:noreply, state}
|
||||
end
|
||||
|
||||
def handle_info(:try_read_peripheral, %{fw_version: "none"} = state) do
|
||||
# Logger.debug("Not reading peripheral. Firmware not booted.")
|
||||
Process.send_after(self(), :try_read_peripheral, @retry_ms)
|
||||
{:noreply, state}
|
||||
end
|
||||
|
||||
def handle_info(:try_read_peripheral, %{fw_configured: false} = state) do
|
||||
# Logger.debug("Not reading peripheral. Firmware not configured.")
|
||||
Process.send_after(self(), :try_read_peripheral, @retry_ms)
|
||||
{:noreply, state}
|
||||
end
|
||||
|
||||
def handle_info(:try_read_peripheral, %{fw_idle: false} = state) do
|
||||
# Logger.debug("Not reading peripheral. Firmware not idle.")
|
||||
Process.send_after(self(), :timeout, @retry_ms)
|
||||
Process.send_after(self(), :try_read_peripheral, @retry_ms)
|
||||
{:noreply, state}
|
||||
end
|
||||
|
||||
def handle_info(:timeout, %{peripheral: peripheral, errors: errors} = state) do
|
||||
def handle_info(:try_read_peripheral, %{peripheral: peripheral, errors: errors} = state) do
|
||||
Logger.debug("Read peripheral: #{peripheral.label}")
|
||||
rpc = peripheral_to_rpc(peripheral)
|
||||
case FarmbotCeleryScript.execute(rpc, make_ref()) do
|
||||
|
@ -52,8 +99,8 @@ defimpl FarmbotCore.AssetWorker, for: FarmbotCore.Asset.Peripheral do
|
|||
{:noreply, state}
|
||||
|
||||
{:error, reason} when errors < 5 ->
|
||||
Logger.error("Read peripheral: #{peripheral.label} error: #{reason} errors=#{state.errors}")
|
||||
Process.send_after(self(), :timeout, @retry_ms)
|
||||
Logger.error("Read peripheral: #{peripheral.label} error: #{reason} errors=#{state.errors} status=#{state.fbos_config_status}")
|
||||
Process.send_after(self(), :try_read_peripheral, @retry_ms)
|
||||
{:noreply, %{state | errors: state.errors + 1}}
|
||||
|
||||
{:error, reason} when errors == 5 ->
|
||||
|
@ -70,6 +117,15 @@ defimpl FarmbotCore.AssetWorker, for: FarmbotCore.Asset.Peripheral do
|
|||
{:noreply, %{state | fw_version: fw_version}}
|
||||
end
|
||||
|
||||
def handle_info({BotState, %{changes: %{informational_settings: %{changes: %{firmware_configured: fw_configured}}}}}, state) do
|
||||
# this should really be fixed upstream not to dispatch if version is none.
|
||||
if state.fw_version == "none" do
|
||||
{:noreply, state}
|
||||
else
|
||||
{:noreply, %{state | fw_configured: fw_configured}}
|
||||
end
|
||||
end
|
||||
|
||||
def handle_info({BotState, _}, state) do
|
||||
{:noreply, state}
|
||||
end
|
||||
|
@ -80,7 +136,7 @@ defimpl FarmbotCore.AssetWorker, for: FarmbotCore.Asset.Peripheral do
|
|||
|
||||
def peripheral_to_rpc(peripheral) do
|
||||
AST.Factory.new()
|
||||
|> AST.Factory.rpc_request(peripheral.local_id)
|
||||
|> AST.Factory.rpc_request("peripheral." <> peripheral.local_id)
|
||||
|> AST.Factory.set_pin_io_mode(peripheral.pin, "output")
|
||||
|> AST.Factory.read_pin(peripheral.pin, peripheral.mode)
|
||||
end
|
||||
|
|
|
@ -8,7 +8,7 @@ defmodule FarmbotCore.FirmwareOpenTask do
|
|||
use GenServer
|
||||
require FarmbotCore.Logger
|
||||
alias FarmbotFirmware.{UARTTransport, StubTransport}
|
||||
alias FarmbotCore.{Asset, Config}
|
||||
alias FarmbotCore.{Asset, Config, DepTracker}
|
||||
@attempt_threshold Application.get_env(:farmbot_core, __MODULE__)[:attempt_threshold]
|
||||
@attempt_threshold || Mix.raise """
|
||||
Firmware open attempt threshold not configured:
|
||||
|
@ -89,6 +89,7 @@ defmodule FarmbotCore.FirmwareOpenTask do
|
|||
:ok ->
|
||||
Config.update_config_value(:bool, "settings", "firmware_needs_open", false)
|
||||
timer = Process.send_after(self(), :open, 5000)
|
||||
DepTracker.register_service(:firmware, :init)
|
||||
{:noreply, %{state | timer: timer, attempts: 0}}
|
||||
_ ->
|
||||
FarmbotCore.Logger.debug 3, "Firmware failed to open"
|
||||
|
|
Loading…
Reference in New Issue