Merge staging into feature/api_settings

This commit is contained in:
connor rigby 2018-01-23 12:29:47 -08:00
commit 8b23690cc4
12 changed files with 279 additions and 127 deletions

View file

@ -1,118 +1,14 @@
# 2.1.9
* changed folder structure around
* moved farmbot_auth and farmbot_configurator back into an umbrella application
* begin migration to CeleryScript for all the things
* Multi Platform support
* `Configurator` looks great. thanks @MrChristofferson && @RickCarlino
* Code base was converted to CeleryScript, so it is much more stable
* bot configuration is now based on a single (json) that is shared across platforms/targets
# 6.1.1
* Fix bug that caused the "update" button on the frontend to give an error log.
* Fix flashing `beta` channel updates.
* Add feature to send user an email if the bot has been e-stopped for 10 minutes.
* Add feature to `espeak` logs.
# 2.1.10
* a few minor bug fixes to the previous release.
# 3.0.0
* Makefile
# 3.0.1
* implement bot state migrations
* logger fixes.
# 3.0.2
* Farmware initial concepts.
# 3.0.3
* Farmware fixes
# 3.0.4
* Logger bug fixes
# 3.0.5
* Configurator got a facelift + a few extra features.
# 3.0.6
* Syncing is now a multiple request action and is now much faster and safer.
* change folder structure
* begin adding redis support.
# 3.0.8
* Rewrite Serial handler and bundle FW into the OS.
# 3.1.0
* Fix a bug with unwanted Logs going to the frontend/backend.
# 3.1.1
* Bundle a new FW fixing z axis and gravity.
# 3.1.2
* Fix bug caused by Github changing their release api.
# 3.1.3
* Fix peripheral bug.
# 3.1.4
* Bundle new FW
* Add Rollbar client
# 3.1.5
* Clean up a ton of log messages causing RollBar problems.
* Finally rewrite the firmware uploader.
* Bump Firmware Version.
* Misc bug fixes.
# 3.1.6
* Bundle new FW (01.13)
* Increase WiFi Stability
* Refresh auth token more frequently
* Clean up noisy log messages
# 4.0.0
* bundle new Arduino Firmware
* overhaul HTTP adapter
* start fixing cross cutting concerns within the application
# 4.0.1
* fix bug in E-Stop
# 5.0.0
* add a progress bar to http client for downloads.
* Bundle new Arduino Firmware.
* Rewrite Farmware Handler again, to use HTTP/REST this time instead of STDIN/STDOUT.
* Add location_data to bot state. This includes encoder position.
* Add `jobs` field to bot state.
# 5.0.1
* Fix not being able to move to a point in some cases.
* Fix a sub sequence never returning.
* add `busy` flag to the bot's state.
# 5.0.2
* Fix a bug causing `busy` to be set erroneously.
* add note to configurator for osx users.
# 5.0.3
* Add selector for firmware hardware to Configurator.
* Fix an OS update bug.
* Fix an image upload bug.
* Fix a farmware download bug.
# 5.0.4
* Fix lag when communicating over MQTT
* Don't retain last will log message.
* Update node packages.
# 5.0.5
* Fix token refreshing.
# 5.0.6
* Fix images double uploading.
* Allow reinstallation of first party farmware.
# 5.0.8
* Update underlying Linux System deps.
* Preperation for 6.x releases.
# 5.0.9
* Add missing redis-py package for Farmware.
# 6.1.0
* Remove all the migration code to safely get from 5.0.x to 6.0.1.
* Clean up and upgrade dependencies.
* Fix bug that could cause Image uploads to silently fail.
* Fix bug in `tzdata` that could cause the sdcard to fill up.
# 6.0.1
* Add feature auto sync.
@ -132,8 +28,118 @@
* Refactored FarmEvent Calendar generator.
* Fix a ton of little bugs.
# 6.1.0
* Remove all the migration code to safely get from 5.0.x to 6.0.1.
* Clean up and upgrade dependencies.
* Fix bug that could cause Image uploads to silently fail.
* Fix bug in `tzdata` that could cause the sdcard to fill up.
# 5.0.9
* Add missing redis-py package for Farmware.
# 5.0.8
* Update underlying Linux System deps.
* Preperation for 6.x releases.
# 5.0.6
* Fix images double uploading.
* Allow reinstallation of first party farmware.
# 5.0.5
* Fix token refreshing.
# 5.0.4
* Fix lag when communicating over MQTT
* Don't retain last will log message.
* Update node packages.
# 5.0.3
* Add selector for firmware hardware to Configurator.
* Fix an OS update bug.
* Fix an image upload bug.
* Fix a farmware download bug.
# 5.0.2
* Fix a bug causing `busy` to be set erroneously.
* add note to configurator for osx users.
# 5.0.1
* Fix not being able to move to a point in some cases.
* Fix a sub sequence never returning.
* add `busy` flag to the bot's state.
# 5.0.0
* add a progress bar to http client for downloads.
* Bundle new Arduino Firmware.
* Rewrite Farmware Handler again, to use HTTP/REST this time instead of STDIN/STDOUT.
* Add location_data to bot state. This includes encoder position.
* Add `jobs` field to bot state.
# 4.0.1
* fix bug in E-Stop
# 4.0.0
* bundle new Arduino Firmware
* overhaul HTTP adapter
* start fixing cross cutting concerns within the application
# 3.1.6
* Bundle new FW (01.13)
* Increase WiFi Stability
* Refresh auth token more frequently
* Clean up noisy log messages
# 3.1.5
* Clean up a ton of log messages causing RollBar problems.
* Finally rewrite the firmware uploader.
* Bump Firmware Version.
* Misc bug fixes.
# 3.1.4
* Bundle new FW
* Add Rollbar client
# 3.1.3
* Fix peripheral bug.
# 3.1.2
* Fix bug caused by Github changing their release api.
# 3.1.1
* Bundle a new FW fixing z axis and gravity.
# 3.1.0
* Fix a bug with unwanted Logs going to the frontend/backend.
# 3.0.8
* Rewrite Serial handler and bundle FW into the OS.
# 3.0.6
* Syncing is now a multiple request action and is now much faster and safer.
* change folder structure
* begin adding redis support.
# 3.0.5
* Configurator got a facelift + a few extra features.
# 3.0.4
* Logger bug fixes
# 3.0.3
* Farmware fixes
# 3.0.2
* Farmware initial concepts.
# 3.0.1
* implement bot state migrations
* logger fixes.
# 3.0.0
* Makefile
# 2.1.10
* a few minor bug fixes to the previous release.
# 2.1.9
* changed folder structure around
* moved farmbot_auth and farmbot_configurator back into an umbrella application
* begin migration to CeleryScript for all the things
* Multi Platform support
* `Configurator` looks great. thanks @MrChristofferson && @RickCarlino
* Code base was converted to CeleryScript, so it is much more stable
* bot configuration is now based on a single (json) that is shared across platforms/targets

