Skip to content

Commit 5519e8c

Browse files
committed
Add freezer_eye_fw to deploy on device with nerves
1 parent 600da12 commit 5519e8c

File tree

17 files changed

+521
-4
lines changed

17 files changed

+521
-4
lines changed

README.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ of the umbrella app's `app/<app_name>` folder structure.
1212

1313
The project is made up of the following libraries:
1414

15+
* [`freezer_eye_fw`](freezer_eye_fw): Nerves firmware that runs the freezer_eye
16+
application
1517
* [`freezer_eye`](freezer_eye): Main application logic of freezer_eye.
1618
* [`fe_reporting`](fe_reporting): Internal application that manages how
1719
freezer_eye interacts with the chosen reporting service. The default
@@ -27,10 +29,11 @@ needed. This gets run on the CI pipeline as well.
2729
The dependency tree looks like this:
2830

2931
```
30-
freezer_eye
31-
├── fe_test_helpers (../fe_test_helpers)
32-
└── fe_reporting (../fe_reporting)
33-
└── adafruit_io_http_client (../adafruit_io_http_client)
32+
freezer_eye_fw
33+
└── freezer_eye (../freezer_eye)
34+
├── fe_test_helpers (../fe_test_helpers)
35+
└── fe_reporting (../fe_reporting)
36+
└── adafruit_io_http_client (../adafruit_io_http_client)
3437
```
3538

3639
[poncho_project]: https://embedded-elixir.com/post/2017-05-19-poncho-projects/

freezer_eye_fw/.formatter.exs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Used by "mix format"
2+
[
3+
inputs: ["mix.exs", "{config,lib,test}/**/*.{ex,exs}"]
4+
]

