Work toward farmware/celeryscript stuff
* Fix logger erros * Fix migrations * Fix compile errors * Fix tzdata child_specpull/974/head
parent
bdb11b2ea8
commit
10a4379568
|
@ -79,18 +79,6 @@ defmodule Farmbot.CeleryScript.RunTime.InstructionSet do
|
|||
@doc "Set environment variables for a Farmware."
|
||||
simple_io_instruction(:set_user_env)
|
||||
|
||||
@doc "(Re)Install Farmware written and developed by Farmbot, Inc."
|
||||
simple_io_instruction(:install_first_party_farmware)
|
||||
|
||||
@doc "Install a Farmware from the web."
|
||||
simple_io_instruction(:install_farmware)
|
||||
|
||||
@doc "Remove a Farmware."
|
||||
simple_io_instruction(:remove_farmware)
|
||||
|
||||
@doc "Update a Farmware."
|
||||
simple_io_instruction(:update_farmware)
|
||||
|
||||
@doc "Force the bot's state to be dispatched."
|
||||
simple_io_instruction(:read_status)
|
||||
|
||||
|
|
|
@ -61,10 +61,6 @@ defmodule Farmbot.CeleryScript.RunTime.InstructionSetTest do
|
|||
io_test("take_photo")
|
||||
io_test("config_update")
|
||||
io_test("set_user_env")
|
||||
io_test("install_first_party_farmware")
|
||||
io_test("install_farmware")
|
||||
io_test("remove_farmware")
|
||||
io_test("update_farmware")
|
||||
io_test("read_status")
|
||||
io_test("sync")
|
||||
io_test("power_off")
|
||||
|
|
|
@ -10,6 +10,8 @@ defmodule Farmbot.Asset do
|
|||
|
||||
Device,
|
||||
FarmEvent,
|
||||
FarmwareEnv,
|
||||
FarmwareInstallation,
|
||||
Peripheral,
|
||||
PinBinding,
|
||||
Point,
|
||||
|
@ -30,6 +32,8 @@ defmodule Farmbot.Asset do
|
|||
|
||||
@device_fields ~W(id name timezone)
|
||||
@farm_events_fields ~W(calendar end_time executable_id executable_type id repeat start_time time_unit)
|
||||
@farmware_envs_fields ~W(id key value)
|
||||
@farmware_installations_fields ~W(id url first_party)
|
||||
@peripherals_fields ~W(id label mode pin)
|
||||
@pin_bindings_fields ~W(id pin_num sequence_id special_action)
|
||||
@points_fields ~W(id meta name pointer_type tool_id x y z)
|
||||
|
@ -45,6 +49,8 @@ defmodule Farmbot.Asset do
|
|||
|
||||
def to_asset(body, Device), do: resource_decode(body, @device_fields, Device)
|
||||
def to_asset(body, FarmEvent), do: resource_decode(body, @farm_events_fields, FarmEvent)
|
||||
def to_asset(body, FarmwareEnv), do: resource_decode(body, @farmware_envs_fields, FarmwareEnv)
|
||||
def to_asset(body, FarmwareInstallation), do: resource_decode(body, @farmware_installations_fields, FarmwareInstallation)
|
||||
def to_asset(body, Peripheral), do: resource_decode(body, @peripherals_fields, Peripheral)
|
||||
def to_asset(body, PinBinding), do: resource_decode(body, @pin_bindings_fields, PinBinding)
|
||||
def to_asset(body, Point), do: resource_decode(body, @points_fields, Point)
|
||||
|
@ -66,6 +72,8 @@ defmodule Farmbot.Asset do
|
|||
def string_to_atom({k, v}), do: {String.to_atom(k), v}
|
||||
def into_struct(data, kind), do: struct(kind, data)
|
||||
|
||||
# TODO(Connor) - 2018-08-05 *_sync should upload dirty artifacts
|
||||
# before applying sync commands?
|
||||
def fragment_sync(verbosity \\ 1) do
|
||||
Farmbot.Logger.busy verbosity, "Syncing"
|
||||
Farmbot.Registry.dispatch(__MODULE__, {:sync_status, :syncing})
|
||||
|
@ -161,7 +169,7 @@ defmodule Farmbot.Asset do
|
|||
# When `body` is nil, it means an object was deleted.
|
||||
def do_apply_sync_cmd(%{body: nil, remote_id: id, kind: kind}) do
|
||||
mod = Module.concat(["Farmbot", "Asset", kind])
|
||||
case Repo.get(mod, id) do
|
||||
case Repo.one(from m in mod, where: m.id == ^id) do
|
||||
nil ->
|
||||
:ok
|
||||
|
||||
|
@ -175,7 +183,7 @@ defmodule Farmbot.Asset do
|
|||
not_struct = strip_struct(obj)
|
||||
mod = Module.concat(["Farmbot", "Asset", kind])
|
||||
# We need to check if this object exists in the database.
|
||||
case Repo.get(mod, id) do
|
||||
case Repo.one(from m in mod, where: m.id == ^id) do
|
||||
# If it does not, just return the newly created object.
|
||||
nil ->
|
||||
change = mod.changeset(struct(mod, not_struct), not_struct)
|
||||
|
@ -273,8 +281,11 @@ defmodule Farmbot.Asset do
|
|||
end
|
||||
|
||||
def clear_all_data do
|
||||
# remote assets.
|
||||
Repo.delete_all(Device)
|
||||
Repo.delete_all(FarmEvent)
|
||||
Repo.delete_all(FarmwareEnv)
|
||||
Repo.delete_all(FarmwareInstallation)
|
||||
Repo.delete_all(Peripheral)
|
||||
Repo.delete_all(PinBinding)
|
||||
Repo.delete_all(Point)
|
||||
|
@ -282,6 +293,8 @@ defmodule Farmbot.Asset do
|
|||
Repo.delete_all(Sensor)
|
||||
Repo.delete_all(Sequence)
|
||||
Repo.delete_all(Tool)
|
||||
|
||||
# Interanal assets.
|
||||
Repo.delete_all(PersistentRegimen)
|
||||
Repo.delete_all(SyncCmd)
|
||||
:ok
|
||||
|
|
|
@ -8,7 +8,9 @@ defmodule Farmbot.Asset.Device do
|
|||
use Ecto.Schema
|
||||
import Ecto.Changeset
|
||||
|
||||
@primary_key {:local_id, :binary_id, autogenerate: true}
|
||||
schema "devices" do
|
||||
field(:id, :integer)
|
||||
field(:name, :string)
|
||||
field(:timezone, :string)
|
||||
end
|
||||
|
|
|
@ -29,7 +29,9 @@ defmodule Farmbot.Asset.FarmEvent do
|
|||
import Ecto.Changeset
|
||||
require Farmbot.Logger
|
||||
|
||||
@primary_key {:local_id, :binary_id, autogenerate: true}
|
||||
schema "farm_events" do
|
||||
field(:id, :integer)
|
||||
field(:start_time, :string)
|
||||
field(:end_time, :string)
|
||||
field(:repeat, :integer)
|
||||
|
|
|
@ -8,7 +8,9 @@ defmodule Farmbot.Asset.FarmwareEnv do
|
|||
use Ecto.Schema
|
||||
import Ecto.Changeset
|
||||
|
||||
schema "farmware_env" do
|
||||
@primary_key {:local_id, :binary_id, autogenerate: true}
|
||||
schema "farmware_envs" do
|
||||
field(:id, :integer)
|
||||
field(:key, :string)
|
||||
field(:value, JSONType)
|
||||
end
|
||||
|
|
|
@ -7,7 +7,10 @@ defmodule Farmbot.Asset.FarmwareInstallation do
|
|||
use Ecto.Schema
|
||||
import Ecto.Changeset
|
||||
|
||||
@primary_key {:local_id, :binary_id, autogenerate: true}
|
||||
schema "farmware_installations" do
|
||||
field(:id, :integer)
|
||||
field(:first_party, :boolean)
|
||||
field(:url, :string)
|
||||
end
|
||||
|
||||
|
|
|
@ -7,7 +7,9 @@ defmodule Farmbot.Asset.Peripheral do
|
|||
use Ecto.Schema
|
||||
import Ecto.Changeset
|
||||
|
||||
@primary_key {:local_id, :binary_id, autogenerate: true}
|
||||
schema "peripherals" do
|
||||
field(:id, :integer)
|
||||
field(:pin, :integer)
|
||||
field(:mode, :integer)
|
||||
field(:label, :string)
|
||||
|
|
|
@ -5,7 +5,9 @@ defmodule Farmbot.Asset.PinBinding do
|
|||
use Ecto.Schema
|
||||
import Ecto.Changeset
|
||||
|
||||
@primary_key {:local_id, :binary_id, autogenerate: true}
|
||||
schema "pin_bindings" do
|
||||
field(:id, :integer)
|
||||
field(:pin_num, :integer)
|
||||
field(:sequence_id, :integer)
|
||||
field(:special_action, :string)
|
||||
|
|
|
@ -7,7 +7,9 @@ defmodule Farmbot.Asset.Point do
|
|||
alias Farmbot.EctoTypes.ModuleType
|
||||
alias Farmbot.EctoTypes.TermType
|
||||
|
||||
@primary_key {:local_id, :binary_id, autogenerate: true}
|
||||
schema "points" do
|
||||
field(:id, :integer)
|
||||
field(:name, :string)
|
||||
field(:tool_id, :integer)
|
||||
field(:x, :float)
|
||||
|
|
|
@ -11,7 +11,9 @@ defmodule Farmbot.Asset.Regimen do
|
|||
use Ecto.Schema
|
||||
import Ecto.Changeset
|
||||
|
||||
@primary_key {:local_id, :binary_id, autogenerate: true}
|
||||
schema "regimens" do
|
||||
field(:id, :integer)
|
||||
field(:name, :string)
|
||||
field(:farm_event_id, :integer, virtual: true)
|
||||
field(:regimen_items, TermType)
|
||||
|
|
|
@ -7,7 +7,9 @@ defmodule Farmbot.Asset.Sensor do
|
|||
use Ecto.Schema
|
||||
import Ecto.Changeset
|
||||
|
||||
@primary_key {:local_id, :binary_id, autogenerate: true}
|
||||
schema "sensors" do
|
||||
field(:id, :integer)
|
||||
field(:pin, :integer)
|
||||
field(:mode, :integer)
|
||||
field(:label, :string)
|
||||
|
|
|
@ -9,7 +9,9 @@ defmodule Farmbot.Asset.Sequence do
|
|||
import Ecto.Changeset
|
||||
require Farmbot.Logger
|
||||
|
||||
@primary_key {:local_id, :binary_id, autogenerate: true}
|
||||
schema "sequences" do
|
||||
field(:id, :integer)
|
||||
field(:name, :string)
|
||||
field(:kind, :string)
|
||||
field(:args, TermType)
|
||||
|
|
|
@ -5,7 +5,9 @@ defmodule Farmbot.Asset.Tool do
|
|||
use Ecto.Schema
|
||||
import Ecto.Changeset
|
||||
|
||||
@primary_key {:local_id, :binary_id, autogenerate: true}
|
||||
schema "tools" do
|
||||
field(:id, :integer)
|
||||
field(:name, :string)
|
||||
end
|
||||
|
||||
|
|
|
@ -23,10 +23,6 @@ defmodule Farmbot.Core.CeleryScript.IOLayer do
|
|||
@callback take_photo(args, body) :: :ok | {:error, String.t}
|
||||
@callback config_update(args, body) :: :ok | {:error, String.t}
|
||||
@callback set_user_env(args, body) :: :ok | {:error, String.t}
|
||||
@callback install_first_party_farmware(args, body) :: :ok | {:error, String.t}
|
||||
@callback install_farmware(args, body) :: :ok | {:error, String.t}
|
||||
@callback remove_farmware(args, body) :: :ok | {:error, String.t}
|
||||
@callback update_farmware(args, body) :: :ok | {:error, String.t}
|
||||
@callback read_status(args, body) :: :ok | {:error, String.t}
|
||||
@callback sync(args, body) :: :ok | {:error, String.t}
|
||||
@callback power_off(args, body) :: :ok | {:error, String.t}
|
||||
|
|
|
@ -12,8 +12,6 @@ defmodule Farmbot.Core.CeleryScript.StubIOLayer do
|
|||
def factory_reset(_args, _body), do: {:error, "Stubbed"}
|
||||
def find_home(_args, _body), do: {:error, "Stubbed"}
|
||||
def home(_args, _body), do: {:error, "Stubbed"}
|
||||
def install_farmware(_args, _body), do: {:error, "Stubbed"}
|
||||
def install_first_party_farmware(_args, _body), do: {:error, "Stubbed"}
|
||||
def move_absolute(_args, _body), do: {:error, "Stubbed"}
|
||||
def move_relative(_args, _body), do: {:error, "Stubbed"}
|
||||
def power_off(_args, _body), do: {:error, "Stubbed"}
|
||||
|
@ -26,8 +24,6 @@ defmodule Farmbot.Core.CeleryScript.StubIOLayer do
|
|||
def sync(_args, _body), do: {:error, "Stubbed"}
|
||||
def take_photo(_args, _body), do: {:error, "Stubbed"}
|
||||
def toggle_pin(_args, _body), do: {:error, "Stubbed"}
|
||||
def remove_farmware(_args, _body), do: {:error, "Stubbed"}
|
||||
def update_farmware(_args, _body), do: {:error, "Stubbed"}
|
||||
def wait(_args, _body), do: {:error, "Stubbed"}
|
||||
def write_pin(_args, _body), do: {:error, "Stubbed"}
|
||||
def zero(_args, _body), do: {:error, "Stubbed"}
|
||||
|
|
|
@ -6,10 +6,24 @@ defmodule Farmbot.JSON.JasonParser do
|
|||
def encode(data), do: Jason.encode(data)
|
||||
|
||||
require Protocol
|
||||
# Bot State
|
||||
Protocol.derive Jason.Encoder, Farmbot.BotState
|
||||
Protocol.derive Jason.Encoder, Farmbot.BotState.Configuration
|
||||
Protocol.derive Jason.Encoder, Farmbot.BotState.InformationalSettings
|
||||
Protocol.derive Jason.Encoder, Farmbot.BotState.LocationData
|
||||
Protocol.derive Jason.Encoder, Farmbot.BotState.McuParams
|
||||
Protocol.derive Jason.Encoder, Farmbot.BotState.Pin
|
||||
|
||||
# Assets
|
||||
Protocol.derive Jason.Encoder, Farmbot.Asset.Device
|
||||
Protocol.derive Jason.Encoder, Farmbot.Asset.FarmEvent
|
||||
Protocol.derive Jason.Encoder, Farmbot.Asset.FarmwareEnv
|
||||
Protocol.derive Jason.Encoder, Farmbot.Asset.FarmwareInstallation
|
||||
Protocol.derive Jason.Encoder, Farmbot.Asset.Peripheral
|
||||
Protocol.derive Jason.Encoder, Farmbot.Asset.PinBinding
|
||||
Protocol.derive Jason.Encoder, Farmbot.Asset.Point
|
||||
Protocol.derive Jason.Encoder, Farmbot.Asset.Regimen
|
||||
Protocol.derive Jason.Encoder, Farmbot.Asset.Sensor
|
||||
Protocol.derive Jason.Encoder, Farmbot.Asset.Sequence
|
||||
Protocol.derive Jason.Encoder, Farmbot.Asset.Tool
|
||||
end
|
||||
|
|
|
@ -2,12 +2,12 @@ defmodule Farmbot.Asset.Repo.Migrations.CreateFarmwareEnvTable do
|
|||
use Ecto.Migration
|
||||
|
||||
def change do
|
||||
create table("farmware_env", primary_key: false) do
|
||||
create table("farmware_envs", primary_key: false) do
|
||||
add(:id, :integer)
|
||||
add(:key, :string)
|
||||
add(:value, :text)
|
||||
end
|
||||
|
||||
create(unique_index("farmware_env", [:id]))
|
||||
create(unique_index("farmware_envs", [:id]))
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,9 +5,9 @@ defmodule Farmbot.Asset.Repo.Migrations.CreateFarmwareInstallationsTable do
|
|||
create table("farmware_installations", primary_key: false) do
|
||||
add(:id, :integer)
|
||||
add(:url, :string)
|
||||
add(:first_party, :boolean)
|
||||
end
|
||||
|
||||
create(unique_index("farmware_installations", [:id]))
|
||||
end
|
||||
create(unique_index("farmware_installations", [:id, :url]))
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
defmodule Farmbot.Asset.Repo.Migrations.AddLocalIdAndDirtyFields do
|
||||
use Ecto.Migration
|
||||
|
||||
def change do
|
||||
alter table("devices") do
|
||||
add(:local_id, :uuid, primary: true)
|
||||
add(:dirty, :boolean, default: false)
|
||||
end
|
||||
|
||||
alter table("farm_events") do
|
||||
add(:local_id, :uuid, primary: true)
|
||||
add(:dirty, :boolean, default: false)
|
||||
end
|
||||
|
||||
alter table("farmware_installations") do
|
||||
add(:local_id, :uuid, primary: true)
|
||||
add(:dirty, :boolean, default: false)
|
||||
end
|
||||
|
||||
alter table("farmware_envs") do
|
||||
add(:local_id, :uuid, primary: true)
|
||||
add(:dirty, :boolean, default: false)
|
||||
end
|
||||
|
||||
alter table("peripherals") do
|
||||
add(:local_id, :uuid, primary: true)
|
||||
add(:dirty, :boolean, default: false)
|
||||
end
|
||||
|
||||
alter table("pin_bindings") do
|
||||
add(:local_id, :uuid, primary: true)
|
||||
add(:dirty, :boolean, default: false)
|
||||
end
|
||||
|
||||
alter table("points") do
|
||||
add(:local_id, :uuid, primary: true)
|
||||
add(:dirty, :boolean, default: false)
|
||||
end
|
||||
|
||||
alter table("regimens") do
|
||||
add(:local_id, :uuid, primary: true)
|
||||
add(:dirty, :boolean, default: false)
|
||||
end
|
||||
|
||||
alter table("sensors") do
|
||||
add(:local_id, :uuid, primary: true)
|
||||
add(:dirty, :boolean, default: false)
|
||||
end
|
||||
|
||||
alter table("sequences") do
|
||||
add(:local_id, :uuid, primary: true)
|
||||
add(:dirty, :boolean, default: false)
|
||||
end
|
||||
|
||||
alter table("tools") do
|
||||
add(:local_id, :uuid, primary: true)
|
||||
add(:dirty, :boolean, default: false)
|
||||
end
|
||||
|
||||
# TODO(Connor) - 2018-08-15 All things without a UUID will probably need one?
|
||||
# However first HTTP sync will wipe out all assets, and redownload them
|
||||
# So i guess not?
|
||||
end
|
||||
|
||||
end
|
|
@ -1,7 +1,6 @@
|
|||
defmodule Farmbot.System.ConfigStorage.Migrations.AddIgnoreFwConfig do
|
||||
use Ecto.Migration
|
||||
import Farmbot.Config
|
||||
|
||||
import Farmbot.Config.MigrationHelpers
|
||||
def change do
|
||||
create_settings_config("ignore_fw_config", :bool, false)
|
||||
end
|
||||
|
|
|
@ -1,16 +1,21 @@
|
|||
defmodule Farmbot.HTTP.Error do
|
||||
@moduledoc "Some Farmbot HTTP Adapter error."
|
||||
|
||||
alias Farmbot.HTTP.{Response}
|
||||
alias Farmbot.HTTP.{Response, Error}
|
||||
|
||||
defexception [:message, :response]
|
||||
|
||||
@doc false
|
||||
def exception(desc) when is_atom(desc) or is_binary(desc) do
|
||||
%__MODULE__{message: String.trim(desc)}
|
||||
%Error{message: String.trim(desc)}
|
||||
end
|
||||
|
||||
def exception(%Response{status_code: code, body: body} = resp) do
|
||||
%__MODULE__{message: "HTTP Request failed (#{code}) body: #{body}", response: resp}
|
||||
case Farmbot.JSON.decode(body) do
|
||||
{:ok, %{"error" => reason}} ->
|
||||
%Error{message: "HTTP Request failed (#{code}) #{reason}", response: resp}
|
||||
_ ->
|
||||
%Error{message: "HTTP Request failed (#{code})", response: resp}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,14 +1,19 @@
|
|||
defmodule Farmbot.HTTP.Helpers do
|
||||
@moduledoc """
|
||||
Helpful stuff.
|
||||
"""
|
||||
@moduledoc false
|
||||
|
||||
@doc """
|
||||
Helper for checking status codes
|
||||
"""
|
||||
@doc "Helper for checking status codes"
|
||||
defmacro is_2xx(number) do
|
||||
quote do
|
||||
unquote(number) > 199 and unquote(number) < 300
|
||||
end
|
||||
end
|
||||
|
||||
# Defines a function to fetch and decode an api resource.
|
||||
@doc "Helper to define fetch and decode resource function in Farmbot.HTTP"
|
||||
defmacro fadr(plural, kind) do
|
||||
quote do
|
||||
def unquote(plural)(),
|
||||
do: fetch_and_decode("/api/#{unquote(plural)}.json", unquote(kind))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,6 +5,7 @@ defmodule Farmbot.HTTP do
|
|||
|
||||
use GenServer
|
||||
alias Farmbot.HTTP.{Adapter, Error, Response}
|
||||
import Farmbot.HTTP.Helpers
|
||||
alias Farmbot.JSON
|
||||
|
||||
@adapter Application.get_env(:farmbot_ext, :behaviour)[:http_adapter]
|
||||
|
@ -19,6 +20,8 @@ defmodule Farmbot.HTTP do
|
|||
alias Farmbot.Asset.{
|
||||
Device,
|
||||
FarmEvent,
|
||||
FarmwareEnv,
|
||||
FarmwareInstallation,
|
||||
Peripheral,
|
||||
PinBinding,
|
||||
Point,
|
||||
|
@ -28,21 +31,63 @@ defmodule Farmbot.HTTP do
|
|||
Tool,
|
||||
}
|
||||
|
||||
def device, do: fetch_and_decode("/api/device.json", Device)
|
||||
def farm_events, do: fetch_and_decode("/api/farm_events.json", FarmEvent)
|
||||
def peripherals, do: fetch_and_decode("/api/peripherals.json", Peripheral)
|
||||
def pin_bindings, do: fetch_and_decode("/api/pin_bindings.json", PinBinding)
|
||||
def points, do: fetch_and_decode("/api/points.json", Point)
|
||||
def regimens, do: fetch_and_decode("/api/regimens.json", Regimen)
|
||||
def sensors, do: fetch_and_decode("/api/sensors.json", Sensor)
|
||||
def sequences, do: fetch_and_decode("/api/sequences.json", Sequence)
|
||||
def tools, do: fetch_and_decode("/api/tools.json", Tool)
|
||||
fadr :device, Device
|
||||
fadr :farm_events, FarmEvent
|
||||
fadr :farmware_installations, FarmwareInstallation
|
||||
|
||||
# TODO(Connor) - 2018-08-15 Make this a macro if/when it starts
|
||||
# happening more often.
|
||||
def new_farmware_installation(%FarmwareInstallation{} = data) do
|
||||
json = JSON.encode!(data)
|
||||
case post("/api/farmware_installations", json) do
|
||||
{:error, reason} -> {:error, reason}
|
||||
{:ok, %{body: body, status_code: code}} when is_2xx(code) ->
|
||||
r = body |> JSON.decode!() |> Farmbot.Asset.to_asset(FarmwareInstallation)
|
||||
{:ok, r}
|
||||
end
|
||||
end
|
||||
|
||||
fadr :farmware_envs, FarmwareEnv
|
||||
|
||||
# TODO(Connor) - 2018-08-15 Make this a macro if/when it starts
|
||||
# happening more often.
|
||||
def new_farmware_env(%FarmwareEnv{} = data) do
|
||||
json = JSON.encode!(data)
|
||||
case post("/api/farmware_env", json) do
|
||||
{:error, reason} -> {:error, reason}
|
||||
{:ok, %{body: body, status_code: code}} when is_2xx(code) ->
|
||||
r = body |> JSON.decode!() |> Farmbot.Asset.to_asset(FarmwareEnv)
|
||||
{:ok, r}
|
||||
end
|
||||
end
|
||||
|
||||
fadr :peripherals, Peripheral
|
||||
fadr :pin_bindings, PinBinding
|
||||
fadr :points, Point
|
||||
fadr :regimens, Regimen
|
||||
fadr :sensors, Sensor
|
||||
fadr :sequences, Sequence
|
||||
fadr :tools, Tool
|
||||
|
||||
# These aren't synced.
|
||||
def fbos_config, do: fetch("/api/fbos_config")
|
||||
def firmware_config, do: fetch("/api/firmware_config")
|
||||
|
||||
@doc "Fetches data and decodes as JSON."
|
||||
def fetch(url) do
|
||||
url
|
||||
|> get!([{"content-type", "Application/JSON"}])
|
||||
|> case do
|
||||
%{body: body, status_code: code} when is_2xx(code) -> body
|
||||
_ -> raise "[#{url}] HTTP Error"
|
||||
end
|
||||
|> JSON.decode!()
|
||||
end
|
||||
|
||||
@doc "Fetches a url and decodes as a Farmbot struct."
|
||||
def fetch_and_decode(url, kind) do
|
||||
url
|
||||
|> get!()
|
||||
|> Map.fetch!(:body)
|
||||
|> JSON.decode!()
|
||||
|> fetch()
|
||||
|> Farmbot.Asset.to_asset(kind)
|
||||
end
|
||||
|
||||
|
|
|
@ -68,19 +68,11 @@ defmodule Farmbot.OS.IOLayer do
|
|||
{:error, "config_update depreciated since 6.1.0"}
|
||||
end
|
||||
|
||||
def set_user_env(_args, _body) do
|
||||
IO.inspect {:error, "not implemented: set_user_env"}
|
||||
def set_user_env(_args, pairs) do
|
||||
IO.puts "not implemented: set_user_env(#{inspect pairs})"
|
||||
:ok
|
||||
end
|
||||
|
||||
def install_first_party_farmware(args, body), do: Farmware.first_party(args, body)
|
||||
|
||||
def install_farmware(args, body), do: Farmware.install(args, body)
|
||||
|
||||
def remove_farmware(args, body), do: Farmware.remove(args, body)
|
||||
|
||||
def update_farmware(args, body), do: Farmware.update(args, body)
|
||||
|
||||
def execute_script(args, body), do: Farmware.execute(args, body)
|
||||
|
||||
def take_photo(_args, body) do
|
||||
|
|
|
@ -1,14 +1,11 @@
|
|||
defmodule Farmbot.OS.IOLayer.Farmware do
|
||||
require Farmbot.Logger
|
||||
alias Farmbot.OS.IOLayer.Farmware.Server
|
||||
|
||||
@fpf_url "https://raw.githubusercontent.com/FarmBot-Labs/farmware_manifests/master/manifest.json"
|
||||
|
||||
def first_party(_args, []) do
|
||||
{:error, "not implemented"}
|
||||
end
|
||||
|
||||
def install(%{url: u_rl}, []) do
|
||||
def install(%{url: _url}, []) do
|
||||
{:error, "not implemented"}
|
||||
end
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
defmodule Farmbot.OS.IOLayer.Farmware.Server do
|
||||
# use GenServer
|
||||
end
|
|
@ -6,6 +6,8 @@ defmodule Farmbot.OS.IOLayer.Sync do
|
|||
alias Farmbot.Asset.{
|
||||
Device,
|
||||
FarmEvent,
|
||||
# FarmwareEnv,
|
||||
# FarmwareInstallation,
|
||||
Peripheral,
|
||||
PinBinding,
|
||||
Point,
|
||||
|
@ -29,6 +31,11 @@ defmodule Farmbot.OS.IOLayer.Sync do
|
|||
[
|
||||
Task.Supervisor.async_nolink(pid, fn -> {Device, HTTP.device() |> List.wrap() |> list_to_sync_cmds()} end),
|
||||
Task.Supervisor.async_nolink(pid, fn -> {FarmEvent, HTTP.farm_events() |> list_to_sync_cmds()} end),
|
||||
|
||||
# These aren't a thing yet.
|
||||
# Task.Supervisor.async_nolink(pid, fn -> {FarmwareEnv, HTTP.farmware_envs() |> list_to_sync_cmds()} end),
|
||||
# Task.Supervisor.async_nolink(pid, fn -> {FarmwareInstallation, HTTP.farmware_installations() |> list_to_sync_cmds()} end),
|
||||
|
||||
Task.Supervisor.async_nolink(pid, fn -> {Peripheral, HTTP.peripherals() |> list_to_sync_cmds()} end),
|
||||
Task.Supervisor.async_nolink(pid, fn -> {PinBinding, HTTP.pin_bindings() |> list_to_sync_cmds()} end),
|
||||
Task.Supervisor.async_nolink(pid, fn -> {Point, HTTP.points() |> list_to_sync_cmds()} end),
|
||||
|
@ -52,9 +59,7 @@ defmodule Farmbot.OS.IOLayer.Sync do
|
|||
end
|
||||
|
||||
def to_sync_cmd(%kind{} = data) do
|
||||
kind = Module.split(kind)
|
||||
|> List.last()
|
||||
|
||||
kind = Module.split(kind) |> List.last()
|
||||
Farmbot.Asset.new_sync_cmd(data.id, kind, data)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -12,7 +12,8 @@ defmodule Farmbot.OS do
|
|||
{Farmbot.Platform.Supervisor, []},
|
||||
{Farmbot.System.UpdateTimer, []},
|
||||
{Farmbot.System.ExtStart, []},
|
||||
{Farmbot.EasterEggs, [] },
|
||||
{Farmbot.EasterEggs, []},
|
||||
{Farmbot.FarmwareMigration, []}
|
||||
]
|
||||
opts = [strategy: :one_for_one, name: __MODULE__]
|
||||
Supervisor.start_link(children, opts)
|
||||
|
|
|
@ -2,16 +2,31 @@ defmodule Farmbot.FarmwareMigration do
|
|||
# TODO(Connor) 2018-08-14 Delete this after 6.5.0 is released
|
||||
import Farmbot.Config, only: [get_config_value: 3, update_config_value: 4]
|
||||
require Farmbot.Logger
|
||||
alias Farmbot.CeleryScript.AST
|
||||
alias Farmbot.Asset.{FarmwareEnv, FarmwareInstallation}
|
||||
|
||||
@doc false
|
||||
def child_spec(_) do
|
||||
%{
|
||||
id: __MODULE__,
|
||||
start: {__MODULE__, :migrate, []},
|
||||
type: :worker,
|
||||
restart: :transient,
|
||||
shutdown: 500
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
@data_path Application.get_env(:farmbot_ext, :data_path)
|
||||
@farmware_dir Path.join(@data_path, "farmware")
|
||||
|
||||
def migrate do
|
||||
File.mkdir_p(@farmware_dir)
|
||||
if get_config_value(:bool, "settings", "firmware_needs_migration") do
|
||||
Farmbot.Logger.busy 1, "Starting Farmware migration."
|
||||
migrate_user_env()
|
||||
migrate_farmware_installations()
|
||||
update_config_value(:bool, "settings", "firmware_needs_migration", false)
|
||||
Farmbot.Logger.success 1, "Farmware migrated to the API."
|
||||
else
|
||||
Farmbot.Logger.debug 3, "Farmware has already been migrated."
|
||||
end
|
||||
|
@ -27,30 +42,35 @@ defmodule Farmbot.FarmwareMigration do
|
|||
LEFT JOIN string_values sv on sv.id == c.string_value_id
|
||||
WHERE g.group_name == "settings"
|
||||
"""
|
||||
%{rows: [[value]]} = Ecto.Adapters.SQL.query!(Farmbot.Config.Repo, qry, [])
|
||||
%{rows: [[value]]} = Ecto.Adapters.SQL.query!(Farmbot.Config.Repo, full_qry, [])
|
||||
|
||||
Ecto.Adapters.SQL.query!(Farmbot.System.ConfigStorage, qry, [])
|
||||
|
||||
data = Farmbot.JSON.decode!(value)
|
||||
pairs = Enum.map(data, fn({key, value}) ->
|
||||
%AST{kind: :pair, args: %{key: key, value: value}, body: []}
|
||||
value
|
||||
|> Farmbot.JSON.decode!()
|
||||
|> Enum.map(fn({key, val}) ->
|
||||
%FarmwareEnv{key: key, value: val}
|
||||
end)
|
||||
body = %AST{kind: :set_user_env, args: %{}, body: pairs}
|
||||
rpc = %AST{kind: :rpc_request, args: %{label: "migrate_user_env"}, body: body}
|
||||
Farmbot.Core.CeleryScript.rpc_request(rpc, &log_results/1)
|
||||
|> Enum.each(fn(env) ->
|
||||
case Farmbot.HTTP.new_farmware_env(env) do
|
||||
{:ok, _} ->
|
||||
Farmbot.Logger.success 1, "migration task: migrate_user_env '#{env.key}' completed."
|
||||
{:error, _} ->
|
||||
Farmbot.Logger.error 1, "migration task: migrate_user_env: '#{env.key}' failed."
|
||||
end
|
||||
end)
|
||||
|
||||
update_config_value(:string, "settings", "user_env", nil)
|
||||
end
|
||||
|
||||
def migrate_farmware_installations do
|
||||
# Migrate first party stuff.
|
||||
qry = "SELECT manifests FROM farmware_repositories"
|
||||
%{rows: rows} = Ecto.Adapters.SQL.query!(Farmbot.Config, qry, [])
|
||||
%{rows: rows} = Ecto.Adapters.SQL.query!(Farmbot.Config.Repo, qry, [])
|
||||
|
||||
repos = Enum.map(rows, &Farmbot.JSON.decode/1)
|
||||
migrated = repos |> Enum.map(&migrate_repo/1) |> List.flatten()
|
||||
|
||||
drop_qry = "DROP TABLE [IF EXISTS] farmware_repositories"
|
||||
Ecto.Adapters.SQL.query!(Farmbot.Config, qry, [])
|
||||
Ecto.Adapters.SQL.query!(Farmbot.Config.Repo, qry, [])
|
||||
|
||||
# Migrate installed farmwares.
|
||||
@farmware_dir
|
||||
|
@ -65,11 +85,11 @@ defmodule Farmbot.FarmwareMigration do
|
|||
end
|
||||
|
||||
def migrate_repo(list, acc \\ [])
|
||||
def migrate_repo([]), do: :ok
|
||||
def migrate_repo([], acc), do: Enum.reverse(acc)
|
||||
def migrate_repo([%{"manifest" => url, "name" => name} | rest], acc) do
|
||||
first_party? = match?("https://raw.githubusercontent.com/FarmBot-Labs/farmware_manifests/master/" <> _, url)
|
||||
data = Farmbot.JSON.encode(%{first_party: first_party?, url: url})
|
||||
case Farmbot.HTTP.post("/api/farmware_installations/", data) do
|
||||
data = %FarmwareInstallation{url: url, first_party: first_party?}
|
||||
case Farmbot.HTTP.new_farmware_installation(data) do
|
||||
{:ok, _} ->
|
||||
Farmbot.Logger.success 1, "migration task: migrate_farmware '#{name}' completed."
|
||||
{:error, _} ->
|
||||
|
@ -77,13 +97,4 @@ defmodule Farmbot.FarmwareMigration do
|
|||
end
|
||||
migrate_repo(rest, [name | acc])
|
||||
end
|
||||
|
||||
defp log_results(%AST{kind: :rpc_ok, args: %{label: label}}) do
|
||||
Farmbot.Logger.success 1, "migration task: #{label} completed."
|
||||
end
|
||||
|
||||
defp log_results(%AST{kind: :rpc_error, args: %{label: label}, body: [expl]}) do
|
||||
%AST{kind: :explanation, args: %{message: message}} = message
|
||||
Farmbot.Logger.error 1, "migration task: #{label} failed: #{message}"
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,6 +2,7 @@ defmodule Farmbot.System do
|
|||
@moduledoc """
|
||||
Common functionality that should be implemented by a system
|
||||
"""
|
||||
require Farmbot.Logger
|
||||
|
||||
require Farmbot.Logger
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@ defmodule Farmbot.Target.Bootstrap.Configurator.Router do
|
|||
end
|
||||
|
||||
@version Farmbot.Project.version()
|
||||
@data_path Application.get_env(:farmbot_ext, :data_path)
|
||||
@log_db Application.get_env(:logger_backend_ecto, LoggerBackendEcto.Repo)[:database]
|
||||
@log_db || Mix.raise("LoggerBackendEcto probably not configured properly.")
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@ defmodule Farmbot.Target.Network.TzdataTask do
|
|||
@fb_data_dir Path.join(Application.get_env(:farmbot_ext, :data_path), "tmp_downloads")
|
||||
@timer_ms round(1.2e+6) # 20 minutes
|
||||
|
||||
def start_link(_, _) do
|
||||
GenServer.start_link(__MODULE__, [], [name: __MODULE__])
|
||||
def start_link(args) do
|
||||
GenServer.start_link(__MODULE__, args, [name: __MODULE__])
|
||||
end
|
||||
|
||||
def init([]) do
|
||||
|
|
Loading…
Reference in New Issue