View file

@ -3,3 +3,5 @@ use Mix.Config
config :nerves_leds, names: [ status: "led0" ]
config :farmbot, :gpio, status_led_on: false
config :farmbot, :gpio, status_led_off: true
config :farmbot, kernel_modules: ["snd-bcm2835"]

View file

@ -9,3 +9,5 @@ config :farmbot, :captive_portal_address, "192.168.24.1"
config :bootloader,
init: [:nerves_runtime, :nerves_firmware_ssh],
app: :farmbot
config :farmbot, kernel_modules: ["snd-bcm2835"]

View file

@ -125,6 +125,7 @@ defmodule Farmbot.Bootstrap.Supervisor do
children = [
worker(Farmbot.Bootstrap.AuthTask, []),
worker(Farmbot.CeleryScript.EstopTimer, []),
supervisor(Farmbot.HTTP.Supervisor, []),
worker(Farmbot.Bootstrap.SettingsSync, [], [restart: :transient]),
supervisor(Farmbot.Firmware.Supervisor, []),

View file

@ -20,6 +20,14 @@ defmodule Farmbot.BotState.Transport.HTTP.Router do
send_resp conn, 200, data
end
get "/api/v1/bot/speak" do
case conn.params do
%{"text" => text} when is_binary(text) ->
System.cmd("espeak", [text])
end
send_resp conn, 200, ""
end
post "/api/v1/celery_script" do
with {:ok, _, conn} <- conn |> read_body(),
{:ok, ast} <- Farmbot.CeleryScript.AST.decode(conn.params)

View file

@ -2,15 +2,17 @@ defmodule Farmbot.CeleryScript.AST.Node.Sequence do
@moduledoc false
use Farmbot.CeleryScript.AST.Node
use Farmbot.Logger
import Farmbot.System.ConfigStorage, only: [get_config_value: 3]
alias Farmbot.CeleryScript.EstopTimer
allow_args [:version, :label, :locals, :is_outdated]
def execute(%{label: name}, body, env) do
if Farmbot.System.ConfigStorage.get_config_value(:bool, "settings", "sequence_init_log") do
if get_config_value(:bool, "settings", "sequence_init_log") do
Logger.busy 2, "[#{name}] - Sequence init."
end
env = mutate_env(env)
if Farmbot.BotState.locked? do
Logger.error 1, "[#{name}] - Sequence failed. Bot is locked!"
maybe_send_email("[#{name}] - Sequence failed. Bot is locked!")
{:error, :locked, env}
else
do_reduce(body, env, name)
@ -18,26 +20,38 @@ defmodule Farmbot.CeleryScript.AST.Node.Sequence do
end
defp do_reduce([ast | rest], env, name) do
if Farmbot.System.ConfigStorage.get_config_value(:bool, "settings", "sequence_body_log") do
if get_config_value(:bool, "settings", "sequence_body_log") do
Logger.info 2, "[#{name}] - Sequence Executing: #{inspect ast}"
end
case Farmbot.CeleryScript.execute(ast, env) do
{:ok, new_env} -> do_reduce(rest, new_env, name)
{:error, reason, env} ->
Logger.warn 1, "[#{name}] - Sequence failed. Locking bot!"
case Farmbot.Firmware.emergency_lock() do
:ok -> :ok
:ok ->
maybe_send_email("[#{name}] - Sequence failed. Locking bot!")
:ok
{:error, :emergency_lock} -> :ok
{:error, reason} -> Logger.error 1, "Failed to lock the firmware! #{inspect reason}"
{:error, reason} ->
Logger.error 1, "Failed to lock the firmware! #{inspect reason}"
end
{:error, reason, env}
end
end
defp do_reduce([], env, name) do
if Farmbot.System.ConfigStorage.get_config_value(:bool, "settings", "sequence_complete_log") do
if get_config_value(:bool, "settings", "sequence_complete_log") do
Logger.success 2, "[#{name}] - Sequence complete."
end
{:ok, env}
end
defp maybe_send_email(msg) do
Logger.error(1, msg)
if get_config_value(:bool, "settings", "email_on_estop") do
if !EstopTimer.timer_active? do
EstopTimer.start_timer(msg)
end
end
end
end

View file

@ -0,0 +1,74 @@
defmodule Farmbot.CeleryScript.EstopTimer do
@moduledoc """
Module responsible for timing emails about E stops.
"""
use GenServer
use Farmbot.Logger
@msg "Farmbot has been E-Stopped for more than 10 minutes."
# Ten minutes.
@timer_ms 600000
# fifteen seconds.
# @timer_ms 15000
@doc "Checks if the timer is active."
def timer_active? do
GenServer.call(__MODULE__, :timer_active?)
end
@doc "Starts a new timer if one isn't started."
def start_timer(msg) do
GenServer.call(__MODULE__, {:start_timer, msg})
end
@doc "Cancels a timer if it exists."
def cancel_timer do
GenServer.call(__MODULE__, :cancel_timer)
end
@doc false
def start_link do
GenServer.start_link(__MODULE__, [], [name: __MODULE__])
end
@doc false
def init([]) do
{:ok, %{timer: nil, already_sent: false}}
end
def handle_call(:timer_active?, _, state) do
{:reply, is_timer_active?(state.timer), state}
end
def handle_call({:start_timer, _msg}, _from, state) do
if !is_timer_active?(state.timer) do
{:reply, :ok, %{state | timer: do_start_timer(self())}}
else
{:reply, :ok, state}
end
end
def handle_call(:cancel_timer, _from, state) do
if is_timer_active?(state.timer) do
Process.cancel_timer(state.timer)
end
{:reply, :ok, %{state | timer: nil, already_sent: false}}
end
def handle_info(:timer, state) do
if state.already_sent do
{:noreply, %{state | timer: nil}}
else
Logger.warn 1, @msg, [channels: [:email]]
{:noreply, %{state | timer: nil, already_sent: true}}
end
end
defp is_timer_active?(timer) do
if timer, do: is_number(Process.read_timer(timer)), else: false
end
defp do_start_timer(pid) do
Process.send_after(pid, :timer, @timer_ms)
end
end

View file

@ -506,6 +506,10 @@ defmodule Farmbot.Firmware do
defp do_reply(state, reply) do
maybe_cancel_timer(state.timer)
case state.current do
%Current{fun: :emergency_unlock, from: from} ->
# i really don't want this to be here..
Farmbot.CeleryScript.EstopTimer.cancel_timer()
:ok = GenServer.reply from, reply
%Current{fun: :emergency_lock, from: from} ->
:ok = GenServer.reply from, {:error, :emergency_lock}
%Current{fun: _fun, from: from} ->

View file

@ -101,7 +101,8 @@ defmodule Farmbot.Logger do
for b <- backends do
Elixir.Logger.add_backend(b, [])
end
{:producer, %{}, dispatcher: GenStage.BroadcastDispatcher}
espeak = System.find_executable("espeak")
{:producer, %{espeak: espeak}, dispatcher: GenStage.BroadcastDispatcher}
end
def handle_demand(_, state) do
@ -119,6 +120,7 @@ defmodule Farmbot.Logger do
nil -> "no_function"
end
meta_map = Map.new(meta)
maybe_espeak(message, Map.get(meta_map, :channels, []), state.espeak)
log = struct(Farmbot.Log, [
time: time,
level: level,
@ -142,4 +144,12 @@ defmodule Farmbot.Logger do
Elixir.Logger.remove_backend(b, [])
end
end
defp maybe_espeak(_message, _channels, nil), do: :ok
defp maybe_espeak(message, channels, exe) do
if :espeak in channels do
spawn System, :cmd, [exe, [message]]
end
:ok
end
end

View file

@ -0,0 +1,21 @@
defmodule Farmbot.System.Init.KernelMods do
use Supervisor
use Farmbot.Logger
@mods Application.get_env(:farmbot, :kernel_modules, [])
def start_link(_, opts \\ []) do
Supervisor.start_link(__MODULE__, [], opts)
end
def init([]) do
do_checkup()
:ignore
end
defp do_checkup do
for mod <- @mods do
Logger.info 1, "Loading kernel module: #{mod}"
System.cmd "modprobe", [mod], into: IO.stream(:stdio, :line)
end
end
end

View file

@ -12,6 +12,7 @@ defmodule Farmbot.System.Supervisor do
def init([]) do
before_init_children = [
worker(Farmbot.System.Init.KernelMods, [[], []]),
worker(Farmbot.System.Init.FSCheckup, [[], []]),
supervisor(Farmbot.System.Init.Ecto, [[], []]),
supervisor(Farmbot.System.ConfigStorage, []),

View file

@ -0,0 +1,9 @@
defmodule Farmbot.System.ConfigStorage.Migrations.EmailOnEstop do
use Ecto.Migration
import Farmbot.System.ConfigStorage.MigrationHelpers
def change do
create_settings_config("email_on_estop", :bool, true)
end
end