making progress
parent
b6b3020702
commit
94e3a21970
|
@ -21,14 +21,15 @@ defmodule Farmbot.Bootstrap.Configurator do
|
||||||
"""
|
"""
|
||||||
def start_link(_, opts) do
|
def start_link(_, opts) do
|
||||||
Logger.info "Configuring Farmbot."
|
Logger.info "Configuring Farmbot."
|
||||||
case Supervisor.start_link(__MODULE__, [self()], opts) do
|
sup = Supervisor.start_link(__MODULE__, [self()], opts)
|
||||||
{:ok, pid} ->
|
# case supervisor do
|
||||||
receive do
|
# {:ok, pid} ->
|
||||||
:ok -> stop(pid, :ignore)
|
# receive do
|
||||||
{:error, _reason} = err -> stop(pid, err)
|
# :ok -> stop(pid, :ignore)
|
||||||
end
|
# {:error, _reason} = err -> stop(pid, err)
|
||||||
:ignore -> :ignore
|
# end
|
||||||
end
|
# :ignore -> :ignore
|
||||||
|
# end
|
||||||
end
|
end
|
||||||
|
|
||||||
def init(cb) do
|
def init(cb) do
|
||||||
|
|
|
@ -9,7 +9,7 @@ defmodule Farmbot.Bootstrap.Configurator.HTML do
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc "Render a page in the `priv/templates/page` dir."
|
@doc "Render a page in the `priv/templates/page` dir."
|
||||||
def render(page) do
|
def render(page, conn \\ %{}) do
|
||||||
eval_file("page", [page: page, render: fn -> eval_file("page/#{page}") end])
|
eval_file("page", [page: page, conn: conn, render: fn -> eval_file("page/#{page}") end])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,59 +3,101 @@ defmodule Farmbot.Bootstrap.Configurator.Router do
|
||||||
|
|
||||||
use Plug.Router
|
use Plug.Router
|
||||||
|
|
||||||
|
if Mix.env == :dev do
|
||||||
|
use Plug.Debugger, otp_app: :farmbot
|
||||||
|
end
|
||||||
|
|
||||||
plug Plug.Static, from: {:farmbot, "priv/static"}, at: "/"
|
plug Plug.Static, from: {:farmbot, "priv/static"}, at: "/"
|
||||||
plug Plug.Session, store: :ets, key: "session", table: :session
|
plug Plug.Session, store: :ets, key: "page", table: :session
|
||||||
|
plug Plug.Session, store: :ets, key: "page_complete", table: :session
|
||||||
|
plug Plug.Logger, log: :debug
|
||||||
|
plug Plug.Parsers, parsers: [:urlencoded, :multipart]
|
||||||
plug :match
|
plug :match
|
||||||
plug :dispatch
|
plug :dispatch
|
||||||
|
|
||||||
import Farmbot.Bootstrap.Configurator.HTML
|
import Farmbot.Bootstrap.Configurator.HTML
|
||||||
|
require Logger
|
||||||
|
|
||||||
get "/" do
|
get "/" do
|
||||||
conn = conn |> fetch_session()
|
|
||||||
# session = conn |> get_session("session")
|
|
||||||
conn
|
conn
|
||||||
|> put_session("session", 0)
|
|> fetch_session()
|
||||||
|> send_resp(200, render("page0"))
|
# Reset the page session.
|
||||||
end
|
|> put_session("page_complete", false)
|
||||||
|
# Goto 0.
|
||||||
get "/previous" do
|
|> handle_step(0)
|
||||||
conn = conn |> fetch_session()
|
|
||||||
session = conn |> get_session("session")
|
|
||||||
cond do
|
|
||||||
is_nil(session) ->
|
|
||||||
conn
|
|
||||||
|> put_session("session", 0)
|
|
||||||
|> send_resp(200, render("page0"))
|
|
||||||
is_number(session) ->
|
|
||||||
conn |> handle_step(session - 1)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
get "/next" do
|
get "/next" do
|
||||||
|
# Fetch sessions.
|
||||||
conn = conn |> fetch_session()
|
conn = conn |> fetch_session()
|
||||||
session = conn |> get_session("session")
|
# get the current page.
|
||||||
|
page = conn |> get_session("page")
|
||||||
|
# check if the page is complete.
|
||||||
|
comp = conn |> get_session("page_complete")
|
||||||
|
# Set page complete to false for the next page.
|
||||||
|
conn = conn |> put_session("page_complete", false)
|
||||||
cond do
|
cond do
|
||||||
is_nil(session) ->
|
# if page is complete, and we are actually on a page go to the next page.
|
||||||
conn
|
(comp == true) and (is_number(page)) ->
|
||||||
|> put_session("session", 0)
|
conn |> handle_step(page + 1)
|
||||||
|> send_resp(200, render("page0"))
|
# if we aren't on a page, go back to index.
|
||||||
is_number(session) ->
|
is_nil(page) ->
|
||||||
conn |> handle_step(session + 1)
|
conn |> put_resp_header("location", "/") |> send_resp(302, "/")
|
||||||
|
# Else, just refresh this page.
|
||||||
|
true -> do_render(conn, page)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
post "/next" do
|
||||||
|
conn
|
||||||
|
# Read and store this pages data.
|
||||||
|
|> save_data
|
||||||
|
# Set page to complete.
|
||||||
|
|> put_session("page_complete", true)
|
||||||
|
# GET the next page.
|
||||||
|
|> put_resp_header("location", "/next")
|
||||||
|
|> send_resp(302, "/next")
|
||||||
|
end
|
||||||
|
|
||||||
|
post "/finish" do
|
||||||
|
conn
|
||||||
|
|> save_data()
|
||||||
|
|> send_resp(200, "goodbye.")
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/flash_fw" do
|
||||||
|
Process.sleep(5000)
|
||||||
|
conn |> send_resp(200, "ok")
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/scan_wifi" do
|
||||||
|
conn |> send_resp(200, Poison.encode!(["hello", "world"]))
|
||||||
|
end
|
||||||
|
|
||||||
|
defp save_data(conn) do
|
||||||
|
{:ok, _, conn} = conn |> fetch_session() |> read_body()
|
||||||
|
IO.inspect conn.body_params
|
||||||
|
conn
|
||||||
|
end
|
||||||
|
|
||||||
defp handle_step(conn, num) do
|
defp handle_step(conn, num) do
|
||||||
try do
|
try do
|
||||||
conn
|
conn
|
||||||
|> put_session("session", num)
|
|> put_session("page", num)
|
||||||
|> send_resp(200, render("page#{num}"))
|
|> do_render(num)
|
||||||
rescue
|
rescue
|
||||||
_ ->
|
_ ->
|
||||||
|
Logger.warn "Resetting page."
|
||||||
conn
|
conn
|
||||||
|> put_session("session", 0)
|
|> put_session("page", nil)
|
||||||
|> send_resp(200, render("page0"))
|
|> put_resp_header("location", "/")
|
||||||
|
|> send_resp(302, "/")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp do_render(conn, num) do
|
||||||
|
conn |> send_resp(200, render("page#{num}", conn))
|
||||||
|
end
|
||||||
|
|
||||||
match _, do: send_resp(conn, 404, "Page not found.")
|
match _, do: send_resp(conn, 404, "Page not found.")
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,78 +0,0 @@
|
||||||
defmodule Plug.Session.ETS do
|
|
||||||
@moduledoc """
|
|
||||||
Stores the session in an in-memory ETS table.
|
|
||||||
This store does not create the ETS table; it expects that an
|
|
||||||
existing named table with public properties is passed as an
|
|
||||||
argument.
|
|
||||||
We don't recommend using this store in production as every
|
|
||||||
session will be stored in ETS and never cleaned until you
|
|
||||||
create a task responsible for cleaning up old entries.
|
|
||||||
Also, since the store is in-memory, it means sessions are
|
|
||||||
not shared between servers. If you deploy to more than one
|
|
||||||
machine, using this store is again not recommended.
|
|
||||||
This store, however, can be used as an example for creating
|
|
||||||
custom storages, based on Redis, Memcached, or a database
|
|
||||||
itself.
|
|
||||||
## Options
|
|
||||||
* `:table` - ETS table name (required)
|
|
||||||
For more information on ETS tables, visit the Erlang documentation at
|
|
||||||
http://www.erlang.org/doc/man/ets.html.
|
|
||||||
## Storage
|
|
||||||
The data is stored in ETS in the following format:
|
|
||||||
{sid :: String.t, data :: map, timestamp :: :erlang.timestamp}
|
|
||||||
The timestamp is updated whenever there is a read or write to the
|
|
||||||
table and it may be used to detect if a session is still active.
|
|
||||||
## Examples
|
|
||||||
# Create an ETS table when the application starts
|
|
||||||
:ets.new(:session, [:named_table, :public, read_concurrency: true])
|
|
||||||
# Use the session plug with the table name
|
|
||||||
plug Plug.Session, store: :ets, key: "sid", table: :session
|
|
||||||
"""
|
|
||||||
|
|
||||||
@behaviour Plug.Session.Store
|
|
||||||
|
|
||||||
@max_tries 100
|
|
||||||
|
|
||||||
def init(opts) do
|
|
||||||
Keyword.fetch!(opts, :table)
|
|
||||||
end
|
|
||||||
|
|
||||||
def get(_conn, sid, table) do
|
|
||||||
case :ets.lookup(table, sid) do
|
|
||||||
[{^sid, data, _timestamp}] ->
|
|
||||||
:ets.update_element(table, sid, {3, now()})
|
|
||||||
{sid, data}
|
|
||||||
[] ->
|
|
||||||
{nil, %{}}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def put(_conn, nil, data, table) do
|
|
||||||
put_new(data, table)
|
|
||||||
end
|
|
||||||
|
|
||||||
def put(_conn, sid, data, table) do
|
|
||||||
:ets.insert(table, {sid, data, now()})
|
|
||||||
sid
|
|
||||||
end
|
|
||||||
|
|
||||||
def delete(_conn, sid, table) do
|
|
||||||
:ets.delete(table, sid)
|
|
||||||
:ok
|
|
||||||
end
|
|
||||||
|
|
||||||
defp put_new(data, table, counter \\ 0)
|
|
||||||
when counter < @max_tries do
|
|
||||||
sid = Base.encode64(:crypto.strong_rand_bytes(96))
|
|
||||||
|
|
||||||
if :ets.insert_new(table, {sid, data, now()}) do
|
|
||||||
sid
|
|
||||||
else
|
|
||||||
put_new(data, table, counter + 1)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
defp now() do
|
|
||||||
:os.timestamp()
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -6,8 +6,9 @@
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
<%= inspect(conn |> Map.from_struct |> Map.get(:private, %{}) |> Map.get(:plug_session)) %>
|
||||||
<div id="content">
|
<div id="content">
|
||||||
<div id=<%= page %>>
|
<div id=<%= page %> >
|
||||||
<%= render.() %>
|
<%= render.() %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
Get ready to configure your Farmbot!
|
Get ready to configure your Farmbot!
|
||||||
|
|
||||||
<form action="next">
|
<form action="next", method="post">
|
||||||
<button> Go! </button>
|
<button> next </button>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -1,6 +1,64 @@
|
||||||
Lets configure Network!
|
Lets configure Network!
|
||||||
<form action="next">
|
<script>
|
||||||
<input> SSID </input>
|
window["ScanWifi"] = function() {
|
||||||
<input> PSK </input>
|
var xhr = new XMLHttpRequest();
|
||||||
<button> next </button>
|
xhr.open("GET", "/scan_wifi", false);
|
||||||
|
xhr.send();
|
||||||
|
var resp = JSON.parse(xhr.responseText);
|
||||||
|
var elem = document.getElementById("wifi");
|
||||||
|
elem.hidden=false;
|
||||||
|
|
||||||
|
|
||||||
|
var elem = document.getElementById("ssid");
|
||||||
|
var opts = ""; for(var i = 0; i < resp.length; i++) {opts = opts + "<option value=" + resp[i] + " >" + resp[i] + "</option>\n"}
|
||||||
|
elem.innerHTML = opts;
|
||||||
|
}
|
||||||
|
|
||||||
|
window["UseEthernet"] = function() {
|
||||||
|
var elem = document.getElementById("ethernet");
|
||||||
|
elem.hidden=false;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<form action="next" method="post" enctype="multipart/form-data">
|
||||||
|
<button type="button" onclick="ScanWifi()"> Scan for Wifi </button>
|
||||||
|
<button type="button" onclick="UseEthernet()"> Use Ethernet </button>
|
||||||
|
|
||||||
|
<div id="wifi" hidden="true">
|
||||||
|
<label for="ssid"> Select your SSID </label>
|
||||||
|
<!-- This will get populated by the ScanWifi function. -->
|
||||||
|
<select id="ssid" name="ssid"> </select>
|
||||||
|
<label for="psk"> Password </label>
|
||||||
|
<input id="psk" name="psk" type="password">
|
||||||
|
|
||||||
|
<button type="button" onclick="document.getElementById('wifi_static_settings').hidden=false;"> Use static settings </button>
|
||||||
|
|
||||||
|
<div id="wifi_static_settings" hidden="true" disabled="true">
|
||||||
|
<label for="ipv4_address"> ip address </label>
|
||||||
|
<input id="ipv4_address" name="ipv4_address">
|
||||||
|
|
||||||
|
<label for="ipv4_subnet_mask"> subnet mask </label>
|
||||||
|
<input id="ipv4_subnet_mask" name="ipv4_subnet_mask">
|
||||||
|
|
||||||
|
<label for="nameservers"> ip address </label>
|
||||||
|
<input id="nameservers" name="nameservers">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="ethernet" hidden="true">
|
||||||
|
<button type="button" onclick="document.getElementById('eth_static_settings').hidden=false;"> Use static settings </button>
|
||||||
|
|
||||||
|
<div id="eth_static_settings" hidden="true">
|
||||||
|
<label for="ipv4_address"> ip address </label>
|
||||||
|
<input id="ipv4_address" name="ipv4_address">
|
||||||
|
|
||||||
|
<label for="ipv4_subnet_mask"> subnet mask </label>
|
||||||
|
<input id="ipv4_subnet_mask" name="ipv4_subnet_mask">
|
||||||
|
|
||||||
|
<label for="nameservers"> ip address </label>
|
||||||
|
<input id="nameservers" name="nameservers">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit"> next </button>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
Lets configure Network!
|
Lets configure the Farmbot Web App
|
||||||
<form action="next">
|
<form action="next" enctype="multipart/form-data", method="post">
|
||||||
<input> Email </input>
|
<input> Email </input>
|
||||||
<input> Password </input>
|
<input> Password </input>
|
||||||
<input> Server </input>
|
<input> Server </input>
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
Now lets configure your Arduino or Farmduino
|
||||||
|
<form action="next" method="post">
|
||||||
|
<label for="hardware"> Select your device </label>
|
||||||
|
<select id="hardware" name="hardware">
|
||||||
|
<option value="farmduino"> Farmduino </option>
|
||||||
|
<option value="arduino"> Arduino Mega </option>
|
||||||
|
</select>
|
||||||
|
<button> next </button>
|
||||||
|
</form>
|
|
@ -0,0 +1,23 @@
|
||||||
|
Now lets configure your Arduino or Farmduino
|
||||||
|
<script>
|
||||||
|
window["SkipStep"] = function() {
|
||||||
|
console.log("skipping step!");
|
||||||
|
var elem = document.getElementById("submit_button");
|
||||||
|
elem.disabled=false;
|
||||||
|
}
|
||||||
|
|
||||||
|
window["FlashFW"] = function() {
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
xhr.open("GET", "/flash_fw", false);
|
||||||
|
// xhr.setRequestHeader("content-type", "multipart/form-data");
|
||||||
|
xhr.send("hello?");
|
||||||
|
var elem = document.getElementById("submit_button");
|
||||||
|
elem.disabled=false;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<form action="next" method="post">
|
||||||
|
<button type="button" id="flash" onclick="FlashFW()"> Flash Firmware</button>
|
||||||
|
<button type="button" id="skip" onclick="SkipStep()"> Skip this step </button>
|
||||||
|
<input id="submit_button" type="submit" disabled="true" value="next">
|
||||||
|
</form>
|
|
@ -0,0 +1,4 @@
|
||||||
|
Congrats! Your device will now disconnect blah blah blah
|
||||||
|
<form method="post" action="finish">
|
||||||
|
<button> ok </button>
|
||||||
|
<form>
|
Loading…
Reference in New Issue