2019-03-05 12:35:09 -07:00
|
|
|
defmodule FarmbotOS.SysCalls do
|
|
|
|
require FarmbotCore.Logger
|
2019-04-23 14:34:56 -06:00
|
|
|
require Logger
|
2019-03-05 12:35:09 -07:00
|
|
|
|
|
|
|
alias FarmbotCeleryScript.AST
|
|
|
|
alias FarmbotFirmware
|
|
|
|
|
2019-07-03 16:15:26 -06:00
|
|
|
alias FarmbotCore.Asset.{
|
|
|
|
BoxLed,
|
|
|
|
Peripheral,
|
|
|
|
Sensor
|
|
|
|
}
|
|
|
|
|
2019-04-15 17:04:50 -06:00
|
|
|
alias FarmbotOS.SysCalls.{
|
2019-05-06 10:43:57 -06:00
|
|
|
ChangeOwnership,
|
|
|
|
CheckUpdate,
|
|
|
|
DumpInfo,
|
2019-04-15 17:04:50 -06:00
|
|
|
ExecuteScript,
|
2019-07-05 11:10:52 -06:00
|
|
|
FactoryReset,
|
2019-04-15 17:04:50 -06:00
|
|
|
FlashFirmware,
|
2019-05-06 10:43:57 -06:00
|
|
|
SendMessage
|
2019-04-15 17:04:50 -06:00
|
|
|
}
|
2019-03-05 12:35:09 -07:00
|
|
|
|
2019-06-12 14:23:39 -06:00
|
|
|
alias FarmbotCore.{Asset, Asset.Repo, Asset.Private, Asset.Sync, BotState, Leds}
|
2019-03-05 12:35:09 -07:00
|
|
|
alias FarmbotExt.{API, API.Reconciler, API.SyncGroup}
|
|
|
|
|
|
|
|
@behaviour FarmbotCeleryScript.SysCalls
|
2019-02-20 12:57:45 -07:00
|
|
|
|
2019-06-14 10:21:52 -06:00
|
|
|
@impl true
|
2019-02-20 12:57:45 -07:00
|
|
|
defdelegate send_message(level, message, channels), to: SendMessage
|
2019-06-14 10:21:52 -06:00
|
|
|
|
|
|
|
@impl true
|
2019-03-14 11:29:23 -06:00
|
|
|
defdelegate execute_script(name, env), to: ExecuteScript
|
2019-06-14 10:21:52 -06:00
|
|
|
|
|
|
|
@impl true
|
2019-03-19 14:59:22 -06:00
|
|
|
defdelegate flash_firmware(package), to: FlashFirmware
|
2019-06-14 10:21:52 -06:00
|
|
|
|
|
|
|
@impl true
|
2019-04-18 13:55:49 -06:00
|
|
|
defdelegate change_ownership(email, secret, server), to: ChangeOwnership
|
2019-06-14 10:21:52 -06:00
|
|
|
|
|
|
|
@impl true
|
2019-04-15 17:04:50 -06:00
|
|
|
defdelegate dump_info(), to: DumpInfo
|
2019-06-14 10:21:52 -06:00
|
|
|
|
|
|
|
@impl true
|
2019-05-06 10:43:57 -06:00
|
|
|
defdelegate check_update(), to: CheckUpdate
|
2019-06-14 10:21:52 -06:00
|
|
|
|
|
|
|
@impl true
|
2019-06-05 13:53:59 -06:00
|
|
|
defdelegate read_status(), to: FarmbotExt.AMQP.BotStateChannel
|
2019-04-17 12:19:28 -06:00
|
|
|
|
2019-07-05 11:10:52 -06:00
|
|
|
@impl true
|
|
|
|
defdelegate factory_reset(package), to: FactoryReset
|
|
|
|
|
2019-07-03 14:04:53 -06:00
|
|
|
@impl true
|
|
|
|
def log(message) do
|
|
|
|
if FarmbotCore.Asset.fbos_config(:sequence_body_log) do
|
|
|
|
FarmbotCore.Logger.info(2, message)
|
|
|
|
:ok
|
|
|
|
else
|
|
|
|
:ok
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-07-09 15:42:55 -06:00
|
|
|
@impl true
|
|
|
|
def sequence_init_log(message) do
|
|
|
|
if FarmbotCore.Asset.fbos_config(:sequence_init_log) do
|
|
|
|
FarmbotCore.Logger.info(2, message)
|
|
|
|
:ok
|
|
|
|
else
|
|
|
|
:ok
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
@impl true
|
|
|
|
def sequence_complete_log(message) do
|
|
|
|
if FarmbotCore.Asset.fbos_config(:sequence_complete_log) do
|
|
|
|
FarmbotCore.Logger.info(2, message)
|
|
|
|
:ok
|
|
|
|
else
|
|
|
|
:ok
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-06-14 10:21:52 -06:00
|
|
|
@impl true
|
2019-04-15 17:04:50 -06:00
|
|
|
def reboot do
|
2019-04-29 09:05:41 -06:00
|
|
|
FarmbotOS.System.reboot("Reboot requested by Sequence or frontend")
|
2019-04-15 17:04:50 -06:00
|
|
|
:ok
|
|
|
|
end
|
|
|
|
|
2019-06-14 10:21:52 -06:00
|
|
|
@impl true
|
2019-04-15 17:04:50 -06:00
|
|
|
def power_off do
|
2019-04-29 09:05:41 -06:00
|
|
|
FarmbotOS.System.reboot("Shut down requested by Sequence or frontend")
|
2019-04-15 17:04:50 -06:00
|
|
|
:ok
|
|
|
|
end
|
|
|
|
|
2019-06-14 10:21:52 -06:00
|
|
|
@impl true
|
2019-04-15 17:04:50 -06:00
|
|
|
def firmware_reboot do
|
|
|
|
GenServer.stop(FarmbotFirmware, :reboot)
|
|
|
|
end
|
|
|
|
|
2019-06-14 10:21:52 -06:00
|
|
|
@impl true
|
2019-04-15 17:04:50 -06:00
|
|
|
def resource_update(kind, id, params) do
|
|
|
|
module = Module.concat(Asset, kind)
|
|
|
|
|
|
|
|
with true <- Code.ensure_loaded?(module),
|
|
|
|
%{} = orig <- Repo.get_by(module, [id: id], preload: [:local_meta]),
|
|
|
|
%{valid?: true} = change <- module.changeset(orig, params),
|
|
|
|
{:ok, new} <- Repo.update(change),
|
|
|
|
new <- Repo.preload(new, [:local_meta]) do
|
|
|
|
Private.mark_dirty!(new, %{})
|
|
|
|
:ok
|
|
|
|
else
|
|
|
|
false ->
|
|
|
|
{:error, "unknown asset kind: #{kind}"}
|
|
|
|
|
|
|
|
nil ->
|
|
|
|
{:error, "Could not find asset by kind: #{kind} and id: #{id}"}
|
|
|
|
|
|
|
|
%{valid?: false} = changeset ->
|
|
|
|
{:error, "failed to update #{kind}: #{inspect(changeset.errors)}"}
|
|
|
|
end
|
|
|
|
end
|
2019-02-20 12:57:45 -07:00
|
|
|
|
2019-06-14 10:21:52 -06:00
|
|
|
@impl true
|
2019-02-20 12:57:45 -07:00
|
|
|
def set_user_env(key, value) do
|
2019-03-05 12:35:09 -07:00
|
|
|
FarmbotCore.BotState.set_user_env(key, value)
|
2019-02-20 12:57:45 -07:00
|
|
|
end
|
|
|
|
|
2019-06-14 10:21:52 -06:00
|
|
|
@impl true
|
2019-02-20 12:57:45 -07:00
|
|
|
def get_current_x do
|
|
|
|
get_position(:x)
|
|
|
|
end
|
|
|
|
|
2019-06-14 10:21:52 -06:00
|
|
|
@impl true
|
2019-02-20 12:57:45 -07:00
|
|
|
def get_current_y do
|
|
|
|
get_position(:y)
|
|
|
|
end
|
|
|
|
|
2019-06-14 10:21:52 -06:00
|
|
|
@impl true
|
2019-02-20 12:57:45 -07:00
|
|
|
def get_current_z do
|
|
|
|
get_position(:z)
|
|
|
|
end
|
|
|
|
|
2019-06-14 10:21:52 -06:00
|
|
|
@impl true
|
2019-05-21 14:24:51 -06:00
|
|
|
def zero(axis) do
|
|
|
|
axis = assert_axis!(axis)
|
|
|
|
|
|
|
|
case FarmbotFirmware.command({:position_write_zero, [axis]}) do
|
|
|
|
:ok ->
|
|
|
|
:ok
|
|
|
|
|
|
|
|
{:error, reason} ->
|
|
|
|
{:error, "Firmware error: #{inspect(reason)}"}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-06-14 10:21:52 -06:00
|
|
|
@impl true
|
2019-07-03 18:53:48 -06:00
|
|
|
def read_pin(%Peripheral{pin: _} = data, mode) do
|
|
|
|
do_read_pin(data, mode)
|
2019-06-12 14:23:39 -06:00
|
|
|
end
|
|
|
|
|
2019-07-03 18:53:48 -06:00
|
|
|
def read_pin(%Sensor{pin: pin} = data, mode) do
|
|
|
|
case do_read_pin(data, mode) do
|
2019-06-12 14:23:39 -06:00
|
|
|
{:error, _} = error ->
|
|
|
|
error
|
|
|
|
|
|
|
|
value ->
|
|
|
|
position = get_position()
|
|
|
|
|
|
|
|
params = %{
|
|
|
|
pin: pin,
|
|
|
|
mode: mode,
|
|
|
|
value: value,
|
|
|
|
x: position[:x],
|
|
|
|
y: position[:y],
|
|
|
|
z: position[:z]
|
|
|
|
}
|
|
|
|
|
|
|
|
_ = Asset.new_sensor_reading!(params)
|
|
|
|
value
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-07-03 16:15:26 -06:00
|
|
|
def read_pin(%BoxLed{}, _mode) do
|
2019-06-12 14:23:39 -06:00
|
|
|
# {:error, "cannot read values of BoxLed"}
|
|
|
|
1
|
|
|
|
end
|
|
|
|
|
2019-06-12 15:11:37 -06:00
|
|
|
def read_pin(pin_number, mode) when is_number(pin_number) do
|
|
|
|
sensor = Asset.get_sensor_by_pin(pin_number)
|
|
|
|
peripheral = Asset.get_peripheral_by_pin(pin_number)
|
|
|
|
|
|
|
|
cond do
|
|
|
|
is_map(sensor) ->
|
2019-07-03 16:15:26 -06:00
|
|
|
read_pin(sensor, mode)
|
2019-06-12 15:11:37 -06:00
|
|
|
|
|
|
|
is_map(peripheral) ->
|
2019-07-03 16:15:26 -06:00
|
|
|
read_pin(peripheral, mode)
|
2019-06-12 15:11:37 -06:00
|
|
|
|
|
|
|
true ->
|
|
|
|
do_read_pin(pin_number, mode)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-07-03 18:53:48 -06:00
|
|
|
# digital peripheral
|
|
|
|
|
|
|
|
defp do_read_pin(%Peripheral{pin: pin_number, label: label}, 0) when is_number(pin_number) do
|
|
|
|
case FarmbotFirmware.request({:pin_read, [p: pin_number, m: 0]}) do
|
|
|
|
{:ok, {_, {:report_pin_value, [p: _, v: 1]}}} ->
|
|
|
|
FarmbotCore.Logger.info(2, "The #{label} peripheral value is ON (digital)")
|
|
|
|
1
|
|
|
|
|
|
|
|
{:ok, {_, {:report_pin_value, [p: _, v: 0]}}} ->
|
|
|
|
FarmbotCore.Logger.info(2, "The #{label} peripheral value is OFF (digital)")
|
|
|
|
0
|
|
|
|
|
|
|
|
# Just in case
|
|
|
|
{:ok, {_, {:report_pin_value, [p: _, v: value]}}} ->
|
|
|
|
FarmbotCore.Logger.info(2, "The #{label} peripheral value is #{value} (analog)")
|
|
|
|
value
|
|
|
|
|
|
|
|
{:error, reason} ->
|
|
|
|
{:error, "Firmware error: #{inspect(reason)}"}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# analog peripheral
|
|
|
|
|
|
|
|
defp do_read_pin(%Peripheral{pin: pin_number, label: label}, 1) when is_number(pin_number) do
|
|
|
|
case FarmbotFirmware.request({:pin_read, [p: pin_number, m: 1]}) do
|
|
|
|
{:ok, {_, {:report_pin_value, [p: _, v: value]}}} ->
|
|
|
|
FarmbotCore.Logger.info(2, "The #{label} peripheral value is #{value} (analog)")
|
|
|
|
value
|
|
|
|
|
|
|
|
{:error, reason} ->
|
|
|
|
{:error, "Firmware error: #{inspect(reason)}"}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# digital sensor
|
|
|
|
|
|
|
|
defp do_read_pin(%Sensor{pin: pin_number, label: label}, 0) when is_number(pin_number) do
|
|
|
|
case FarmbotFirmware.request({:pin_read, [p: pin_number, m: 0]}) do
|
|
|
|
{:ok, {_, {:report_pin_value, [p: _, v: 1]}}} ->
|
2019-07-03 20:30:04 -06:00
|
|
|
FarmbotCore.Logger.info(2, "The #{label} sensor value is 1 (digital)")
|
2019-07-03 18:53:48 -06:00
|
|
|
1
|
|
|
|
|
|
|
|
{:ok, {_, {:report_pin_value, [p: _, v: 0]}}} ->
|
2019-07-03 20:30:04 -06:00
|
|
|
FarmbotCore.Logger.info(2, "The #{label} sensor value is 0 (digital)")
|
2019-07-03 18:53:48 -06:00
|
|
|
0
|
|
|
|
|
|
|
|
{:ok, {_, {:report_pin_value, [p: _, v: value]}}} ->
|
|
|
|
FarmbotCore.Logger.info(2, "The #{label} sensor value is #{value} (analog)")
|
|
|
|
|
|
|
|
{:error, reason} ->
|
|
|
|
{:error, "Firmware error: #{inspect(reason)}"}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# analog sensor
|
|
|
|
|
|
|
|
defp do_read_pin(%Sensor{pin: pin_number, label: label}, 1) when is_number(pin_number) do
|
|
|
|
case FarmbotFirmware.request({:pin_read, [p: pin_number, m: 1]}) do
|
|
|
|
{:ok, {_, {:report_pin_value, [p: _, v: value]}}} ->
|
|
|
|
FarmbotCore.Logger.info(2, "The #{label} sensor value is #{value} (analog)")
|
|
|
|
value
|
|
|
|
|
|
|
|
{:error, reason} ->
|
|
|
|
{:error, "Firmware error: #{inspect(reason)}"}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# Generic pin digital
|
|
|
|
defp do_read_pin(pin_number, 0) when is_number(pin_number) do
|
|
|
|
case FarmbotFirmware.request({:pin_read, [p: pin_number, m: 0]}) do
|
|
|
|
{:ok, {_, {:report_pin_value, [p: _, v: 0]}}} ->
|
|
|
|
FarmbotCore.Logger.info(2, "Pin #{pin_number} value is OFF (digital)")
|
|
|
|
0
|
|
|
|
|
|
|
|
{:ok, {_, {:report_pin_value, [p: _, v: 1]}}} ->
|
|
|
|
FarmbotCore.Logger.info(2, "Pin #{pin_number} value is ON (digital)")
|
|
|
|
1
|
|
|
|
|
|
|
|
{:ok, {_, {:report_pin_value, [p: _, v: value]}}} ->
|
|
|
|
FarmbotCore.Logger.info(2, "Pin #{pin_number} is #{value} (analog)")
|
|
|
|
value
|
|
|
|
|
|
|
|
{:error, reason} ->
|
|
|
|
{:error, "Firmware error: #{inspect(reason)}"}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# Generic pin digital
|
|
|
|
defp do_read_pin(pin_number, 1) when is_number(pin_number) do
|
|
|
|
case FarmbotFirmware.request({:pin_read, [p: pin_number, m: 1]}) do
|
|
|
|
{:ok, {_, {:report_pin_value, [p: _, v: value]}}} ->
|
|
|
|
FarmbotCore.Logger.info(2, "Pin #{pin_number} is #{value} (analog)")
|
|
|
|
value
|
2019-03-04 14:32:56 -07:00
|
|
|
|
|
|
|
{:error, reason} ->
|
2019-04-08 15:48:17 -06:00
|
|
|
{:error, "Firmware error: #{inspect(reason)}"}
|
2019-03-04 14:32:56 -07:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-06-14 10:21:52 -06:00
|
|
|
@impl true
|
2019-07-03 18:53:48 -06:00
|
|
|
|
|
|
|
# Peripheral digital
|
|
|
|
def write_pin(%Peripheral{pin: pin, label: label}, 0, 1) do
|
|
|
|
FarmbotCore.Logger.info(2, "Turning the #{label} ON (digital)")
|
|
|
|
do_write_pin(pin, 0, 1)
|
|
|
|
end
|
|
|
|
|
|
|
|
def write_pin(%Peripheral{pin: pin, label: label}, 0, 0) do
|
|
|
|
FarmbotCore.Logger.info(2, "Turning the #{label} OFF (digital)")
|
|
|
|
do_write_pin(pin, 0, 0)
|
|
|
|
end
|
|
|
|
|
|
|
|
# Peripheral analog
|
|
|
|
def write_pin(%Peripheral{pin: pin, label: label}, 1, value) do
|
|
|
|
FarmbotCore.Logger.info(2, "Setting the #{label} to #{value} (analog)")
|
|
|
|
do_write_pin(pin, 0, 0)
|
2019-06-12 14:23:39 -06:00
|
|
|
end
|
|
|
|
|
2019-07-03 16:15:26 -06:00
|
|
|
def write_pin(%Sensor{pin: _pin}, _mode, _value) do
|
2019-06-12 14:23:39 -06:00
|
|
|
{:error, "cannot write Sensor value. Use a Peripheral"}
|
|
|
|
end
|
|
|
|
|
2019-07-03 18:53:48 -06:00
|
|
|
def write_pin(%BoxLed{id: id}, 0, 1) do
|
|
|
|
FarmbotCore.Logger.info(2, "Turning Boxled#{id} ON")
|
|
|
|
Leds.white4(:solid)
|
2019-06-12 14:23:39 -06:00
|
|
|
:ok
|
|
|
|
end
|
|
|
|
|
2019-07-03 18:53:48 -06:00
|
|
|
def write_pin(%BoxLed{id: id}, 0, 0) do
|
|
|
|
FarmbotCore.Logger.info(2, "Turning Boxled#{id} OFF")
|
|
|
|
Leds.white4(:off)
|
2019-06-12 14:23:39 -06:00
|
|
|
:ok
|
|
|
|
end
|
|
|
|
|
2019-07-03 18:53:48 -06:00
|
|
|
def write_pin(%BoxLed{id: id}, _mode, _) do
|
|
|
|
{:error, "cannon write Boxled#{id} in analog mode"}
|
|
|
|
end
|
|
|
|
|
|
|
|
# Generic pin digital
|
|
|
|
def write_pin(pin, 0, 1) do
|
|
|
|
FarmbotCore.Logger.info(2, "Turning pin #{pin} ON (digital)")
|
|
|
|
do_write_pin(pin, 0, 1)
|
|
|
|
end
|
|
|
|
|
|
|
|
def write_pin(pin, 0, 0) do
|
|
|
|
FarmbotCore.Logger.info(2, "Turning pin #{pin} OFF (digital)")
|
|
|
|
do_write_pin(pin, 0, 0)
|
|
|
|
end
|
|
|
|
|
|
|
|
def write_pin(pin, 1, value) do
|
|
|
|
FarmbotCore.Logger.info(2, "Setting pin #{pin} to #{value} (analog)")
|
|
|
|
do_write_pin(pin, 1, value)
|
|
|
|
end
|
|
|
|
|
|
|
|
def do_write_pin(pin_number, mode, value) do
|
2019-03-05 12:35:09 -07:00
|
|
|
case FarmbotFirmware.command({:pin_write, [p: pin_number, v: value, m: mode]}) do
|
2019-04-08 15:48:17 -06:00
|
|
|
:ok ->
|
|
|
|
:ok
|
|
|
|
|
|
|
|
{:error, reason} ->
|
|
|
|
{:error, "Firmware error: #{inspect(reason)}"}
|
2019-03-04 14:32:56 -07:00
|
|
|
end
|
2019-02-20 12:57:45 -07:00
|
|
|
end
|
|
|
|
|
2019-06-14 10:21:52 -06:00
|
|
|
@impl true
|
2019-02-20 12:57:45 -07:00
|
|
|
def point(kind, id) do
|
2019-03-05 12:35:09 -07:00
|
|
|
case Asset.get_point(id: id) do
|
2019-02-20 12:57:45 -07:00
|
|
|
nil -> {:error, "#{kind} not found"}
|
|
|
|
%{x: x, y: y, z: z} -> %{x: x, y: y, z: z}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-06-12 14:23:39 -06:00
|
|
|
def get_position() do
|
2019-03-05 12:35:09 -07:00
|
|
|
case FarmbotFirmware.request({nil, {:position_read, []}}) do
|
2019-03-04 14:32:56 -07:00
|
|
|
{:ok, {_, {:report_position, params}}} ->
|
2019-06-12 14:23:39 -06:00
|
|
|
params
|
2019-02-20 12:57:45 -07:00
|
|
|
|
2019-03-04 14:32:56 -07:00
|
|
|
{:error, reason} ->
|
2019-04-08 15:48:17 -06:00
|
|
|
{:error, "Firmware error: #{inspect(reason)}"}
|
2019-02-20 12:57:45 -07:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-06-12 14:23:39 -06:00
|
|
|
def get_position(axis) do
|
|
|
|
axis = assert_axis!(axis)
|
|
|
|
|
|
|
|
case get_position() do
|
|
|
|
{:error, _} = error -> error
|
|
|
|
position -> Keyword.fetch!(position, axis)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-06-14 10:21:52 -06:00
|
|
|
@impl true
|
2019-02-20 12:57:45 -07:00
|
|
|
def move_absolute(x, y, z, speed) do
|
|
|
|
params = [x: x / 1.0, y: y / 1.0, z: z / 1.0, s: speed / 1.0]
|
2019-04-23 14:34:56 -06:00
|
|
|
# Logger.debug "moving to location: #{inspect(params)}"
|
2019-02-20 12:57:45 -07:00
|
|
|
|
2019-03-05 12:35:09 -07:00
|
|
|
case FarmbotFirmware.command({nil, {:command_movement, params}}) do
|
2019-03-04 14:32:56 -07:00
|
|
|
:ok ->
|
|
|
|
:ok
|
|
|
|
|
|
|
|
{:error, reason} ->
|
2019-04-08 15:48:17 -06:00
|
|
|
{:error, "Firmware error: #{inspect(reason)}"}
|
2019-03-04 14:32:56 -07:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-06-14 10:21:52 -06:00
|
|
|
@impl true
|
2019-03-04 14:32:56 -07:00
|
|
|
def calibrate(axis) do
|
2019-04-09 15:43:41 -06:00
|
|
|
axis = assert_axis!(axis)
|
|
|
|
|
2019-04-17 15:16:49 -06:00
|
|
|
case FarmbotFirmware.command({:command_movement_calibrate, [axis]}) do
|
2019-03-04 14:32:56 -07:00
|
|
|
:ok ->
|
|
|
|
:ok
|
|
|
|
|
|
|
|
{:error, reason} ->
|
2019-04-09 15:43:41 -06:00
|
|
|
{:error, "Firmware error: #{inspect(reason)}"}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-06-14 10:21:52 -06:00
|
|
|
@impl true
|
2019-04-09 15:43:41 -06:00
|
|
|
def find_home(axis) do
|
|
|
|
axis = assert_axis!(axis)
|
|
|
|
|
2019-04-17 15:16:49 -06:00
|
|
|
case FarmbotFirmware.command({:command_movement_find_home, [axis]}) do
|
2019-04-09 15:43:41 -06:00
|
|
|
:ok ->
|
|
|
|
:ok
|
|
|
|
|
|
|
|
{:error, reason} ->
|
|
|
|
{:error, "Firmware error: #{inspect(reason)}"}
|
2019-02-20 12:57:45 -07:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-06-14 10:21:52 -06:00
|
|
|
@impl true
|
2019-04-17 17:04:12 -06:00
|
|
|
def home(axis, _speed) do
|
|
|
|
# TODO(Connor) fix speed
|
|
|
|
axis = assert_axis!(axis)
|
|
|
|
|
|
|
|
case FarmbotFirmware.command({:command_movement_home, [axis]}) do
|
|
|
|
:ok ->
|
|
|
|
:ok
|
|
|
|
|
|
|
|
{:error, reason} ->
|
|
|
|
{:error, "Firmware error: #{inspect(reason)}"}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-06-14 10:21:52 -06:00
|
|
|
@impl true
|
2019-04-17 11:52:44 -06:00
|
|
|
def emergency_lock do
|
|
|
|
_ = FarmbotFirmware.command({:command_emergency_lock, []})
|
|
|
|
:ok
|
|
|
|
end
|
|
|
|
|
2019-06-14 10:21:52 -06:00
|
|
|
@impl true
|
2019-04-17 11:52:44 -06:00
|
|
|
def emergency_unlock do
|
|
|
|
_ = FarmbotFirmware.command({:command_emergency_unlock, []})
|
|
|
|
:ok
|
|
|
|
end
|
|
|
|
|
2019-04-09 15:43:41 -06:00
|
|
|
defp assert_axis!(axis) when is_atom(axis),
|
|
|
|
do: axis
|
|
|
|
|
|
|
|
defp assert_axis!(axis) when axis in ~w(x y z),
|
|
|
|
do: String.to_existing_atom(axis)
|
|
|
|
|
|
|
|
defp assert_axis!(axis) do
|
|
|
|
# {:error, "unknown axis #{axis}"}
|
|
|
|
raise("unknown axis #{axis}")
|
|
|
|
end
|
|
|
|
|
2019-06-14 10:21:52 -06:00
|
|
|
@impl true
|
2019-04-09 15:43:41 -06:00
|
|
|
def wait(ms) do
|
|
|
|
Process.sleep(ms)
|
|
|
|
:ok
|
|
|
|
end
|
|
|
|
|
2019-06-14 10:21:52 -06:00
|
|
|
@impl true
|
2019-04-23 15:03:54 -06:00
|
|
|
def named_pin("Peripheral", id) do
|
|
|
|
case Asset.get_peripheral(id: id) do
|
2019-07-03 16:15:26 -06:00
|
|
|
%{} = peripheral -> peripheral
|
2019-04-23 15:03:54 -06:00
|
|
|
nil -> {:error, "Could not find peripheral by id: #{id}"}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def named_pin("Sensor", id) do
|
2019-06-12 13:07:58 -06:00
|
|
|
case Asset.get_sensor(id) do
|
2019-07-03 16:15:26 -06:00
|
|
|
%{} = sensor -> sensor
|
2019-04-23 15:03:54 -06:00
|
|
|
nil -> {:error, "Could not find peripheral by id: #{id}"}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-06-12 14:23:39 -06:00
|
|
|
def named_pin("BoxLed" <> id, _) do
|
2019-07-03 16:15:26 -06:00
|
|
|
%BoxLed{id: String.to_integer(id)}
|
2019-06-12 14:23:39 -06:00
|
|
|
end
|
|
|
|
|
2019-04-09 15:43:41 -06:00
|
|
|
def named_pin(kind, id) do
|
|
|
|
{:error, "unknown pin kind: #{kind} of id: #{id}"}
|
|
|
|
end
|
|
|
|
|
2019-06-14 10:21:52 -06:00
|
|
|
@impl true
|
2019-02-20 12:57:45 -07:00
|
|
|
def get_sequence(id) do
|
2019-06-07 09:25:48 -06:00
|
|
|
case Asset.get_sequence(id) do
|
2019-07-09 15:42:55 -06:00
|
|
|
nil ->
|
|
|
|
{:error, "sequence not found"}
|
|
|
|
|
|
|
|
%{} = sequence ->
|
|
|
|
%{AST.decode(sequence) | meta: %{sequence_name: sequence.name}}
|
2019-02-20 12:57:45 -07:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-06-14 10:21:52 -06:00
|
|
|
@impl true
|
2019-04-17 17:04:12 -06:00
|
|
|
def get_toolslot_for_tool(id) do
|
|
|
|
with %{id: ^id} <- Asset.get_tool(id: id),
|
|
|
|
%{x: x, y: y, z: z} <- Asset.get_point(tool_id: id) do
|
|
|
|
%{x: x, y: y, z: z}
|
|
|
|
else
|
|
|
|
nil -> {:error, "Could not find point for tool by id: #{id}"}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-06-14 10:21:52 -06:00
|
|
|
@impl true
|
2019-02-20 12:57:45 -07:00
|
|
|
def sync() do
|
2019-03-05 12:35:09 -07:00
|
|
|
FarmbotCore.Logger.busy(3, "Syncing")
|
2019-02-20 12:57:45 -07:00
|
|
|
|
2019-06-07 10:14:03 -06:00
|
|
|
with {:ok, sync_changeset} <- API.get_changeset(Sync),
|
|
|
|
:ok <- BotState.set_sync_status("syncing"),
|
2019-06-19 12:58:05 -06:00
|
|
|
sync_changeset <- Reconciler.sync_group(sync_changeset, SyncGroup.group_0()),
|
|
|
|
sync_changeset <- Reconciler.sync_group(sync_changeset, SyncGroup.group_1()),
|
|
|
|
sync_changeset <- Reconciler.sync_group(sync_changeset, SyncGroup.group_2()),
|
|
|
|
sync_changeset <- Reconciler.sync_group(sync_changeset, SyncGroup.group_3()),
|
|
|
|
_sync_changeset <- Reconciler.sync_group(sync_changeset, SyncGroup.group_4()) do
|
2019-03-05 12:35:09 -07:00
|
|
|
FarmbotCore.Logger.success(3, "Synced")
|
|
|
|
:ok = BotState.set_sync_status("synced")
|
2019-02-20 12:57:45 -07:00
|
|
|
:ok
|
|
|
|
else
|
|
|
|
error ->
|
2019-03-05 12:35:09 -07:00
|
|
|
:ok = BotState.set_sync_status("sync_error")
|
2019-02-20 12:57:45 -07:00
|
|
|
{:error, inspect(error)}
|
|
|
|
end
|
|
|
|
end
|
2019-06-14 10:21:52 -06:00
|
|
|
|
|
|
|
@impl true
|
|
|
|
def coordinate(x, y, z) do
|
|
|
|
%{x: x, y: y, z: z}
|
|
|
|
end
|
|
|
|
|
|
|
|
@impl true
|
|
|
|
def set_servo_angle(_pin, _angle) do
|
|
|
|
{:error, "set_servo_angle not yet supported"}
|
|
|
|
end
|
|
|
|
|
|
|
|
@impl true
|
|
|
|
def install_first_party_farmware() do
|
|
|
|
{:error, "install_first_party_farmware not yet supported"}
|
|
|
|
end
|
|
|
|
|
|
|
|
@impl true
|
|
|
|
def nothing(), do: nil
|
2019-02-20 12:57:45 -07:00
|
|
|
end
|