/
bot_state_ng.ex
111 lines (93 loc) · 3.11 KB
/
bot_state_ng.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
defmodule FarmbotCore.BotStateNG do
@moduledoc """
The data strucutre behind the bot state tree (not the living process).
Also has some helpers for batching changes.
"""
alias FarmbotCore.{
BotStateNG,
BotStateNG.McuParams,
BotStateNG.LocationData,
BotStateNG.InformationalSettings,
BotStateNG.Configuration
}
use Ecto.Schema
import Ecto.Changeset
@primary_key false
embedded_schema do
embeds_one(:mcu_params, McuParams, on_replace: :update)
embeds_one(:location_data, LocationData, on_replace: :update)
embeds_one(:informational_settings, InformationalSettings, on_replace: :update)
embeds_one(:configuration, Configuration, on_replace: :update)
field(:user_env, {:map, {:string, :any}}, default: %{})
field(:process_info, {:map, {:string, :any}}, default: %{farmwares: %{}})
field(:pins, {:map, {:integer, :map}}, default: %{})
field(:jobs, {:map, {:string, :map}}, default: %{})
end
def new do
%BotStateNG{}
|> changeset(%{})
|> put_embed(:mcu_params, McuParams.new())
|> put_embed(:location_data, LocationData.new())
|> put_embed(:informational_settings, InformationalSettings.new())
|> put_embed(:configuration, Configuration.new())
|> apply_changes()
end
def changeset(bot_state, params \\ %{}) do
bot_state
|> cast(params, [:user_env, :pins, :jobs, :process_info])
|> cast_embed(:mcu_params, [])
|> cast_embed(:location_data, [])
|> cast_embed(:informational_settings, [])
|> cast_embed(:configuration, [])
end
def view(bot_state) do
%{
mcu_params: McuParams.view(bot_state.mcu_params),
location_data: LocationData.view(bot_state.location_data),
informational_settings: InformationalSettings.view(bot_state.informational_settings),
configuration: Configuration.view(bot_state.configuration),
process_info: bot_state.process_info,
user_env: bot_state.user_env,
pins: bot_state.pins,
jobs: bot_state.jobs
}
end
@doc "Add or update a pin to state.pins."
def add_or_update_pin(state, number, mode, value) do
cs = changeset(state, %{})
new_pins =
cs
|> get_field(:pins)
|> Map.put(number, %{mode: mode, value: value})
put_change(cs, :pins, new_pins)
end
@doc "Add or update a farmware to state.farmwares"
def add_or_update_farmware(state, name, %{} = manifest) do
# TODO(Connor) finish this.
cs = changeset(state, %{})
new_farmwares =
cs
|> get_field(:process_info)
|> Map.get(:farmwares)
|> Map.put(name, manifest)
put_change(cs, :process_info, %{farmwares: new_farmwares})
end
@doc "Sets an env var on the state.user_env"
def set_user_env(state, key, value) do
cs = changeset(state, %{})
new_user_env =
cs
|> get_field(:user_env)
|> Map.put(key, value)
put_change(cs, :user_env, new_user_env)
end
@doc "Sets a progress objecto on state.jobs"
def set_job_progress(state, name, progress) do
cs = changeset(state, %{})
new_jobs =
cs
|> get_field(:jobs)
|> Map.put(name, progress)
put_change(cs, :jobs, new_jobs)
end
end