code consistency is now part of tests

pull/241/head
connor rigby 2017-02-01 08:20:55 -08:00
parent 6b72cc11d1
commit c77252ed90
27 changed files with 219 additions and 163 deletions

View File

@ -12,3 +12,5 @@ erl_crash.dump
npm-debug.log
ttb_last_config
cover
doc

View File

@ -26,7 +26,7 @@ defmodule Farmbot.BotState.Monitor do
@doc """
Starts the state producer.
"""
def start_link(), do: GenStage.start_link(__MODULE__, [], name: __MODULE__)
def start_link, do: GenStage.start_link(__MODULE__, [], name: __MODULE__)
def init([]), do: {:producer, %State{}}
def handle_demand(_demand, state), do: dispatch state

View File

@ -6,9 +6,14 @@ defmodule Farmbot.BotState.ProcessSupervisor do
use Supervisor
require Logger
def start_link(), do: Supervisor.start_link(__MODULE__, [], name: __MODULE__)
@doc """
Starts the Farm Procss Supervisor
"""
@spec start_link :: {:ok, pid}
def start_link, do: Supervisor.start_link(__MODULE__, [], name: __MODULE__)
def init(_) do
@spec init([]) :: {:ok, pid}
def init([]) do
Logger.debug ">> Starting FarmProcess Supervisor"
children = [
worker(Farmbot.BotState.ProcessTracker, [], [restart: :permanent])

View File

@ -13,8 +13,12 @@ defmodule Farmbot.BotState.ProcessTracker do
defmodule Info do
@moduledoc false
defstruct [:name, :uuid, :status, :stuff]
@typedoc """
Status of this process
"""
@type status :: atom
@type t :: %__MODULE__{name: String.t, uuid: binary, status: status, stuff: map}
@type t ::
%__MODULE__{name: String.t, uuid: binary, status: status, stuff: map}
end
defmodule State do
@ -23,19 +27,22 @@ defmodule Farmbot.BotState.ProcessTracker do
@type uuid :: binary
@type kind :: :event | :farmware | :regimen
@type t ::
%__MODULE__{events: [Info.t],
%__MODULE__{
events: [Info.t],
regimens: [Info.t],
farmwares: [Info.t]}
end
def init(_) do
@spec init([]) :: {:ok, State.t}
def init([]) do
{:ok, %State{}}
end
@doc """
Starts the Process Tracker
"""
def start_link(), do: GenServer.start_link(__MODULE__, [], name: __MODULE__)
@spec start_link :: {:ok, pid}
def start_link, do: GenServer.start_link(__MODULE__, [], name: __MODULE__)
@doc """
Registers a kind, name with a database entry to be tracked
@ -55,13 +62,15 @@ defmodule Farmbot.BotState.ProcessTracker do
starts a process by its uuid.
"""
@spec start_process(State.uuid) :: {:ok, pid} | {:error, term}
def start_process(uuid), do: GenServer.call(__MODULE__, {:start_process, uuid})
def start_process(uuid),
do: GenServer.call(__MODULE__, {:start_process, uuid})
@doc """
Stops a process by it's uuid.
"""
@spec stop_process(State.uuid) :: :ok | {:error, term}
def stop_process(uuid), do: GenServer.call(__MODULE__, {:stop_process, uuid})
def stop_process(uuid),
do: GenServer.call(__MODULE__, {:stop_process, uuid})
@doc """
Lookup a uuid by its kind and name
@ -74,8 +83,8 @@ defmodule Farmbot.BotState.ProcessTracker do
@doc """
Gets the state of the tracker.
"""
@spec get_state() :: State.t
def get_state(), do: GenServer.call(__MODULE__, :state)
@spec get_state :: State.t
def get_state, do: GenServer.call(__MODULE__, :state)
# GenServer stuffs
@ -122,7 +131,12 @@ defmodule Farmbot.BotState.ProcessTracker do
Logger.debug ">> is registering a #{kind} as #{name}"
uuid = UUID.generate
key = kind_to_key(kind)
new_list = [%Info{name: name, uuid: uuid, status: :not_running, stuff: stuff} | Map.get(state, key)]
new_list = [
%Info{name: name,
uuid: uuid,
status: :not_running,
stuff: stuff} | Map.get(state, key)]
new_state = %{state | key => new_list}
dispatch(new_state)
end
@ -146,6 +160,7 @@ defmodule Farmbot.BotState.ProcessTracker do
def terminate(_reason, _state), do: :ok #TODO(connor) save the state here?
@spec nest_the_loops(State.uuid, State.t) :: {State.kind, Info.t} | nil
@lint {Credo.Check.Refactor.Nesting, false}
defp nest_the_loops(uuid, state) do
# I have to enumerate over all the processes "kind"s here...
# this is the most javascript elixir i have ever wrote.

View File

@ -201,7 +201,6 @@ defmodule Farmbot.BotState.Configuration do
dispatch false, state
end
# Allow the frontend to do stuff again.
def handle_call({:remove_lock, string}, _from, %State{} = state) do
# Get the index of the lock

View File

@ -9,7 +9,10 @@ defmodule Farmbot.StateTracker do
quote do
alias Farmbot.System.FS.ConfigStorage, as: FBConfigStorage
defmodule State, do: defstruct unquote(model)
defmodule State do
@moduledoc false
defstruct unquote(model)
end
defp get_config(:all) do
GenServer.call(FBConfigStorage, {:get, unquote(name), :all})
@ -26,12 +29,12 @@ defmodule Farmbot.StateTracker do
@doc """
Starts a #{unquote(name)} state tracker.
"""
def start_link(), do: start_link([])
def start_link, do: start_link([])
def start_link(args),
do: GenServer.start_link(unquote(name), args, name: unquote(name))
def init(args) do
n = Module.split(unquote(name)) |> List.last
n = unquote(name) |> Module.split |> List.last
Logger.debug ">> is starting #{n}."
case load(args) do
{:ok, %State{} = state} ->

View File

@ -24,7 +24,10 @@ defmodule Farmbot.CeleryScript.Ast do
def parse(%{"kind" => kind, "args" => args} = thing) do
body = thing["body"] || []
comment = thing["comment"]
%__MODULE__{kind: kind, args: parse_args(args), body: parse(body), comment: comment}
%__MODULE__{kind: kind,
args: parse_args(args),
body: parse(body),
comment: comment}
end
def parse(%{__struct__: _} = thing) do
@ -34,10 +37,12 @@ defmodule Farmbot.CeleryScript.Ast do
def parse(%{kind: kind, args: args} = thing) do
body = thing[:body] || []
comment = thing[:comment]
%__MODULE__{kind: kind, body: parse(body), args: parse_args(args), comment: comment}
%__MODULE__{kind: kind,
body: parse(body),
args: parse_args(args),
comment: comment}
end
# You can give a list of nodes.
@spec parse([map,...]) :: [t,...]
def parse(body) when is_list(body) do
@ -46,7 +51,6 @@ defmodule Farmbot.CeleryScript.Ast do
end)
end
def parse(_), do: %__MODULE__{kind: "nothing", args: %{}, body: []}
# TODO: This is a pretty heavy memory leak, what should happen is

View File

@ -1,5 +1,5 @@
defmodule Farmbot.CeleryScript.Command do
@moduledoc """
@moduledoc ~s"""
Actionable CeleryScript Commands.
There should be very little side affects here. just serial commands and
ways to execute those serial commands.
@ -37,7 +37,7 @@ defmodule Farmbot.CeleryScript.Command do
# ALSO THE COMPILER CAN'T PROPERLY CHECK SOMETHING BEING THAT THE ARGS ARE
# NOT POSITIONAL.
@doc """
@doc ~s"""
move_absolute to a prticular position.
args: %{
speed: integer,
@ -52,6 +52,7 @@ defmodule Farmbot.CeleryScript.Command do
location: coordinate_ast | Ast.t
}
@spec move_absolute(move_absolute_args, []) :: no_return
@lint {Credo.Check.Refactor.ABCSize, false}
def move_absolute(%{speed: s, offset: offset, location: location}, []) do
with %Ast{kind: "coordinate", args: %{x: xa, y: ya, z: za}, body: []} <-
ast_to_coord(location),
@ -74,7 +75,7 @@ defmodule Farmbot.CeleryScript.Command do
|> Farmbot.BotState.get_config()
end
@doc """
@doc ~s"""
move_relative to a location
args: %{speed: number, x: number, y: number, z: number}
body: []
@ -91,7 +92,7 @@ defmodule Farmbot.CeleryScript.Command do
move_absolute(%{speed: speed, offset: offset, location: location}, [])
end
@doc """
@doc ~s"""
Convert an ast node to a coodinate or return :error.
"""
@spec ast_to_coord(Ast.t) :: coordinate_ast | :error
@ -105,6 +106,7 @@ defmodule Farmbot.CeleryScript.Command do
# fortool_id == tool_id, which returned
# all of them, because every toolslots tool_id
# always equals that toolslots tool id lol
@lint {Credo.Check.Refactor.PipeChainStart, false}
def ast_to_coord(%Ast{kind: "tool", args: %{tool_id: tool_id_}, body: []}) do
blah = Amnesia.transaction do
ToolSlot.where(tool_id == tool_id_) |> Amnesia.Selection.values
@ -128,7 +130,7 @@ defmodule Farmbot.CeleryScript.Command do
:error
end
@doc """
@doc ~s"""
coodinate
args: %{x: integer, y: integer, z: integer}
body: []
@ -140,7 +142,7 @@ defmodule Farmbot.CeleryScript.Command do
%Ast{kind: "coordinate", args: args, body: []}
end
@doc """
@doc ~s"""
read_status
args: %{},
body: []
@ -148,7 +150,7 @@ defmodule Farmbot.CeleryScript.Command do
@spec read_status(%{}, []) :: no_return
def read_status(%{}, []), do: Farmbot.BotState.Monitor.get_state
@doc """
@doc ~s"""
sync
args: %{},
body: []
@ -163,7 +165,7 @@ defmodule Farmbot.CeleryScript.Command do
Logger.error ">> encountered an error syncing!: #{inspect reason}"
end
end
@doc """
@doc ~s"""
Handles an RPC Request.
args: %{label: String.t},
body: [Ast.t,...]
@ -191,15 +193,15 @@ defmodule Farmbot.CeleryScript.Command do
@spec handle_req({Ast.t, [explanation_type]}, String.t) :: no_return
defp handle_req({_, []}, id) do
# there were no failed asts.
rpc_ok(%{label: id}, []) |> Farmbot.Transport.emit
%{label: id} |> rpc_ok([]) |> Farmbot.Transport.emit
end
defp handle_req({_, failed}, id) do
# there were some failed asts.
rpc_error(%{label: id}, failed) |> Farmbot.Transport.emit
%{label: id} |> rpc_error(failed) |> Farmbot.Transport.emit
end
@doc """
@doc ~s"""
Return for a valid Rpc Request
args: %{label: String.t},
body: []
@ -209,7 +211,7 @@ defmodule Farmbot.CeleryScript.Command do
%Ast{kind: "rpc_ok", args: %{label: id}, body: []}
end
@doc """
@doc ~s"""
bad return for a valid Rpc Request
args: %{label: String.t},
body: [Explanation]
@ -219,7 +221,7 @@ defmodule Farmbot.CeleryScript.Command do
%Ast{kind: "rpc_error", args: %{label: id}, body: explanations}
end
@doc """
@doc ~s"""
Explanation for an rpc error
args: %{label: String.t},
body: []
@ -231,7 +233,7 @@ defmodule Farmbot.CeleryScript.Command do
%Ast{kind: "explanation", args: %{message: message}, body: []}
end
@doc """
@doc ~s"""
reboots your bot
args: %{},
body: []
@ -241,7 +243,7 @@ defmodule Farmbot.CeleryScript.Command do
FBSys.reboot
end
@doc """
@doc ~s"""
Powers off your bot
args: %{},
body: []
@ -251,8 +253,9 @@ defmodule Farmbot.CeleryScript.Command do
FBSys.power_off
end
@type pair :: %Ast{kind: String.t, args: %{label: String.t, value: any}, body: []}
@doc """
@type pair
:: %Ast{kind: String.t, args: %{label: String.t, value: any}, body: []}
@doc ~s"""
Updates configuration on a package
args: %{package: String.t},
body: [Ast.t]
@ -290,12 +293,13 @@ defmodule Farmbot.CeleryScript.Command do
end)
end
@doc """
@doc ~s"""
calibrates an axis:
args: %{axis: "x" | "y" | "z"}
body: []
"""
@spec calibrate(%{axis: String.t}, []) :: no_return
@lint {Credo.Check.Refactor.PipeChainStart, false}
def calibrate(%{axis: axis}, []) do
case axis do
"x" -> "F14"
@ -304,7 +308,7 @@ defmodule Farmbot.CeleryScript.Command do
end |> GHan.block_send
end
@doc """
@doc ~s"""
Reads all mcu_params
args: %{},
body: []
@ -312,7 +316,7 @@ defmodule Farmbot.CeleryScript.Command do
@spec read_all_params(%{}, []) :: no_return
def read_all_params(%{}, []), do: GHan.block_send("F20")
@doc """
@doc ~s"""
Homes an axis
args: %{axis: "x" | "y" | "z" | "all"},
body: []
@ -339,7 +343,7 @@ defmodule Farmbot.CeleryScript.Command do
move_absolute(%{speed: speed, location: location, offset: blah }, [])
end
@doc """
@doc ~s"""
executes a thing
args: %{sequence_id_id: integer}
body: []
@ -347,12 +351,13 @@ defmodule Farmbot.CeleryScript.Command do
@spec execute(%{sequence_id: integer}, []) :: no_return
def execute(%{sequence_id: id}, []) do
{:ok, _} = Farmbot.Sync.sync()
Farmbot.Sync.get_sequence(id)
id
|> Farmbot.Sync.get_sequence
|> Ast.parse
|> do_command
end
@doc """
@doc ~s"""
does absolutely nothing.
args: %{},
body: []
@ -361,7 +366,7 @@ defmodule Farmbot.CeleryScript.Command do
@spec nothing(%{}, []) :: nothing_ast
def nothing(args, body), do: %Ast{kind: "nothing", args: args, body: body}
@doc """
@doc ~s"""
Executes a sequence. Be carefully.
args: %{},
body: [Ast.t]
@ -375,7 +380,7 @@ defmodule Farmbot.CeleryScript.Command do
end
end
@doc """
@doc ~s"""
Conditionally does something
args: %{_else: Ast.t
_then: Ast.t,
@ -435,7 +440,7 @@ defmodule Farmbot.CeleryScript.Command do
defp eval_if(_, _, _, _, _), do: Logger.debug "bad if operator"
@doc """
@doc ~s"""
Logs a message to some places
args: %{},
body: []
@ -468,7 +473,7 @@ defmodule Farmbot.CeleryScript.Command do
ch
end
@doc """
@doc ~s"""
writes an arduino pin
args: %{
pin_number: integer,
@ -477,7 +482,7 @@ defmodule Farmbot.CeleryScript.Command do
},
body: []
"""
@typedoc """
@typedoc ~s"""
0 is digital
1 is pwm
"""
@ -498,7 +503,7 @@ defmodule Farmbot.CeleryScript.Command do
Farmbot.BotState.set_pin_value(pin, val)
end
@doc """
@doc ~s"""
Reads an arduino pin
args: %{
label: String.t
@ -515,7 +520,7 @@ defmodule Farmbot.CeleryScript.Command do
"F42 P#{pin} M#{mode}" |> GHan.block_send
end
@doc """
@doc ~s"""
toggles a digital pin
args: %{pin_number: String.t},
body: []
@ -539,7 +544,7 @@ defmodule Farmbot.CeleryScript.Command do
end
end
@doc """
@doc ~s"""
sleeps for a number of milliseconds
args: %{milliseconds: integer},
body: []
@ -547,7 +552,7 @@ defmodule Farmbot.CeleryScript.Command do
@spec wait(%{milliseconds: integer}, []) :: no_return
def wait(%{milliseconds: millis}, []), do: Process.sleep(millis)
@doc """
@doc ~s"""
Checks updates for given package
args: %{package: "arduino_firmware" | "farmbot_os"},
body: []
@ -567,7 +572,7 @@ defmodule Farmbot.CeleryScript.Command do
end
end
@doc """
@doc ~s"""
Reads a param value
args: %{label: String.t}
body: []
@ -582,7 +587,7 @@ defmodule Farmbot.CeleryScript.Command do
end
end
@doc """
@doc ~s"""
Sends a warning message. Used for denoting hax and what not
args: %{message: String.t}
body: []
@ -592,7 +597,7 @@ defmodule Farmbot.CeleryScript.Command do
send_message(%{message: str <> @shrug, message_type: :warn}, [])
end
@doc """
@doc ~s"""
Locks the bot from movement until unlocked
args: %{},
body: []
@ -606,7 +611,7 @@ defmodule Farmbot.CeleryScript.Command do
shrug(%{message: ">> is lost. Probably a good idea to reboot."}, [])
end
@doc """
@doc ~s"""
unlocks the bot allowing movement again.
args: %{},
body: []
@ -616,7 +621,7 @@ defmodule Farmbot.CeleryScript.Command do
Logger.warn ">> needs to be rebooted"
end
@doc """
@doc ~s"""
Factory resets bot.
"""
@spec factory_reset(%{}, []) :: no_return
@ -628,7 +633,7 @@ defmodule Farmbot.CeleryScript.Command do
end
end
@doc """
@doc ~s"""
Executes a farmware
args: %{label: String.t},
body: [pair]
@ -637,7 +642,6 @@ defmodule Farmbot.CeleryScript.Command do
def execute_script(%{label: "image-capture"}, _env_vars) do
Logger.debug ">> Is doing hax!!@@"
Farmbot.Camera.capture()
Farmbot.Camera.blah()
end
def execute_script(%{label: farmware}, env_vars) do
@ -645,19 +649,20 @@ defmodule Farmbot.CeleryScript.Command do
Farmware.execute(farmware, real_args)
end
@doc """
@doc ~s"""
Sets a bunch of user environment variables for farmware
args: %{},
body: [pair]
"""
@spec set_user_env(%{}, [pair]) :: no_return
@lint {Credo.Check.Refactor.PipeChainStart, false}
def set_user_env(%{}, env_pairs) do
pairs_to_tuples(env_pairs)
|> Map.new
|> Farmbot.BotState.set_user_env
end
@doc """
@doc ~s"""
Executes an ast node.
"""
@spec do_command(Ast.t) :: :no_instruction | any

View File

@ -61,19 +61,18 @@ defmodule Farmbot.Sync do
end
# downloads all the information from the api
@spec down() :: {:ok, SyncObject.t} | {:error, term}
defp down() do
with {:ok, resp} <- fetch_sync_object(), # {:error, reason} | %HTTPoison.Response{}
{:ok, json} <- parse_http(resp),
{:ok, parsed} <- Poison.decode(json),
{:ok, validated} <- SyncObject.validate(parsed),
@spec down :: {:ok, SyncObject.t} | {:error, term}
defp down do
with {:ok, resp} <- fetch_sync_object(),
{:ok, json} <- parse_http(resp),
{:ok, parsed} <- Poison.decode(json),
{:ok, validated} <- SyncObject.validate(parsed),
do: enter_into_db(validated)
end
# uploads all the information to the api
@spec up() :: :ok | {:error, term}
#TODO(Connor) upload images to the api
defp up(), do: :ok
@spec up :: :ok | {:error, term}
defp up, do: :ok
def enter_into_db(%SyncObject{} = so) do
clear_all(so)
@ -157,8 +156,8 @@ defmodule Farmbot.Sync do
@doc """
Tries to do an HTTP request on server/api/sync
"""
@spec fetch_sync_object() :: {:error, atom} | {:ok, HTTPoison.Response.t}
def fetch_sync_object() do
@spec fetch_sync_object :: {:error, atom} | {:ok, HTTPoison.Response.t}
def fetch_sync_object do
case Farmbot.HTTP.get("/api/sync") do
{:ok, %HTTPoison.Response{} = f} -> {:ok, f}
{:error, %HTTPoison.Error{reason: reason}} -> {:error, reason}

View File

@ -1,7 +1,7 @@
defmodule Syncable do
use Amnesia
@moduledoc """
Creates a syncable object from Farmbot's rest api.
@moduledoc ~s"""
Creates a syncable object from Farmbots rest api.
Example:
iex> defmodule BubbleGum do
...> use Syncable, name: __MODULE__, model: [:flavors, :brands]
@ -90,7 +90,7 @@ defmodule Syncable do
end
end
@doc """
@doc ~s"""
Transforms the state before it is entered into the struct.
Basically you call transform(key) do something end where something will be
the new value for key.

View File

@ -75,7 +75,7 @@ defmodule Farmbot.EasterEggs do
@spec say_random_sentence(pid) :: :ok
def say_random_sentence(pid \\ __MODULE__), do: GenServer.cast(pid, verb())
@doc """
@doc ~s"""
Loads new json into the state.
Example:
iex> json = %{"nouns" => [%{"im_a_var" => "im a string"}],
@ -116,6 +116,7 @@ defmodule Farmbot.EasterEggs do
defp do_delete_job(_), do: :no_job
# GEN SERVER CALLBACKS
@lint false
def handle_cast(sentence, %{nouns: nouns, verbs: verbs})
when is_binary(sentence) do
rendered = Mustache.render sentence, nouns
@ -123,19 +124,25 @@ defmodule Farmbot.EasterEggs do
{:noreply, %{nouns: nouns, verbs: verbs}}
end
@lint false
def handle_cast(%{"nouns" => _, "verbs" => _} = json, _state) do
{:ok, state} = parse_easter_eggs_json(json)
{:noreply, state}
end
@lint false
def handle_cast(_event, state), do: {:noreply, state}
@lint false
def handle_call(:state, _from, state), do: {:reply, state, state}
@lint false
def handle_call(:verb, _from, %{nouns: n, verbs: v}) do
rv = v |> Enum.random
{:reply, rv, %{nouns: n, verbs: v}}
end
def handle_call(_event, _from, state), do: {:reply, :unhandled, state}
@lint false
def handle_info(_event, state), do: {:noreply, state}
end

View File

@ -7,8 +7,13 @@ defmodule Downloader do
require Logger
# TODO MOVE ME
@doc """
Downloads a file to a path. Returns the path
"""
@spec run(binary, binary) :: binary
def run(url, path) do
{:ok, %HTTPoison.Response{body: thing}} = HTTPoison.get(url, [], [follow_redirect: true])
{:ok, %HTTPoison.Response{body: thing}} =
HTTPoison.get(url, [], [follow_redirect: true])
File.write!(path, thing)
path
end

View File

@ -6,20 +6,26 @@ defmodule Farmbot do
use Supervisor
alias Farmbot.Sync.Database
def init(%{target: target, compat_version: compat_version, version: version, commit: commit})
@spec init(map) :: [{:ok, pid}]
def init(%{target: target,
compat_version: compat_version,
version: version,
commit: commit})
do
children = [
# Handles tracking of various parts of the bots state.
supervisor(Farmbot.BotState.Supervisor,
[%{target: target, compat_version: compat_version, version: version, commit: commit}],
restart: :permanent),
[%{target: target,
compat_version: compat_version,
version: version,
commit: commit}], restart: :permanent),
# Handles the passing of messages from one part of the system to another.
supervisor(Farmbot.Transport.Supervisor, [], restart: :permanent),
# Handles external scripts and what not
supervisor(Farmware.Supervisor, [], restart: :permanent),
# handles communications between bot and arduino
supervisor(Farmbot.Serial.Supervisor, [], restart: :permanent),
]
@ -27,6 +33,10 @@ defmodule Farmbot do
supervise(children, opts)
end
@doc """
Starts the Farmbot Application
"""
@spec start(atom, [any]) :: {:ok, pid}
def start(_, [args]) do
Logger.debug ">> init!"
Amnesia.start

View File

@ -13,7 +13,15 @@ defmodule Farmware.FarmScript do
* how to handle failures?
"""
@type t :: %__MODULE__{executable: binary, args: [binary], path: binary, name: binary, envs: [{binary, binary}]}
@typedoc """
The things required to describe a FarmScript
"""
@type t ::
%__MODULE__{executable: binary,
args: [binary],
path: binary,
name: binary,
envs: [{binary, binary}]}
@enforce_keys [:executable, :args, :path, :name, :envs]
defstruct [:executable, :args, :path, :name, :envs]

View File

@ -49,6 +49,7 @@ defmodule Farmware do
Installs a package from a manifest url
"""
@spec install(binary) :: map | no_return
@lint {Credo.Check.Refactor.ABCSize, false}
def install(manifest_url) do
Logger.debug "Getting Farmware Manifest"
{manifest, json} = Manifest.get!(manifest_url).body

View File

@ -3,7 +3,11 @@ defmodule Farmware.Supervisor do
require Logger
alias Farmbot.System.FS
def start_link() do
@doc """
Starts the Farmware Supervisor
"""
@spec start_link :: {:ok, pid}
def start_link do
import Supervisor.Spec, warn: false
# create the farmware folder if it doesnt exist.
check_dir()
@ -12,15 +16,14 @@ defmodule Farmware.Supervisor do
Supervisor.start_link(children, opts)
end
defp check_dir() do
@spec check_dir :: no_return
defp check_dir do
path = FS.path() <> "/farmware"
if !File.exists?(path) do
unless File.exists?(path) do
Logger.debug ">> creating farmware dir."
FS.transaction fn() ->
File.mkdir(path)
end
else
Logger.debug ">> farmware dir already exists."
end
end
end

View File

@ -45,6 +45,7 @@ defmodule Farmware.Worker do
{:noreply, [], environment}
end
@lint false
def handle_call(:get_state, _from, state) do
{:reply, state, [], state}
end

View File

@ -7,6 +7,7 @@ defmodule Farmbot.ImageWatcher do
@checkup_frequency 10_000
@images_path "/tmp/images"
@type state :: []
@doc """
Starts the Image Watcher
@ -20,6 +21,7 @@ defmodule Farmbot.ImageWatcher do
{:ok, []}
end
@spec handle_info(any, state) :: {:noreply, state}
def handle_info(:checkup, []) do
do_checkup()
{:noreply, []}
@ -47,6 +49,7 @@ defmodule Farmbot.ImageWatcher do
Logger.debug "Image Watcher trying to upload #{file_path}"
Farmbot.HTTP.upload_file(file_path)
end
@spec print_thing(boolean, integer) :: :ok
defp print_thing(_, count) when count == 0, do: :ok
defp print_thing(true, _count) do

View File

@ -49,13 +49,20 @@ defmodule Farmbot.Transport do
defp translate(%MonState{} = monstate) do
%Serialized{
mcu_params: monstate.hardware.mcu_params,
location: monstate.hardware.location,
pins: monstate.hardware.pins,
configuration: Map.delete(monstate.configuration.configuration, :user_env),
informational_settings: monstate.configuration.informational_settings,
process_info: monstate.process_info,
user_env: monstate.configuration.configuration.user_env
mcu_params:
monstate.hardware.mcu_params,
location:
monstate.hardware.location,
pins:
monstate.hardware.pins,
configuration:
Map.delete(monstate.configuration.configuration, :user_env),
informational_settings:
monstate.configuration.informational_settings,
process_info:
monstate.process_info,
user_env:
monstate.configuration.configuration.user_env
}
end

View File

@ -33,13 +33,12 @@ defmodule Farmbot.Mixfile do
images_path: "../../images/#{target(Mix.env)}",
config_path: "../../config/config.exs",
lockfile: "../../mix.lock",
aliases: aliases(Mix.env),
deps: deps() ++ system(target(Mix.env)),
aliases: aliases(Mix.env),
deps: deps() ++ system(target(Mix.env)),
name: "Farmbot",
source_url: "https://github.com/Farmbot/farmbot_os",
homepage_url: "http://farmbot.io",
docs: [main: "farmbot", # The main page in the docs
extras: ["README.md"]]
docs: [main: "farmbot", extras: ["../../README.md", "../../BUILDING.md"]]
]
end
@ -118,7 +117,8 @@ defmodule Farmbot.Mixfile do
# if not in prod mode nothing special.
def aliases(_), do: [
"firmware": ["farmbot.warning"],
"credo": ["credo list --only readability,warning,todo,inspect,refactor --ignore-checks todo"]
"credo": ["credo list --only readability,warning,todo,inspect,refactor --ignore-checks todo,spec"],
"test": ["credo", "test"]
]
# the nerves_system_* dir to use for this build.

View File

@ -90,10 +90,10 @@ defmodule Farmbot.BotStateTest do
test "sets a lock and fails to set the same lock again" do
str = "Bot doesnt work on christmas."
Farmbot.BotState.add_lock(str)
old_locks = get_locks
old_locks = get_locks()
Farmbot.BotState.add_lock(str)
new_locks = get_locks
new_locks = get_locks()
assert(new_locks == old_locks)
end

View File

@ -2,28 +2,28 @@ defmodule Farmbot.BotState.ConfigurationTest do
use ExUnit.Case, async: false
test "makes sure we dont mess state up with bad calls or casts" do
before_call = get_state
before_call = get_state()
resp = GenServer.call(Farmbot.BotState.Configuration, :do_a_barrel_roll)
after_call = get_state
after_call = get_state()
assert(resp == :unhandled)
assert(after_call == before_call)
GenServer.cast(Farmbot.BotState.Configuration, :bot_net_start)
after_cast = get_state
after_cast = get_state()
assert(before_call == after_cast)
end
test "updates a setting inside informational settings" do
old = get_state
old = get_state()
GenServer.cast(Farmbot.BotState.Configuration,
{:update_info, :i_know_this, :its_unix})
# maybe bug? change this cast to a call?
new = get_state
new = get_state()
assert(old != new)
end
defp get_state do
defp get_state() do
Process.sleep(10)
Farmbot.BotState.Monitor.get_state |> Map.get(:configuration)
Farmbot.BotState.Monitor.get_state() |> Map.get(:configuration)
end
end

View File

@ -3,12 +3,12 @@ defmodule Farmbot.Sync.SyncObjectTest do
use ExUnit.Case, async: true
test "validates and creates a SyncObject" do
{:ok, blah } = Farmbot.Sync.SyncObject.validate(json_resp)
{:ok, blah } = Farmbot.Sync.SyncObject.validate(json_resp())
assert blah.__struct__ == Farmbot.Sync.SyncObject
end
test "validates and does not raise an exception" do
blah = Farmbot.Sync.SyncObject.validate!({:ok, json_resp})
blah = Farmbot.Sync.SyncObject.validate!({:ok, json_resp()})
assert blah.__struct__ == Farmbot.Sync.SyncObject
end
@ -42,44 +42,44 @@ defmodule Farmbot.Sync.SyncObjectTest do
end
test "makes sure all keys are validated" do
json1 = json_resp |> break("device")
json1 = json_resp() |> break("device")
{:error, Farmbot.Sync.Database.Device, reason1} = Farmbot.Sync.SyncObject.validate(json1)
assert reason1 == :bad_map
json2 = json_resp |> break("peripherals")
json2 = json_resp() |> break("peripherals")
{:error, Farmbot.Sync.Database.Peripheral, reason2} = Farmbot.Sync.SyncObject.validate(json2)
assert reason2 == [{:error, Farmbot.Sync.Database.Peripheral, :bad_map}]
json3 = json_resp |> break("plants")
json3 = json_resp() |> break("plants")
{:error, Farmbot.Sync.Database.Plant, reason3} = Farmbot.Sync.SyncObject.validate(json3)
assert reason3 == [{:error, Farmbot.Sync.Database.Plant, :bad_map}]
json4 = json_resp |> break("regimen_items")
json4 = json_resp() |> break("regimen_items")
{:error, Farmbot.Sync.Database.RegimenItem, reason4} = Farmbot.Sync.SyncObject.validate(json4)
assert reason4 == [{:error, Farmbot.Sync.Database.RegimenItem, :bad_map}]
json5 = json_resp |> break("regimens")
json5 = json_resp() |> break("regimens")
{:error, Farmbot.Sync.Database.Regimen, reason5} = Farmbot.Sync.SyncObject.validate(json5)
assert reason5 == [{:error, Farmbot.Sync.Database.Regimen, :bad_map}]
json6 = json_resp |> break("sequences")
json6 = json_resp() |> break("sequences")
{:error, Farmbot.Sync.Database.Sequence, reason6} = Farmbot.Sync.SyncObject.validate(json6)
assert reason6 == [{:error, Farmbot.Sync.Database.Sequence, :bad_map}]
json7 = json_resp |> break("tool_bays")
json7 = json_resp() |> break("tool_bays")
{:error, Farmbot.Sync.Database.ToolBay, reason7} = Farmbot.Sync.SyncObject.validate(json7)
assert reason7 == [{:error, Farmbot.Sync.Database.ToolBay, :bad_map}]
json8 = json_resp |> break("tool_slots")
json8 = json_resp() |> break("tool_slots")
{:error, Farmbot.Sync.Database.ToolSlot, reason8} = Farmbot.Sync.SyncObject.validate(json8)
assert reason8 == [{:error, Farmbot.Sync.Database.ToolSlot, :bad_map}]
json9 = json_resp |> break("tools")
json9 = json_resp() |> break("tools")
{:error, Farmbot.Sync.Database.Tool, reason9} = Farmbot.Sync.SyncObject.validate(json9)
assert reason9 == [{:error, Farmbot.Sync.Database.Tool, :bad_map}]
json10 = json_resp |> break("users")
json10 = json_resp() |> break("users")
{:error, Farmbot.Sync.Database.User, reason10} = Farmbot.Sync.SyncObject.validate(json10)
assert reason10 == [{:error, Farmbot.Sync.Database.User, :bad_map}]
@ -89,17 +89,17 @@ defmodule Farmbot.Sync.SyncObjectTest do
Map.put(map, key, ["failure"])
end
def json_resp do
%{"device" => json_device,
"peripherals" => json_peripherals,
def json_resp() do
%{"device" => json_device(),
"peripherals" => json_peripherals(),
"plants" => [],
"regimen_items" => json_regimen_items,
"regimens" => json_regimens,
"sequences" => json_sequences,
"tool_bays" => json_tool_bays,
"tool_slots" => json_tool_slots,
"tools" => json_tools,
"users" => json_users}
"regimen_items" => json_regimen_items(),
"regimens" => json_regimens(),
"sequences" => json_sequences(),
"tool_bays" => json_tool_bays(),
"tool_slots" => json_tool_slots(),
"tools" => json_tools(),
"users" => json_users()}
end
def json_device do
@ -111,7 +111,7 @@ defmodule Farmbot.Sync.SyncObjectTest do
}
end
def json_peripherals, do: [json_peripheral]
def json_peripherals, do: [json_peripheral()]
def json_peripheral do
%{
"id" => 1,
@ -124,7 +124,7 @@ defmodule Farmbot.Sync.SyncObjectTest do
}
end
def json_regimens, do: [json_regimen]
def json_regimens, do: [json_regimen()]
def json_regimen do
%{
"id" => 1,
@ -134,7 +134,7 @@ defmodule Farmbot.Sync.SyncObjectTest do
}
end
def json_regimen_items, do: [json_regimen_item]
def json_regimen_items, do: [json_regimen_item()]
def json_regimen_item do
%{
"id" => 1,
@ -144,7 +144,7 @@ defmodule Farmbot.Sync.SyncObjectTest do
}
end
def json_sequences, do: [json_sequence]
def json_sequences, do: [json_sequence()]
def json_sequence do
%{
"kind" => "sequence",
@ -157,7 +157,7 @@ defmodule Farmbot.Sync.SyncObjectTest do
}
end
def json_tool_bays, do: [json_tool_bay]
def json_tool_bays, do: [json_tool_bay()]
def json_tool_bay do
%{
"id" => 1,
@ -166,7 +166,7 @@ defmodule Farmbot.Sync.SyncObjectTest do
}
end
def json_tool_slots, do: [json_tool_slot]
def json_tool_slots, do: [json_tool_slot()]
def json_tool_slot do
%{
"id" => 1,
@ -179,7 +179,7 @@ defmodule Farmbot.Sync.SyncObjectTest do
}
end
def json_tools, do: [json_tool]
def json_tools, do: [json_tool()]
def json_tool do
%{
"id" => 1,
@ -188,7 +188,7 @@ defmodule Farmbot.Sync.SyncObjectTest do
}
end
def json_users, do: [json_user]
def json_users, do: [json_user()]
def json_user do
%{
"id" => 1,

View File

@ -9,10 +9,9 @@ defmodule SyncableTest do
syncable Person, [:legs, :arms]
end
setup_all do
Amnesia.start
TestDB.create! Keyword.put([], :memory, [node])
TestDB.create! Keyword.put([], :memory, [node()])
end
test "gets keys for a syncable" do

View File

@ -2,7 +2,7 @@ defmodule Farmbot.EasterEggsTest do
@moduledoc false
use ExUnit.Case, async: true
setup_all do
write_me = test_json |> Poison.encode!
write_me = test_json() |> Poison.encode!
File.write!("/tmp/test.json", write_me)
:ok
end
@ -14,7 +14,7 @@ defmodule Farmbot.EasterEggsTest do
end
test "starts the server with a json object" do
json = test_json_with_strings
json = test_json_with_strings()
{:ok, pid} = Farmbot.EasterEggs.start_link({:name, :test_2}, {:json, json})
assert is_pid(pid) == true
end

View File

@ -1,20 +0,0 @@
defmodule F do
use GenServer
require Logger
alias Farmbot.BotState.ProcessTracker, as: P
def start_link(name) do
Atom.to_string(name)
GenServer.start_link(__MODULE__, [name], name: name)
end
def init([name]) do
P.register(:event, name)
{:ok, name}
end
def terminate(_reason, name) do
pid = self()
{uuid, ^pid} = P.lookup(:event, name)
P.deregister(uuid)
end
end

View File

@ -38,7 +38,7 @@
"nerves_ssdp_server": {:hex, :nerves_ssdp_server, "0.2.1", "2d010552023fc1a724e8cb5c92479a58552976e6f805b6dbf09babd31f923b8f", [:mix], []},
"nerves_system_br": {:hex, :nerves_system_br, "0.8.2", "f9917e75b54fb3eadbd67c2123ac1406d0a7fdef24f1960e3577c759d0a6fbc7", [:mix], []},
"nerves_toolchain_arm_unknown_linux_gnueabihf": {:hex, :nerves_toolchain_arm_unknown_linux_gnueabihf, "0.9.0", "5a1bca8c46776ad24c358ab58800ed470f91a3e294ac6eb8ffda0041954781e1", [:mix], [{:nerves, "~> 0.4.0", [hex: :nerves, optional: false]}, {:nerves_toolchain_ctng, "~> 0.8.0", [hex: :nerves_toolchain_ctng, optional: false]}]},
"nerves_toolchain_armv6_rpi_linux_gnueabi": {:hex, :nerves_toolchain_armv6_rpi_linux_gnueabi, "0.8.0", "7e46564ce2b8eca7fed4d50a41a5bb7381d817e6d80d198c22e204758f49ff11", [:mix], [{:nerves, "~> 0.4.0", [hex: :nerves, optional: false]}, {:nerves_toolchain_ctng, "~> 0.8.0", [hex: :nerves_toolchain_ctng, optional: false]}]},
"nerves_toolchain_armv6_rpi_linux_gnueabi": {:hex, :nerves_toolchain_armv6_rpi_linux_gnueabi, "0.9.0", "11618febee06ceb16eae5833e0df331599c135727630e1aedec7b2677a5fa9dc", [:mix], [{:nerves, "~> 0.4.0", [hex: :nerves, optional: false]}, {:nerves_toolchain_ctng, "~> 0.8.0", [hex: :nerves_toolchain_ctng, optional: false]}]},
"nerves_toolchain_ctng": {:hex, :nerves_toolchain_ctng, "0.8.0", "6dff7ed51e1711c5f4da3d559bc528a8265e3dd950dda95f4d6832aed9dbe320", [:mix], []},
"nerves_uart": {:hex, :nerves_uart, "0.1.1", "32e6186b1a1b1d744631126df0b6c4049ddde5b04bc0303de29ab86a2edf60a2", [:make, :mix], [{:elixir_make, "~> 0.3", [hex: :elixir_make, optional: false]}]},
"nerves_wpa_supplicant": {:hex, :nerves_wpa_supplicant, "0.2.2", "da829baec94a8afa7da3a6beaaf1725b9ca7f5f58779ba50b73568b7d37d3d98", [:make, :mix], [{:elixir_make, "~> 0.3", [hex: :elixir_make, optional: false]}]},