start to bundle arduino firmware with os
parent
735124eb86
commit
157770fa2e
|
@ -35,3 +35,4 @@ _images
|
||||||
Makefile
|
Makefile
|
||||||
release-*
|
release-*
|
||||||
dump.rdb
|
dump.rdb
|
||||||
|
#priv/firmware.hex
|
||||||
|
|
35
blah.exs
35
blah.exs
|
@ -1,35 +0,0 @@
|
||||||
defmodule F do
|
|
||||||
require Logger
|
|
||||||
@path "/tmp/logs.txt"
|
|
||||||
|
|
||||||
def blah(count) when count > 10000 do
|
|
||||||
print()
|
|
||||||
end
|
|
||||||
|
|
||||||
def blah(count \\ 0) do
|
|
||||||
Logger.debug random_number()
|
|
||||||
blah(count + 1)
|
|
||||||
end
|
|
||||||
|
|
||||||
def print do
|
|
||||||
f = case File.stat(@path) do
|
|
||||||
{:ok, f} -> f
|
|
||||||
_ ->
|
|
||||||
seed()
|
|
||||||
print()
|
|
||||||
end
|
|
||||||
if f.size > 52000, do: Logger.warn "File is too big!"
|
|
||||||
blah = File.read! @path
|
|
||||||
[rhead | _rest] = String.split(blah, "\r\n")
|
|
||||||
Logger.debug "File size is: #{f.size}"
|
|
||||||
Logger.debug "First line is: #{rhead}"
|
|
||||||
end
|
|
||||||
|
|
||||||
def random_number do
|
|
||||||
:rand.uniform(:os.system_time)
|
|
||||||
end
|
|
||||||
|
|
||||||
def seed do
|
|
||||||
for i <- 0..50, do: Logger.debug "Seeding: #{i}"
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -14,7 +14,6 @@ defmodule Farmbot.BotState.Configuration do
|
||||||
configuration: %{
|
configuration: %{
|
||||||
user_env: %{},
|
user_env: %{},
|
||||||
os_auto_update: false,
|
os_auto_update: false,
|
||||||
fw_auto_update: false,
|
|
||||||
steps_per_mm_x: 10,
|
steps_per_mm_x: 10,
|
||||||
steps_per_mm_y: 10,
|
steps_per_mm_y: 10,
|
||||||
steps_per_mm_z: 50,
|
steps_per_mm_z: 50,
|
||||||
|
@ -46,7 +45,6 @@ defmodule Farmbot.BotState.Configuration do
|
||||||
configuration: %{
|
configuration: %{
|
||||||
user_env: map,
|
user_env: map,
|
||||||
os_auto_update: boolean,
|
os_auto_update: boolean,
|
||||||
fw_auto_update: boolean,
|
|
||||||
steps_per_mm_x: integer,
|
steps_per_mm_x: integer,
|
||||||
steps_per_mm_y: integer,
|
steps_per_mm_y: integer,
|
||||||
steps_per_mm_z: integer,
|
steps_per_mm_z: integer,
|
||||||
|
@ -73,7 +71,6 @@ defmodule Farmbot.BotState.Configuration do
|
||||||
}
|
}
|
||||||
{:ok, user_env} = get_config("user_env")
|
{:ok, user_env} = get_config("user_env")
|
||||||
{:ok, os_a_u} = get_config("os_auto_update")
|
{:ok, os_a_u} = get_config("os_auto_update")
|
||||||
{:ok, fw_a_u} = get_config("fw_auto_update")
|
|
||||||
{:ok, spm_x} = get_config("steps_per_mm_x")
|
{:ok, spm_x} = get_config("steps_per_mm_x")
|
||||||
{:ok, spm_y} = get_config("steps_per_mm_y")
|
{:ok, spm_y} = get_config("steps_per_mm_y")
|
||||||
{:ok, spm_z} = get_config("steps_per_mm_z")
|
{:ok, spm_z} = get_config("steps_per_mm_z")
|
||||||
|
@ -84,7 +81,6 @@ defmodule Farmbot.BotState.Configuration do
|
||||||
%State{initial | configuration: %{
|
%State{initial | configuration: %{
|
||||||
user_env: user_env,
|
user_env: user_env,
|
||||||
os_auto_update: os_a_u,
|
os_auto_update: os_a_u,
|
||||||
fw_auto_update: fw_a_u,
|
|
||||||
steps_per_mm_x: spm_x,
|
steps_per_mm_x: spm_x,
|
||||||
steps_per_mm_y: spm_y,
|
steps_per_mm_y: spm_y,
|
||||||
steps_per_mm_z: spm_z,
|
steps_per_mm_z: spm_z,
|
||||||
|
@ -110,19 +106,6 @@ defmodule Farmbot.BotState.Configuration do
|
||||||
dispatch true, new_state
|
dispatch true, new_state
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_call({:update_config, "fw_auto_update", f_value},
|
|
||||||
_from, %State{} = state) do
|
|
||||||
value = cond do
|
|
||||||
f_value == 1 -> true
|
|
||||||
f_value == 0 -> false
|
|
||||||
is_boolean(f_value) -> f_value
|
|
||||||
end
|
|
||||||
new_config = Map.put(state.configuration, :fw_auto_update, value)
|
|
||||||
new_state = %State{state | configuration: new_config}
|
|
||||||
put_config("fw_auto_update", value)
|
|
||||||
dispatch true, new_state
|
|
||||||
end
|
|
||||||
|
|
||||||
def handle_call({:update_config, "steps_per_mm_x", val}, _, state) do
|
def handle_call({:update_config, "steps_per_mm_x", val}, _, state) do
|
||||||
config = state.configuration
|
config = state.configuration
|
||||||
new_config = %{config | steps_per_mm_x: val}
|
new_config = %{config | steps_per_mm_x: val}
|
||||||
|
|
|
@ -202,6 +202,9 @@ defmodule Farmbot.CeleryScript.Command do
|
||||||
@spec pairs_to_tuples([pair]) :: [tuple]
|
@spec pairs_to_tuples([pair]) :: [tuple]
|
||||||
def pairs_to_tuples(config_pairs) do
|
def pairs_to_tuples(config_pairs) do
|
||||||
Enum.map(config_pairs, fn(%Ast{} = thing) ->
|
Enum.map(config_pairs, fn(%Ast{} = thing) ->
|
||||||
|
if thing.args.label == nil do
|
||||||
|
Logger.error("FINDME: #{inspect config_pairs}")
|
||||||
|
end
|
||||||
{thing.args.label, thing.args.value}
|
{thing.args.label, thing.args.value}
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
@ -469,8 +472,8 @@ defmodule Farmbot.CeleryScript.Command do
|
||||||
def check_updates(%{package: package}, []) do
|
def check_updates(%{package: package}, []) do
|
||||||
case package do
|
case package do
|
||||||
"arduino_firmware" ->
|
"arduino_firmware" ->
|
||||||
# TODO(Connor): Move this, and its contents somewhere else
|
Logger.warn "Arduino Firmware is now coupled to farmbot_os and can't " <>
|
||||||
Farmbot.Updates.Handler.check_and_download_updates(:fw)
|
"updated individually."
|
||||||
"farmbot_os" ->
|
"farmbot_os" ->
|
||||||
Farmbot.System.Updates.check_and_download_updates()
|
Farmbot.System.Updates.check_and_download_updates()
|
||||||
|
|
||||||
|
|
|
@ -11,9 +11,9 @@ defmodule Farmbot.Configurator.Router do
|
||||||
# this is so we can serve the bundle.js file.
|
# this is so we can serve the bundle.js file.
|
||||||
plug Plug.Static, at: "/", from: :farmbot
|
plug Plug.Static, at: "/", from: :farmbot
|
||||||
plug Plug.Static, at: "/image", from: "/tmp/images", gzip: false
|
plug Plug.Static, at: "/image", from: "/tmp/images", gzip: false
|
||||||
plug Plug.Parsers, parsers: [:urlencoded, :multipart], length: 111409842
|
|
||||||
plug Plug.Parsers, parsers: [:urlencoded, :json],
|
plug Plug.Parsers, parsers: [:urlencoded, :json],
|
||||||
pass: ["text/*"],
|
pass: ["*/*"],
|
||||||
json_decoder: Poison
|
json_decoder: Poison
|
||||||
plug :match
|
plug :match
|
||||||
plug :dispatch
|
plug :dispatch
|
||||||
|
@ -21,9 +21,7 @@ defmodule Farmbot.Configurator.Router do
|
||||||
|
|
||||||
target = Mix.Project.config[:target]
|
target = Mix.Project.config[:target]
|
||||||
|
|
||||||
if Mix.env == :dev do
|
if Mix.env == :dev, do: use Plug.Debugger, otp_app: :farmbot
|
||||||
use Plug.Debugger, otp_app: :farmbot
|
|
||||||
end
|
|
||||||
|
|
||||||
get "/image/latest" do
|
get "/image/latest" do
|
||||||
list_images = fn() ->
|
list_images = fn() ->
|
||||||
|
@ -69,24 +67,23 @@ defmodule Farmbot.Configurator.Router do
|
||||||
|
|
||||||
post "/api/config" do
|
post "/api/config" do
|
||||||
Logger.info ">> router got config json"
|
Logger.info ">> router got config json"
|
||||||
{:ok, body, _} = read_body(conn)
|
{:ok, _body, conn} = read_body(conn)
|
||||||
rbody = Poison.decode!(body)
|
ConfigStorage.replace_config_file(conn.body_params)
|
||||||
# TODO THIS NEEDS SOME HARD CHECKING. PROBABLY IN THE CONFIG STORAGE MODULE
|
conn |> send_resp(200, "OK")
|
||||||
ConfigStorage.replace_config_file(rbody)
|
|
||||||
conn |> send_resp(200,body)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
post "/api/config/creds" do
|
post "/api/config/creds" do
|
||||||
Logger.info ">> router got credentials"
|
Logger.info ">> router got credentials"
|
||||||
{:ok, body, _} = read_body(conn)
|
{:ok, _body, conn} = read_body(conn)
|
||||||
%{"email" => email,"pass" => pass,"server" => server} = Poison.decode!(body)
|
|
||||||
|
%{"email" => email,"pass" => pass,"server" => server} = conn.body_params
|
||||||
Farmbot.Auth.interim(email, pass, server)
|
Farmbot.Auth.interim(email, pass, server)
|
||||||
conn |> send_resp(200, "ok")
|
conn |> send_resp(200, "OK")
|
||||||
end
|
end
|
||||||
|
|
||||||
post "/api/network/scan" do
|
post "/api/network/scan" do
|
||||||
{:ok, body, _} = read_body(conn)
|
{:ok, _body, conn} = read_body(conn)
|
||||||
%{"iface" => iface} = Poison.decode!(body)
|
%{"iface" => iface} = conn.body_params
|
||||||
scan = NetMan.scan(iface)
|
scan = NetMan.scan(iface)
|
||||||
case scan do
|
case scan do
|
||||||
{:error, reason} -> conn |> send_resp(500, "could not scan: #{inspect reason}")
|
{:error, reason} -> conn |> send_resp(500, "could not scan: #{inspect reason}")
|
||||||
|
@ -147,6 +144,28 @@ defmodule Farmbot.Configurator.Router do
|
||||||
conn |> send_resp(200, json)
|
conn |> send_resp(200, json)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
post "/api/flash_firmware" do
|
||||||
|
"#{:code.priv_dir(:farmbot)}/firmware.hex" |> handle_arduino(conn)
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/firmware/upload" do
|
||||||
|
html = ~s"""
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<p>
|
||||||
|
Upload a FarmbotOS Firmware file (.fw) or a Arduino Firmware file (.hex)
|
||||||
|
</p>
|
||||||
|
<form action="/api/upload_firmware" method="post" enctype="multipart/form-data" accept="*">
|
||||||
|
<input type="file" name="firmware" id="fileupload">
|
||||||
|
<input type="submit" value="submit">
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
"""
|
||||||
|
conn |> send_resp(200, html)
|
||||||
|
end
|
||||||
|
|
||||||
|
plug Plug.Parsers, parsers: [:urlencoded, :multipart], length: 111409842
|
||||||
post "/api/upload_firmware" do
|
post "/api/upload_firmware" do
|
||||||
{:ok, _body, conn} = Plug.Conn.read_body(conn)
|
{:ok, _body, conn} = Plug.Conn.read_body(conn)
|
||||||
upload = conn.body_params["firmware"]
|
upload = conn.body_params["firmware"]
|
||||||
|
@ -163,13 +182,21 @@ defmodule Farmbot.Configurator.Router do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# anything that doesn't match a rest end point gets the index.
|
||||||
|
match _, do: conn |> send_resp(404, "not found")
|
||||||
|
|
||||||
|
@spec make_html :: binary
|
||||||
|
defp make_html do
|
||||||
|
"#{:code.priv_dir(:farmbot)}/static/index.html" |> File.read!
|
||||||
|
end
|
||||||
|
|
||||||
defp handle_arduino(file, conn) do
|
defp handle_arduino(file, conn) do
|
||||||
errrm = fn(blerp) ->
|
errrm = fn(blerp) ->
|
||||||
receive do
|
receive do
|
||||||
:done ->
|
:done ->
|
||||||
blerp |> send_resp(200, "OK")
|
blerp |> send_resp(200, "OK")
|
||||||
{:error, reason} ->
|
{:error, reason} ->
|
||||||
blerp |> send_resp(400, IO.inspect (reason))
|
blerp |> send_resp(400, IO.inspect(reason))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -191,6 +218,7 @@ defmodule Farmbot.Configurator.Router do
|
||||||
errrm.(conn)
|
errrm.(conn)
|
||||||
_ ->
|
_ ->
|
||||||
Logger.warn "Please only have one serial device when updating firmware"
|
Logger.warn "Please only have one serial device when updating firmware"
|
||||||
|
conn |> send_resp(200, "OK")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -209,30 +237,4 @@ defmodule Farmbot.Configurator.Router do
|
||||||
else
|
else
|
||||||
defp handle_os(_file, conn), do: conn |> send_resp(200, "OK")
|
defp handle_os(_file, conn), do: conn |> send_resp(200, "OK")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
get "/firmware/upload" do
|
|
||||||
html = ~s"""
|
|
||||||
<html>
|
|
||||||
<body>
|
|
||||||
<p>
|
|
||||||
Upload a FarmbotOS Firmware file (.fw) or a Arduino Firmware file (.hex)
|
|
||||||
</p>
|
|
||||||
<form action="/api/upload_firmware" method="post" enctype="multipart/form-data" accept="*">
|
|
||||||
<input type="file" name="firmware" id="fileupload">
|
|
||||||
<input type="submit" value="submit">
|
|
||||||
</form>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
"""
|
|
||||||
conn |> send_resp(200, html)
|
|
||||||
end
|
|
||||||
|
|
||||||
# anything that doesn't match a rest end point gets the index.
|
|
||||||
match _, do: conn |> send_resp(404, "not found")
|
|
||||||
|
|
||||||
@spec make_html :: binary
|
|
||||||
defp make_html do
|
|
||||||
"#{:code.priv_dir(:farmbot)}/static/index.html" |> File.read!
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -160,10 +160,14 @@ defmodule Farmbot.Serial.Gcode.Parser do
|
||||||
def parse_param("21"), do: :movement_invert_endpoints_x
|
def parse_param("21"), do: :movement_invert_endpoints_x
|
||||||
def parse_param("22"), do: :movement_invert_endpoints_y
|
def parse_param("22"), do: :movement_invert_endpoints_y
|
||||||
def parse_param("23"), do: :movement_invert_endpoints_z
|
def parse_param("23"), do: :movement_invert_endpoints_z
|
||||||
|
def parse_param("25"), do: :movement_enable_endpoints_x
|
||||||
|
def parse_param("26"), do: :movement_enable_endpoints_y
|
||||||
|
def parse_param("27"), do: :movement_enable_endpoints_z
|
||||||
def parse_param("31"), do: :movement_invert_motor_x
|
def parse_param("31"), do: :movement_invert_motor_x
|
||||||
def parse_param("32"), do: :movement_invert_motor_y
|
def parse_param("32"), do: :movement_invert_motor_y
|
||||||
def parse_param("33"), do: :movement_invert_motor_z
|
def parse_param("33"), do: :movement_invert_motor_z
|
||||||
def parse_param("36"), do: :moevment_secondary_motor_x
|
def parse_param("36"), do: :moevment_secondary_motor_x
|
||||||
|
def parse_param("37"), do: :movement_secondary_motor_invert_x
|
||||||
def parse_param("41"), do: :movement_steps_acc_dec_x
|
def parse_param("41"), do: :movement_steps_acc_dec_x
|
||||||
def parse_param("42"), do: :movement_steps_acc_dec_y
|
def parse_param("42"), do: :movement_steps_acc_dec_y
|
||||||
def parse_param("43"), do: :movement_steps_acc_dec_z
|
def parse_param("43"), do: :movement_steps_acc_dec_z
|
||||||
|
@ -217,7 +221,11 @@ defmodule Farmbot.Serial.Gcode.Parser do
|
||||||
def parse_param(:movement_invert_motor_x), do: 31
|
def parse_param(:movement_invert_motor_x), do: 31
|
||||||
def parse_param(:movement_invert_motor_y), do: 32
|
def parse_param(:movement_invert_motor_y), do: 32
|
||||||
def parse_param(:movement_invert_motor_z), do: 33
|
def parse_param(:movement_invert_motor_z), do: 33
|
||||||
|
def parse_param(:movement_enable_endpoints_x), do: 25
|
||||||
|
def parse_param(:movement_enable_endpoints_y), do: 26
|
||||||
|
def parse_param(:movement_enable_endpoints_z), do: 27
|
||||||
def parse_param(:moevment_secondary_motor_x), do: 36
|
def parse_param(:moevment_secondary_motor_x), do: 36
|
||||||
|
def parse_param(:movement_secondary_motor_invert_x), do: 37
|
||||||
def parse_param(:movement_steps_acc_dec_x), do: 41
|
def parse_param(:movement_steps_acc_dec_x), do: 41
|
||||||
def parse_param(:movement_steps_acc_dec_y), do: 42
|
def parse_param(:movement_steps_acc_dec_y), do: 42
|
||||||
def parse_param(:movement_steps_acc_dec_z), do: 43
|
def parse_param(:movement_steps_acc_dec_z), do: 43
|
||||||
|
@ -260,6 +268,10 @@ defmodule Farmbot.Serial.Gcode.Parser do
|
||||||
def parse_param(param_string) when is_bitstring(param_string),
|
def parse_param(param_string) when is_bitstring(param_string),
|
||||||
do: param_string |> String.to_atom |> parse_param
|
do: param_string |> String.to_atom |> parse_param
|
||||||
|
|
||||||
def parse_param(_), do: nil
|
def parse_param(uhh) do
|
||||||
|
require Logger
|
||||||
|
Logger.error("LOOK AT ME IM IMPORTANT: #{inspect uhh}")
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -127,6 +127,8 @@ defmodule Farmbot.Serial.Handler do
|
||||||
state = %{tty: tty, nerves: nerves, queue: :queue.new(), current: nil}
|
state = %{tty: tty, nerves: nerves, queue: :queue.new(), current: nil}
|
||||||
{:ok, state}
|
{:ok, state}
|
||||||
else
|
else
|
||||||
|
Logger.warn "Handshake failed!"
|
||||||
|
deregister()
|
||||||
# if we cant handshake, kill the previous Nerves
|
# if we cant handshake, kill the previous Nerves
|
||||||
GenServer.stop(nerves, :normal)
|
GenServer.stop(nerves, :normal)
|
||||||
:ignore
|
:ignore
|
||||||
|
@ -166,6 +168,7 @@ defmodule Farmbot.Serial.Handler do
|
||||||
# Recieved happens before our actual response, just go to the next one
|
# Recieved happens before our actual response, just go to the next one
|
||||||
# if it exists
|
# if it exists
|
||||||
{:nerves_uart, ^tty, "R01" <> _} -> do_handshake(nerves, tty, handshake)
|
{:nerves_uart, ^tty, "R01" <> _} -> do_handshake(nerves, tty, handshake)
|
||||||
|
{:nerves_uart, ^tty, "Command:" <> _} -> do_handshake(nerves, tty, handshake)
|
||||||
|
|
||||||
# This COULD be our handshake. Check it.
|
# This COULD be our handshake. Check it.
|
||||||
{:nerves_uart, ^tty, str} ->
|
{:nerves_uart, ^tty, str} ->
|
||||||
|
@ -196,6 +199,13 @@ defmodule Farmbot.Serial.Handler do
|
||||||
|
|
||||||
@spec update_default(pid) :: :ok | no_return
|
@spec update_default(pid) :: :ok | no_return
|
||||||
defp update_default(pid) do
|
defp update_default(pid) do
|
||||||
|
deregister()
|
||||||
|
# Either way, register this pid as the new one.
|
||||||
|
Process.register(pid, __MODULE__)
|
||||||
|
end
|
||||||
|
|
||||||
|
@spec deregister :: no_return
|
||||||
|
defp deregister do
|
||||||
# lookup the old default pid
|
# lookup the old default pid
|
||||||
old_pid = Process.whereis(__MODULE__)
|
old_pid = Process.whereis(__MODULE__)
|
||||||
|
|
||||||
|
@ -204,9 +214,6 @@ defmodule Farmbot.Serial.Handler do
|
||||||
Logger.debug "Deregistering #{inspect old_pid} from default Serial Handler"
|
Logger.debug "Deregistering #{inspect old_pid} from default Serial Handler"
|
||||||
Process.unregister(__MODULE__)
|
Process.unregister(__MODULE__)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Either way, register this pid as the new one.
|
|
||||||
Process.register(pid, __MODULE__)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_call(:get_state, _, state), do: {:reply, state, state}
|
def handle_call(:get_state, _, state), do: {:reply, state, state}
|
||||||
|
@ -371,12 +378,12 @@ defmodule Farmbot.Serial.Handler do
|
||||||
end
|
end
|
||||||
|
|
||||||
defp handle_gcode({:unhandled_gcode, code}, state) do
|
defp handle_gcode({:unhandled_gcode, code}, state) do
|
||||||
Logger.warn ">> got an unhandled gcode! #{code}"
|
Logger.warn ">> got an misc gcode #{code}"
|
||||||
{:noreply, state}
|
{:noreply, state}
|
||||||
end
|
end
|
||||||
|
|
||||||
defp handle_gcode(parsed, state) do
|
defp handle_gcode(parsed, state) do
|
||||||
Logger.warn "Unhandled GCODE: #{inspect parsed}"
|
Logger.warn "Unhandled message: #{inspect parsed}"
|
||||||
{:noreply, state}
|
{:noreply, state}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -395,11 +402,13 @@ defmodule Farmbot.Serial.Handler do
|
||||||
"-Uflash:w:#{hex_file}:i"]
|
"-Uflash:w:#{hex_file}:i"]
|
||||||
|
|
||||||
"avrdude" |> System.cmd(params) |> log(pid)
|
"avrdude" |> System.cmd(params) |> log(pid)
|
||||||
|
handler = Process.whereis(__MODULE__)
|
||||||
|
if handler, do: spawn fn() -> GenServer.stop(handler, :normal) end
|
||||||
|
Farmbot.Serial.Supervisor.open_ttys(Farmbot.Serial.Supervisor, [tty])
|
||||||
end
|
end
|
||||||
|
|
||||||
defp log({_, 0}, pid) do
|
defp log({_, 0}, pid) do
|
||||||
Logger.debug "FLASHED FIRMWARE!"
|
Logger.debug "FLASHED FIRMWARE!"
|
||||||
Farmbot.CeleryScript.Command.reboot(%{}, [])
|
|
||||||
send pid, :done
|
send pid, :done
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -29,12 +29,10 @@ defmodule Farmbot.Serial.Supervisor do
|
||||||
supervise(children, strategy: :one_for_all)
|
supervise(children, strategy: :one_for_all)
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec open_ttys(atom | pid) :: :ok | no_return
|
@spec open_ttys(atom | pid, [binary]) :: :ok | no_return
|
||||||
def open_ttys(supervisor) do
|
def open_ttys(supervisor, ttys \\ nil) do
|
||||||
UART.enumerate()
|
blah = ttys || UART.enumerate() |> Map.drop(["ttyS0","ttyAMA0"]) |> Map.keys
|
||||||
|> Map.drop(["ttyS0","ttyAMA0"])
|
blah |> try_open(supervisor)
|
||||||
|> Map.keys
|
|
||||||
|> try_open(supervisor)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec try_open([binary], atom | pid) :: :ok | no_return
|
@spec try_open([binary], atom | pid) :: :ok | no_return
|
||||||
|
|
|
@ -1,158 +0,0 @@
|
||||||
defmodule Farmbot.Updates.Handler do
|
|
||||||
alias Farmbot.Auth
|
|
||||||
alias Farmbot.BotState
|
|
||||||
require Logger
|
|
||||||
#TODO(connor): please refactor this into a target specific module.
|
|
||||||
|
|
||||||
@moduledoc """
|
|
||||||
Bunch of stuff to do updates.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@type update_output
|
|
||||||
:: {:update, String.t | nil}
|
|
||||||
| {:error, String.t | atom}
|
|
||||||
| :no_updates
|
|
||||||
|
|
||||||
@doc """
|
|
||||||
Another shortcut for the shorcut
|
|
||||||
"""
|
|
||||||
@spec check_and_download_updates(:os | :fw)
|
|
||||||
:: :ok | {:error, atom} | :no_updates
|
|
||||||
def check_and_download_updates(something) do
|
|
||||||
Logger.info ">> Is checking for updates: #{inspect something}"
|
|
||||||
case check_updates(something) do
|
|
||||||
{:error, reason} ->
|
|
||||||
Logger.info """
|
|
||||||
>> encountered an error checking for updates: #{inspect reason}.
|
|
||||||
"""
|
|
||||||
{:update, url} ->
|
|
||||||
install_update(something, url)
|
|
||||||
:no_updates ->
|
|
||||||
Logger.info(">> is already on the latest operating system version.",
|
|
||||||
channels: [:toast], type: :success)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
@spec install_update(:fw, String.t) :: no_return
|
|
||||||
defp install_update(:fw, url) do
|
|
||||||
Logger.info ">> found a firmware update!"
|
|
||||||
File.rm("/tmp/update.hex")
|
|
||||||
file = Downloader.run(url, "/tmp/update.hex")
|
|
||||||
Logger.info """
|
|
||||||
>> is installing a firmware update. I may act weird for a moment
|
|
||||||
""",
|
|
||||||
channels: [:toast]
|
|
||||||
if Farmbot.Serial.Handler.available? do
|
|
||||||
GenServer.cast(Farmbot.Serial.Handler, {:update_fw, file, self()})
|
|
||||||
receive do
|
|
||||||
:done ->
|
|
||||||
Logger.info ">> is done installing a firmware update!", type: :success,
|
|
||||||
channels: [:toast]
|
|
||||||
{:error, reason} ->
|
|
||||||
Logger.error """
|
|
||||||
>> encountered an error installing firmware update!: #{inspect reason}
|
|
||||||
""",
|
|
||||||
channels: [:toast]
|
|
||||||
end
|
|
||||||
else
|
|
||||||
Logger.debug "doing some magic..."
|
|
||||||
herp = Nerves.UART.enumerate()
|
|
||||||
|> Map.drop(["ttyS0","ttyAMA0"])
|
|
||||||
|> Map.keys
|
|
||||||
case herp do
|
|
||||||
[tty] ->
|
|
||||||
Logger.debug "magic complete!"
|
|
||||||
Farmbot.Serial.Handler.flash_firmware(tty, file, self())
|
|
||||||
_ ->
|
|
||||||
Logger.warn "Please only have one serial device when updating firmware"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
@spec check_updates(any) :: no_return
|
|
||||||
def check_updates(:fw) do
|
|
||||||
with {:ok, token} <- Auth.get_token,
|
|
||||||
do: check_updates(
|
|
||||||
token.unencoded.fw_update_server,
|
|
||||||
BotState.get_fw_version,
|
|
||||||
".hex")
|
|
||||||
end
|
|
||||||
|
|
||||||
@doc """
|
|
||||||
Uses Github Release api to check for an update.
|
|
||||||
If there is an update on URL, it returns the asset with the given extension
|
|
||||||
for said update.
|
|
||||||
"""
|
|
||||||
@spec check_updates(String.t, String.t, String.t) :: update_output
|
|
||||||
def check_updates(url, current_version, extension) do
|
|
||||||
resp = HTTPoison.get url, ["User-Agent": "FarmbotOLD"]
|
|
||||||
with {:assets, new_version, assets} <- parse_resp(resp),
|
|
||||||
true <- is_updates?(current_version, new_version),
|
|
||||||
do: get_dl_url(assets, extension)
|
|
||||||
end
|
|
||||||
|
|
||||||
@spec get_dl_url([any,...] | map, String.t)
|
|
||||||
:: {:update, String.t} | {:error, atom}
|
|
||||||
defp get_dl_url(assets, extension)
|
|
||||||
when is_list(assets) do
|
|
||||||
Enum.find_value(assets, {:error, :no_assets},
|
|
||||||
fn asset ->
|
|
||||||
url = get_dl_url(asset)
|
|
||||||
if String.contains?(url, extension) do
|
|
||||||
{:update, url}
|
|
||||||
else
|
|
||||||
nil
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp get_dl_url(asset) when is_map(asset) do
|
|
||||||
Map.get(asset, "browser_download_url")
|
|
||||||
end
|
|
||||||
|
|
||||||
@doc """
|
|
||||||
Checks if two strings are the same lol
|
|
||||||
"""
|
|
||||||
@spec is_updates?(String.t, String.t) :: :no_updates | true
|
|
||||||
def is_updates?(current, new) do
|
|
||||||
if current == new do
|
|
||||||
:no_updates
|
|
||||||
else
|
|
||||||
true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@doc """
|
|
||||||
Parses the httpotion response.
|
|
||||||
"""
|
|
||||||
|
|
||||||
@spec parse_resp(HTTPoison.Response.t)
|
|
||||||
:: {:assets, Strint.t, String.t} | {:error, :bad_resp}
|
|
||||||
def parse_resp(
|
|
||||||
{:ok, %HTTPoison.Response{
|
|
||||||
body: body,
|
|
||||||
status_code: 200}})
|
|
||||||
do
|
|
||||||
json = Poison.decode!(body)
|
|
||||||
"v" <> new_version = Map.get(json, "tag_name")
|
|
||||||
assets = Map.get(json, "assets")
|
|
||||||
{:assets, new_version, assets}
|
|
||||||
end
|
|
||||||
|
|
||||||
def parse_resp(_), do: {:error, :bad_resp}
|
|
||||||
|
|
||||||
def do_update_check do
|
|
||||||
Logger.info ">> is checking for updates."
|
|
||||||
|
|
||||||
# check configuration.
|
|
||||||
case BotState.get_config(:os_auto_update) do
|
|
||||||
true -> Farmbot.System.Updates.check_and_download_updates()
|
|
||||||
_ -> Logger.warn ">> won't check for operating system updates."
|
|
||||||
end
|
|
||||||
|
|
||||||
case BotState.get_config(:fw_auto_update) do
|
|
||||||
true -> check_and_download_updates(:fw)
|
|
||||||
_ -> Logger.warn ">> won't check for firmware updates."
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -6,7 +6,6 @@
|
||||||
"configuration": {
|
"configuration": {
|
||||||
"user_env": {},
|
"user_env": {},
|
||||||
"os_auto_update": false,
|
"os_auto_update": false,
|
||||||
"fw_auto_update": false,
|
|
||||||
"first_party_farmware": true,
|
"first_party_farmware": true,
|
||||||
"steps_per_mm_x": 5,
|
"steps_per_mm_x": 5,
|
||||||
"steps_per_mm_y": 5,
|
"steps_per_mm_y": 5,
|
||||||
|
@ -16,6 +15,7 @@
|
||||||
"distance_mm_z": 800
|
"distance_mm_z": 800
|
||||||
},
|
},
|
||||||
"hardware": {
|
"hardware": {
|
||||||
"params": {}
|
"params": {},
|
||||||
|
"custom_firmware": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ntp": true,
|
"ntp": true,
|
||||||
"ssh": true
|
"ssh": false
|
||||||
},
|
},
|
||||||
"authorization": {
|
"authorization": {
|
||||||
"server": "https://my.farmbot.io"
|
"server": "https://my.farmbot.io"
|
||||||
|
@ -15,7 +15,6 @@
|
||||||
"configuration": {
|
"configuration": {
|
||||||
"user_env": {},
|
"user_env": {},
|
||||||
"os_auto_update": false,
|
"os_auto_update": false,
|
||||||
"fw_auto_update": false,
|
|
||||||
"first_party_farmware": true,
|
"first_party_farmware": true,
|
||||||
"steps_per_mm_x": 5,
|
"steps_per_mm_x": 5,
|
||||||
"steps_per_mm_y": 5,
|
"steps_per_mm_y": 5,
|
||||||
|
@ -25,6 +24,7 @@
|
||||||
"distance_mm_z": 800
|
"distance_mm_z": 800
|
||||||
},
|
},
|
||||||
"hardware": {
|
"hardware": {
|
||||||
"params": {}
|
"params": {},
|
||||||
|
"custom_firmware": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ntp": true,
|
"ntp": true,
|
||||||
"ssh": true
|
"ssh": false
|
||||||
},
|
},
|
||||||
"authorization": {
|
"authorization": {
|
||||||
"server": "https://my.farmbot.io"
|
"server": "https://my.farmbot.io"
|
||||||
|
@ -15,7 +15,6 @@
|
||||||
"configuration": {
|
"configuration": {
|
||||||
"user_env": {},
|
"user_env": {},
|
||||||
"os_auto_update": false,
|
"os_auto_update": false,
|
||||||
"fw_auto_update": false,
|
|
||||||
"first_party_farmware": true,
|
"first_party_farmware": true,
|
||||||
"steps_per_mm_x": 5,
|
"steps_per_mm_x": 5,
|
||||||
"steps_per_mm_y": 5,
|
"steps_per_mm_y": 5,
|
||||||
|
@ -25,6 +24,7 @@
|
||||||
"distance_mm_z": 800
|
"distance_mm_z": 800
|
||||||
},
|
},
|
||||||
"hardware": {
|
"hardware": {
|
||||||
"params": {}
|
"params": {},
|
||||||
|
"custom_firmware": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ntp": true,
|
"ntp": true,
|
||||||
"ssh": true
|
"ssh": false
|
||||||
},
|
},
|
||||||
"authorization": {
|
"authorization": {
|
||||||
"server": "https://my.farmbot.io"
|
"server": "https://my.farmbot.io"
|
||||||
|
@ -22,7 +22,6 @@
|
||||||
"configuration": {
|
"configuration": {
|
||||||
"user_env": {},
|
"user_env": {},
|
||||||
"os_auto_update": false,
|
"os_auto_update": false,
|
||||||
"fw_auto_update": false,
|
|
||||||
"first_party_farmware": true,
|
"first_party_farmware": true,
|
||||||
"steps_per_mm_x": 5,
|
"steps_per_mm_x": 5,
|
||||||
"steps_per_mm_y": 5,
|
"steps_per_mm_y": 5,
|
||||||
|
@ -32,6 +31,7 @@
|
||||||
"distance_mm_z": 800
|
"distance_mm_z": 800
|
||||||
},
|
},
|
||||||
"hardware": {
|
"hardware": {
|
||||||
"params": {}
|
"params": {},
|
||||||
|
"custom_firmware": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,15 @@
|
||||||
|
defmodule DisableSSH do
|
||||||
|
def run(json) do
|
||||||
|
network = json["network"]
|
||||||
|
net_config =
|
||||||
|
if network do
|
||||||
|
# if we have a network config, make ssh key false
|
||||||
|
Map.put(network, "ssh", false)
|
||||||
|
else
|
||||||
|
# if no network, just make it false.
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
%{json | "network" => net_config}
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,7 @@
|
||||||
|
defmodule RemoveArduinoFwUpdates do
|
||||||
|
def run(json) do
|
||||||
|
configuration = json["configuration"]
|
||||||
|
configuration = Map.delete(configuration, "fw_auto_update")
|
||||||
|
%{json | "configuration" => configuration}
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,7 @@
|
||||||
|
defmodule RemoveArduinoFwUpdates do
|
||||||
|
def run(json) do
|
||||||
|
hardware = json["hardware"]
|
||||||
|
hardware = Map.put(hardware, "custom_firmware", false)
|
||||||
|
%{json | "hardware" => hardware}
|
||||||
|
end
|
||||||
|
end
|
|
@ -49,10 +49,6 @@ defmodule Farmbot.BotStateTest do
|
||||||
os_auto_update = Farmbot.BotState.get_config(:os_auto_update)
|
os_auto_update = Farmbot.BotState.get_config(:os_auto_update)
|
||||||
assert(os_auto_update == false)
|
assert(os_auto_update == false)
|
||||||
|
|
||||||
true = Farmbot.BotState.update_config("fw_auto_update", false)
|
|
||||||
fw_auto_update = Farmbot.BotState.get_config(:fw_auto_update)
|
|
||||||
assert(fw_auto_update == false)
|
|
||||||
|
|
||||||
true = Farmbot.BotState.update_config("steps_per_mm_x", 123)
|
true = Farmbot.BotState.update_config("steps_per_mm_x", 123)
|
||||||
true = Farmbot.BotState.update_config("steps_per_mm_y", 456)
|
true = Farmbot.BotState.update_config("steps_per_mm_y", 456)
|
||||||
true = Farmbot.BotState.update_config("steps_per_mm_z", 789)
|
true = Farmbot.BotState.update_config("steps_per_mm_z", 789)
|
||||||
|
|
|
@ -6,10 +6,11 @@ import { observer } from "mobx-react";
|
||||||
interface Props {
|
interface Props {
|
||||||
mobx: MainState;
|
mobx: MainState;
|
||||||
}
|
}
|
||||||
export function AdvancedSettings({mobx}: Props) {
|
export function AdvancedSettings({ mobx }: Props) {
|
||||||
let ssh = false;
|
let ssh = false;
|
||||||
let ntp = false
|
let ntp = false;
|
||||||
let hasNetwork = mobx.configuration.network ? true : false;
|
let hasNetwork = mobx.configuration.network ? true : false;
|
||||||
|
let customFW = false;
|
||||||
|
|
||||||
if (mobx.configuration.network) {
|
if (mobx.configuration.network) {
|
||||||
ssh = mobx.configuration.network.ssh;
|
ssh = mobx.configuration.network.ssh;
|
||||||
|
@ -22,9 +23,20 @@ export function AdvancedSettings({mobx}: Props) {
|
||||||
<label> Factory Reset Your Bot </label>
|
<label> Factory Reset Your Bot </label>
|
||||||
<button type="button" onClick={() => {
|
<button type="button" onClick={() => {
|
||||||
mobx.factoryReset();
|
mobx.factoryReset();
|
||||||
} }> Factory Reset your bot! </button>
|
}}> Factory Reset your bot! </button>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
|
{/* Allow the user to force custom firmware */}
|
||||||
|
<div>
|
||||||
|
<label> Use Custom Arduino Firmware </label>
|
||||||
|
<input type="checkbox"
|
||||||
|
defaultChecked={false}
|
||||||
|
onChange={(event) => {
|
||||||
|
customFW = event.currentTarget.checked;
|
||||||
|
mobx.CustomFW(customFW);
|
||||||
|
}} />
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Allow the user to force network to be enabled */}
|
{/* Allow the user to force network to be enabled */}
|
||||||
<div>
|
<div>
|
||||||
<label> Enable Network</label>
|
<label> Enable Network</label>
|
||||||
|
@ -33,8 +45,7 @@ export function AdvancedSettings({mobx}: Props) {
|
||||||
onChange={(event) => {
|
onChange={(event) => {
|
||||||
mobx.toggleNetwork();
|
mobx.toggleNetwork();
|
||||||
hasNetwork = event.currentTarget.checked;
|
hasNetwork = event.currentTarget.checked;
|
||||||
}
|
}} />
|
||||||
} />
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* hide these settings if we dont have network */}
|
{/* hide these settings if we dont have network */}
|
||||||
|
@ -46,7 +57,7 @@ export function AdvancedSettings({mobx}: Props) {
|
||||||
onChange={(event) => {
|
onChange={(event) => {
|
||||||
let blah = event.currentTarget.checked;
|
let blah = event.currentTarget.checked;
|
||||||
mobx.toggleSSH(blah);
|
mobx.toggleSSH(blah);
|
||||||
} } />
|
}} />
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
{/* NTP */}
|
{/* NTP */}
|
||||||
|
@ -56,10 +67,12 @@ export function AdvancedSettings({mobx}: Props) {
|
||||||
onChange={(event) => {
|
onChange={(event) => {
|
||||||
let blah = event.currentTarget.checked;
|
let blah = event.currentTarget.checked;
|
||||||
mobx.toggleNTP(blah);
|
mobx.toggleNTP(blah);
|
||||||
} } />
|
}} />
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
|
@ -66,11 +66,11 @@ export interface DhcpConfigFileNetIface extends ConfigFileNetIface {
|
||||||
default: "dhcp";
|
default: "dhcp";
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Farmbot's Configuratrion
|
/** Farmbot's Configuratrion
|
||||||
* doing an HTTP get to "/api/config" will give the bots current config.
|
* doing an HTTP get to "/api/config" will give the bots current config.
|
||||||
*/
|
*/
|
||||||
export interface BotConfigFile {
|
export interface BotConfigFile {
|
||||||
/** network false indicates that farmbot will already have network
|
/** network false indicates that farmbot will already have network
|
||||||
* when started.
|
* when started.
|
||||||
*/
|
*/
|
||||||
network: {
|
network: {
|
||||||
|
@ -92,8 +92,6 @@ export interface BotConfigFile {
|
||||||
configuration: {
|
configuration: {
|
||||||
/** auto update the operating system */
|
/** auto update the operating system */
|
||||||
os_auto_update: boolean;
|
os_auto_update: boolean;
|
||||||
/** auto update the arduino firmware */
|
|
||||||
fw_auto_update: boolean;
|
|
||||||
/** steps per milimeter for the arduino firmware */
|
/** steps per milimeter for the arduino firmware */
|
||||||
steps_per_mm: {
|
steps_per_mm: {
|
||||||
x: number;
|
x: number;
|
||||||
|
@ -104,6 +102,7 @@ export interface BotConfigFile {
|
||||||
/** hardware mcu stuff */
|
/** hardware mcu stuff */
|
||||||
hardware: {
|
hardware: {
|
||||||
params: McuParams;
|
params: McuParams;
|
||||||
|
custom_firmware: boolean;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export type LogChannel = "toast";
|
export type LogChannel = "toast";
|
||||||
|
|
|
@ -49,12 +49,12 @@ export class Main extends React.Component<MainProps, FormState> {
|
||||||
showCustomNetworkWidget: false,
|
showCustomNetworkWidget: false,
|
||||||
ssidSelection: {},
|
ssidSelection: {},
|
||||||
customInterface: null,
|
customInterface: null,
|
||||||
connecting: false
|
connecting: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
handleSubmit(event: React.SyntheticEvent<HTMLFormElement>) {
|
async handleSubmit(event: React.SyntheticEvent<HTMLFormElement>) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
let mainState = this.props.mobx;
|
let mainState = this.props.mobx;
|
||||||
let fullFile = mainState.configuration;
|
let fullFile = mainState.configuration;
|
||||||
|
@ -65,8 +65,19 @@ export class Main extends React.Component<MainProps, FormState> {
|
||||||
console.log("server: " + server);
|
console.log("server: " + server);
|
||||||
|
|
||||||
if ((email && pass && server) && this.state.connecting != true) {
|
if ((email && pass && server) && this.state.connecting != true) {
|
||||||
// this.state.connecting = true;
|
|
||||||
this.setState({ connecting: true });
|
this.setState({ connecting: true });
|
||||||
|
|
||||||
|
// try to flash the arduino
|
||||||
|
if (!fullFile.hardware.custom_firmware) {
|
||||||
|
try {
|
||||||
|
await mainState.flashFW();
|
||||||
|
console.log("Firmware Flashed!!!");
|
||||||
|
} catch (_error) {
|
||||||
|
console.error("Firmware failed!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mainState.uploadCreds(email, pass, server)
|
mainState.uploadCreds(email, pass, server)
|
||||||
.then((thing) => {
|
.then((thing) => {
|
||||||
console.log("uploaded web app credentials!");
|
console.log("uploaded web app credentials!");
|
||||||
|
@ -75,6 +86,7 @@ export class Main extends React.Component<MainProps, FormState> {
|
||||||
.catch((thing) => {
|
.catch((thing) => {
|
||||||
console.error("Error uploading web app credentials!")
|
console.error("Error uploading web app credentials!")
|
||||||
});
|
});
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
console.error("Email, Password, or Server is incomplete or already connecting!")
|
console.error("Email, Password, or Server is incomplete or already connecting!")
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -62,10 +62,9 @@ export class MainState {
|
||||||
},
|
},
|
||||||
configuration: {
|
configuration: {
|
||||||
os_auto_update: false,
|
os_auto_update: false,
|
||||||
fw_auto_update: false,
|
|
||||||
steps_per_mm: { x: 500, y: 500, z: 500 }
|
steps_per_mm: { x: 500, y: 500, z: 500 }
|
||||||
},
|
},
|
||||||
hardware: { params: {} }
|
hardware: { params: {}, custom_firmware: false }
|
||||||
};
|
};
|
||||||
|
|
||||||
@observable ssids: string[] = [];
|
@observable ssids: string[] = [];
|
||||||
|
@ -142,6 +141,15 @@ export class MainState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
CustomFW(bool: boolean) {
|
||||||
|
this.configuration.hardware.custom_firmware = bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
flashFW() {
|
||||||
|
return Axios.post("/api/flash_firmware");
|
||||||
|
}
|
||||||
|
|
||||||
enumerateInterfaces() {
|
enumerateInterfaces() {
|
||||||
Axios.get("/api/network/interfaces")
|
Axios.get("/api/network/interfaces")
|
||||||
.then(this.enumerateInterfacesOK.bind(this))
|
.then(this.enumerateInterfacesOK.bind(this))
|
||||||
|
|
Loading…
Reference in New Issue