bring back slack uploader

pull/363/head
Connor Rigby 2017-11-11 15:35:50 -08:00
parent 426c762b52
commit bd84c64796
10 changed files with 164 additions and 8 deletions

View File

@ -44,7 +44,7 @@ config :farmbot, Farmbot.System.ConfigStorage,
# SystemTasks for host mode.
config :farmbot, :behaviour,
authorization: Farmbot.Bootstrap.Authorization,
system_tasks: Farmbot.Host.SystemTasks,
firmware_handler: Farmbot.Firmware.UartHandler
system_tasks: Farmbot.Host.SystemTasks
# firmware_handler: Farmbot.Firmware.UartHandler
config :farmbot, :uart_handler, tty: "/dev/ttyACM0"

View File

@ -27,8 +27,6 @@ config :farmbot, :init, [
# Autodetects if a Arduino is plugged in and configures accordingly.
Farmbot.Firmware.UartHandler.AutoDetector,
Farmbot.System.Debug,
# Allows for first boot configuration.
Farmbot.Target.Bootstrap.Configurator,
@ -36,6 +34,9 @@ config :farmbot, :init, [
Farmbot.Target.Network,
# Wait for time time come up.
Farmbot.Target.Network.WaitForTime
# Debug stuff
Farmbot.System.Debug,
]
config :farmbot, :transport, [

View File

@ -8,7 +8,7 @@ defmodule Farmbot.FarmEvent.Supervisor do
def init([]) do
children = [
worker(Farmbot.FarmEvent.Manager, [])
# worker(Farmbot.FarmEvent.Manager, [])
]
supervise(children, strategy: :one_for_one)

View File

@ -17,7 +17,8 @@ defmodule Farmbot.System.Debug do
],
]
children = [
Plug.Adapters.Cowboy.child_spec(:http, Farmbot.System.DebugRouter, [], options)
Plug.Adapters.Cowboy.child_spec(:http, Farmbot.System.DebugRouter, [], options),
worker(Farmbot.System.Updates.SlackUpdater, [])
]
opts = [strategy: :one_for_one]

View File

@ -0,0 +1,143 @@
defmodule Farmbot.System.Updates.SlackUpdater do
@moduledoc """
Development module for auto flashing fw updates.
"""
@token System.get_env("SLACK_TOKEN")
@target Mix.Project.config()[:target]
use Farmbot.Logger
use GenServer
defmodule RTMSocket do
@moduledoc false
def start_link(url, cb) do
pid = spawn(__MODULE__, :socket_init, [url, cb])
{:ok, pid}
end
def socket_init("wss://" <> url, cb) do
[domain | rest] = String.split(url, "/")
domain
|> Socket.Web.connect!(secure: true, path: "/" <> Enum.join(rest, "/"))
|> socket_loop(cb)
end
def socket_init("ws://" <> url, cb) do
[domain | rest] = String.split(url, "/")
domain
|> Socket.Web.connect!(secure: false, path: "/" <> Enum.join(rest, "/"))
|> socket_loop(cb)
end
defp socket_loop(socket, cb) do
case socket |> Socket.Web.recv!() do
{:text, data} -> data |> Poison.decode!() |> handle_data(socket, cb)
{:ping, _} -> Socket.Web.send!(socket, {:pong, ""})
end
receive do
{:stop, _reason} ->
term_msg =
%{
type: "message",
id: 2,
channel: "C58DCU4A3",
text: ":farmbot-genesis: #{node()} Disconnected!"
}
|> Poison.encode!()
Socket.Web.send!(socket, {:text, term_msg})
Socket.Web.close(socket)
data ->
Socket.Web.send!(socket, {:text, Poison.encode!(data)})
socket_loop(socket, cb)
after
500 -> socket_loop(socket, cb)
end
end
defp handle_data(%{"type" => "hello"}, socket, _) do
Logger.success(3, "Connected to slack!")
msg =
%{
type: "message",
id: 1,
channel: "C58DCU4A3",
text: ":farmbot-genesis: #{node()} Connected!"
}
|> Poison.encode!()
Socket.Web.send!(socket, {:text, msg})
end
defp handle_data(msg, _socket, cb), do: send(cb, {:socket, msg})
end
def start_link() do
GenServer.start_link(__MODULE__, @token, name: __MODULE__)
end
def init(nil) do
Logger.warn(3, "Not setting up slack.")
:ignore
end
def init(token) do
url = "https://slack.com/api/rtm.connect"
payload = {:multipart, [{"token", token}]}
headers = [{'User-Agent', 'Farmbot HTTP Adapter'}]
case HTTPoison.post(url, payload, headers) do
{:ok, %{status_code: 200, body: body}} ->
{:ok, rtm_socket} =
body
|> Poison.decode!()
|> ensure_good_login
|> Map.get("url")
|> RTMSocket.start_link(self())
{:ok, %{rtm_socket: rtm_socket, token: token}}
err ->
Logger.error(3, "Failed to get RTM Auth: #{inspect(err)}")
:ignore
end
end
defp ensure_good_login(%{"ok" => true} = msg), do: msg
defp ensure_good_login(msg) do
raise("failed to auth: #{inspect(msg)}")
end
def handle_info({:socket, %{"file" => %{ "url_private_download" => dl_url, "name" => name}}}, state) do
if Path.extname(name) == ".fw" do
if match?(<<@target, <<"-">>, _rest :: binary>>, name) do
Logger.warn(3, "Downloading and applying an image from slack!")
path = Farmbot.HTTP.download_file(dl_url, "/tmp/#{name}", [], [{'Authorization', 'Bearer #{state.token}'}])
Nerves.Firmware.upgrade_and_finalize(path)
Farmbot.System.reboot("Slack update.")
{:stop, :normal, state}
else
Logger.debug(3, "Not downloading #{name} (wrong target)")
{:noreply, state}
end
else
{:noreply, state}
end
end
def handle_info({:socket, _msg}, state) do
# Logger.debug 2, "got message: #{inspect msg}"
{:noreply, state}
end
def terminate(reason, state) do
send(state.rtm_socket, {:stop, reason})
end
end

