Time for bed.

pull/200/head
connor rigby 2016-11-16 17:05:03 -08:00
parent 7b6bb8eb52
commit 2b9a3716c3
14 changed files with 161 additions and 104 deletions

View File

@ -4,6 +4,12 @@ import_config "#{Mix.env}.exs"
config :farmbot_auth,
callbacks: [Farmbot.Sync, Farmbot.RPC.Transport.Mqtt]
config :farmbot_configurator,
callback: Farmbot.BotState.Monitor
config :json_rpc,
transport: Farmbot.RPC.Transport.Mqtt,
handler: Farmbot.RPC.Handler
transport: Farmbot.RPC.Transport.Mqtt,
handler: Farmbot.RPC.Handler
config :uart,
baud: 115200

View File

@ -1,6 +1,3 @@
use Mix.Config
config :uart,
baud: 115200
config :farmbot,
state_path: "/tmp/state"

View File

@ -3,17 +3,17 @@ config :nerves, :firmware,
rootfs_additions: "config/rootfs-additions-#{Mix.Project.config[:target]}",
hardware: "config/rootfs-additions-#{Mix.Project.config[:target]}"
config :uart,
baud: 115200
config :farmbot,
state_path: "/state",
state_path: "/state"
config :farmbot_networking,
dnsmasq_path: "/root/dnsmasq.lease"
config :logger, :console,
# format: "$metadata[$level] $levelpad$message\r\n",
colors: [enabled: true ]
config :Logger,
config :logger,
handle_sasl_reports: true,
handle_otp_reports: true
@ -28,9 +28,3 @@ config :iex,
"%node",
">",
:reset ] |> IO.ANSI.format |> IO.chardata_to_string
config :blinky, led_list: [ :green ]
config :nerves_leds, names: [ green: "led0" ]
config :farmbot_configurator,
event_handler: Farmbot.BotState.EventManager

View File

@ -1,38 +0,0 @@
defmodule Farmbot.BotState.EventManager do
@moduledoc """
Handles stuff like logging in to web services and what not.
"""
use GenEvent
require Logger
def handle_event({:login,
%{"email" => email,
"network" => "ethernet",
"password" => password,
"server" => server,
"tz" => timezone}}, parent)
do
Farmbot.BotState.update_config("timezone", timezone)
Farmbot.BotState.add_creds({email,password,server})
NetMan.connect(:ethernet, Farmbot.BotState)
{:ok, parent}
end
def handle_event({:login,
%{"email" => email,
"network" => %{"psk" => psk, "ssid" => ssid},
"password" => password,
"server" => server,
"tz" => timezone}}, parent)
do
Farmbot.BotState.update_config("timezone", timezone)
Farmbot.BotState.add_creds({email,password,server})
NetMan.connect({ssid, psk}, Farmbot.BotState)
{:ok, parent}
end
def handle_event(event, parent) do
Logger.warn("unhandled botstate event #{inspect event}")
{:ok, parent}
end
end

View File