freezer_eye_fw/.gitignore

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# The directory Mix will write compiled artifacts to.
2+
/_build/
3+
4+
# If you run "mix test --cover", coverage assets end up here.
5+
/cover/
6+
7+
# The directory Mix downloads your dependencies sources to.
8+
/deps/
9+
10+
# Where 3rd-party dependencies like ExDoc output generated docs.
11+
/doc/
12+
13+
# Ignore .fetch files in case you like to edit your project deps locally.
14+
/.fetch
15+
16+
# If the VM crashes, it generates a dump, let's ignore it too.
17+
erl_crash.dump
18+
19+
# Ignore secret files
20+
/config/*.secret.exs

freezer_eye_fw/README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# FreezerEyeFW
2+
3+
Nerves firmware for FreezerEye
4+
5+
## Development
6+
7+
## Handling secrets
8+
9+
In order to keep secrets out of source control, this project keeps its development settings in an optional config.secret.exs.
10+
11+
cp config/config.secret.exs.template config/config.secret.exs
12+
13+
Once the template is copied, update them with your desired settings.
14+
15+
## Building the project
16+
17+
1. `export MIX_TARGET=rpi0` - To set the target you're compiling for
18+
2. `mix deps.get` - Fetch the dependencies
19+
3. `mix firmware` - Build the firmware
20+
4. `mix firmware.burn` or `./upload.sh` to burn the program onto a SD card
21+
or do an OTA update, respectively.

freezer_eye_fw/config/config.exs

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# This file is responsible for configuring your application
2+
# and its dependencies with the aid of the Mix.Config module.
3+
#
4+
# This configuration file is loaded before any dependency and
5+
# is restricted to this project.
6+
use Mix.Config
7+
8+
# Customize non-Elixir parts of the firmware. See
9+
# https://hexdocs.pm/nerves/advanced-configuration.html for details.
10+
11+
config :nerves, :firmware, rootfs_overlay: "rootfs_overlay"
12+
13+
# Use shoehorn to start the main application. See the shoehorn
14+
# docs for separating out critical OTP applications such as those
15+
# involved with firmware updates.
16+
17+
config :shoehorn,
18+
init: [:nerves_runtime, :nerves_init_gadget],
19+
app: Mix.Project.config()[:app]
20+
21+
# Use Ringlogger as the logger backend and remove :console.
22+
# See https://hexdocs.pm/ring_logger/readme.html for more information on
23+
# configuring ring_logger.
24+
25+
config :logger, backends: [RingLogger]
26+
27+
# Authorize the device to receive firmware using your public key.
28+
# See https://hexdocs.pm/nerves_firmware_ssh/readme.html for more information
29+
# on configuring nerves_firmware_ssh.
30+
31+
keys =
32+
[
33+
Path.join([System.user_home!(), ".ssh", "id_rsa.pub"]),
34+
Path.join([System.user_home!(), ".ssh", "id_ecdsa.pub"]),
35+
Path.join([System.user_home!(), ".ssh", "id_ed25519.pub"])
36+
]
37+
|> Enum.filter(&File.exists?/1)
38+
39+
if keys == [],
40+
do:
41+
Mix.raise("""
42+
No SSH public keys found in ~/.ssh. An ssh authorized key is needed to
43+
log into the Nerves device and update firmware on it using ssh.
44+
See your project's config.exs for this error message.
45+
""")
46+
47+
config :nerves_firmware_ssh,
48+
authorized_keys: Enum.map(keys, &File.read!/1)
49+
50+
# Configure nerves_init_gadget.
51+
# See https://hexdocs.pm/nerves_init_gadget/readme.html for more information.
52+
53+
# Setting the node_name will enable Erlang Distribution.
54+
# Only enable this for prod if you understand the risks.
55+
node_name = if Mix.env() != :prod, do: "freezer_eye_fw"
56+
57+
config :nerves_init_gadget,
58+
ifname: "wlan0",
59+
address_method: :dhcp,
60+
mdns_domain: "nerves.local",
61+
node_name: node_name,
62+
node_host: :mdns_domain
63+
64+
# Configure wireless settings
65+
66+
config :nerves_network,
67+
regulatory_domain: "US"
68+
69+
# Application specific config
70+
config :freezer_eye,
71+
heartbeat_interval: 60_000
72+
73+
config :fe_reporting, :adafruit_io, heartbeat_value: 1
74+
75+
# Support optional config.secret.exs files
76+
try do
77+
import_config "config.secret.exs"
78+
rescue
79+
Code.LoadError -> :ok
80+
end
81+
82+
# Import target specific config. This must remain at the bottom
83+
# of this file so it overrides the configuration defined above.
84+
# Uncomment to use target specific configurations
85+
86+
# import_config "#{Mix.target()}.exs"
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
use Mix.Config
2+
3+
config :nerves_network, :default,
4+
wlan0: [
5+
ssid: "set me",
6+
psk: "set me",
7+
key_mgmt: :"WPA-PSK"
8+
]
9+
10+
config :fe_reporting, :adafruit_io,
11+
username: "set me",
12+
secret_key: "set me",
13+
heartbeat_feed: "set me",
14+
heartbeat_value: 1

freezer_eye_fw/lib/freezer_eye_fw.ex

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
defmodule FreezerEyeFW do
2+
@moduledoc """
3+
Nerves firmware for FreezerEye
4+
"""
5+
end
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
defmodule FreezerEyeFW.Application do
2+
# See https://hexdocs.pm/elixir/Application.html
3+
# for more information on OTP Applications
4+
@moduledoc false
5+
6+
@target Mix.target()
7+
8+
use Application
9+
10+
def start(_type, _args) do
11+
# See https://hexdocs.pm/elixir/Supervisor.html
12+
# for other strategies and supported options
13+
opts = [strategy: :one_for_one, name: FreezerEyeFW.Supervisor]
14+
Supervisor.start_link(children(@target), opts)
15+
end
16+
17+
# List all child processes to be supervised
18+
def children(:host) do
19+
[
20+
# Starts a worker by calling: FreezerEyeFW.Worker.start_link(arg)
21+
# {FreezerEyeFW.Worker, arg},
22+
]
23+
end
24+
25+
def children(_target) do
26+
[
27+
# Starts a worker by calling: FreezerEyeFW.Worker.start_link(arg)
28+
# {FreezerEyeFW.Worker, arg},
29+
]
30+
end
31+
end

freezer_eye_fw/mix.exs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
defmodule FreezerEyeFW.MixProject do
2+
use Mix.Project
3+
4+
@all_targets [:rpi0]
5+
6+
def project do
7+
[
8+
app: :freezer_eye_fw,
9+
version: "0.1.0",
10+
elixir: "~> 1.8",
11+
archives: [nerves_bootstrap: "~> 1.5"],
12+
start_permanent: Mix.env() == :prod,
13+
build_embedded: true,
14+
aliases: [loadconfig: [&bootstrap/1]],
15+
deps: deps()
16+
]
17+
end
18+
19+
# Starting nerves_bootstrap adds the required aliases to Mix.Project.config()
20+
# Aliases are only added if MIX_TARGET is set.
21+
def bootstrap(args) do
22+
Application.start(:nerves_bootstrap)
23+
Mix.Task.run("loadconfig", args)
24+
end
25+
26+
# Run "mix help compile.app" to learn about applications.
27+
def application do
28+
[
29+
mod: {FreezerEyeFW.Application, []},
30+
extra_applications: [:logger, :runtime_tools]
31+
]
32+
end
33+
34+
# Run "mix help deps" to learn about dependencies.
35+
defp deps do
36+
[
37+
# Dependencies for all targets
38+
{:nerves, "~> 1.4", runtime: false},
39+
{:shoehorn, "~> 0.4"},
40+
{:ring_logger, "~> 0.6"},
41+
{:toolshed, "~> 0.2"},
42+
{:freezer_eye, path: "../freezer_eye"},
43+
44+
# Dependencies for all targets except :host
45+
{:nerves_runtime, "~> 0.6", targets: @all_targets},
46+
{:nerves_init_gadget, "~> 0.4", targets: @all_targets},
47+
{:nerves_time, "~> 0.2", targets: @all_targets},
48+
49+
# Dependencies for specific targets
50+
{:nerves_system_rpi0, "~> 1.6", runtime: false, targets: :rpi0}
51+
]
52+
end
53+
end

freezer_eye_fw/mix.lock

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
%{
2+
"artificery": {:hex, :artificery, "0.4.2", "3ded6e29e13113af52811c72f414d1e88f711410cac1b619ab3a2666bbd7efd4", [:mix], [], "hexpm"},
3+
"certifi": {:hex, :certifi, "2.5.1", "867ce347f7c7d78563450a18a6a28a8090331e77fa02380b4a21962a65d36ee5", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm"},
4+
"distillery": {:hex, :distillery, "2.0.12", "6e78fe042df82610ac3fa50bd7d2d8190ad287d120d3cd1682d83a44e8b34dfb", [:mix], [{:artificery, "~> 0.2", [hex: :artificery, repo: "hexpm", optional: false]}], "hexpm"},
5+
"dns": {:hex, :dns, "2.1.2", "81c46d39f7934f0e73368355126e4266762cf227ba61d5889635d83b2d64a493", [:mix], [{:socket, "~> 0.3.13", [hex: :socket, repo: "hexpm", optional: false]}], "hexpm"},
6+
"elixir_make": {:hex, :elixir_make, "0.5.2", "96a28c79f5b8d34879cd95ebc04d2a0d678cfbbd3e74c43cb63a76adf0ee8054", [:mix], [], "hexpm"},
7+
"hackney": {:hex, :hackney, "1.15.1", "9f8f471c844b8ce395f7b6d8398139e26ddca9ebc171a8b91342ee15a19963f4", [:rebar3], [{:certifi, "2.5.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.4", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"},
8+
"idna": {:hex, :idna, "6.0.0", "689c46cbcdf3524c44d5f3dde8001f364cd7608a99556d8fbd8239a5798d4c10", [:rebar3], [{:unicode_util_compat, "0.4.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"},
9+
"jason": {:hex, :jason, "1.1.2", "b03dedea67a99223a2eaf9f1264ce37154564de899fd3d8b9a21b1a6fd64afe7", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"},
10+
"mdns": {:hex, :mdns, "1.0.2", "c8228dd44d3fdd55e9842cb7111c9145f2eeaa8b7adac75012ee0e250962215e", [:mix], [{:dns, "~> 2.0", [hex: :dns, repo: "hexpm", optional: false]}], "hexpm"},
11+
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm"},
12+
"mime": {:hex, :mime, "1.3.1", "30ce04ab3175b6ad0bdce0035cba77bba68b813d523d1aac73d9781b4d193cf8", [:mix], [], "hexpm"},
13+
"mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm"},
14+
"muontrap": {:hex, :muontrap, "0.4.1", "4d12af9d1a8f45037cf6d602b614bdc1e1781d110b0fef5df4c3a0aaec76dfae", [:make, :mix], [{:elixir_make, "~> 0.5", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm"},
15+
"nerves": {:hex, :nerves, "1.4.4", "7d2d6c0129d541e12ed12117ae059e7db8849faaefc4b4d30f4af55ba6f8d089", [:mix], [{:distillery, "2.0.12", [hex: :distillery, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm"},
16+
"nerves_firmware_ssh": {:hex, :nerves_firmware_ssh, "0.4.3", "043912d54d1774ef62979465cfd2dbbb407e2bf4f8622b6d388f64ed4ae1a3b8", [:mix], [{:nerves_runtime, "~> 0.6", [hex: :nerves_runtime, repo: "hexpm", optional: false]}], "hexpm"},
17+
"nerves_init_gadget": {:hex, :nerves_init_gadget, "0.6.0", "64eb8877b438678aed6d421737326a8cac3810b425e00abd5c7a3a0e95054988", [:mix], [{:mdns, "~> 1.0", [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]}, {:one_dhcpd, "~> 0.1", [hex: :one_dhcpd, repo: "hexpm", optional: false]}, {:ring_logger, "~> 0.4", [hex: :ring_logger, repo: "hexpm", optional: false]}], "hexpm"},
18+
"nerves_network": {:hex, :nerves_network, "0.5.5", "4690c362707f76c4072810bd9639b2ae8eb7dd9c21119656308b462a087230aa", [:make, :mix], [{:elixir_make, "~> 0.5", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:nerves_network_interface, "~> 0.4.4", [hex: :nerves_network_interface, repo: "hexpm", optional: false]}, {:nerves_wpa_supplicant, "~> 0.5", [hex: :nerves_wpa_supplicant, repo: "hexpm", optional: false]}, {:one_dhcpd, "~> 0.2.0", [hex: :one_dhcpd, repo: "hexpm", optional: false]}, {:system_registry, "~> 0.7", [hex: :system_registry, repo: "hexpm", optional: false]}], "hexpm"},
19+
"nerves_network_interface": {:hex, :nerves_network_interface, "0.4.6", "d50e57daca8154f0f780fd98eb5ae94a005579e0d72d69840e80e228375d88ad", [:make, :mix], [{:elixir_make, "~> 0.5", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm"},
20+
"nerves_runtime": {:hex, :nerves_runtime, "0.9.5", "029ae154c8a85c5c4dc0dfcc5c2be976982fc6007426d8bb631726f1625adfce", [:make, :mix], [{:elixir_make, "~> 0.5", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:system_registry, "~> 0.5", [hex: :system_registry, repo: "hexpm", optional: false]}, {:uboot_env, "~> 0.1", [hex: :uboot_env, repo: "hexpm", optional: false]}], "hexpm"},
21+
"nerves_system_br": {:hex, :nerves_system_br, "1.7.2", "e34895b19241a6f847e16c4b659e89566376ee3a9e8af303f0d36c73d1a98c64", [:mix], [], "hexpm"},
22+
"nerves_system_linter": {:hex, :nerves_system_linter, "0.3.0", "84e0f63c8ac196b16b77608bbe7df66dcf352845c4e4fb394bffd2b572025413", [:mix], [], "hexpm"},
23+
"nerves_system_rpi0": {:hex, :nerves_system_rpi0, "1.7.2", "7bff1a168d83c1f4ece902ffc1a7f6b782d12062dbe01e47f77e29cb48d23369", [:mix], [{:nerves, "~> 1.3", [hex: :nerves, repo: "hexpm", optional: false]}, {:nerves_system_br, "1.7.2", [hex: :nerves_system_br, repo: "hexpm", optional: false]}, {:nerves_system_linter, "~> 0.3.0", [hex: :nerves_system_linter, repo: "hexpm", optional: false]}, {:nerves_toolchain_armv6_rpi_linux_gnueabi, "1.1.0", [hex: :nerves_toolchain_armv6_rpi_linux_gnueabi, repo: "hexpm", optional: false]}], "hexpm"},
24+
"nerves_time": {:hex, :nerves_time, "0.2.1", "7472fdc643c4dd93b841c710b84aa83ac6ef6879b50b7568b2ed8c862db673aa", [:make, :mix], [{:elixir_make, "~> 0.5", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:muontrap, "~> 0.4", [hex: :muontrap, repo: "hexpm", optional: false]}], "hexpm"},
25+
"nerves_toolchain_armv6_rpi_linux_gnueabi": {:hex, :nerves_toolchain_armv6_rpi_linux_gnueabi, "1.1.0", "2753102e667d9778047b351618f3dfdc016b81148df58d142fee7630d96a31fe", [:mix], [{:nerves, "~> 1.0", [hex: :nerves, repo: "hexpm", optional: false]}, {:nerves_toolchain_ctng, "~> 1.5.0", [hex: :nerves_toolchain_ctng, repo: "hexpm", optional: false]}], "hexpm"},
26+
"nerves_toolchain_ctng": {:hex, :nerves_toolchain_ctng, "1.5.0", "34b8f5664858ff6ce09730b26221441398acd1fa361b8c6d744d9ec18238c16b", [:mix], [{:nerves, "~> 1.0", [hex: :nerves, repo: "hexpm", optional: false]}], "hexpm"},
27+
"nerves_wpa_supplicant": {:hex, :nerves_wpa_supplicant, "0.5.2", "4ec392fc08faf35f50d1070446c2e5019f6b85bd53f5716f904e3f75716d9596", [:make, :mix], [{:elixir_make, "~> 0.5", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm"},
28+
"one_dhcpd": {:hex, :one_dhcpd, "0.2.2", "2dfdcad61ed7c6d9f652bc1a06f14924a497de2c2aa2d4f48ee3b1aa13be0f33", [:make, :mix], [{:elixir_make, "~> 0.5", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm"},
29+
"parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm"},
30+
"ring_logger": {:hex, :ring_logger, "0.7.0", "37c748addaaaf35bcbe5a9e0506019bce9a56ef75e3178857ddc9390321b3d31", [:mix], [], "hexpm"},
31+
"shoehorn": {:hex, :shoehorn, "0.5.0", "da8e37dbee92454dd8e20c86953de94bdcaddb2dcda6c72cf4a3de5f52e0f322", [:mix], [{:distillery, "~> 2.0", [hex: :distillery, repo: "hexpm", optional: false]}], "hexpm"},
32+
"socket": {:hex, :socket, "0.3.13", "98a2ab20ce17f95fb512c5cadddba32b57273e0d2dba2d2e5f976c5969d0c632", [:mix], [], "hexpm"},
33+
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.4", "f0eafff810d2041e93f915ef59899c923f4568f4585904d010387ed74988e77b", [:make, :mix, :rebar3], [], "hexpm"},
34+
"system_registry": {:hex, :system_registry, "0.8.2", "df791dc276652fcfb53be4dab823e05f8269b96ac57c26f86a67838dbc0eefe7", [:mix], [], "hexpm"},
35+
"tesla": {:hex, :tesla, "1.2.1", "864783cc27f71dd8c8969163704752476cec0f3a51eb3b06393b3971dc9733ff", [:mix], [{:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]}, {:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "~> 4.4.0", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}], "hexpm"},
36+
"toolshed": {:hex, :toolshed, "0.2.8", "836e010c580ffe9c4cec336075db6f5c29ee8ab4197df251cb200676edeb6ef1", [:mix], [{:nerves_runtime, "~> 0.8", [hex: :nerves_runtime, repo: "hexpm", optional: true]}], "hexpm"},
37+
"uboot_env": {:hex, :uboot_env, "0.1.1", "b01e3ec0973e99473234f27839e29e63b5b81eba6a136a18a78d049d4813d6c5", [:mix], [], "hexpm"},
38+
"unicode_util_compat": {:hex, :unicode_util_compat, "0.4.1", "d869e4c68901dd9531385bb0c8c40444ebf624e60b6962d95952775cac5e90cd", [:rebar3], [], "hexpm"},
39+
}

0 commit comments

Comments
 (0)