View File

@ -13,6 +13,7 @@ defmodule Mix.Tasks.Farmbot.Env do
@doc false
def fw_file do
# Path.join([images_dir(), "test.fw"])
Path.join([images_dir(), "#{mix_config(:app)}.fw"])
end

View File

@ -13,14 +13,14 @@ defmodule Mix.Tasks.Farmbot.Firmware.Slack do
fw_file_to_upload = if signed?, do: signed_fw_file(), else: fw_file()
time = format_date_time(File.stat!(fw_file_to_upload))
filename = "#{mix_config(:app)}-#{env()}-#{mix_config(:commit)}#{if signed?, do: "-signed-", else: "-"}#{time}.fw"
filename = "#{mix_config(:app)}-#{target()}-#{env()}-#{mix_config(:commit)}#{if signed?, do: "-signed-", else: "-"}#{time}.fw"
comment = Enum.join(comment, " ")
Mix.shell.info [:green, "Uploading: #{filename} (#{fw_file_to_upload})"]
url = "https://slack.com/api/files.upload"
form_data = %{
:file => fw_file_to_upload,
"token" => token,
"channels" => "embedded-systems",
"channels" => "embedded-systems,C58DCU4A3",
"filename" => filename,
"title" => filename,
"initial_comment" => """

View File

@ -96,6 +96,7 @@ defmodule Farmbot.Mixfile do
{:sqlite_ecto2, "~> 2.2.1"},
{:wobserver, "~> 0.1.8"},
{:joken, "~> 1.1"},
{:socket, "~> 0.3"}
]
end

View File

@ -48,6 +48,7 @@
"ranch": {:hex, :ranch, "1.3.2", "e4965a144dc9fbe70e5c077c65e73c57165416a901bd02ea899cfd95aa890986", [:rebar3], [], "hexpm"},
"rsa": {:hex, :rsa, "0.0.1", "a63069f88ce342ffdf8448b7cdef4b39ba7dee3c1510644a39385c7e63ba246f", [], [], "hexpm"},
"sbroker": {:hex, :sbroker, "1.0.0", "28ff1b5e58887c5098539f236307b36fe1d3edaa2acff9d6a3d17c2dcafebbd0", [], [], "hexpm"},
"socket": {:hex, :socket, "0.3.12", "4a6543815136503fee67eff0932da1742fad83f84c49130c854114153cc549a6", [], [], "hexpm"},
"sqlite_ecto2": {:hex, :sqlite_ecto2, "2.2.1", "6447456ef4264177d16e489b88f7abc63463e9eddc1fef4358b3f73562b7a2d8", [], [{:connection, "~> 1.0.3", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 1.1.0", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.2", [hex: :decimal, repo: "hexpm", optional: false]}, {:ecto, "~> 2.2.2", [hex: :ecto, repo: "hexpm", optional: false]}, {:esqlite, "~> 0.2.3", [hex: :esqlite, repo: "hexpm", optional: false]}, {:poison, "~> 2.2 or ~> 3.0", [hex: :poison, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.13.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:sbroker, "~> 1.0", [hex: :sbroker, repo: "hexpm", optional: false]}, {:sqlitex, "~> 1.3.2 or ~> 1.4", [hex: :sqlitex, repo: "hexpm", optional: false]}], "hexpm"},
"sqlitex": {:hex, :sqlitex, "1.3.3", "3aac5fd702be346f71d9de6e01702c9954484cd0971aa443490bb3bde045d919", [], [{:decimal, "~> 1.1", [hex: :decimal, repo: "hexpm", optional: false]}, {:esqlite, "~> 0.2.3", [hex: :esqlite, repo: "hexpm", optional: false]}], "hexpm"},
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [], [], "hexpm"},

View File

@ -6,7 +6,15 @@ defmodule Farmbot.Host.Bootstrap.Configurator do
Supervisor.start_link(__MODULE__, [], opts)
end
defp start_node() do
case Node.start(:"farmbot-host@127.0.0.1") do
{:ok, _} -> :ok
_ -> :ok
end
end
def init(_) do
start_node()
# Get out authorization data out of the environment.
# for host environment this will be configured at compile time.
# for target environment it will be configured by `configurator`.