@ -1,8 +1,8 @@
alias Farmbot.BotState.Hardware, as: Hardware
alias Farmbot.BotState.Configuration, as: Configuration
alias Farmbot.BotState.Authorization, as: Authorization
alias Serialized, as: State # DELETE ME
alias Serialized, as: State
defmodule Farmbot.BotState do
require Logger
@moduledoc """
@ -95,39 +95,6 @@ defmodule Farmbot.BotState do
{:reply, state.location, state}
end
# This call should probably be a cast actually, and im sorry.
# Returns true for configs that exist and are the correct typpe,
# and false for anything else
# TODO make sure these are properly typed.
def handle_call({:update_config, "os_auto_update", value}, _from, state)
when is_boolean(value) do
new_config = Map.put(state.configuration, :os_auto_update, value)
{:reply, true, Map.put(state, :configuration, new_config)}
end
def handle_call({:update_config, "fw_auto_update", value}, _from, state)
when is_boolean(value) do
new_config = Map.put(state.configuration, :fw_auto_update, value)
{:reply, true, Map.put(state, :configuration, new_config)}
end
def handle_call({:update_config, "timezone", value}, _from, state)
when is_bitstring(value) do
new_config = Map.put(state.configuration, :timezone, value)
{:reply, true, Map.put(state, :configuration, new_config)}
end
def handle_call({:update_config, "steps_per_mm", value}, _from, state)
when is_integer(value) do
new_config = Map.put(state.configuration, :steps_per_mm, value)
{:reply, true, Map.put(state, :configuration, new_config)}
end
def handle_call({:update_config, key, _value}, _from, state) do
Logger.error("#{key} is not a valid config.")
{:reply, false, state}
end
def handle_call({:get_config, key}, _from, state)
when is_atom(key) do
{:reply, Map.get(state.configuration, key), state}

View File

@ -1,6 +1,7 @@
alias Farmbot.BotState.Hardware.State, as: Hardware
alias Farmbot.BotState.Configuration.State, as: Configuration
alias Farmbot.BotState.Authorization.State, as: Authorization
alias Farmbot.Scheduler.State.Serializer, as: Scheduler
defmodule Farmbot.BotState.Monitor do
@moduledoc """
@ -15,12 +16,14 @@ defmodule Farmbot.BotState.Monitor do
@type t :: %__MODULE__{
hardware: Hardware.t,
configuration: Configuration.t,
authorization: Authorization.t
authorization: Authorization.t,
scheduler: Scheduler.t
}
defstruct [
hardware: %Hardware{},
configuration: %Configuration{},
authorization: %Authorization{}
authorization: %Authorization{},
scheduler: %Scheduler{}
]
end
@ -63,6 +66,38 @@ defmodule Farmbot.BotState.Monitor do
dispatch(mgr, new_state)
end
# When we get a state update from Scheduler
def handle_cast(%Scheduler{} = new_things, {mgr, state}) do
new_state = %State{state | scheduler: new_things}
dispatch(mgr, new_state)
end
def handle_cast({:login,
%{"email" => email,
"network" => "ethernet",
"password" => password,
"server" => server,
"tz" => timezone}}, {mgr, state})
do
Farmbot.BotState.update_config("timezone", timezone)
Farmbot.BotState.add_creds({email,password,server})
NetMan.connect(:ethernet, Farmbot.BotState.Configuration)
dispatch(mgr,state)
end
def handle_cast({:login,
%{"email" => email,
"network" => %{"psk" => psk, "ssid" => ssid},
"password" => password,
"server" => server,
"tz" => timezone}}, {mgr, state})
do
Farmbot.BotState.update_config("timezone", timezone)
Farmbot.BotState.add_creds({email,password,server})
NetMan.connect({ssid, psk}, Farmbot.BotState.Configuration)
dispatch(mgr,state)
end
# If a handler dies, we try to restart it
def handle_info({:gen_event_EXIT, handler, _reason}, {mgr, state}) do
Logger.warn("HANDLER DIED: #{inspect handler} Goint to try to restart")

View File

@ -31,4 +31,24 @@ defmodule Farmbot.BotState.Authorization do
def start_link(args) do
GenServer.start_link(__MODULE__, args, name: __MODULE__)
end
def handle_call(event, _from, %State{} = state) do
Logger.warn("[#{__MODULE__}] UNHANDLED CALL!: #{inspect event}", [__MODULE__])
dispatch :unhandled, state
end
def handle_cast(event, %State{} = state) do
Logger.warn("[#{__MODULE__}] UNHANDLED CAST!: #{inspect event}", [__MODULE__])
dispatch state
end
defp dispatch(reply, %State{} = state) do
State.broadcast(state)
{:reply, reply, state}
end
defp dispatch(%State{} = state) do
State.broadcast(state)
{:noreply, state}
end
end

View File

@ -27,4 +27,57 @@ defmodule Farmbot.BotState.Configuration do
def start_link(args) do
GenServer.start_link(__MODULE__, args, name: __MODULE__)
end
# This call should probably be a cast actually, and im sorry.
# Returns true for configs that exist and are the correct typpe,
# and false for anything else
# TODO make sure these are properly typed.
def handle_call({:update_config, "os_auto_update", value}, _from, %State{} = state)
when is_boolean(value) do
new_config = Map.put(state.configuration, :os_auto_update, value)
dispatch true, %State{configuration: new_config}
end
def handle_call({:update_config, "fw_auto_update", value}, _from, %State{} = state)
when is_boolean(value) do
new_config = Map.put(state.configuration, :fw_auto_update, value)
dispatch true, %State{configuration: new_config}
end
def handle_call({:update_config, "timezone", value}, _from, %State{} = state)
when is_bitstring(value) do
new_config = Map.put(state.configuration, :timezone, value)
dispatch true, %State{configuration: new_config}
end
def handle_call({:update_config, "steps_per_mm", value}, _from, %State{} = state)
when is_integer(value) do
new_config = Map.put(state.configuration, :steps_per_mm, value)
dispatch true, %State{configuration: new_config}
end
def handle_call({:update_config, key, _value}, _from, %State{} = state) do
Logger.error("#{key} is not a valid config.")
dispatch false, state
end
def handle_call(event, _from, %State{} = state) do
Logger.warn("[#{__MODULE__}] UNHANDLED CALL!: #{inspect event}", [__MODULE__])
dispatch :unhandled, state
end
def handle_cast(event, %State{} = state) do
Logger.warn("[#{__MODULE__}] UNHANDLED CAST!: #{inspect event}", [__MODULE__])
dispatch state
end
defp dispatch(reply, %State{} = state) do
State.broadcast(state)
{:reply, reply, state}
end
defp dispatch(%State{} = state) do
State.broadcast(state)
{:noreply, state}
end
end

View File

