Skip to content

Commit 7d0b042

Browse files
authored
Merge pull request #198 from ConnorRigby/master
E stop fixes and regimen persistance
2 parents 54e48bf + 228b73b commit 7d0b042

File tree

8 files changed

+250
-68
lines changed

8 files changed

+250
-68
lines changed

lib/bot_command/bot_commands.ex

Lines changed: 45 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,29 +18,44 @@ defmodule Command do
1818
def e_stop do
1919
msg = "E STOPPING!"
2020
Logger.debug(msg)
21-
RPC.MessageHandler.log(msg, [:error_toast, :error_ticker], [@log_tag])
22-
Serial.Handler.e_stop
23-
Farmbot.Scheduler.e_stop
21+
is_locked = BotState.get_status
22+
|> Map.get(:informational_settings)
23+
|> Map.get(:locked)
24+
if(is_locked == false) do
25+
GenServer.cast(BotState, {:update_info, :locked, true})
26+
RPC.MessageHandler.log(msg, [:error_toast, :error_ticker], [@log_tag])
27+
Serial.Handler.e_stop
28+
Farmbot.Scheduler.e_stop_lock
29+
end
2430
end
2531

2632
@doc """
2733
resume from an e stop
2834
"""
2935
@spec resume() :: :ok | :fail
3036
def resume do
31-
RPC.MessageHandler.log("Bot Back Up and Running!", [:ticker], [@log_tag])
32-
Serial.Handler.resume
33-
params = BotState.get_status.mcu_params
34-
case Enum.partition(params, fn({param, value}) ->
35-
param_int = Gcode.Parser.parse_param(param)
36-
Command.update_param(param_int, value)
37-
end)
38-
do
39-
{_, []} ->
40-
:ok
41-
{_, failed} ->
42-
Logger.error("Param setting failed! #{inspect failed}")
43-
:fail
37+
is_locked = BotState.get_status
38+
|> Map.get(:informational_settings)
39+
|> Map.get(:locked)
40+
if(is_locked == true) do
41+
Serial.Handler.resume
42+
params = BotState.get_status.mcu_params
43+
# The firmware takes forever to become ready again.
44+
Process.sleep(2000)
45+
case Enum.partition(params, fn({param, value}) ->
46+
param_int = Gcode.Parser.parse_param(param)
47+
Command.update_param(param_int, value)
48+
end)
49+
do
50+
{_, []} ->
51+
RPC.MessageHandler.log("Bot Back Up and Running!", [:ticker], [@log_tag])
52+
GenServer.cast(BotState, {:update_info, :locked, false})
53+
Farmbot.Scheduler.e_stop_unlock
54+
:ok
55+
{_, failed} ->
56+
Logger.error("Param setting failed! #{inspect failed}")
57+
:fail
58+
end
4459
end
4560
end
4661

