Refactor so that player/respawn is dynamically chosen

This commit is contained in:
Mikko Ahlroth 2018-05-10 16:36:04 +03:00
parent 788c9db781
commit 4710ebe6e2
19 changed files with 405 additions and 104 deletions

2
.gitignore vendored
View file

@ -15,3 +15,5 @@ erl_crash.dump
config/*.secret.exs
ssh/known_hosts
/.elixir_ls

6
config/device.exs Normal file
View file

@ -0,0 +1,6 @@
use Mix.Config
config :nerves_init_net_kernel,
name: "duck_tag_device"
import_config "device.secret.exs"

View file

@ -1,7 +0,0 @@
use Mix.Config
config :nerves_init_net_kernel,
iface: "wlan0",
name: "duck_tag_player"
import_config "player.secret.exs"

View file

@ -1,7 +0,0 @@
use Mix.Config
config :nerves_init_net_kernel,
iface: "eth0",
name: "duck_tag_respawn"
import_config "respawn.secret.exs"

View file

@ -1,5 +1,8 @@
# RPi 1 Model B specific config
config :nerves_init_net_kernel,
iface: "eth0"
use Mix.Config
import_config "rpi.secret.exs"

View file

@ -2,4 +2,7 @@
use Mix.Config
config :nerves_init_net_kernel,
iface: "wlan0"
import_config "rpi0.secret.exs"

View file

@ -3,6 +3,18 @@ defmodule DuckTag.DB.Manager do
This module is responsible for defining and initialising the game state Mnesia database.
"""
@typedoc """
Game's status:
- `:wait_connect` - Waiting for all nodes to connect.
- `:init_players` - Initialising players.
- `:init_respawn` - Initialising respawns.
- `:game_on` - Game is running.
- `:stopped` - Game was stopped or finished.
"""
@type game_status ::
:wait_connect | :init_players | :init_respawn | :wait_start | :game_on | :stopped
@typedoc """
Player's status in the game:
@ -18,36 +30,71 @@ defmodule DuckTag.DB.Manager do
require Logger
defdatabase GameDB do
deftable Player, [{:id, autoincrement}, :name, :status, :score], type: :set, index: [:name] do
deftable State, [{:id, autoincrement}, :status], type: :set do
@type t :: %State{id: integer, status: DuckTag.DB.Manager.game_status()}
def init_state() do
State.write(%State{status: :wait_connect})
end
def set_status(%State{} = state, status) do
State.write(%{state | status: status})
end
end
deftable Player, [{:id, autoincrement}, :name, :status, :score, :last_respawn],
type: :set,
index: [:name] do
@type t :: %Player{
id: integer,
name: String.t(),
status: DuckTag.DB.Manager.player_status(),
score: integer
score: integer,
last_respawn: DateTime.t() | nil
}
def add(name) do
Player.write(%Player{name: name, status: :wait_start, score: 0})
Player.write(%Player{name: name, status: :wait_start, score: 0, last_respawn: nil})
end
def add_score(%Player{} = player, score) do
Player.write(%{player | score: player.score + score})
end
def set_score(%Player{} = player, score) do
Player.write(%{player | score: score})
end
def set_status(%Player{} = player, status) when is_atom(status) do
Player.write(%{player | status: status})
end
def reset_last_respawn(%Player{} = player) do
Player.write(%{player | last_respawn: DateTime.utc_now()})
end
end
deftable Device, [:rfid, :player_id], type: :set do
deftable Device, [:node, :rfid, :player_id, :type],
type: :set,
index: [:rfid, :player_id] do
@type t :: %Device{
node: atom,
rfid: String.t(),
player_id: integer
player_id: integer,
type: :player | :respawn
}
def add(tag_id, player_id) do
def add(node, tag_id, player_id, type) do
if not Player.member?(player_id) do
Logger.error("Unknown player #{player_id}!")
else
Device.write(%Device{rfid: tag_id, player_id: player_id})
Device.write(%Device{node: node, rfid: tag_id, player_id: player_id, type: type})
end
end
def set_rfid(%Device{} = device, tag_id) do
Device.write(%{device | rfid: tag_id})
end
end
end
@ -57,6 +104,7 @@ defmodule DuckTag.DB.Manager do
def init(_opts) do
:ok = create_db()
:ok = init_db()
{:ok, :ok}
end
@ -86,6 +134,17 @@ defmodule DuckTag.DB.Manager do
:ok = GameDB.wait(15_000)
end
@doc """
Init game state to wait for nodes.
"""
def init_db() do
Amnesia.transaction do
GameDB.State.init_state()
end
:ok
end
@doc """
Start mnesia.
"""

View file

@ -1,32 +1,108 @@
defmodule DuckTag do
@moduledoc """
Util module for stuff that doesn't fit anywhere else.
"""
@type role :: :player | :respawn | :judge
require Logger
use Amnesia
alias DuckTag.DB.Manager.GameDB
import Ex2ms
@doc """
Get project config.
Start new game by adding new players. Do this when all nodes are connected.
"""
@spec get_conf(atom) :: any
def get_conf(key) do
Application.get_env(:duck_tag, key)
def add_players() do
Logger.debug("PLEASE ADD PLAYERS BY TAGGING DEVICES WITH THEIR RESPECTIVE TAGS.")
GameDB.Device.clear()
GameDB.Player.clear()
Amnesia.transaction do
GameDB.State.first!()
|> GameDB.State.set_status(:init_players)
end
end
@doc """
Get the currently active role, set at build time.
Add respawn points, do this after adding players.
"""
@spec role() :: role
def role() do
get_conf(:role)
def add_respawns() do
Logger.debug("PLEASE ADD RESPAWN POINTS BY TAGGING DEVICES WITH ANY TAG.")
Amnesia.transaction do
GameDB.State.first!()
|> GameDB.State.set_status(:init_respawns)
end
end
@doc """
Get the Judge's node name.
Start gameplay!
"""
@spec judge_node() :: atom
def judge_node() do
# Assume Judge has static IP
"duck_tag_judge@#{DuckTag.get_conf(:judge_ip)}" |> String.to_atom()
def start_game() do
Logger.debug("Resetting players...")
Amnesia.transaction do
case GameDB.Player.select(
fun do
p -> p
end
) do
nil ->
nil
selection ->
selection
|> Amnesia.Selection.values()
|> Enum.each(fn {_, id, name, status, score, last_respawn} ->
player = %GameDB.Player{
id: id,
name: name,
status: status,
score: score,
last_respawn: last_respawn
}
GameDB.Player.set_status(player, :alive)
GameDB.Player.set_score(player, 0)
end)
end
end
Amnesia.transaction do
GameDB.State.first!()
|> GameDB.State.set_status(:game_on)
end
end
@doc """
Stop running game.
"""
def stop_game() do
Amnesia.transaction do
case GameDB.Player.select(
fun do
p -> p
end
) do
nil ->
nil
selection ->
selection
|> Amnesia.Selection.values()
|> Enum.each(fn {_, id, name, status, score, last_respawn} ->
player = %GameDB.Player{
id: id,
name: name,
status: status,
score: score,
last_respawn: last_respawn
}
GameDB.Player.set_status(player, :out)
end)
end
end
Amnesia.transaction do
GameDB.State.first!()
|> GameDB.State.set_status(:stopped)
end
end
end

View file

@ -6,23 +6,16 @@ defmodule DuckTag.Application do
@doc """
Get the workers that should be started for the given role.
"""
@spec workers(DuckTag.role()) :: [any]
@spec workers(DuckTag.Utils.role_t()) :: [any]
def workers(type)
def workers(:common) do
[]
end
def workers(:player) do
def workers(:device) do
[
DuckTag.Player.JudgeAPI.child_spec(name: DuckTag.Player.JudgeAPI),
rfid_worker()
]
end
def workers(:respawn) do
[
DuckTag.Player.JudgeAPI.child_spec(name: DuckTag.Player.JudgeAPI),
DuckTag.JudgeAPI.child_spec(name: DuckTag.Player.JudgeAPI),
rfid_worker()
]
end
@ -36,10 +29,14 @@ defmodule DuckTag.Application do
]
end
def workers(unknown_role) do
raise "Unknown role #{inspect(unknown_role)}!"
end
# See http://elixir-lang.org/docs/stable/elixir/Application.html
# for more information on OTP Applications
def start(_type, _args) do
device_type = DuckTag.role()
device_type = DuckTag.Utils.role()
# Define workers and child supervisors to be supervised
children = Enum.concat(workers(:common), workers(device_type))

View file

@ -1,4 +1,4 @@
defmodule DuckTag.Player.JudgeAPI do
defmodule DuckTag.JudgeAPI do
@moduledoc """
Functions for talking to the Judge and a GenServer that manages the connection.
"""
@ -22,7 +22,7 @@ defmodule DuckTag.Player.JudgeAPI do
def handle_info(:retry_connect, _state), do: {:noreply, try_connect()}
defp try_connect() do
remote_node = DuckTag.judge_node()
remote_node = DuckTag.Utils.judge_node()
case connect(remote_node) do
true ->

View file

@ -7,10 +7,6 @@ defmodule DuckTag.RFIDHandler do
IO.puts("TAG SCANNED")
IO.inspect(uid)
tagged(DuckTag.role(), uid)
end
def tagged(:player, tag_id) do
DuckTag.Player.TagHandler.tagged(tag_id)
DuckTag.TagHandler.tagged(uid)
end
end

127
lib/duck_tag/tag_handler.ex Normal file
View file

@ -0,0 +1,127 @@
defmodule DuckTag.TagHandler do
@moduledoc """
Tagging handler for devices.
"""
alias DuckTag.DB.Manager.GameDB
use Amnesia
require Logger
require GameDB.Device
import Ex2ms
@points_per_tag 100
def tagged(tag_id) do
{gs, od} =
Amnesia.transaction do
game_state = GameDB.State.first!()
IO.inspect(game_state)
our_device = GameDB.Device.read(node())
{game_state, our_device}
end
tagged(od, gs, tag_id)
end
def tagged(nil, %GameDB.State{status: :init_players}, tag_id) do
name =
Amnesia.transaction do
Logger.debug("Tagged by #{tag_id} so we are now a player.")
name = UUID.uuid4()
Logger.debug("Our name shall be #{name}!")
GameDB.Player.add(name)
name
end
Amnesia.transaction do
id = get_player_id(name)
Logger.debug("Our ID is #{id}.")
Logger.debug("We have no device so let us create one.")
GameDB.Device.add(node(), tag_id, id, :player)
end
end
def tagged(%GameDB.Device{} = our_device, %GameDB.State{status: :init_players}, tag_id) do
Amnesia.transaction do
Logger.debug("Resetting device #{our_device.node} to tag #{tag_id}.")
GameDB.Device.set_rfid(our_device, tag_id)
end
end
def tagged(nil, %GameDB.State{status: :init_respawns}, tag_id) do
Amnesia.transaction do
Logger.debug("Tagged by #{tag_id} so we are now a respawn point.")
GameDB.Device.add(node(), tag_id, nil, :respawn)
end
end
def tagged(_, %GameDB.State{status: :init_respawns}, _) do
Logger.error(
"Cannot reassign spawn point. Please reinit game if you want to do that, ya dingus."
)
end
def tagged(%GameDB.Device{} = our_device, %GameDB.State{status: :game_on}, tag_id) do
Amnesia.transaction do
case GameDB.Device.read(tag_id) do
nil ->
Logger.debug("I was tagged by unknown tag #{tag_id}")
%GameDB.Device{} = device ->
case GameDB.Player.read(device.player_id) do
nil ->
Logger.debug("Tag #{tag_id} associated with nonexistent player #{device.player_id}")
%GameDB.Player{status: status} = player when status != :alive ->
Logger.debug("Tagged by #{player.name} but they are not in contention.")
%GameDB.Player{status: :alive} = player ->
Logger.debug("Tagged by #{player.name}. #{@points_per_tag} points!")
GameDB.Player.add_score(player, @points_per_tag)
# TODO: KILL OUR PLAYER
GameDB.Player.set_status(player, :dead)
end
end
end
end
def get_player_id(player_name) do
case GameDB.Player.select(
fun do
{_, id, name, _, _, _} when name == ^player_name -> id
end
) do
nil -> nil
selection -> selection |> Amnesia.Selection.values() |> Enum.at(0, nil)
end
end
def get_our_device(tag_id) do
case GameDB.Device.select(
fun do
{_, node, rfid, player_id, type} when rfid == ^tag_id ->
{node, rfid, player_id, type}
end
) do
nil ->
nil
selection ->
case Amnesia.Selection.values(selection) |> Enum.at(0, nil) do
nil ->
nil
{node, rfid, player_id, type} ->
%GameDB.Device{node: node, rfid: rfid, player_id: player_id, type: type}
end
end
end
end

32
lib/duck_tag/utils.ex Normal file
View file

@ -0,0 +1,32 @@
defmodule DuckTag.Utils do
@moduledoc """
Util module for stuff that doesn't fit anywhere else.
"""
@type role_t :: :common | :device | :judge
@doc """
Get project config.
"""
@spec get_conf(atom) :: any
def get_conf(key) do
Application.get_env(:duck_tag, key)
end
@doc """
Get the currently active role, set at build time.
"""
@spec role() :: role_t
def role() do
get_conf(:role)
end
@doc """
Get the Judge's node name.
"""
@spec judge_node() :: atom
def judge_node() do
# Assume Judge has static IP
"duck_tag_judge@#{DuckTag.Utils.get_conf(:judge_ip)}" |> String.to_atom()
end
end

View file

@ -19,8 +19,8 @@ defmodule DuckTag.NetUtils.NodeStart do
def start(role)
def start(:judge) do
Logger.debug("Setting node name to '#{inspect(DuckTag.judge_node())}'")
Logger.debug("Setting node name to '#{inspect(DuckTag.Utils.judge_node())}'")
Node.start(DuckTag.judge_node())
Node.start(DuckTag.Utils.judge_node())
end
end

View file

@ -1,12 +1,12 @@
defmodule DuckTag.Player.TagHandler do
defmodule DuckTag.Respawn.TagHandler do
@moduledoc """
Tagging handler for player.
Tagging handler for respawn.
"""
alias DuckTag.DB.Manager.GameDB
use Amnesia
require Logger
@points_per_tag 100
@respawned_status :alive
def tagged(tag_id) do
Amnesia.transaction do
@ -20,8 +20,9 @@ defmodule DuckTag.Player.TagHandler do
Logger.debug("Tag #{tag_id} associated with nonexistent player #{device.player_id}")
%GameDB.Player{} = player ->
Logger.debug("I was tagged by #{player.name}. #{@points_per_tag} points!")
GameDB.Player.add_score(player, @points_per_tag)
Logger.debug("I was tagged by #{player.name}. Respawned!")
GameDB.Player.set_status(player, @respawned_status)
GameDB.Player.reset_last_respawn(player)
end
end
end

19
mix.exs
View file

@ -57,14 +57,18 @@ defmodule DuckTag.Mixfile do
#
# Type "mix help deps" for more examples and options
def deps do
[{:nerves, "~> 0.7", runtime: false}] ++ deps(@target)
[
{:nerves, "~> 0.7", runtime: false},
{:ex2ms, "~> 1.5.0"},
{:amnesia, "~> 0.2.7"},
{:uuid, "~> 1.1"}
] ++ deps(@target)
end
# Specify target specific dependencies
def deps("host"),
do: [
{:nerves_firmware_ssh, "~> 0.3"},
{:amnesia, "~> 0.2.7"}
{:nerves_firmware_ssh, "~> 0.3"}
]
def deps(target) do
@ -75,7 +79,6 @@ defmodule DuckTag.Mixfile do
{:nerves_io_rc522, "~> 0.1.0"},
{:observer_cli, "~> 1.1.0"},
{:nerves_network, "~> 0.3"},
{:amnesia, "~> 0.2.7"},
{:nerves_init_net_kernel, github: "mobileoverlord/nerves_init_net_kernel"}
] ++ system(target)
end
@ -96,7 +99,13 @@ defmodule DuckTag.Mixfile do
def aliases(_target) do
[
"deps.precompile": ["nerves.precompile", "deps.precompile"],
"deps.loadpaths": ["deps.loadpaths", "nerves.loadpaths"]
"deps.loadpaths": ["deps.loadpaths", "nerves.loadpaths"],
loadconfig: [&bootstrap/1]
]
end
def bootstrap(args) do
Application.start(:nerves_bootstrap)
Mix.Task.run("loadconfig", args)
end
end

View file

@ -1,10 +1,12 @@
%{
"amnesia": {:hex, :amnesia, "0.2.7", "ffc2221bf72da4cfafbbb497adf9cf7e52138f1333cec5836187a53f94ae0665", [], [{:exquisite, "~> 0.1.7", [hex: :exquisite, repo: "hexpm", optional: false]}], "hexpm"},
"distillery": {:hex, :distillery, "1.5.2", "eec18b2d37b55b0bcb670cf2bcf64228ed38ce8b046bb30a9b636a6f5a4c0080", [], [], "hexpm"},
"elixir_make": {:hex, :elixir_make, "0.4.0", "992f38fabe705bb45821a728f20914c554b276838433349d4f2341f7a687cddf", [], [], "hexpm"},
"elixir_make": {:hex, :elixir_make, "0.4.0", "992f38fabe705bb45821a728f20914c554b276838433349d4f2341f7a687cddf", [:mix], [], "hexpm"},
"ex2ms": {:hex, :ex2ms, "1.5.0", "19e27f9212be9a96093fed8cdfbef0a2b56c21237196d26760f11dfcfae58e97", [:mix], [], "hexpm"},
"exquisite": {:hex, :exquisite, "0.1.8", "ee8f56aae477287ce5e7dfcbc163a420cccbb73e680a6d80a09203e9ef514fa4", [], [], "hexpm"},
"nerves": {:hex, :nerves, "0.7.5", "3aa6a336b2ad6c1c9589cc2b577511b3c4c375c1ba6c533ab9f88adb8c21f0c3", [], [{:distillery, "~> 1.4", [hex: :distillery, repo: "hexpm", optional: false]}], "hexpm"},
"nerves_firmware_ssh": {:hex, :nerves_firmware_ssh, "0.3.1", "e8b1967fa0aff255230be539c68ec868d33884193a385caff957ebad7d6aa8af", [], [{:nerves_runtime, "~> 0.4", [hex: :nerves_runtime, repo: "hexpm", optional: false]}], "hexpm"},
"nerves_runtime": {:hex, :nerves_runtime, "0.5.0", "5f4135fe3c94ca5c9e25d677350fbb136f279d14aac4871236961b6f5ccbcfa5", [], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:system_registry, "~> 0.5", [hex: :system_registry, repo: "hexpm", optional: false]}], "hexpm"},
"system_registry": {:hex, :system_registry, "0.6.0", "31642177e6002d3cff2ada3553ed4e9c0a6ca015797d62d7d17c0ab8696185fc", [], [], "hexpm"},
"nerves": {:hex, :nerves, "0.7.5", "3aa6a336b2ad6c1c9589cc2b577511b3c4c375c1ba6c533ab9f88adb8c21f0c3", [:mix], [{:distillery, "~> 1.4", [hex: :distillery, repo: "hexpm", optional: false]}], "hexpm"},
"nerves_firmware_ssh": {:hex, :nerves_firmware_ssh, "0.3.1", "e8b1967fa0aff255230be539c68ec868d33884193a385caff957ebad7d6aa8af", [:mix], [{:nerves_runtime, "~> 0.4", [hex: :nerves_runtime, repo: "hexpm", optional: false]}], "hexpm"},
"nerves_runtime": {:hex, :nerves_runtime, "0.5.0", "5f4135fe3c94ca5c9e25d677350fbb136f279d14aac4871236961b6f5ccbcfa5", [:make, :mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:system_registry, "~> 0.5", [hex: :system_registry, repo: "hexpm", optional: false]}], "hexpm"},
"system_registry": {:hex, :system_registry, "0.6.0", "31642177e6002d3cff2ada3553ed4e9c0a6ca015797d62d7d17c0ab8696185fc", [:mix], [], "hexpm"},
"uuid": {:hex, :uuid, "1.1.8", "e22fc04499de0de3ed1116b770c7737779f226ceefa0badb3592e64d5cfb4eb9", [:mix], [], "hexpm"},
}

View file

@ -1,26 +1,26 @@
%{
"amnesia": {:hex, :amnesia, "0.2.7", "ffc2221bf72da4cfafbbb497adf9cf7e52138f1333cec5836187a53f94ae0665", [], [{:exquisite, "~> 0.1.7", [hex: :exquisite, repo: "hexpm", optional: false]}], "hexpm"},
"bootloader": {:hex, :bootloader, "0.1.2", "835ddcf50b796714658f342061d5d48ebc34cbd0d81cdbd5a5a8ae00705d72b1", [], [{:distillery, "~> 1.0", [hex: :distillery, repo: "hexpm", optional: false]}], "hexpm"},
"bootloader": {:hex, :bootloader, "0.1.2", "835ddcf50b796714658f342061d5d48ebc34cbd0d81cdbd5a5a8ae00705d72b1", [:mix], [{:distillery, "~> 1.0", [hex: :distillery, repo: "hexpm", optional: false]}], "hexpm"},
"distillery": {:hex, :distillery, "1.5.2", "eec18b2d37b55b0bcb670cf2bcf64228ed38ce8b046bb30a9b636a6f5a4c0080", [], [], "hexpm"},
"dns": {:hex, :dns, "1.0.1", "1d88187fdf564d937cee202949141090707fd0c9d7fcae903a6878ef24ef5d1e", [], [{:socket, "~> 0.3.12", [hex: :socket, repo: "hexpm", optional: false]}], "hexpm"},
"elixir_make": {:hex, :elixir_make, "0.4.0", "992f38fabe705bb45821a728f20914c554b276838433349d4f2341f7a687cddf", [], [], "hexpm"},
"dns": {:hex, :dns, "1.0.1", "1d88187fdf564d937cee202949141090707fd0c9d7fcae903a6878ef24ef5d1e", [:mix], [{:socket, "~> 0.3.12", [hex: :socket, repo: "hexpm", optional: false]}], "hexpm"},
"elixir_make": {:hex, :elixir_make, "0.4.0", "992f38fabe705bb45821a728f20914c554b276838433349d4f2341f7a687cddf", [:mix], [], "hexpm"},
"exquisite": {:hex, :exquisite, "0.1.8", "ee8f56aae477287ce5e7dfcbc163a420cccbb73e680a6d80a09203e9ef514fa4", [], [], "hexpm"},
"mdns": {:hex, :mdns, "0.1.6", "b51b902b15b50e0e1522483c6a5fb073413e3d3d6ef52a44b93a541460b47d29", [], [{:dns, "~> 1.0", [hex: :dns, repo: "hexpm", optional: false]}], "hexpm"},
"nerves": {:hex, :nerves, "0.7.5", "3aa6a336b2ad6c1c9589cc2b577511b3c4c375c1ba6c533ab9f88adb8c21f0c3", [], [{:distillery, "~> 1.4", [hex: :distillery, repo: "hexpm", optional: false]}], "hexpm"},
"nerves_firmware_ssh": {:hex, :nerves_firmware_ssh, "0.3.1", "e8b1967fa0aff255230be539c68ec868d33884193a385caff957ebad7d6aa8af", [], [{:nerves_runtime, "~> 0.4", [hex: :nerves_runtime, repo: "hexpm", optional: false]}], "hexpm"},
"nerves_init_gadget": {:hex, :nerves_init_gadget, "0.2.1", "20f36dd062fb00e2be8817ddff1b9ced9762877cfe23f6ec1d5936a37e3fc2c8", [], [{:mdns, "~> 0.1", [hex: :mdns, repo: "hexpm", optional: false]}, {:nerves_firmware_ssh, "~> 0.2", [hex: :nerves_firmware_ssh, repo: "hexpm", optional: false]}, {:nerves_network, "~> 0.3", [hex: :nerves_network, repo: "hexpm", optional: false]}, {:nerves_runtime, "~> 0.3", [hex: :nerves_runtime, repo: "hexpm", optional: false]}], "hexpm"},
"mdns": {:hex, :mdns, "0.1.6", "b51b902b15b50e0e1522483c6a5fb073413e3d3d6ef52a44b93a541460b47d29", [:mix], [{:dns, "~> 1.0", [hex: :dns, repo: "hexpm", optional: false]}], "hexpm"},
"nerves": {:hex, :nerves, "0.7.5", "3aa6a336b2ad6c1c9589cc2b577511b3c4c375c1ba6c533ab9f88adb8c21f0c3", [:mix], [{:distillery, "~> 1.4", [hex: :distillery, repo: "hexpm", optional: false]}], "hexpm"},
"nerves_firmware_ssh": {:hex, :nerves_firmware_ssh, "0.3.1", "e8b1967fa0aff255230be539c68ec868d33884193a385caff957ebad7d6aa8af", [:mix], [{:nerves_runtime, "~> 0.4", [hex: :nerves_runtime, repo: "hexpm", optional: false]}], "hexpm"},
"nerves_init_gadget": {:hex, :nerves_init_gadget, "0.2.1", "20f36dd062fb00e2be8817ddff1b9ced9762877cfe23f6ec1d5936a37e3fc2c8", [:mix], [{:mdns, "~> 0.1", [hex: :mdns, repo: "hexpm", optional: false]}, {:nerves_firmware_ssh, "~> 0.2", [hex: :nerves_firmware_ssh, repo: "hexpm", optional: false]}, {:nerves_network, "~> 0.3", [hex: :nerves_network, repo: "hexpm", optional: false]}, {:nerves_runtime, "~> 0.3", [hex: :nerves_runtime, repo: "hexpm", optional: false]}], "hexpm"},
"nerves_init_net_kernel": {:git, "https://github.com/mobileoverlord/nerves_init_net_kernel.git", "7772c8558ed5bb32853bb47209621b40b1331ee3", []},
"nerves_io_rc522": {:hex, :nerves_io_rc522, "0.1.0", "5a84a23ff2ac6e4c9cc0ea2931e43cf06d175b991bfd8b0ef664192cee25b7a4", [], [{:elixir_make, "~> 0.3", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm"},
"nerves_network": {:hex, :nerves_network, "0.3.4", "c50a36b8263cda2bee18f408287d0f4474f8367702d170864325abbd5d424e4d", [:make, :mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:nerves_network_interface, "~> 0.4.0", [hex: :nerves_network_interface, repo: "hexpm", optional: false]}, {:nerves_wpa_supplicant, "~> 0.3.0", [hex: :nerves_wpa_supplicant, repo: "hexpm", optional: false]}, {:system_registry, "~> 0.4", [hex: :system_registry, repo: "hexpm", optional: false]}], "hexpm"},
"nerves_network_interface": {:hex, :nerves_network_interface, "0.4.2", "7a3663a07803f2f9f1e37146714d24ccec1e9349268586e4ed8c41f38641d837", [], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm"},
"nerves_runtime": {:hex, :nerves_runtime, "0.5.0", "5f4135fe3c94ca5c9e25d677350fbb136f279d14aac4871236961b6f5ccbcfa5", [], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:system_registry, "~> 0.5", [hex: :system_registry, repo: "hexpm", optional: false]}], "hexpm"},
"nerves_system_br": {:hex, :nerves_system_br, "0.14.1", "b108f8e12b2fd5cfd75be72d8ade4a1cfa9b9fd9076380c431ad930a7ccd5526", [], [], "hexpm"},
"nerves_system_rpi": {:hex, :nerves_system_rpi, "0.17.1", "f31e4c20901ed14ed99e672b7778b83f75caa09f52ab76c4474d24ab9876c17d", [], [{:nerves, "~> 0.7", [hex: :nerves, repo: "hexpm", optional: false]}, {:nerves_system_br, "~> 0.14.1", [hex: :nerves_system_br, repo: "hexpm", optional: false]}, {:nerves_toolchain_armv6_rpi_linux_gnueabi, "~> 0.11.0", [hex: :nerves_toolchain_armv6_rpi_linux_gnueabi, repo: "hexpm", optional: false]}], "hexpm"},
"nerves_toolchain_armv6_rpi_linux_gnueabi": {:hex, :nerves_toolchain_armv6_rpi_linux_gnueabi, "0.11.0", "74ee72f15baffe773e41bae1baeef3942fc8f97fa47d9d1bf9db07c17eca90bd", [], [{:nerves, "~> 0.7", [hex: :nerves, repo: "hexpm", optional: false]}, {:nerves_toolchain_ctng, "~> 1.1", [hex: :nerves_toolchain_ctng, repo: "hexpm", optional: false]}], "hexpm"},
"nerves_toolchain_ctng": {:hex, :nerves_toolchain_ctng, "1.1.0", "0f03e4a3f3beef5fe271de0148b9f106c417e57f303f635c21c74b4bd6eb68ee", [], [], "hexpm"},
"nerves_network_interface": {:hex, :nerves_network_interface, "0.4.2", "7a3663a07803f2f9f1e37146714d24ccec1e9349268586e4ed8c41f38641d837", [:make, :mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm"},
"nerves_runtime": {:hex, :nerves_runtime, "0.5.0", "5f4135fe3c94ca5c9e25d677350fbb136f279d14aac4871236961b6f5ccbcfa5", [:make, :mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:system_registry, "~> 0.5", [hex: :system_registry, repo: "hexpm", optional: false]}], "hexpm"},
"nerves_system_br": {:hex, :nerves_system_br, "0.14.1", "b108f8e12b2fd5cfd75be72d8ade4a1cfa9b9fd9076380c431ad930a7ccd5526", [:mix], [], "hexpm"},
"nerves_system_rpi": {:hex, :nerves_system_rpi, "0.17.1", "f31e4c20901ed14ed99e672b7778b83f75caa09f52ab76c4474d24ab9876c17d", [:mix], [{:nerves, "~> 0.7", [hex: :nerves, repo: "hexpm", optional: false]}, {:nerves_system_br, "~> 0.14.1", [hex: :nerves_system_br, repo: "hexpm", optional: false]}, {:nerves_toolchain_armv6_rpi_linux_gnueabi, "~> 0.11.0", [hex: :nerves_toolchain_armv6_rpi_linux_gnueabi, repo: "hexpm", optional: false]}], "hexpm"},
"nerves_toolchain_armv6_rpi_linux_gnueabi": {:hex, :nerves_toolchain_armv6_rpi_linux_gnueabi, "0.11.0", "74ee72f15baffe773e41bae1baeef3942fc8f97fa47d9d1bf9db07c17eca90bd", [:mix], [{:nerves, "~> 0.7", [hex: :nerves, repo: "hexpm", optional: false]}, {:nerves_toolchain_ctng, "~> 1.1", [hex: :nerves_toolchain_ctng, repo: "hexpm", optional: false]}], "hexpm"},
"nerves_toolchain_ctng": {:hex, :nerves_toolchain_ctng, "1.1.0", "0f03e4a3f3beef5fe271de0148b9f106c417e57f303f635c21c74b4bd6eb68ee", [:mix], [], "hexpm"},
"nerves_wpa_supplicant": {:hex, :nerves_wpa_supplicant, "0.3.2", "19dc7e1248336e7f542b11b2b857ceb5b088d3eb41a6ca75b7b76628dcf67aad", [], [{:elixir_make, "~> 0.3", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm"},
"observer_cli": {:hex, :observer_cli, "1.1.0", "f3a47c22327424291758167df3c4600dcf8bf34795a3787612019aa5b86a5c21", [], [{:recon, "2.3.2", [hex: :recon, repo: "hexpm", optional: false]}], "hexpm"},
"recon": {:hex, :recon, "2.3.2", "4444c879be323b1b133eec5241cb84bd3821ea194c740d75617e106be4744318", [], [], "hexpm"},
"socket": {:hex, :socket, "0.3.12", "4a6543815136503fee67eff0932da1742fad83f84c49130c854114153cc549a6", [], [], "hexpm"},
"system_registry": {:hex, :system_registry, "0.6.0", "31642177e6002d3cff2ada3553ed4e9c0a6ca015797d62d7d17c0ab8696185fc", [], [], "hexpm"},
"socket": {:hex, :socket, "0.3.12", "4a6543815136503fee67eff0932da1742fad83f84c49130c854114153cc549a6", [:mix], [], "hexpm"},
"system_registry": {:hex, :system_registry, "0.6.0", "31642177e6002d3cff2ada3553ed4e9c0a6ca015797d62d7d17c0ab8696185fc", [:mix], [], "hexpm"},
}

View file

@ -1,26 +1,28 @@
%{
"amnesia": {:hex, :amnesia, "0.2.7", "ffc2221bf72da4cfafbbb497adf9cf7e52138f1333cec5836187a53f94ae0665", [], [{:exquisite, "~> 0.1.7", [hex: :exquisite, repo: "hexpm", optional: false]}], "hexpm"},
"bootloader": {:hex, :bootloader, "0.1.2", "835ddcf50b796714658f342061d5d48ebc34cbd0d81cdbd5a5a8ae00705d72b1", [], [{:distillery, "~> 1.0", [hex: :distillery, repo: "hexpm", optional: false]}], "hexpm"},
"bootloader": {:hex, :bootloader, "0.1.2", "835ddcf50b796714658f342061d5d48ebc34cbd0d81cdbd5a5a8ae00705d72b1", [:mix], [{:distillery, "~> 1.0", [hex: :distillery, repo: "hexpm", optional: false]}], "hexpm"},
"distillery": {:hex, :distillery, "1.5.2", "eec18b2d37b55b0bcb670cf2bcf64228ed38ce8b046bb30a9b636a6f5a4c0080", [], [], "hexpm"},
"dns": {:hex, :dns, "1.0.1", "1d88187fdf564d937cee202949141090707fd0c9d7fcae903a6878ef24ef5d1e", [], [{:socket, "~> 0.3.12", [hex: :socket, repo: "hexpm", optional: false]}], "hexpm"},
"elixir_make": {:hex, :elixir_make, "0.4.0", "992f38fabe705bb45821a728f20914c554b276838433349d4f2341f7a687cddf", [], [], "hexpm"},
"dns": {:hex, :dns, "1.0.1", "1d88187fdf564d937cee202949141090707fd0c9d7fcae903a6878ef24ef5d1e", [:mix], [{:socket, "~> 0.3.12", [hex: :socket, repo: "hexpm", optional: false]}], "hexpm"},
"elixir_make": {:hex, :elixir_make, "0.4.0", "992f38fabe705bb45821a728f20914c554b276838433349d4f2341f7a687cddf", [:mix], [], "hexpm"},
"ex2ms": {:hex, :ex2ms, "1.5.0", "19e27f9212be9a96093fed8cdfbef0a2b56c21237196d26760f11dfcfae58e97", [:mix], [], "hexpm"},
"exquisite": {:hex, :exquisite, "0.1.8", "ee8f56aae477287ce5e7dfcbc163a420cccbb73e680a6d80a09203e9ef514fa4", [], [], "hexpm"},
"mdns": {:hex, :mdns, "0.1.6", "b51b902b15b50e0e1522483c6a5fb073413e3d3d6ef52a44b93a541460b47d29", [], [{:dns, "~> 1.0", [hex: :dns, repo: "hexpm", optional: false]}], "hexpm"},
"nerves": {:hex, :nerves, "0.7.5", "3aa6a336b2ad6c1c9589cc2b577511b3c4c375c1ba6c533ab9f88adb8c21f0c3", [], [{:distillery, "~> 1.4", [hex: :distillery, repo: "hexpm", optional: false]}], "hexpm"},
"nerves_firmware_ssh": {:hex, :nerves_firmware_ssh, "0.3.1", "e8b1967fa0aff255230be539c68ec868d33884193a385caff957ebad7d6aa8af", [], [{:nerves_runtime, "~> 0.4", [hex: :nerves_runtime, repo: "hexpm", optional: false]}], "hexpm"},
"nerves_init_gadget": {:hex, :nerves_init_gadget, "0.2.1", "20f36dd062fb00e2be8817ddff1b9ced9762877cfe23f6ec1d5936a37e3fc2c8", [], [{:mdns, "~> 0.1", [hex: :mdns, repo: "hexpm", optional: false]}, {:nerves_firmware_ssh, "~> 0.2", [hex: :nerves_firmware_ssh, repo: "hexpm", optional: false]}, {:nerves_network, "~> 0.3", [hex: :nerves_network, repo: "hexpm", optional: false]}, {:nerves_runtime, "~> 0.3", [hex: :nerves_runtime, repo: "hexpm", optional: false]}], "hexpm"},
"mdns": {:hex, :mdns, "0.1.6", "b51b902b15b50e0e1522483c6a5fb073413e3d3d6ef52a44b93a541460b47d29", [:mix], [{:dns, "~> 1.0", [hex: :dns, repo: "hexpm", optional: false]}], "hexpm"},
"nerves": {:hex, :nerves, "0.7.5", "3aa6a336b2ad6c1c9589cc2b577511b3c4c375c1ba6c533ab9f88adb8c21f0c3", [:mix], [{:distillery, "~> 1.4", [hex: :distillery, repo: "hexpm", optional: false]}], "hexpm"},
"nerves_firmware_ssh": {:hex, :nerves_firmware_ssh, "0.3.1", "e8b1967fa0aff255230be539c68ec868d33884193a385caff957ebad7d6aa8af", [:mix], [{:nerves_runtime, "~> 0.4", [hex: :nerves_runtime, repo: "hexpm", optional: false]}], "hexpm"},
"nerves_init_gadget": {:hex, :nerves_init_gadget, "0.2.1", "20f36dd062fb00e2be8817ddff1b9ced9762877cfe23f6ec1d5936a37e3fc2c8", [:mix], [{:mdns, "~> 0.1", [hex: :mdns, repo: "hexpm", optional: false]}, {:nerves_firmware_ssh, "~> 0.2", [hex: :nerves_firmware_ssh, repo: "hexpm", optional: false]}, {:nerves_network, "~> 0.3", [hex: :nerves_network, repo: "hexpm", optional: false]}, {:nerves_runtime, "~> 0.3", [hex: :nerves_runtime, repo: "hexpm", optional: false]}], "hexpm"},
"nerves_init_net_kernel": {:git, "https://github.com/mobileoverlord/nerves_init_net_kernel.git", "7772c8558ed5bb32853bb47209621b40b1331ee3", []},
"nerves_io_rc522": {:hex, :nerves_io_rc522, "0.1.0", "5a84a23ff2ac6e4c9cc0ea2931e43cf06d175b991bfd8b0ef664192cee25b7a4", [], [{:elixir_make, "~> 0.3", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm"},
"nerves_network": {:hex, :nerves_network, "0.3.4", "c50a36b8263cda2bee18f408287d0f4474f8367702d170864325abbd5d424e4d", [:make, :mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:nerves_network_interface, "~> 0.4.0", [hex: :nerves_network_interface, repo: "hexpm", optional: false]}, {:nerves_wpa_supplicant, "~> 0.3.0", [hex: :nerves_wpa_supplicant, repo: "hexpm", optional: false]}, {:system_registry, "~> 0.4", [hex: :system_registry, repo: "hexpm", optional: false]}], "hexpm"},
"nerves_network_interface": {:hex, :nerves_network_interface, "0.4.2", "7a3663a07803f2f9f1e37146714d24ccec1e9349268586e4ed8c41f38641d837", [], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm"},
"nerves_runtime": {:hex, :nerves_runtime, "0.5.0", "5f4135fe3c94ca5c9e25d677350fbb136f279d14aac4871236961b6f5ccbcfa5", [], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:system_registry, "~> 0.5", [hex: :system_registry, repo: "hexpm", optional: false]}], "hexpm"},
"nerves_system_br": {:hex, :nerves_system_br, "0.14.1", "b108f8e12b2fd5cfd75be72d8ade4a1cfa9b9fd9076380c431ad930a7ccd5526", [], [], "hexpm"},
"nerves_system_rpi2": {:hex, :nerves_system_rpi2, "0.17.1", "e8e7987d42af17b071e1ece2bedce6ff4c8cbf61ad5587c02bc8d149f67498d8", [], [{:nerves, "~> 0.7", [hex: :nerves, repo: "hexpm", optional: false]}, {:nerves_system_br, "~> 0.14.1", [hex: :nerves_system_br, repo: "hexpm", optional: false]}, {:nerves_toolchain_arm_unknown_linux_gnueabihf, "~> 0.11.0", [hex: :nerves_toolchain_arm_unknown_linux_gnueabihf, repo: "hexpm", optional: false]}], "hexpm"},
"nerves_toolchain_arm_unknown_linux_gnueabihf": {:hex, :nerves_toolchain_arm_unknown_linux_gnueabihf, "0.11.0", "8d7606275a2d19de26ae238cd59475f4c06679aa9222b8987518d7c8a7beae51", [], [{:nerves, "~> 0.7", [hex: :nerves, repo: "hexpm", optional: false]}, {:nerves_toolchain_ctng, "~> 1.1", [hex: :nerves_toolchain_ctng, repo: "hexpm", optional: false]}], "hexpm"},
"nerves_toolchain_ctng": {:hex, :nerves_toolchain_ctng, "1.1.0", "0f03e4a3f3beef5fe271de0148b9f106c417e57f303f635c21c74b4bd6eb68ee", [], [], "hexpm"},
"nerves_network_interface": {:hex, :nerves_network_interface, "0.4.2", "7a3663a07803f2f9f1e37146714d24ccec1e9349268586e4ed8c41f38641d837", [:make, :mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm"},
"nerves_runtime": {:hex, :nerves_runtime, "0.5.0", "5f4135fe3c94ca5c9e25d677350fbb136f279d14aac4871236961b6f5ccbcfa5", [:make, :mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:system_registry, "~> 0.5", [hex: :system_registry, repo: "hexpm", optional: false]}], "hexpm"},
"nerves_system_br": {:hex, :nerves_system_br, "0.14.1", "b108f8e12b2fd5cfd75be72d8ade4a1cfa9b9fd9076380c431ad930a7ccd5526", [:mix], [], "hexpm"},
"nerves_system_rpi2": {:hex, :nerves_system_rpi2, "0.17.1", "e8e7987d42af17b071e1ece2bedce6ff4c8cbf61ad5587c02bc8d149f67498d8", [:mix], [{:nerves, "~> 0.7", [hex: :nerves, repo: "hexpm", optional: false]}, {:nerves_system_br, "~> 0.14.1", [hex: :nerves_system_br, repo: "hexpm", optional: false]}, {:nerves_toolchain_arm_unknown_linux_gnueabihf, "~> 0.11.0", [hex: :nerves_toolchain_arm_unknown_linux_gnueabihf, repo: "hexpm", optional: false]}], "hexpm"},
"nerves_toolchain_arm_unknown_linux_gnueabihf": {:hex, :nerves_toolchain_arm_unknown_linux_gnueabihf, "0.11.0", "8d7606275a2d19de26ae238cd59475f4c06679aa9222b8987518d7c8a7beae51", [:mix], [{:nerves, "~> 0.7", [hex: :nerves, repo: "hexpm", optional: false]}, {:nerves_toolchain_ctng, "~> 1.1", [hex: :nerves_toolchain_ctng, repo: "hexpm", optional: false]}], "hexpm"},
"nerves_toolchain_ctng": {:hex, :nerves_toolchain_ctng, "1.1.0", "0f03e4a3f3beef5fe271de0148b9f106c417e57f303f635c21c74b4bd6eb68ee", [:mix], [], "hexpm"},
"nerves_wpa_supplicant": {:hex, :nerves_wpa_supplicant, "0.3.2", "19dc7e1248336e7f542b11b2b857ceb5b088d3eb41a6ca75b7b76628dcf67aad", [], [{:elixir_make, "~> 0.3", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm"},
"observer_cli": {:hex, :observer_cli, "1.1.0", "f3a47c22327424291758167df3c4600dcf8bf34795a3787612019aa5b86a5c21", [], [{:recon, "2.3.2", [hex: :recon, repo: "hexpm", optional: false]}], "hexpm"},
"recon": {:hex, :recon, "2.3.2", "4444c879be323b1b133eec5241cb84bd3821ea194c740d75617e106be4744318", [], [], "hexpm"},
"socket": {:hex, :socket, "0.3.12", "4a6543815136503fee67eff0932da1742fad83f84c49130c854114153cc549a6", [], [], "hexpm"},
"system_registry": {:hex, :system_registry, "0.6.0", "31642177e6002d3cff2ada3553ed4e9c0a6ca015797d62d7d17c0ab8696185fc", [], [], "hexpm"},
"socket": {:hex, :socket, "0.3.12", "4a6543815136503fee67eff0932da1742fad83f84c49130c854114153cc549a6", [:mix], [], "hexpm"},
"system_registry": {:hex, :system_registry, "0.6.0", "31642177e6002d3cff2ada3553ed4e9c0a6ca015797d62d7d17c0ab8696185fc", [:mix], [], "hexpm"},
"uuid": {:hex, :uuid, "1.1.8", "e22fc04499de0de3ed1116b770c7737779f226ceefa0badb3592e64d5cfb4eb9", [:mix], [], "hexpm"},
}