@ -40,4 +40,24 @@ defmodule Farmbot.BotState.Hardware do
def start_link(args) do
GenServer.start_link(__MODULE__, args, name: __MODULE__)
end
def handle_call(event, _from, %State{} = state) do
Logger.warn("[#{__MODULE__}] UNHANDLED CALL!: #{inspect event}", [__MODULE__])
dispatch :unhandled, state
end
def handle_cast(event, %State{} = state) do
Logger.warn("[#{__MODULE__}] UNHANDLED CAST!: #{inspect event}", [__MODULE__])
dispatch state
end
defp dispatch(reply, %State{} = state) do
State.broadcast(state)
{:reply, reply, state}
end
defp dispatch(%State{} = state) do
State.broadcast(state)
{:noreply, state}
end
end

View File

@ -135,7 +135,7 @@ defmodule Farmbot.RPC.Handler do
"""
@spec serialize_state(Farmbot.BotState.Monitor.State.t) :: Serialized.t
def serialize_state(%Farmbot.BotState.Monitor.State{
hardware: hardware, configuration: configuration
hardware: hardware, configuration: configuration, scheduler: scheduler
}) do
%Serialized{
mcu_params: hardware.mcu_params,
@ -148,7 +148,7 @@ defmodule Farmbot.RPC.Handler do
informational_settings: configuration.informational_settings,
# farm scheduler
farm_scheduler: %Farmbot.Scheduler.State.Serializer{}
farm_scheduler: scheduler
}
end

View File

@ -1,6 +1,6 @@
defmodule Serialized do
@moduledoc """
MOVE THIS SOMEWHERE ELSE
MOVE THIS SOMEWHERE ELSE
"""
defstruct [
# Hardware

View File

@ -280,10 +280,13 @@ defmodule Farmbot.Scheduler do
regimens: regimens}}
end
@doc """
I CAN'T THINK OF A BETTER WAY TO DO THIS IM SORRY
"""
@spec save_and_update(State.t) :: :ok
def save_and_update(%State{} = state) do
GenServer.cast(Farmbot.BotState,
{:scheduler, State.Serializer.serialize(state)})
GenServer.cast(Farmbot.BotState.Monitor,
{State.Serializer.serialize(state)})
SafeStorage.write(__MODULE__, :erlang.term_to_binary(state))
end

View File

@ -3,7 +3,7 @@ defmodule RPC.Supervisor do
@transport Application.get_env(:json_rpc, :transport)
@handler Application.get_env(:json_rpc, :handler)
def init(args) do
def init(_args) do
children = [
worker(RPC.MessageManager, []),
worker(RPC.MessageHandler, [], id: 1, name: RPC.MessageHandler ),

16
mix.exs
View File

@ -34,7 +34,7 @@ defmodule Farmbot.Mixfile do
def application do
[mod: {Farmbot, [%{target: target(Mix.env), compat_version: @compat_version,
version: @version, env: Mix.env}]},
version: @version, env: Mix.env}]},
applications: apps(Mix.env)]
end
@ -51,7 +51,8 @@ defmodule Farmbot.Mixfile do
:runtime_tools,
:mustache,
:timex,
:farmbot_auth]
:farmbot_auth,
:farmbot_configurator]
end
# on device
@ -59,8 +60,7 @@ defmodule Farmbot.Mixfile do
apps ++ platform_apps(target(:prod)) ++
[
:nerves,
:nerves_firmware_http,
:farmbot_configurator
:nerves_firmware_http
]
end
@ -89,6 +89,8 @@ defmodule Farmbot.Mixfile do
{:mustache, "~> 0.0.2"},
{:timex, "~> 3.0"},
{:farmbot_auth, github: "Farmbot/farmbot_auth"},
# {:farmbot_configurator, github: "Farmbot/farmbot_configurator"}
{:farmbot_configurator, path: "../farmbot_configurator"}
# {:farmbot_auth, path: "../farmbot_auth"}
]
end
@ -97,9 +99,7 @@ defmodule Farmbot.Mixfile do
deps ++ platform_deps(target(Mix.env)) ++ system(target(Mix.env)) ++
[
{:nerves, "~> 0.3.0"},
{:nerves_firmware_http, github: "nerves-project/nerves_firmware_http"},
# {:farmbot_configurator, github: "Farmbot/farmbot_configurator"}
{:farmbot_configurator, path: "../farmbot_configurator"}
{:nerves_firmware_http, github: "nerves-project/nerves_firmware_http"}
]
end
@ -113,7 +113,7 @@ defmodule Farmbot.Mixfile do
def deps(:dev) do
deps ++ [
# {:fake_nerves, github: "ConnorRigby/fake_nerves"},
{:fake_nerves, path: "../fake_nerves"},
{:fake_nerves, path: "../fake_nerves", override: true},
{:credo, "~> 0.4"},
{:dialyxir, "~> 0.4"}]
end