@@ -197,16 +212,27 @@ defmodule Command do
197212
"""
198213
@spec read_param(number) :: command_output
199214
def read_param(param) when is_integer param do
200-
Gcode.Handler.block_send "F21 P#{param}"
215+
case Gcode.Handler.block_send "F21 P#{param}" do
216+
:timeout ->
217+
Process.sleep(100)
218+
read_param(param)
219+
whatever -> whatever
220+
end
201221
end
202222

203223
@doc """
204224
Update a param. Param needs to be an integer.
205225
"""
206226
@spec update_param(number | nil, number) :: command_output
207227
def update_param(param, value) when is_integer param do
208-
Gcode.Handler.block_send "F22 P#{param} V#{value}"
209-
Command.read_param(param)
228+
case Gcode.Handler.block_send "F22 P#{param} V#{value}" do
229+
:timeout ->
230+
Process.sleep(10)
231+
update_param(param, value)
232+
_ ->
233+
Process.sleep(100)
234+
Command.read_param(param)
235+
end
210236
end
211237

212238
def update_param(nil, _value) do

lib/bot_state/bot_state.ex

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ defmodule BotState do
66
@twelve_hours 3600000
77

88
def init(_) do
9+
NetMan.put_pid(BotState)
910
save_interval
1011
check_updates
1112
{:ok, load}
@@ -30,6 +31,10 @@ defmodule BotState do
3031
end
3132

3233
def load do
34+
token = case FarmbotAuth.get_token() do
35+
{:ok, token} -> token
36+
_ -> nil
37+
end
3338
default_state = %{
3439
mcu_params: %{},
3540
location: [0, 0, 0],
@@ -41,10 +46,11 @@ defmodule BotState do
4146
informational_settings: %{
4247
controller_version: Fw.version,
4348
private_ip: nil,
44-
throttled: get_throttled
49+
throttled: get_throttled,
50+
locked: false
4551
},
4652
authorization: %{
47-
token: nil,
53+
token: token,
4854
email: nil,
4955
pass: nil,
5056
server: nil,
@@ -185,6 +191,7 @@ defmodule BotState do
185191
end
186192

187193
def handle_info({:connected, network, ip_addr}, state) do
194+
Process.sleep(2000) # UGH
188195
# GenServer.cast(BotState, {:update_info, :private_ip, address})
189196
new_info = Map.put(state.informational_settings, :private_ip, ip_addr)
190197
email = state.authorization.email
@@ -202,8 +209,13 @@ defmodule BotState do
202209
Map.put(state, :authorization, auth)
203210
|> Map.put(:informational_settings, new_info)
204211
}
212+
# If the bot is faster than your router (often) this can happen.
213+
{:error, "enetunreach"} ->
214+
Logger.warn("Something super weird happened.. Probably a race condition.")
215+
# Just crash ourselves and try again.
216+
{:crash, state}
205217
error ->
206-
Logger.error("Something bad happened: #{inspect error}")
218+
Logger.error("Something bad happened when logging in!: #{inspect error}")
207219
Fw.factory_reset
208220
{:noreply, state}
209221
end
@@ -235,8 +247,9 @@ defmodule BotState do
235247
GenServer.cast(__MODULE__, {:creds, {email, pass, server}})
236248
end
237249

250+
# setting that timeout is probably going to be a disaster.
238251
def get_status do
239-
GenServer.call(__MODULE__, :state)
252+
GenServer.call(__MODULE__, :state, :infinity)
240253
end
241254

242255
def get_current_pos do

lib/bot_sync/bot_sync.ex

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,32 @@ defmodule BotSync do
33
require Logger
44

55
def init(_args) do
6-
{:ok, %{token: nil,
6+
token = case FarmbotAuth.get_token() do
7+
{:ok, token} -> token
8+
_ -> nil
9+
end
10+
{:ok, %{token: token,
711
resources: load_old_resources,
812
corpuses: load_old_corpuses
913
}}
1014
end
1115

1216
def load_old_corpuses do
13-
[]
17+
case SafeStorage.read(__MODULE__.Corpuses) do
18+
{:ok, old} ->
19+
Enum.each(old, fn(corpus) ->
20+
Logger.debug("Compiling last known good corpuses.")
21+
m = String.to_atom("Elixir.SequenceInstructionSet_"<>"#{corpus.tag}")
22+
m.create_instruction_set(corpus)
23+
end)
24+
old
25+
_ -> []
26+
end
27+
# []
1428
end
1529

1630
def load_old_resources do
17-
Sync.create(%{"checksum" => "loading...",
31+
default = Sync.create(%{"checksum" => "loading...",
1832
"device" => %{
1933
"id" => -1,
2034
"planting_area_id" => -1,
@@ -27,6 +41,10 @@ defmodule BotSync do
2741
"regimens" => [],
2842
"sequences" => [],
2943
"users" => []})
44+
case SafeStorage.read(__MODULE__.Resources) do
45+
{:ok, %Sync{} = old_state} -> old_state
46+
_ -> default
47+
end
3048
end
3149

3250
def start_link(args) do
@@ -37,8 +55,9 @@ defmodule BotSync do
3755
{:noreply, %{token: nil, resources: old, corpuses: oldc}}
3856
end
3957

58+
# When new stuff comes in from a sync
4059
def handle_cast(:sync, %{token: token, resources: old, corpuses: oldc}) do
41-
server = Map.get(token, "unencoded") |> Map.get("iss")
60+
"//" <> server = Map.get(token, "unencoded") |> Map.get("iss")
4261
auth = Map.get(token, "encoded")
4362

4463
case HTTPotion.get "#{server}/api/sync",
@@ -61,19 +80,16 @@ defmodule BotSync do
6180
end
6281
new_merged = Map.merge(old ,new)
6382
RPC.MessageHandler.log("Synced", [], ["BotSync"])
83+
SafeStorage.write(__MODULE__.Resources, :erlang.term_to_binary(new_merged))
84+
SafeStorage.write(__MODULE__.Corpuses, :erlang.term_to_binary(oldc))
6485
{:noreply, %{token: token, resources: new_merged, corpuses: oldc }}
6586
error ->
66-
Logger.debug("Couldn't get resources: #{error}")
87+
Logger.debug("Couldn't get resources: #{inspect error}")
6788
RPC.MessageHandler.log("Error syncing: #{inspect error}", [:error_toast], ["BotSync"])
6889
{:noreply, %{token: token, resources: old, corpuses: oldc}}
6990
end
7091
end
7192

72-
def handle_call(_,_from, %{token: nil, resources: old, corpuses: oldc}) do
73-
Logger.debug("Please make sure you have a token first.")
74-
{:reply, :no_token, %{token: nil, resources: old, corpuses: oldc}}
75-
end
76-
7793
def handle_call({:save_sequence, seq}, _from, %{token: token, resources: resources, corpuses: oldc}) do
7894
new_resources = Map.put(resources, "sequences", [seq | Map.get(resources, "sequences")] )
7995
{:reply, :ok, %{token: token, resources: new_resources, corpuses: oldc}}
@@ -122,13 +138,13 @@ defmodule BotSync do
122138
msg = "Compiling Sequence Instruction Set"
123139
Logger.debug(msg)
124140
RPC.MessageHandler.log(msg, [], ["BotSync"])
125-
server = Map.get(token, "unencoded") |> Map.get("iss")
141+
"//"<>server = Map.get(token, "unencoded") |> Map.get("iss")
126142
c = get_corpus_from_server(server, id)
127143
m = String.to_atom("Elixir.SequenceInstructionSet_"<>"#{id}")
128144
m.create_instruction_set(c)
129145
{:reply, Module.concat(SiS, "Corpus_#{id}"),
130146
%{token: token,
131-
resources: resources, corpuses: oldc ++ [Corpus.create(c)] }}
147+
resources: resources, corpuses: oldc ++ [c] }}
132148
_corpuses ->
133149
{:reply, Module.concat(SiS, "Corpus_#{id}"),
134150
%{token: token, resources: resources, corpuses: oldc}}
@@ -145,6 +161,7 @@ defmodule BotSync do
145161
headers: _headers,
146162
status_code: 200} ->
147163
Poison.decode!(body)
164+
|> Corpus.create
148165
error -> error
149166
end
150167
end

0 commit comments

Comments
 (0)