re implement uart
parent
a86e986a1d
commit
31dc503bd6
|
@ -8,6 +8,7 @@ defmodule Farmbot.BotState do
|
|||
@env Mix.env()
|
||||
|
||||
alias Farmbot.CeleryScript.AST
|
||||
use Farmbot.Logger
|
||||
|
||||
defstruct mcu_params: %{},
|
||||
jobs: %{},
|
||||
|
@ -26,7 +27,13 @@ defmodule Farmbot.BotState do
|
|||
user_env: %{},
|
||||
process_info: %{}
|
||||
|
||||
@valid_sync_status [ :locked, :maintenance, :sync_error, :sync_now, :synced, :syncing, :unknown,]
|
||||
@doc "Get a current pin value."
|
||||
def get_pin_value(num) do
|
||||
GenStage.call(__MODULE__, {:get_pin_value, num})
|
||||
end
|
||||
|
||||
@valid_sync_status [ :locked, :maintenance, :sync_error, :sync_now, :synced, :syncing, :unknown]
|
||||
@doc "Set the sync status above ticker to a message."
|
||||
def set_sync_status(cmd) when cmd in @valid_sync_status do
|
||||
GenStage.call(__MODULE__, {:set_sync_status, cmd})
|
||||
end
|
||||
|
@ -61,10 +68,21 @@ defmodule Farmbot.BotState do
|
|||
end
|
||||
|
||||
def handle_events(events, _from, state) do
|
||||
# Logger.busy 3, "begin handle bot state events"
|
||||
state = do_handle(events, state)
|
||||
# Logger.success 3, "Finish handle bot state events"
|
||||
{:noreply, [state], state}
|
||||
end
|
||||
|
||||
def handle_call({:get_pin_value, pin}, _from, state) do
|
||||
case state.pins[pin] do
|
||||
nil ->
|
||||
{:reply, {:error, :unknown_pin}, [], state}
|
||||
%{value: value} ->
|
||||
{:reply, {:ok, value}, [], state}
|
||||
end
|
||||
end
|
||||
|
||||
def handle_call(:force_state_push, _from, state) do
|
||||
{:reply, state, [state], state}
|
||||
end
|
||||
|
|
|
@ -118,6 +118,7 @@ defmodule Farmbot.BotState.Transport.GenMQTT.Client do
|
|||
{:ok, encoded_ast} = AST.encode(ast)
|
||||
json = Poison.encode!(encoded_ast)
|
||||
GenMQTT.publish(self(), frontend_topic(state.device), json, 0, false)
|
||||
Logger.success 3, "bot state pushed"
|
||||
{:noreply, state}
|
||||
end
|
||||
|
||||
|
|
|
@ -54,7 +54,9 @@ defmodule Farmbot.BotState.Transport.GenMQTT do
|
|||
Client.emit(client, ast)
|
||||
handle_bot_state_events(rest, {internal_state, old_bot_state})
|
||||
new_bot_state ->
|
||||
Client.push_bot_state(client, new_bot_state)
|
||||
if new_bot_state != old_bot_state do
|
||||
Client.push_bot_state(client, new_bot_state)
|
||||
end
|
||||
handle_bot_state_events(rest, {internal_state, new_bot_state})
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,12 +3,25 @@ defmodule Farmbot.CeleryScript.AST.Node.TogglePin do
|
|||
use Farmbot.CeleryScript.AST.Node
|
||||
alias Farmbot.CeleryScript.AST.Node
|
||||
allow_args [:pin_number]
|
||||
use Farmbot.Logger
|
||||
|
||||
def execute(%{pin_number: num}, _, env) do
|
||||
env = mutate_env(env)
|
||||
case Farmbot.Firmware.read_pin(num, :digital) do
|
||||
{:ok, 0} -> Node.WritePin.execute(%{pin_mode: :digital, pin_number: num, pin_value: 1}, [], env)
|
||||
{:ok, 1} -> Node.WritePin.execute(%{pin_mode: :digital, pin_number: num, pin_value: 0}, [], env)
|
||||
case Farmbot.BotState.get_pin_value(num) do
|
||||
{:ok, 0} -> Node.WritePin.execute(%{pin_mode: :digital, pin_number: num, pin_value: 1}, [], env)
|
||||
{:ok, 1} -> Node.WritePin.execute(%{pin_mode: :digital, pin_number: num, pin_value: 0}, [], env)
|
||||
res when res == {:ok, -1} or res == {:error, :unknown_pin} ->
|
||||
Logger.warn 2, "unknonw pin value. Setting to zero."
|
||||
Node.WritePin.execute(%{pin_mode: :digital, pin_number: num, pin_value: 0}, [], env)
|
||||
{:error, reason} -> {:error, reason, env}
|
||||
end
|
||||
end
|
||||
|
||||
defp do_get_pin_value(num, env) do
|
||||
case Farmbot.BotState.get_pin_value(num) do
|
||||
{:ok, 0} -> Node.WritePin.execute(%{pin_mode: :digital, pin_number: num, pin_value: 1}, [], env)
|
||||
{:ok, 1} -> Node.WritePin.execute(%{pin_mode: :digital, pin_number: num, pin_value: 0}, [], env)
|
||||
{:ok, -1} -> Node.WritePin.execute(%{pin_mode: :digital, pin_number: num, pin_value: 0}, [], env)
|
||||
{:error, reason} -> {:error, reason, env}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,7 +6,12 @@ defmodule Farmbot.CeleryScript.AST.Node.WritePin do
|
|||
def execute(%{pin_mode: mode, pin_value: value, pin_number: num}, [], env) do
|
||||
env = mutate_env(env)
|
||||
case Farmbot.Firmware.write_pin(num, mode, value) do
|
||||
:ok -> {:ok, env}
|
||||
:ok ->
|
||||
{:ok, env}
|
||||
# case Farmbot.Firmware.read_pin(num, mode) do
|
||||
# :ok -> {:ok, env}
|
||||
# {:error, reason} -> {:error, reason, env}
|
||||
# end
|
||||
{:error, reason} -> {:error, reason, env}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,7 +2,6 @@ defmodule Farmbot.CeleryScript.AST.Node.Zero do
|
|||
@moduledoc false
|
||||
use Farmbot.CeleryScript.AST.Node
|
||||
allow_args [:axis]
|
||||
@default_speed 100
|
||||
|
||||
def execute(%{axis: :all}, _, env) do
|
||||
env = mutate_env(env)
|
||||
|
@ -11,7 +10,7 @@ defmodule Farmbot.CeleryScript.AST.Node.Zero do
|
|||
|
||||
def execute(%{axis: axis}, _, env) do
|
||||
env = mutate_env(env)
|
||||
case Farmbot.Firmware.zero(axis, @default_speed) do
|
||||
case Farmbot.Firmware.zero(axis) do
|
||||
:ok -> {:ok, env}
|
||||
{:error, reason} -> {:error, reason, env}
|
||||
end
|
||||
|
|
|
@ -25,8 +25,8 @@ defmodule Farmbot.Firmware do
|
|||
end
|
||||
|
||||
@doc "Manually set an axis's current position to zero."
|
||||
def zero(axis, speed) do
|
||||
GenStage.call(__MODULE__, {:zero, [axis, speed]})
|
||||
def zero(axis) do
|
||||
GenStage.call(__MODULE__, {:zero, [axis]})
|
||||
end
|
||||
|
||||
@doc """
|
||||
|
@ -90,7 +90,15 @@ defmodule Farmbot.Firmware do
|
|||
}
|
||||
end
|
||||
|
||||
def handle_info({:EXIT, _, reason}, state) do
|
||||
Logger.error 1, "Firmware handler: #{state.handler_mod} died: #{inspect reason}"
|
||||
{:ok, handler} = state.handler_mod.start_link()
|
||||
new_state = %{state | handler: handler}
|
||||
{:noreply, [], new_state}
|
||||
end
|
||||
|
||||
def handle_call({fun, args}, _from, %{handler: handler, handler_mod: handler_mod} = state) do
|
||||
Logger.debug 3, "Firmware command: #{fun}#{inspect(args)}"
|
||||
res =
|
||||
case apply(handler_mod, fun, [handler | args]) do
|
||||
{:ok, _} = res -> res
|
||||
|
@ -107,13 +115,6 @@ defmodule Farmbot.Firmware do
|
|||
{:noreply, diffs, state}
|
||||
end
|
||||
|
||||
def handle_info({:EXIT, _, reason}, state) do
|
||||
Logger.error 1, "Firmware handler: #{state.handler_mod} died: #{inspect reason}"
|
||||
{:ok, handler} = state.handler_mod.start_link()
|
||||
new_state = %{state | handler: handler}
|
||||
{:noreply, [], new_state}
|
||||
end
|
||||
|
||||
defp handle_gcodes(codes, state, acc \\ [])
|
||||
|
||||
defp handle_gcodes([], state, acc), do: {Enum.reverse(acc), state}
|
||||
|
@ -148,7 +149,7 @@ defmodule Farmbot.Firmware do
|
|||
end
|
||||
|
||||
defp handle_gcode({:report_pin_mode, pin, mode_atom}, state) do
|
||||
# Logger.debug "Got pin mode report: #{pin}: #{mode_atom}"
|
||||
Logger.debug 3, "Got pin mode report: #{pin}: #{mode_atom}"
|
||||
mode = if(mode_atom == :digital, do: 0, else: 1)
|
||||
case state.pins[pin] do
|
||||
%{mode: _, value: _} = pin_map ->
|
||||
|
@ -159,7 +160,7 @@ defmodule Farmbot.Firmware do
|
|||
end
|
||||
|
||||
defp handle_gcode({:report_pin_value, pin, value}, state) do
|
||||
# Logger.debug "Got pin value report: #{pin}: #{value} old: #{inspect state.pins[pin]}"
|
||||
Logger.debug 3, "Got pin value report: #{pin}: #{value} old: #{inspect state.pins[pin]}"
|
||||
case state.pins[pin] do
|
||||
%{mode: _, value: _} = pin_map ->
|
||||
{:pins, %{pin => %{pin_map | value: value}}, %{state | pins: %{state.pins | pin => %{pin_map | value: value}}}}
|
||||
|
|
|
@ -45,7 +45,7 @@ defmodule Farmbot.Firmware.Handler do
|
|||
@callback find_home(handler, axis, speed) :: fw_ret_val
|
||||
|
||||
@doc "Manually set an axis's current position to zero."
|
||||
@callback zero(handler, axis, speed) :: fw_ret_val
|
||||
@callback zero(handler, axis) :: fw_ret_val
|
||||
|
||||
@doc "Home an axis."
|
||||
@callback home(handler, axis, speed) :: fw_ret_val
|
||||
|
|
|
@ -30,8 +30,8 @@ defmodule Farmbot.Firmware.StubHandler do
|
|||
GenStage.call(handler, {:home, axis, speed})
|
||||
end
|
||||
|
||||
def zero(handler, axis, speed) do
|
||||
GenStage.call(handler, {:zero, axis, speed})
|
||||
def zero(handler, axis) do
|
||||
GenStage.call(handler, {:zero, axis})
|
||||
end
|
||||
|
||||
def update_param(handler, param, val) do
|
||||
|
@ -104,7 +104,7 @@ defmodule Farmbot.Firmware.StubHandler do
|
|||
{:reply, :ok, [{:report_pin_mode, pin, mode}, {:report_pin_value, pin, value}], state}
|
||||
end
|
||||
|
||||
def handle_call({:zero, axis, _speed}, _from, state) do
|
||||
def handle_call({:zero, axis}, _from, state) do
|
||||
state = %{state | pos: %{state.pos | axis => 0}}
|
||||
case axis do
|
||||
:x -> {:reply, :ok, [{:report_current_position, 0, state.pos.y, state.pos.z}], state}
|
||||
|
|
|
@ -28,8 +28,8 @@ defmodule Farmbot.Firmware.UartHandler do
|
|||
GenStage.call(handler, {:home, axis, speed})
|
||||
end
|
||||
|
||||
def zero(handler, axis, speed) do
|
||||
GenStage.call(handler, {:zero, axis, speed})
|
||||
def zero(handler, axis) do
|
||||
GenStage.call(handler, {:zero, axis})
|
||||
end
|
||||
|
||||
def update_param(handler, param, val) do
|
||||
|
@ -61,8 +61,7 @@ defmodule Farmbot.Firmware.UartHandler do
|
|||
defmodule State do
|
||||
@moduledoc false
|
||||
defstruct [
|
||||
:nerves,
|
||||
:codes
|
||||
:nerves
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -76,7 +75,7 @@ defmodule Farmbot.Firmware.UartHandler do
|
|||
Process.link(nerves)
|
||||
|
||||
case open_tty(nerves, tty) do
|
||||
:ok -> {:producer, %State{nerves: nerves, codes: []}, dispatcher: GenStage.BroadcastDispatcher}
|
||||
:ok -> {:producer, %State{nerves: nerves}, dispatcher: GenStage.BroadcastDispatcher}
|
||||
err -> {:stop, err, :no_state}
|
||||
end
|
||||
end
|
||||
|
@ -116,7 +115,7 @@ defmodule Farmbot.Firmware.UartHandler do
|
|||
end
|
||||
|
||||
def handle_info({:nerves_uart, _, {_q, gcode}}, state) do
|
||||
do_dispatch([gcode | state.codes], state)
|
||||
{:noreply, [gcode], state}
|
||||
end
|
||||
|
||||
def handle_info({:nerves_uart, _, bin}, state) when is_binary(bin) do
|
||||
|
@ -125,8 +124,82 @@ defmodule Farmbot.Firmware.UartHandler do
|
|||
end
|
||||
|
||||
def handle_call({:move_absolute, pos, speed}, _from, state) do
|
||||
UART.write(state.nerves, "G00 X#{pos.x} Y#{pos.y} Z#{pos.z} A#{speed} B#{speed} C#{speed}")
|
||||
{:noreply, [], state}
|
||||
r = UART.write(state.nerves, "G00 X#{pos.x} Y#{pos.y} Z#{pos.z} A#{speed} B#{speed} C#{speed}")
|
||||
{:reply, r, [], state}
|
||||
end
|
||||
|
||||
def handle_call({:calibrate, axis, _speed}, _from, state) do
|
||||
num = case axis |> to_string() do
|
||||
"x" -> 14
|
||||
"y" -> 15
|
||||
"z" -> 16
|
||||
end
|
||||
r = UART.write(state.nerves, "F#{num}")
|
||||
{:reply, r, [], state}
|
||||
end
|
||||
|
||||
def handle_call({:find_home, axis, speed}, _from, state) do
|
||||
cmd = case axis |> to_string() do
|
||||
"x" -> "11 A#{speed}"
|
||||
"y" -> "12 B#{speed}"
|
||||
"z" -> "13 C#{speed}"
|
||||
end
|
||||
r = UART.write(state.nerves, "F#{cmd}")
|
||||
{:reply, r, [], state}
|
||||
end
|
||||
|
||||
def handle_call({:home, axis, speed}, _from, state) do
|
||||
cmd = case axis |> to_string() do
|
||||
"x" -> "X0 A#{speed}"
|
||||
"y" -> "Y0 B#{speed}"
|
||||
"z" -> "Z0 C#{speed}"
|
||||
end
|
||||
r = UART.write(state.nerves, "G00 #{cmd}")
|
||||
{:reply, r, [], state}
|
||||
end
|
||||
|
||||
def handle_call({:zero, axis}, _from, state) do
|
||||
axis_format = case axis |> to_string() do
|
||||
"x" -> "X"
|
||||
"y" -> "Y"
|
||||
"z" -> "Z"
|
||||
end
|
||||
r = UART.write(state.nerves, "F84 #{axis_format}")
|
||||
{:reply, r, [], state}
|
||||
end
|
||||
|
||||
def handle_call(:emergency_lock, _from, state) do
|
||||
r = UART.write(state.nerves, "E")
|
||||
{:reply, r, [], state}
|
||||
end
|
||||
|
||||
def handle_call(:emergency_unlock, _from, state) do
|
||||
r = UART.write(state.nerves, "F09")
|
||||
{:reply, r, [], state}
|
||||
end
|
||||
|
||||
def handle_call({:read_pin, pin, mode}, _from, state) do
|
||||
encoded_mode = if(mode == :digital, do: 0, else: 1)
|
||||
case UART.write(state.nerves, "F43 P#{pin} M#{encoded_mode}") do
|
||||
:ok ->
|
||||
Process.sleep(100)
|
||||
r = UART.write(state.nerves, "F42 P#{pin} M#{encoded_mode}")
|
||||
{:reply, r, [{:report_pin_mode, pin, mode}], state}
|
||||
err ->
|
||||
{:reply, err, [], state}
|
||||
end
|
||||
end
|
||||
|
||||
def handle_call({:write_pin, pin, mode, value}, _from, state) do
|
||||
encoded_mode = if(mode == :digital, do: 0, else: 1)
|
||||
case UART.write(state.nerves, "F43 P#{pin} M#{encoded_mode}") do
|
||||
:ok ->
|
||||
Process.sleep(100)
|
||||
r = UART.write(state.nerves, "F41 P#{pin} V#{value} M#{encoded_mode}")
|
||||
{:reply, r, [{:report_pin_mode, pin, mode}, {:report_pin_value, pin, value}], state}
|
||||
err ->
|
||||
{:reply, err, [], state}
|
||||
end
|
||||
end
|
||||
|
||||
def handle_call(_call, _from, state) do
|
||||
|
@ -134,10 +207,6 @@ defmodule Farmbot.Firmware.UartHandler do
|
|||
end
|
||||
|
||||
def handle_demand(_amnt, state) do
|
||||
do_dispatch(state.codes, state)
|
||||
end
|
||||
|
||||
defp do_dispatch(codes, state) do
|
||||
{:noreply, Enum.reverse(codes), %{state | codes: []}}
|
||||
{:noreply, [], state}
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue