changed CHANGELOG.md
 
@@ -1,15 +1,80 @@
1
1
# Changelog
2
2
3
+ ## v0.12.0 - 2024-1-1
4
+
5
+ Happy New Year!
6
+
7
+ * Updates
8
+ * Update Livebook to [v0.12.1](https://github.com/livebook-dev/livebook/releases/tag/v0.12.1)
9
+ * Fix Raspberry Pi 3 regression in v0.11.1
10
+ * Update Elixir to 1.16.0
11
+ * SBOM generation is temporarily off pending a PR getting merged
12
+
13
+ ## v0.11.1 - 2023-12-19
14
+
15
+ * Updates
16
+ * Add 64-bit RPi Zero 2W (`rpi0_2`). 32-bit mode was supported before via
17
+ `rpi3a`, but this enables the JIT
18
+ * Add RPi 5 (`rpi5`). This port is current experimental
19
+ * Update Nerves systems to nerves_system_br 1.25.2 versions
20
+ * Erlang 26.1.2
21
+ * Buildroot 2023.08.4
22
+ * Linux 6.1 on all Raspberry Pi and BBB ports
23
+ * Update Elixir to 1.15.7
24
+ * Update all dependencies to their latest versions
25
+
26
+ ## v0.11.0 - 2023-10-09
27
+
28
+ * Updates
29
+ * Update Livebook to [v0.11.0](https://github.com/livebook-dev/livebook/releases/tag/v0.11.0)
30
+ * Update Nerves systems to nerves_system_br 1.24.1 versions
31
+ * Erlang 26.1.1
32
+ * Buildroot 2023.05.3
33
+ * Update Elixir to 1.15.6
34
+ * Update all dependencies to their latest versions
35
+
36
+ ## v0.10.1 - 2023-07-29
37
+
38
+ * Updates
39
+ * Add `:tflite_elixir` back since it works again
40
+ * Update Nerves systems to nerves_system_br 1.23.2 versions to get CTRL+R fix
41
+ for ssh sessions (and more).
42
+ * Improve PMOD support on GRiSP 2
43
+ * Update Elixir to 1.15.4
44
+
45
+ ## v0.10.0 - 2023-07-14
46
+
47
+ * Updates
48
+ * Update Livebook to [v0.10.0](https://github.com/livebook-dev/livebook/releases/tag/v0.10.0)
49
+ * Update Nerves systems to nerves_system_br 1.23.1 versions. This includes:
50
+ * Erlang 26.0.2
51
+ * Support for all Raspberry Pi Cameras via libcamera on the RPi4
52
+ * Buildroot 2023.02.2
53
+ * Linux updates on various systems
54
+ * Update Elixir to 1.15.2
55
+ * Update all dependencies to their latest versions
56
+
57
+ NOTE: `:tflite_elixir` is temporily removed due to build errors.
58
+
59
+ ## v0.9.1 - 2023-05-14
60
+
61
+ * Updates
62
+ * Update Livebook to [v0.9.2](https://github.com/livebook-dev/livebook/releases/tag/v0.9.2)
63
+ * Include TFLite (`:tflite_elixir`) for all devices that support TensorFlow
64
+ Lite (all but Raspberry Pi 1 and Raspberry Pi Zero). See the `tflite.livemd`
65
+ sample to a quick intro. Thanks to Masatoshi Nishiguchi for this.
66
+ * Update all dependencies to their latest versions.
67
+
3
68
## v0.9.0 - 2023-04-05
4
69
5
70
* Updates
6
- * Update Livebook to [v0.9.1](https://github.com/livebook-dev/livebook/blob/main/CHANGELOG.md#v091-2023-04-06)
71
+ * Update Livebook to [v0.9.1](https://github.com/livebook-dev/livebook/releases/tag/v0.9.1)
7
72
* Update Nerves systems to nerves_system_br 1.22.5 versions. This includes
8
73
Erlang 25.3 and fixes to the Raspberry Pi 3 to support TensorFlow Lite.
9
74
(TFLite isn't built into Nerves Livebook yet)
10
75
* Update all dependencies to their latest versions.
11
76
12
- Fixes
77
+ * Fixes
13
78
* Fixed LEDs on SRHub images (Thanks to Eric Oestrich)
14
79
15
80
## v0.8.3 - 2023-03-12
 
@@ -26,7 +91,7 @@ Fixes
26
91
## v0.8.2 - 2023-02-11
27
92
28
93
* Updates
29
- * Update Livebook to [v0.8.1](https://github.com/livebook-dev/livebook/blob/main/CHANGELOG.md#v081-2023-01-18)
94
+ * Update Livebook to [v0.8.1](https://github.com/livebook-dev/livebook/releases/tag/v0.8.2)
30
95
* Update all dependencies to latest (Nx 0.5.0, RingLogger 0.9.0, Toolshed
31
96
0.3.0, VintageNet 0.13.0)
32
97
* Configure the Erlang compiler for deterministic builds
 
@@ -50,7 +115,7 @@ it. Upgrading is not supported.
50
115
## v0.8.0 - 2022-12-19
51
116
52
117
* Updates
53
- * Update Livebook to [v0.8.0](https://github.com/livebook-dev/livebook/blob/main/CHANGELOG.md#v080-2022-12-08)
118
+ * Update Livebook to [v0.8.0](https://github.com/livebook-dev/livebook/releases/tag/v0.8.0)
54
119
* Reduced logger level to warning to reduce clutter when evaluating cells.
55
120
This is a the same default level as regular Livebook.
56
121
* Support the shutdown button. This will gracefully power off your device.
 
@@ -63,14 +128,14 @@ it. Upgrading is not supported.
63
128
## v0.7.2 - 2022-11-07
64
129
65
130
* Updates
66
- * Update Livebook to [v0.7.2](https://github.com/livebook-dev/livebook/blob/main/CHANGELOG.md#v072-2022-10-26)
131
+ * Update Livebook to [v0.7.2](https://github.com/livebook-dev/livebook/releases/tag/v0.7.2)
67
132
* Update Nerves systems to `nerves_system_br` 1.21.2 versions
68
133
* Fix hyperlinks and move more pages to learn sections (Thanks @mnishiguchi)
69
134
70
135
## v0.7.0 - 2022-10-09
71
136
72
137
* Updates
73
- * Update Livebook to [v0.7.1](https://github.com/livebook-dev/livebook/blob/main/CHANGELOG.md#v071-2022-10-09)
138
+ * Update Livebook to [v0.7.1](https://github.com/livebook-dev/livebook/releases/tag/v0.7.1)
74
139
* Update Nerves systems to `nerves_system_br` 1.20.6 versions
75
140
* Update Nerves to v1.9.1
76
141
 
@@ -87,7 +152,7 @@ it. Upgrading is not supported.
87
152
## v0.6.4 - 2022-08-08
88
153
89
154
* Updates
90
- * Update Livebook to [v0.6.3](https://github.com/livebook-dev/livebook/blob/main/CHANGELOG.md#v063-2022-07-13)
155
+ * Update Livebook to [v0.6.3](https://github.com/livebook-dev/livebook/releases/tag/v0.6.3)
91
156
* Update Nerves systems to `nerves_system_br` 1.20.4 versions. This includes
92
157
Erlang/OTP 25.0.3, Buildroot 2022.05, and GCC 11.3.
93
158
* Fix warnings when building in host mode. (Thanks @axelson)
 
@@ -97,7 +162,7 @@ it. Upgrading is not supported.
97
162
## v0.6.3 - 2022-07-08
98
163
99
164
* Updates
100
- * Update Livebook to [v0.6.2](https://github.com/livebook-dev/livebook/blob/main/CHANGELOG.md#v062-2022-06-30)
165
+ * Update Livebook to [v0.6.2](https://github.com/livebook-dev/livebook/releases/tag/v0.6.2)
101
166
* Support the 64-bit RISC-V MangoPi MQ Pro
102
167
* Change the WiFi regulatory domain default from `US` to the global region (`00`)
103
168
* Update Nerves systems to `nerves_system_br` 1.20.3 versions. This includes
 
@@ -119,7 +184,7 @@ it. Upgrading is not supported.
119
184
## v0.6.0 - 2022-05-07
120
185
121
186
* Updates
122
- * Update Livebook to [v0.6.1](https://github.com/livebook-dev/livebook/blob/main/CHANGELOG.md#v061-2022-05-06)
187
+ * Update Livebook to [v0.6.1](https://github.com/livebook-dev/livebook/releases/tag/v0.6.1)
123
188
124
189
## v0.5.7 - 2022-03-18
125
190
 
@@ -158,7 +223,7 @@ it. Upgrading is not supported.
158
223
## v0.5.2 - 2022-01-31
159
224
160
225
* Updates
161
- * Update Livebook to [v0.5.2](https://github.com/livebook-dev/livebook/blob/main/CHANGELOG.md#v052-2022-01-27)
226
+ * Update Livebook to [v0.5.2](https://github.com/livebook-dev/livebook/releases/tag/v0.5.2)
162
227
* Turn on an LED when networking on the device is ready. This isn't perfect
163
228
for showing status, but aims to be more helpful than the current lack of
164
229
feedback.
 
@@ -172,7 +237,7 @@ it. Upgrading is not supported.
172
237
## v0.5.0 - 2022-01-20
173
238
174
239
* Updates
175
- * Update Livebook to [v0.5.1](https://github.com/livebook-dev/livebook/blob/main/CHANGELOG.md#v051-2022-01-20)
240
+ * Update Livebook to [v0.5.1](https://github.com/livebook-dev/livebook/releases/tag/v0.5.1)
176
241
177
242
## v0.4.2 - 2022-01-16
178
243
 
@@ -185,8 +250,7 @@ it. Upgrading is not supported.
185
250
## v0.4.1 - 2021-12-31
186
251
187
252
* Updates
188
- * Update Livebook to
189
- [v0.4.1](https://github.com/livebook-dev/livebook/blob/main/CHANGELOG.md#v041-2021-12-09)
253
+ * Update Livebook to [v0.4.1](https://github.com/livebook-dev/livebook/releases/tag/v0.4.1)
190
254
* Update Elixir to 1.13.1
191
255
* Update Nerves Systems to use Erlang 24.2, Buildroot 2021.11 and
192
256
miscellaneous platform-specific bug fixes and improvements.
 
@@ -195,8 +259,7 @@ it. Upgrading is not supported.
195
259
## v0.4.0 - 2021-12-05
196
260
197
261
* Updates
198
- * Update Livebook to
199
- [v0.4.0](https://github.com/livebook-dev/livebook/blob/main/CHANGELOG.md#v040-2021-12-05)
262
+ * Update Livebook to [v0.4.0](https://github.com/livebook-dev/livebook/releases/tag/v0.4.0)
200
263
* Update Elixir to 1.13.0
201
264
* Update Nerves Systems to use Erlang 24.1.7, Buildroot 2021.08.2 and
202
265
miscellaneous platform-specific bug fixes and improvements.
 
@@ -252,8 +315,7 @@ this release, the old directory will be kept in case any modifications were made
252
315
to notebooks there.
253
316
254
317
* Updates
255
- * Update Livebook from `v0.2.3` to
256
- [`main@d8a7af62`](https://github.com/livebook-dev/livebook/blob/d8a7af62e78c664b667cb30c8430a1b56e412500/CHANGELOG.md).
318
+ * Update Livebook from `v0.2.3` to [`main@d8a7af62`](https://github.com/livebook-dev/livebook/blob/d8a7af62e78c664b667cb30c8430a1b56e412500/CHANGELOG.md).
257
319
See the unreleased items in the link for Livebook changes.
258
320
* Redirect to the device's specific hostname when using `nerves.local` to
259
321
connect. This makes it more obvious which device you're connected to when
changed README.md
 
@@ -1,11 +1,11 @@
1
1
# Nerves Livebook Firmware
2
2
3
- [![CircleCI](https://circleci.com/gh/livebook-dev/nerves_livebook.svg?style=svg)](https://circleci.com/gh/livebook-dev/nerves_livebook)
3
+ [![CircleCI](https://circleci.com/gh/nerves-livebook/nerves_livebook.svg?style=svg)](https://circleci.com/gh/nerves-livebook/nerves_livebook)
4
4
5
5
The Nerves Livebook firmware lets you try out the Nerves projects on real
6
6
hardware without needing to build anything. Within minutes, you'll have a
7
7
Raspberry Pi or Beaglebone running Nerves. You'll be able to run code in
8
- [Livebook](https://github.com/livebook-dev/livebook) and work through Nerves
8
+ [Livebook](https://github.com/nerves-livebook/nerves_livebook) and work through Nerves
9
9
tutorials from the comfort of your browser.
10
10
11
11
Looking for a quick demo first? Click below for [Underjord's](https://underjord.io/) Nerves Quickstart video.
 
@@ -39,7 +39,7 @@ than the others.
39
39
If you're using a GRiSP 2, skip to the installation instructions below for it.
40
40
41
41
First, find the appropriate firmware or zip'd image file for your hardware in the
42
- [releases](https://github.com/livebook-dev/nerves_livebook/releases). This is a
42
+ [releases](https://github.com/nerves-livebook/nerves_livebook/releases). This is a
43
43
one time step. There's a Livebook notebook for upgrading the firmware for when
44
44
we make releases!
45
45
 
@@ -122,7 +122,7 @@ to do a first time install. Even if you do have Nerves on your GRiSP 2, you can
122
122
still follow these instructions.
123
123
124
124
First, download `nerves_livebook_grisp2.img.gz`from the latest
125
- [releases](https://github.com/livebook-dev/nerves_livebook/releases).
125
+ [releases](https://github.com/nerves-livebook/nerves_livebook/releases).
126
126
127
127
1. Copy `nerves_livebook_grisp2.img.gz` to a FAT-formatted MicroSD card:
128
128
 
@@ -210,7 +210,7 @@ To build the Nerves Livebook firmware, make sure that you have run through the
210
210
Nerves installation steps. Then open a terminal window and run the following:
211
211
212
212
```sh
213
- $ git clone https://github.com/livebook-dev/nerves_livebook.git
213
+ $ git clone https://github.com/nerves-livebook/nerves_livebook.git
214
214
$ cd nerves_livebook
215
215
216
216
# Set the MIX_TARGET to the desired platform (rpi0, bbb, rpi3, etc.)
changed hex_metadata.config
 
@@ -1,7 +1,10 @@
1
- {<<"app">>,<<"nerves_livebook">>}.
2
- {<<"build_tools">>,[<<"mix">>]}.
1
+ {<<"links">>,
2
+ [{<<"GitHub">>,<<"https://github.com/nerves-livebook/nerves_livebook">>}]}.
3
+ {<<"name">>,<<"nerves_livebook">>}.
4
+ {<<"version">>,<<"0.12.0">>}.
3
5
{<<"description">>,<<"Develop on embedded devices with Livebook and Nerves">>}.
4
6
{<<"elixir">>,<<"~> 1.14">>}.
7
+ {<<"app">>,<<"nerves_livebook">>}.
5
8
{<<"files">>,
6
9
[<<"CHANGELOG.md">>,<<"lib">>,<<"lib/nerves_livebook">>,
7
10
<<"lib/nerves_livebook/ui.ex">>,
 
@@ -45,265 +48,288 @@
45
48
<<"priv/samples/networking/cellular_demo_qmi.livemd">>,
46
49
<<"priv/samples/bluetooth">>,
47
50
<<"priv/samples/bluetooth/ble_device_with_nerves.livemd">>,
48
- <<"priv/samples/debug">>,<<"priv/samples/debug/diagnostics.livemd">>]}.
51
+ <<"priv/samples/tflite.livemd">>,<<"priv/samples/debug">>,
52
+ <<"priv/samples/debug/diagnostics.livemd">>]}.
49
53
{<<"licenses">>,[<<"Apache-2.0">>]}.
50
- {<<"links">>,
51
- [{<<"GitHub">>,<<"https://github.com/livebook-dev/nerves_livebook">>}]}.
52
- {<<"name">>,<<"nerves_livebook">>}.
53
54
{<<"requirements">>,
54
- [[{<<"app">>,<<"nerves">>},
55
- {<<"name">>,<<"nerves">>},
55
+ [[{<<"name">>,<<"nerves">>},
56
+ {<<"app">>,<<"nerves">>},
56
57
{<<"optional">>,false},
57
- {<<"repository">>,<<"hexpm">>},
58
- {<<"requirement">>,<<"~> 1.10">>}],
59
- [{<<"app">>,<<"shoehorn">>},
60
- {<<"name">>,<<"shoehorn">>},
58
+ {<<"requirement">>,<<"~> 1.10">>},
59
+ {<<"repository">>,<<"hexpm">>}],
60
+ [{<<"name">>,<<"shoehorn">>},
61
+ {<<"app">>,<<"shoehorn">>},
61
62
{<<"optional">>,false},
62
- {<<"repository">>,<<"hexpm">>},
63
- {<<"requirement">>,<<"~> 0.9.0">>}],
64
- [{<<"app">>,<<"ring_logger">>},
65
- {<<"name">>,<<"ring_logger">>},
63
+ {<<"requirement">>,<<"~> 0.9.0">>},
64
+ {<<"repository">>,<<"hexpm">>}],
65
+ [{<<"name">>,<<"ring_logger">>},
66
+ {<<"app">>,<<"ring_logger">>},
66
67
{<<"optional">>,false},
67
- {<<"repository">>,<<"hexpm">>},
68
- {<<"requirement">>,<<"~> 0.9">>}],
69
- [{<<"app">>,<<"toolshed">>},
70
- {<<"name">>,<<"toolshed">>},
68
+ {<<"requirement">>,<<"~> 0.9">>},
69
+ {<<"repository">>,<<"hexpm">>}],
70
+ [{<<"name">>,<<"toolshed">>},
71
+ {<<"app">>,<<"toolshed">>},
71
72
{<<"optional">>,false},
72
- {<<"repository">>,<<"hexpm">>},
73
- {<<"requirement">>,<<"~> 0.3.0">>}],
74
- [{<<"app">>,<<"jason">>},
75
- {<<"name">>,<<"jason">>},
73
+ {<<"requirement">>,<<"~> 0.3.0">>},
74
+ {<<"repository">>,<<"hexpm">>}],
75
+ [{<<"name">>,<<"jason">>},
76
+ {<<"app">>,<<"jason">>},
76
77
{<<"optional">>,false},
77
- {<<"repository">>,<<"hexpm">>},
78
- {<<"requirement">>,<<"~> 1.2">>}],
79
- [{<<"app">>,<<"nerves_runtime">>},
80
- {<<"name">>,<<"nerves_runtime">>},
78
+ {<<"requirement">>,<<"~> 1.2">>},
79
+ {<<"repository">>,<<"hexpm">>}],
80
+ [{<<"name">>,<<"nerves_runtime">>},
81
+ {<<"app">>,<<"nerves_runtime">>},
81
82
{<<"optional">>,false},
82
- {<<"repository">>,<<"hexpm">>},
83
- {<<"requirement">>,<<"~> 0.13.0">>}],
84
- [{<<"app">>,<<"livebook">>},
85
- {<<"name">>,<<"livebook">>},
83
+ {<<"requirement">>,<<"~> 0.13.0">>},
84
+ {<<"repository">>,<<"hexpm">>}],
85
+ [{<<"name">>,<<"livebook">>},
86
+ {<<"app">>,<<"livebook">>},
86
87
{<<"optional">>,false},
87
- {<<"repository">>,<<"hexpm">>},
88
- {<<"requirement">>,<<"~> 0.9.1">>}],
89
- [{<<"app">>,<<"plug">>},
90
- {<<"name">>,<<"plug">>},
88
+ {<<"requirement">>,<<"~> 0.12.1">>},
89
+ {<<"repository">>,<<"hexpm">>}],
90
+ [{<<"name">>,<<"plug">>},
91
+ {<<"app">>,<<"plug">>},
91
92
{<<"optional">>,false},
92
- {<<"repository">>,<<"hexpm">>},
93
- {<<"requirement">>,<<"~> 1.12">>}],
94
- [{<<"app">>,<<"vintage_net">>},
95
- {<<"name">>,<<"vintage_net">>},
93
+ {<<"requirement">>,<<"~> 1.12">>},
94
+ {<<"repository">>,<<"hexpm">>}],
95
+ [{<<"name">>,<<"vintage_net">>},
96
+ {<<"app">>,<<"vintage_net">>},
96
97
{<<"optional">>,false},
97
- {<<"repository">>,<<"hexpm">>},
98
- {<<"requirement">>,<<"~> 0.13">>}],
99
- [{<<"app">>,<<"blue_heron">>},
100
- {<<"name">>,<<"blue_heron">>},
98
+ {<<"requirement">>,<<"~> 0.13">>},
99
+ {<<"repository">>,<<"hexpm">>}],
100
+ [{<<"name">>,<<"blue_heron">>},
101
+ {<<"app">>,<<"blue_heron">>},
101
102
{<<"optional">>,false},
102
- {<<"repository">>,<<"hexpm">>},
103
- {<<"requirement">>,<<"~> 0.3">>}],
104
- [{<<"app">>,<<"blue_heron_transport_uart">>},
105
- {<<"name">>,<<"blue_heron_transport_uart">>},
103
+ {<<"requirement">>,<<"~> 0.4">>},
104
+ {<<"repository">>,<<"hexpm">>}],
105
+ [{<<"name">>,<<"blue_heron_transport_uart">>},
106
+ {<<"app">>,<<"blue_heron_transport_uart">>},
106
107
{<<"optional">>,false},
107
- {<<"repository">>,<<"hexpm">>},
108
- {<<"requirement">>,<<"~> 0.1.2">>}],
109
- [{<<"app">>,<<"bmp280">>},
110
- {<<"name">>,<<"bmp280">>},
108
+ {<<"requirement">>,<<"~> 0.1.4">>},
109
+ {<<"repository">>,<<"hexpm">>}],
110
+ [{<<"name">>,<<"bmp280">>},
111
+ {<<"app">>,<<"bmp280">>},
111
112
{<<"optional">>,false},
112
- {<<"repository">>,<<"hexpm">>},
113
- {<<"requirement">>,<<"~> 0.2">>}],
114
- [{<<"app">>,<<"circuits_gpio">>},
115
- {<<"name">>,<<"circuits_gpio">>},
113
+ {<<"requirement">>,<<"~> 0.2">>},
114
+ {<<"repository">>,<<"hexpm">>}],
115
+ [{<<"name">>,<<"circuits_gpio">>},
116
+ {<<"app">>,<<"circuits_gpio">>},
116
117
{<<"optional">>,false},
117
- {<<"repository">>,<<"hexpm">>},
118
- {<<"requirement">>,<<"~> 1.0">>}],
119
- [{<<"app">>,<<"circuits_i2c">>},
120
- {<<"name">>,<<"circuits_i2c">>},
118
+ {<<"requirement">>,<<"~> 1.0">>},
119
+ {<<"repository">>,<<"hexpm">>}],
120
+ [{<<"name">>,<<"circuits_i2c">>},
121
+ {<<"app">>,<<"circuits_i2c">>},
121
122
{<<"optional">>,false},
122
- {<<"repository">>,<<"hexpm">>},
123
- {<<"requirement">>,<<"~> 1.0">>}],
124
- [{<<"app">>,<<"circuits_spi">>},
125
- {<<"name">>,<<"circuits_spi">>},
123
+ {<<"requirement">>,<<"~> 2.0 or ~> 1.0">>},
124
+ {<<"repository">>,<<"hexpm">>}],
125
+ [{<<"name">>,<<"circuits_spi">>},
126
+ {<<"app">>,<<"circuits_spi">>},
126
127
{<<"optional">>,false},
127
- {<<"repository">>,<<"hexpm">>},
128
- {<<"requirement">>,<<"~> 1.0 or ~> 0.1">>}],
129
- [{<<"app">>,<<"circuits_uart">>},
130
- {<<"name">>,<<"circuits_uart">>},
128
+ {<<"requirement">>,<<"~> 2.0 or ~> 1.0">>},
129
+ {<<"repository">>,<<"hexpm">>}],
130
+ [{<<"name">>,<<"circuits_uart">>},
131
+ {<<"app">>,<<"circuits_uart">>},
131
132
{<<"optional">>,false},
132
- {<<"repository">>,<<"hexpm">>},
133
- {<<"requirement">>,<<"~> 1.3">>}],
134
- [{<<"app">>,<<"delux">>},
135
- {<<"name">>,<<"delux">>},
133
+ {<<"requirement">>,<<"~> 1.3">>},
134
+ {<<"repository">>,<<"hexpm">>}],
135
+ [{<<"name">>,<<"delux">>},
136
+ {<<"app">>,<<"delux">>},
136
137
{<<"optional">>,false},
137
- {<<"repository">>,<<"hexpm">>},
138
- {<<"requirement">>,<<"~> 0.2">>}],
139
- [{<<"app">>,<<"hts221">>},
140
- {<<"name">>,<<"hts221">>},
138
+ {<<"requirement">>,<<"~> 0.2">>},
139
+ {<<"repository">>,<<"hexpm">>}],
140
+ [{<<"name">>,<<"hts221">>},
141
+ {<<"app">>,<<"hts221">>},
141
142
{<<"optional">>,false},
142
- {<<"repository">>,<<"hexpm">>},
143
- {<<"requirement">>,<<"~> 1.0">>}],
144
- [{<<"app">>,<<"input_event">>},
145
- {<<"name">>,<<"input_event">>},
143
+ {<<"requirement">>,<<"~> 1.0">>},
144
+ {<<"repository">>,<<"hexpm">>}],
145
+ [{<<"name">>,<<"input_event">>},
146
+ {<<"app">>,<<"input_event">>},
146
147
{<<"optional">>,false},
147
- {<<"repository">>,<<"hexpm">>},
148
- {<<"requirement">>,<<"~> 1.0 or ~> 0.4">>}],
149
- [{<<"app">>,<<"kino">>},
150
- {<<"name">>,<<"kino">>},
148
+ {<<"requirement">>,<<"~> 1.0 or ~> 0.4">>},
149
+ {<<"repository">>,<<"hexpm">>}],
150
+ [{<<"name">>,<<"kino">>},
151
+ {<<"app">>,<<"kino">>},
151
152
{<<"optional">>,false},
152
- {<<"repository">>,<<"hexpm">>},
153
- {<<"requirement">>,<<"~> 0.7">>}],
154
- [{<<"app">>,<<"kino_maplibre">>},
155
- {<<"name">>,<<"kino_maplibre">>},
153
+ {<<"requirement">>,<<"~> 0.7">>},
154
+ {<<"repository">>,<<"hexpm">>}],
155
+ [{<<"name">>,<<"kino_maplibre">>},
156
+ {<<"app">>,<<"kino_maplibre">>},
156
157
{<<"optional">>,false},
157
- {<<"repository">>,<<"hexpm">>},
158
- {<<"requirement">>,<<"~> 0.1.0">>}],
159
- [{<<"app">>,<<"kino_vega_lite">>},
160
- {<<"name">>,<<"kino_vega_lite">>},
158
+ {<<"requirement">>,<<"~> 0.1.0">>},
159
+ {<<"repository">>,<<"hexpm">>}],
160
+ [{<<"name">>,<<"kino_vega_lite">>},
161
+ {<<"app">>,<<"kino_vega_lite">>},
161
162
{<<"optional">>,false},
162
- {<<"repository">>,<<"hexpm">>},
163
- {<<"requirement">>,<<"~> 0.1.1">>}],
164
- [{<<"app">>,<<"maplibre">>},
165
- {<<"name">>,<<"maplibre">>},
163
+ {<<"requirement">>,<<"~> 0.1.1">>},
164
+ {<<"repository">>,<<"hexpm">>}],
165
+ [{<<"name">>,<<"maplibre">>},
166
+ {<<"app">>,<<"maplibre">>},
166
167
{<<"optional">>,false},
167
- {<<"repository">>,<<"hexpm">>},
168
- {<<"requirement">>,<<"~> 0.1.0">>}],
169
- [{<<"app">>,<<"nerves_key">>},
170
- {<<"name">>,<<"nerves_key">>},
168
+ {<<"requirement">>,<<"~> 0.1.7">>},
169
+ {<<"repository">>,<<"hexpm">>}],
170
+ [{<<"name">>,<<"nerves_key">>},
171
+ {<<"app">>,<<"nerves_key">>},
171
172
{<<"optional">>,false},
172
- {<<"repository">>,<<"hexpm">>},
173
- {<<"requirement">>,<<"~> 1.0">>}],
174
- [{<<"app">>,<<"nerves_pack">>},
175
- {<<"name">>,<<"nerves_pack">>},
173
+ {<<"requirement">>,<<"~> 1.0">>},
174
+ {<<"repository">>,<<"hexpm">>}],
175
+ [{<<"name">>,<<"nerves_pack">>},
176
+ {<<"app">>,<<"nerves_pack">>},
176
177
{<<"optional">>,false},
177
- {<<"repository">>,<<"hexpm">>},
178
- {<<"requirement">>,<<"~> 0.7.0">>}],
179
- [{<<"app">>,<<"nerves_time_zones">>},
180
- {<<"name">>,<<"nerves_time_zones">>},
178
+ {<<"requirement">>,<<"~> 0.7.0">>},
179
+ {<<"repository">>,<<"hexpm">>}],
180
+ [{<<"name">>,<<"nerves_time_zones">>},
181
+ {<<"app">>,<<"nerves_time_zones">>},
181
182
{<<"optional">>,false},
182
- {<<"repository">>,<<"hexpm">>},
183
- {<<"requirement">>,<<"~> 0.3.0">>}],
184
- [{<<"app">>,<<"nx">>},
185
- {<<"name">>,<<"nx">>},
183
+ {<<"requirement">>,<<"~> 0.3.0">>},
184
+ {<<"repository">>,<<"hexpm">>}],
185
+ [{<<"name">>,<<"nx">>},
186
+ {<<"app">>,<<"nx">>},
186
187
{<<"optional">>,false},
187
- {<<"repository">>,<<"hexpm">>},
188
- {<<"requirement">>,<<"~> 0.5.0">>}],
189
- [{<<"app">>,<<"phoenix_pubsub">>},
190
- {<<"name">>,<<"phoenix_pubsub">>},
188
+ {<<"requirement">>,<<"~> 0.6.2">>},
189
+ {<<"repository">>,<<"hexpm">>}],
190
+ [{<<"name">>,<<"phoenix_pubsub">>},
191
+ {<<"app">>,<<"phoenix_pubsub">>},
191
192
{<<"optional">>,false},
192
- {<<"repository">>,<<"hexpm">>},
193
- {<<"requirement">>,<<"~> 2.0">>}],
194
- [{<<"app">>,<<"picam">>},
195
- {<<"name">>,<<"picam">>},
193
+ {<<"requirement">>,<<"~> 2.0">>},
194
+ {<<"repository">>,<<"hexpm">>}],
195
+ [{<<"name">>,<<"picam">>},
196
+ {<<"app">>,<<"picam">>},
196
197
{<<"optional">>,false},
197
- {<<"repository">>,<<"hexpm">>},
198
- {<<"requirement">>,<<"~> 0.4.0">>}],
199
- [{<<"app">>,<<"pigpiox">>},
200
- {<<"name">>,<<"pigpiox">>},
198
+ {<<"requirement">>,<<"~> 0.4.0">>},
199
+ {<<"repository">>,<<"hexpm">>}],
200
+ [{<<"name">>,<<"pigpiox">>},
201
+ {<<"app">>,<<"pigpiox">>},
201
202
{<<"optional">>,false},
202
- {<<"repository">>,<<"hexpm">>},
203
- {<<"requirement">>,<<"~> 0.1">>}],
204
- [{<<"app">>,<<"pinout">>},
205
- {<<"name">>,<<"pinout">>},
203
+ {<<"requirement">>,<<"~> 0.1">>},
204
+ {<<"repository">>,<<"hexpm">>}],
205
+ [{<<"name">>,<<"pinout">>},
206
+ {<<"app">>,<<"pinout">>},
206
207
{<<"optional">>,false},
207
- {<<"repository">>,<<"hexpm">>},
208
- {<<"requirement">>,<<"~> 0.1">>}],
209
- [{<<"app">>,<<"ramoops_logger">>},
210
- {<<"name">>,<<"ramoops_logger">>},
208
+ {<<"requirement">>,<<"~> 0.1">>},
209
+ {<<"repository">>,<<"hexpm">>}],
210
+ [{<<"name">>,<<"progress_bar">>},
211
+ {<<"app">>,<<"progress_bar">>},
211
212
{<<"optional">>,false},
212
- {<<"repository">>,<<"hexpm">>},
213
- {<<"requirement">>,<<"~> 0.1">>}],
214
- [{<<"app">>,<<"recon">>},
215
- {<<"name">>,<<"recon">>},
213
+ {<<"requirement">>,<<"~> 3.0">>},
214
+ {<<"repository">>,<<"hexpm">>}],
215
+ [{<<"name">>,<<"ramoops_logger">>},
216
+ {<<"app">>,<<"ramoops_logger">>},
216
217
{<<"optional">>,false},
217
- {<<"repository">>,<<"hexpm">>},
218
- {<<"requirement">>,<<"~> 2.5">>}],
219
- [{<<"app">>,<<"req">>},
220
- {<<"name">>,<<"req">>},
218
+ {<<"requirement">>,<<"~> 0.1">>},
219
+ {<<"repository">>,<<"hexpm">>}],
220
+ [{<<"name">>,<<"recon">>},
221
+ {<<"app">>,<<"recon">>},
221
222
{<<"optional">>,false},
222
- {<<"repository">>,<<"hexpm">>},
223
- {<<"requirement">>,<<"~> 0.3.0">>}],
224
- [{<<"app">>,<<"scroll_hat">>},
225
- {<<"name">>,<<"scroll_hat">>},
223
+ {<<"requirement">>,<<"~> 2.5">>},
224
+ {<<"repository">>,<<"hexpm">>}],
225
+ [{<<"name">>,<<"req">>},
226
+ {<<"app">>,<<"req">>},
226
227
{<<"optional">>,false},
227
- {<<"repository">>,<<"hexpm">>},
228
- {<<"requirement">>,<<"~> 0.1">>}],
229
- [{<<"app">>,<<"vega_lite">>},
230
- {<<"name">>,<<"vega_lite">>},
228
+ {<<"requirement">>,<<"~> 0.4.4">>},
229
+ {<<"repository">>,<<"hexpm">>}],
230
+ [{<<"name">>,<<"scroll_hat">>},
231
+ {<<"app">>,<<"scroll_hat">>},
231
232
{<<"optional">>,false},
232
- {<<"repository">>,<<"hexpm">>},
233
- {<<"requirement">>,<<"~> 0.1">>}],
234
- [{<<"app">>,<<"vintage_net_mobile">>},
235
- {<<"name">>,<<"vintage_net_mobile">>},
233
+ {<<"requirement">>,<<"~> 0.1">>},
234
+ {<<"repository">>,<<"hexpm">>}],
235
+ [{<<"name">>,<<"stb_image">>},
236
+ {<<"app">>,<<"stb_image">>},
236
237
{<<"optional">>,false},
237
- {<<"repository">>,<<"hexpm">>},
238
- {<<"requirement">>,<<"~> 0.11">>}],
239
- [{<<"app">>,<<"vintage_net_qmi">>},
240
- {<<"name">>,<<"vintage_net_qmi">>},
238
+ {<<"requirement">>,<<"~> 0.6.0">>},
239
+ {<<"repository">>,<<"hexpm">>}],
240
+ [{<<"name">>,<<"tflite_elixir">>},
241
+ {<<"app">>,<<"tflite_elixir">>},
241
242
{<<"optional">>,false},
242
- {<<"repository">>,<<"hexpm">>},
243
- {<<"requirement">>,<<"~> 0.3">>}],
244
- [{<<"app">>,<<"nerves_system_rpi">>},
245
- {<<"name">>,<<"nerves_system_rpi">>},
243
+ {<<"requirement">>,<<"~> 0.3.4">>},
244
+ {<<"repository">>,<<"hexpm">>}],
245
+ [{<<"name">>,<<"vega_lite">>},
246
+ {<<"app">>,<<"vega_lite">>},
246
247
{<<"optional">>,false},
247
- {<<"repository">>,<<"hexpm">>},
248
- {<<"requirement">>,<<"~> 1.21">>}],
249
- [{<<"app">>,<<"nerves_system_rpi0">>},
250
- {<<"name">>,<<"nerves_system_rpi0">>},
248
+ {<<"requirement">>,<<"~> 0.1">>},
249
+ {<<"repository">>,<<"hexpm">>}],
250
+ [{<<"name">>,<<"vintage_net_mobile">>},
251
+ {<<"app">>,<<"vintage_net_mobile">>},
251
252
{<<"optional">>,false},
252
- {<<"repository">>,<<"hexpm">>},
253
- {<<"requirement">>,<<"~> 1.21">>}],
254
- [{<<"app">>,<<"nerves_system_rpi2">>},
255
- {<<"name">>,<<"nerves_system_rpi2">>},
253
+ {<<"requirement">>,<<"~> 0.11">>},
254
+ {<<"repository">>,<<"hexpm">>}],
255
+ [{<<"name">>,<<"vintage_net_qmi">>},
256
+ {<<"app">>,<<"vintage_net_qmi">>},
256
257
{<<"optional">>,false},
257
- {<<"repository">>,<<"hexpm">>},
258
- {<<"requirement">>,<<"~> 1.21">>}],
259
- [{<<"app">>,<<"nerves_system_rpi3">>},
260
- {<<"name">>,<<"nerves_system_rpi3">>},
258
+ {<<"requirement">>,<<"~> 0.3">>},
259
+ {<<"repository">>,<<"hexpm">>}],
260
+ [{<<"name">>,<<"nerves_system_rpi">>},
261
+ {<<"app">>,<<"nerves_system_rpi">>},
261
262
{<<"optional">>,false},
262
- {<<"repository">>,<<"hexpm">>},
263
- {<<"requirement">>,<<"~> 1.21">>}],
264
- [{<<"app">>,<<"nerves_system_rpi3a">>},
265
- {<<"name">>,<<"nerves_system_rpi3a">>},
263
+ {<<"requirement">>,<<"~> 1.25">>},
264
+ {<<"repository">>,<<"hexpm">>}],
265
+ [{<<"name">>,<<"nerves_system_rpi0">>},
266
+ {<<"app">>,<<"nerves_system_rpi0">>},
266
267
{<<"optional">>,false},
267
- {<<"repository">>,<<"hexpm">>},
268
- {<<"requirement">>,<<"~> 1.21">>}],
269
- [{<<"app">>,<<"nerves_system_rpi4">>},
270
- {<<"name">>,<<"nerves_system_rpi4">>},
268
+ {<<"requirement">>,<<"~> 1.25">>},
269
+ {<<"repository">>,<<"hexpm">>}],
270
+ [{<<"name">>,<<"nerves_system_rpi2">>},
271
+ {<<"app">>,<<"nerves_system_rpi2">>},
271
272
{<<"optional">>,false},
272
- {<<"repository">>,<<"hexpm">>},
273
- {<<"requirement">>,<<"~> 1.21">>}],
274
- [{<<"app">>,<<"nerves_system_bbb">>},
275
- {<<"name">>,<<"nerves_system_bbb">>},
273
+ {<<"requirement">>,<<"~> 1.25">>},
274
+ {<<"repository">>,<<"hexpm">>}],
275
+ [{<<"name">>,<<"nerves_system_rpi3">>},
276
+ {<<"app">>,<<"nerves_system_rpi3">>},
276
277
{<<"optional">>,false},
277
- {<<"repository">>,<<"hexpm">>},
278
- {<<"requirement">>,<<"~> 2.13">>}],
279
- [{<<"app">>,<<"nerves_system_osd32mp1">>},
280
- {<<"name">>,<<"nerves_system_osd32mp1">>},
278
+ {<<"requirement">>,<<"~> 1.25">>},
279
+ {<<"repository">>,<<"hexpm">>}],
280
+ [{<<"name">>,<<"nerves_system_rpi3a">>},
281
+ {<<"app">>,<<"nerves_system_rpi3a">>},
281
282
{<<"optional">>,false},
282
- {<<"repository">>,<<"hexpm">>},
283
- {<<"requirement">>,<<"~> 0.9">>}],
284
- [{<<"app">>,<<"nerves_system_x86_64">>},
285
- {<<"name">>,<<"nerves_system_x86_64">>},
283
+ {<<"requirement">>,<<"~> 1.25">>},
284
+ {<<"repository">>,<<"hexpm">>}],
285
+ [{<<"name">>,<<"nerves_system_rpi4">>},
286
+ {<<"app">>,<<"nerves_system_rpi4">>},
286
287
{<<"optional">>,false},
287
- {<<"repository">>,<<"hexpm">>},
288
- {<<"requirement">>,<<"~> 1.21">>}],
289
- [{<<"app">>,<<"nerves_system_npi_imx6ull">>},
290
- {<<"name">>,<<"nerves_system_npi_imx6ull">>},
288
+ {<<"requirement">>,<<"~> 1.25">>},
289
+ {<<"repository">>,<<"hexpm">>}],
290
+ [{<<"name">>,<<"nerves_system_bbb">>},
291
+ {<<"app">>,<<"nerves_system_bbb">>},
291
292
{<<"optional">>,false},
292
- {<<"repository">>,<<"hexpm">>},
293
- {<<"requirement">>,<<"~> 0.5">>}],
294
- [{<<"app">>,<<"nerves_system_grisp2">>},
295
- {<<"name">>,<<"nerves_system_grisp2">>},
293
+ {<<"requirement">>,<<"~> 2.17">>},
294
+ {<<"repository">>,<<"hexpm">>}],
295
+ [{<<"name">>,<<"nerves_system_osd32mp1">>},
296
+ {<<"app">>,<<"nerves_system_osd32mp1">>},
296
297
{<<"optional">>,false},
297
- {<<"repository">>,<<"hexpm">>},
298
- {<<"requirement">>,<<"~> 0.2">>}],
299
- [{<<"app">>,<<"nerves_system_mangopi_mq_pro">>},
300
- {<<"name">>,<<"nerves_system_mangopi_mq_pro">>},
298
+ {<<"requirement">>,<<"~> 0.16">>},
299
+ {<<"repository">>,<<"hexpm">>}],
300
+ [{<<"name">>,<<"nerves_system_x86_64">>},
301
+ {<<"app">>,<<"nerves_system_x86_64">>},
301
302
{<<"optional">>,false},
302
- {<<"repository">>,<<"hexpm">>},
303
- {<<"requirement">>,<<"~> 0.4">>}],
304
- [{<<"app">>,<<"nerves_system_srhub">>},
305
- {<<"name">>,<<"nerves_system_srhub">>},
303
+ {<<"requirement">>,<<"~> 1.25">>},
304
+ {<<"repository">>,<<"hexpm">>}],
305
+ [{<<"name">>,<<"nerves_system_npi_imx6ull">>},
306
+ {<<"app">>,<<"nerves_system_npi_imx6ull">>},
306
307
{<<"optional">>,false},
307
- {<<"repository">>,<<"hexpm">>},
308
- {<<"requirement">>,<<"~> 0.25">>}]]}.
309
- {<<"version">>,<<"0.9.0">>}.
308
+ {<<"requirement">>,<<"~> 0.13">>},
309
+ {<<"repository">>,<<"hexpm">>}],
310
+ [{<<"name">>,<<"nerves_system_grisp2">>},
311
+ {<<"app">>,<<"nerves_system_grisp2">>},
312
+ {<<"optional">>,false},
313
+ {<<"requirement">>,<<"~> 0.9">>},
314
+ {<<"repository">>,<<"hexpm">>}],
315
+ [{<<"name">>,<<"nerves_system_mangopi_mq_pro">>},
316
+ {<<"app">>,<<"nerves_system_mangopi_mq_pro">>},
317
+ {<<"optional">>,false},
318
+ {<<"requirement">>,<<"~> 0.7">>},
319
+ {<<"repository">>,<<"hexpm">>}],
320
+ [{<<"name">>,<<"nerves_system_srhub">>},
321
+ {<<"app">>,<<"nerves_system_srhub">>},
322
+ {<<"optional">>,false},
323
+ {<<"requirement">>,<<"~> 0.27">>},
324
+ {<<"repository">>,<<"hexpm">>}],
325
+ [{<<"name">>,<<"nerves_system_rpi0_2">>},
326
+ {<<"app">>,<<"nerves_system_rpi0_2">>},
327
+ {<<"optional">>,false},
328
+ {<<"requirement">>,<<"~> 1.25">>},
329
+ {<<"repository">>,<<"hexpm">>}],
330
+ [{<<"name">>,<<"nerves_system_rpi5">>},
331
+ {<<"app">>,<<"nerves_system_rpi5">>},
332
+ {<<"optional">>,false},
333
+ {<<"requirement">>,<<"~> 0.0.1">>},
334
+ {<<"repository">>,<<"hexpm">>}]]}.
335
+ {<<"build_tools">>,[<<"mix">>]}.
changed lib/nerves_livebook.ex
 
@@ -39,11 +39,11 @@ defmodule NervesLivebook do
39
39
40
40
def ssh_show_prompt(_peer, _username, _service) do
41
41
msg = """
42
- https://github.com/livebook-dev/nerves_livebook
42
+ https://github.com/nerves-livebook/nerves_livebook
43
43
44
44
ssh #{Node.self()} # Use password "nerves"
45
45
"""
46
46
47
- {'Nerves Livebook', to_charlist(msg), 'Password: ', false}
47
+ {~c"Nerves Livebook", to_charlist(msg), ~c"Password: ", false}
48
48
end
49
49
end
changed lib/nerves_livebook/github_release.ex
 
@@ -41,7 +41,7 @@ defmodule NervesLivebook.GithubRelease do
41
41
42
42
@spec req(String.t()) :: {:error, any()} | {:ok, any()}
43
43
def req(url) do
44
- headers = [{'user-agent', user_agent()}, {'Accept', 'application/vnd.github.v3+json'}]
44
+ headers = [{~c"user-agent", user_agent()}, {~c"Accept", ~c"application/vnd.github.v3+json"}]
45
45
request = {String.to_charlist(url), headers}
46
46
http_options = []
47
47
options = [body_format: :binary]
 
@@ -86,6 +86,6 @@ defmodule NervesLivebook.GithubRelease do
86
86
end
87
87
88
88
defp user_agent() do
89
- 'NervesLivebook/#{NervesLivebook.version()}'
89
+ ~c"NervesLivebook/#{NervesLivebook.version()}"
90
90
end
91
91
end
changed lib/nerves_livebook/mix_install.ex
 
@@ -52,7 +52,7 @@ defmodule NervesLivebook.MixInstall do
52
52
Mix.install/2 is not supported on Nerves Livebook (yet!).
53
53
54
54
All is not lost, but you will have to rebuild the Nerves Livebook firmware.
55
- Go to https://github.com/livebook-dev/nerves_livebook and clone the repository.
55
+ Go to https://github.com/nerves-livebook/nerves_livebook and clone the repository.
56
56
Add #{inspect(app)} to the dependencies listed in the `mix.exs` file, build,
57
57
and then try again.
58
58
"""
changed lib/nerves_livebook/wifi_monitor.ex
 
@@ -80,7 +80,7 @@ defmodule NervesLivebook.WiFiMonitor do
80
80
def handle_info({VintageNet, @presence_prop, true, _new, _meta}, state) do
81
81
# wlan0 is gone for some reason. Matching here stops any GenServer timer so
82
82
# we can continue waiting for wlan0 to come back
83
- Logger.warn("[WiFiMonitor] wlan0 interface gone")
83
+ Logger.warning("[WiFiMonitor] wlan0 interface gone")
84
84
_ = if state.test_fn, do: state.test_fn.(:continue)
85
85
{:noreply, state}
86
86
end
 
@@ -92,7 +92,7 @@ defmodule NervesLivebook.WiFiMonitor do
92
92
end
93
93
94
94
def handle_info({VintageNet, @connection_prop, _old, new, _meta}, state) do
95
- Logger.warn("[WiFiMonitor] wlan0 connection: #{new}")
95
+ Logger.warning("[WiFiMonitor] wlan0 connection: #{new}")
96
96
{:noreply, state, {:continue, :check_connection}}
97
97
end
changed mix.exs
 
@@ -2,10 +2,10 @@ defmodule NervesLivebook.MixProject do
2
2
use Mix.Project
3
3
4
4
@app :nerves_livebook
5
- @version "0.9.0"
6
- @source_url "https://github.com/livebook-dev/nerves_livebook"
5
+ @version "0.12.0"
6
+ @source_url "https://github.com/nerves-livebook/nerves_livebook"
7
7
8
- @rpi_targets [:rpi, :rpi0, :rpi2, :rpi3, :rpi3a, :rpi4]
8
+ @rpi_targets [:rpi, :rpi0, :rpi2, :rpi3, :rpi3a, :rpi4, :rpi0_2, :rpi5]
9
9
@all_targets @rpi_targets ++
10
10
[:bbb, :osd32mp1, :x86_64, :npi_imx6ull, :grisp2, :mangopi_mq_pro, :srhub]
11
11
 
@@ -19,6 +19,9 @@ defmodule NervesLivebook.MixProject do
19
19
# Targets supporting cellular modems
20
20
@cellular_targets [:srhub]
21
21
22
+ # TFLite isn't building on the RPi and RPi0 (armv6), so just don't include it there.
23
+ @tflite_targets @all_targets -- [:rpi, :rpi0]
24
+
22
25
# Instruct the compiler to create deterministic builds to minimize
23
26
# differences between firmware versions. This helps delta firmware update
24
27
# compression.
 
@@ -28,7 +31,7 @@ defmodule NervesLivebook.MixProject do
28
31
[
29
32
app: @app,
30
33
description: "Develop on embedded devices with Livebook and Nerves",
31
- author: "https://github.com/livebook-dev/nerves_livebook/graphs/contributors",
34
+ author: "https://github.com/nerves-livebook/nerves_livebook/graphs/contributors",
32
35
version: @version,
33
36
package: package(),
34
37
elixir: "~> 1.14",
 
@@ -81,17 +84,17 @@ defmodule NervesLivebook.MixProject do
81
84
{:toolshed, "~> 0.3.0"},
82
85
{:jason, "~> 1.2"},
83
86
{:nerves_runtime, "~> 0.13.0"},
84
- {:livebook, "~> 0.9.1"},
87
+ {:livebook, "~> 0.12.1"},
85
88
{:plug, "~> 1.12"},
86
89
{:vintage_net, "~> 0.13"},
87
90
88
91
# Pull in commonly used libraries as a convenience to users.
89
- {:blue_heron, "~> 0.3", targets: @ble_targets},
90
- {:blue_heron_transport_uart, "~> 0.1.2", targets: @ble_targets},
92
+ {:blue_heron, "~> 0.4", targets: @ble_targets},
93
+ {:blue_heron_transport_uart, "~> 0.1.4", targets: @ble_targets},
91
94
{:bmp280, "~> 0.2", targets: @all_targets},
92
95
{:circuits_gpio, "~> 1.0"},
93
- {:circuits_i2c, "~> 1.0"},
94
- {:circuits_spi, "~> 1.0 or ~> 0.1"},
96
+ {:circuits_i2c, "~> 2.0 or ~> 1.0"},
97
+ {:circuits_spi, "~> 2.0 or ~> 1.0"},
95
98
{:circuits_uart, "~> 1.3"},
96
99
{:delux, "~> 0.2"},
97
100
{:hts221, "~> 1.0", targets: @all_targets},
 
@@ -99,43 +102,48 @@ defmodule NervesLivebook.MixProject do
99
102
{:kino, "~> 0.7"},
100
103
{:kino_maplibre, "~> 0.1.0"},
101
104
{:kino_vega_lite, "~> 0.1.1"},
102
- {:maplibre, "~> 0.1.0"},
105
+ {:maplibre, "~> 0.1.7"},
103
106
{:nerves_key, "~> 1.0", targets: @all_targets},
104
107
{:nerves_pack, "~> 0.7.0", targets: @all_targets},
105
108
{:nerves_time_zones, "~> 0.3.0", targets: @all_targets},
106
- {:nx, "~> 0.5.0"},
109
+ {:nx, "~> 0.6.2"},
107
110
{:phoenix_pubsub, "~> 2.0"},
108
111
{:picam, "~> 0.4.0", targets: @rpi_mmal_targets},
109
- {:pigpiox, "~> 0.1", targets: @rpi_targets},
112
+ {:pigpiox, "~> 0.1", targets: @rpi_mmal_targets},
110
113
{:pinout, "~> 0.1"},
114
+ {:progress_bar, "~> 3.0"},
111
115
{:ramoops_logger, "~> 0.1", targets: @all_targets},
112
116
{:recon, "~> 2.5"},
113
- {:req, "~> 0.3.0"},
117
+ {:req, "~> 0.4.4"},
114
118
{:scroll_hat, "~> 0.1", targets: @rpi_targets},
119
+ {:stb_image, "~> 0.6.0"},
120
+ {:tflite_elixir, "~> 0.3.4", targets: @tflite_targets},
115
121
{:vega_lite, "~> 0.1"},
116
122
{:vintage_net_mobile, "~> 0.11", targets: @cellular_targets},
117
123
{:vintage_net_qmi, "~> 0.3", targets: @cellular_targets},
118
124
119
125
# Nerves system dependencies
120
- {:nerves_system_rpi, "~> 1.21", runtime: false, targets: :rpi},
121
- {:nerves_system_rpi0, "~> 1.21", runtime: false, targets: :rpi0},
122
- {:nerves_system_rpi2, "~> 1.21", runtime: false, targets: :rpi2},
123
- {:nerves_system_rpi3, "~> 1.21", runtime: false, targets: :rpi3},
124
- {:nerves_system_rpi3a, "~> 1.21", runtime: false, targets: :rpi3a},
125
- {:nerves_system_rpi4, "~> 1.21", runtime: false, targets: :rpi4},
126
- {:nerves_system_bbb, "~> 2.13", runtime: false, targets: :bbb},
127
- {:nerves_system_osd32mp1, "~> 0.9", runtime: false, targets: :osd32mp1},
128
- {:nerves_system_x86_64, "~> 1.21", runtime: false, targets: :x86_64},
129
- {:nerves_system_npi_imx6ull, "~> 0.5", runtime: false, targets: :npi_imx6ull},
130
- {:nerves_system_grisp2, "~> 0.2", runtime: false, targets: :grisp2},
131
- {:nerves_system_mangopi_mq_pro, "~> 0.4", runtime: false, targets: :mangopi_mq_pro},
132
- {:nerves_system_srhub, "~> 0.25", runtime: false, targets: :srhub},
126
+ {:nerves_system_rpi, "~> 1.25", runtime: false, targets: :rpi},
127
+ {:nerves_system_rpi0, "~> 1.25", runtime: false, targets: :rpi0},
128
+ {:nerves_system_rpi2, "~> 1.25", runtime: false, targets: :rpi2},
129
+ {:nerves_system_rpi3, "~> 1.25", runtime: false, targets: :rpi3},
130
+ {:nerves_system_rpi3a, "~> 1.25", runtime: false, targets: :rpi3a},
131
+ {:nerves_system_rpi4, "~> 1.25", runtime: false, targets: :rpi4},
132
+ {:nerves_system_bbb, "~> 2.17", runtime: false, targets: :bbb},
133
+ {:nerves_system_osd32mp1, "~> 0.16", runtime: false, targets: :osd32mp1},
134
+ {:nerves_system_x86_64, "~> 1.25", runtime: false, targets: :x86_64},
135
+ {:nerves_system_npi_imx6ull, "~> 0.13", runtime: false, targets: :npi_imx6ull},
136
+ {:nerves_system_grisp2, "~> 0.9", runtime: false, targets: :grisp2},
137
+ {:nerves_system_mangopi_mq_pro, "~> 0.7", runtime: false, targets: :mangopi_mq_pro},
138
+ {:nerves_system_srhub, "~> 0.27", runtime: false, targets: :srhub},
139
+ {:nerves_system_rpi0_2, "~> 1.25", runtime: false, targets: :rpi0_2},
140
+ {:nerves_system_rpi5, "~> 0.0.1", runtime: false, targets: :rpi5},
133
141
134
142
# Compile-time only
135
143
{:credo, "~> 1.6", only: :dev, runtime: false},
136
- {:dialyxir, "~> 1.2.0", only: :dev, runtime: false},
137
- {:ex_doc, "~> 0.22", only: :docs, runtime: false},
138
- {:sbom, "~> 0.6", only: :dev, runtime: false}
144
+ {:dialyxir, "~> 1.3", only: :dev, runtime: false},
145
+ {:ex_doc, "~> 0.22", only: :docs, runtime: false}
146
+ # {:sbom, "~> 0.6", only: :dev, runtime: false}
139
147
]
140
148
end
changed priv/samples/basics/blink.livemd
 
@@ -12,7 +12,7 @@ Lets set a variable so that we dont have to choose the GPIO pin every time.
12
12
First, refer to the GPIO ports for your Nerves device.
13
13
In this example, we will be using pin 20 on the raspberry pi platform.
14
14
15
- ![](https://raw.githubusercontent.com/livebook-dev/nerves_livebook/main/assets/gpio/rpi_pinout.png)
15
+ ![](https://raw.githubusercontent.com/nerves-livebook/nerves_livebook/main/assets/gpio/rpi_pinout.png)
16
16
17
17
```elixir
18
18
led_pin = 20
 
@@ -23,7 +23,7 @@ the to our `led_pin` and `ground` through a 220Ω resistor. The long leg
23
23
can be connected to our `led_pin` and the short pin can connect from
24
24
the shorter leg to a 220Ω resistor, then to our ground.
25
25
26
- ![Fritzing Diagram](https://raw.githubusercontent.com/livebook-dev/nerves_livebook/main/assets/gpio/led_rpi4_rpi0.svg)
26
+ ![Fritzing Diagram](https://raw.githubusercontent.com/nerves-livebook/nerves_livebook/main/assets/gpio/led_rpi4_rpi0.svg)
27
27
28
28
Now we will create a connection to that GPIO pin and set it as an :output.
changed priv/samples/basics/button.livemd
 
@@ -11,7 +11,7 @@ Lets set a variable for the LED and button so that we dont have to choose the GP
11
11
12
12
First, refer to the GPIO ports for your Nerves device.
13
13
14
- ![](https://raw.githubusercontent.com/livebook-dev/nerves_livebook/main/assets/gpio/rpi_pinout.png)
14
+ ![](https://raw.githubusercontent.com/nerves-livebook/nerves_livebook/main/assets/gpio/rpi_pinout.png)
15
15
16
16
```elixir
17
17
led_pin = 20
 
@@ -25,7 +25,7 @@ the shorter leg to a 220Ω resistor, then to our ground.
25
25
26
26
Connect one of the legs of the button to a 10kΩ resistor to 5v, and the diagonal leg to your `button_pin`.
27
27
28
- ![Fritzing Diagram](https://raw.githubusercontent.com/livebook-dev/nerves_livebook/main/assets/gpio/button_and_led_rpi4_rpi0.svg)
28
+ ![Fritzing Diagram](https://raw.githubusercontent.com/nerves-livebook/nerves_livebook/main/assets/gpio/button_and_led_rpi4_rpi0.svg)
29
29
30
30
The following code will configure the `led_pin` as an `:output` and the `button_pin` as an `input`.
changed priv/samples/basics/controlling_a_servo_with_pwm.livemd
 
@@ -11,11 +11,11 @@ Lets set a variable so that we don't have to choose the GPIO pin every time.
11
11
First, refer to the GPIO ports for your Nerves device.
12
12
In this example, we will be using pin 12 on the raspberry pi platform.
13
13
14
- ![](https://raw.githubusercontent.com/livebook-dev/nerves_livebook/main/assets/gpio/rpi_pinout.png)
14
+ ![](https://raw.githubusercontent.com/nerves-livebook/nerves_livebook/main/assets/gpio/rpi_pinout.png)
15
15
16
16
Wire everything up like in the diagram below. Servos have 3 wires: ground, vcc and pwm. In this case the black is ground the red is vcc and the yellow is pwm. Hook it up to pin 12 of the raspberry pi.
17
17
18
- ![](https://raw.githubusercontent.com/livebook-dev/nerves_livebook/main/assets/gpio/rpi_servo.png)
18
+ ![](https://raw.githubusercontent.com/nerves-livebook/nerves_livebook/main/assets/gpio/rpi_servo.png)
19
19
20
20
Lets set the pin as a variable so we don't have to choose the GPIO pin every time.
changed priv/samples/basics/pwm.livemd
 
@@ -16,7 +16,7 @@ Let's set a variable so that we don't have to choose the GPIO pin every time.
16
16
17
17
First, refer to the GPIO ports for your Nerves device. In this example, we will be using pin 20 on the Raspberry Pi platform.
18
18
19
- ![](https://raw.githubusercontent.com/livebook-dev/nerves_livebook/main/assets/gpio/rpi_pinout.png)
19
+ ![](https://raw.githubusercontent.com/nerves-livebook/nerves_livebook/main/assets/gpio/rpi_pinout.png)
20
20
21
21
```elixir
22
22
led_pin = 20
 
@@ -27,7 +27,7 @@ the to our `led_pin` and `ground` through a 220Ω resistor. The long leg
27
27
can be connected to our `led_pin` and the short pin can connect from
28
28
the shorter leg to a 220Ω resistor, then to our ground.
29
29
30
- ![Fritzing Diagram](https://raw.githubusercontent.com/livebook-dev/nerves_livebook/main/assets/gpio/led_rpi4_rpi0.svg)
30
+ ![Fritzing Diagram](https://raw.githubusercontent.com/nerves-livebook/nerves_livebook/main/assets/gpio/led_rpi4_rpi0.svg)
31
31
32
32
Now we will create a connection to that GPIO pin and set it as an `:output`.
changed priv/samples/bluetooth/ble_device_with_nerves.livemd
 
@@ -276,7 +276,7 @@ There's a few steps to this:
276
276
* `<<0x02, 0x01, 0b00000110>>`: This is an advertising bitmask that conveys connection information.
277
277
In this case, the two high bits mean that our device only supports BLE (and not BR/EDR),
278
278
and that our device is "General Connectable", meaning any device can connect to it at any time.
279
- * `<<0x09, 0x09, "MyApp-XY">>` This is the "Complete Local Name".
279
+ * `<<byte_size(short_name) + 1, 0x08, short_name::binary-size(short_name)>>` This is the "Short Name".
280
280
When you scan for BLE devices, you will see this name on the list.
281
281
* `<<0x11, 0x06, <<0x42A31ABD030C4D5CA8DF09686DD16CC0::little-128>>::binary>>`:
282
282
An incomplete list of 128 bit service UUIDs.
 
@@ -287,21 +287,38 @@ There's a few steps to this:
287
287
It will just have to scan for advertising packets that advertise the service UUID of the service
288
288
that we are interested in.
289
289
290
- 3. Start advertising.
290
+ 3. Setting the scan response data.
291
+ This is the data that will be sent in respones to a scan from the Central. This is an additional frame on top
292
+ of the advertising data that allows an additional 31 bytes of advertising data to be sent to the scanning device.
293
+ All scan responses have the same format as advertising data. In this case, we will only include:
294
+
295
+ * `<<byte_size(long_name) + 1, 0x09, long_name::binary-size(byte_size(long_name))>>` this is the "Complete Local Name".
296
+ When you scan for BLE devices, you will see this name on the list.
297
+
298
+ 4. Start advertising.
291
299
292
300
```elixir
301
+ short_name = "nerves"
302
+ long_name = "nerves-" <> Nerves.Runtime.serial_number()
303
+
293
304
BlueHeron.Peripheral.set_advertising_parameters(peripheral, %{})
294
305
295
306
# Advertising Data Flags: BR/EDR not supported, GeneralConnectable
296
- # Complete Local Name
307
+ # Short Name
297
308
# Incomplete List of 128-bit Servive UUIDs
298
309
advertising_data =
299
310
<<0x02, 0x01, 0b00000110>> <>
300
- <<0x09, 0x09, "MyApp-XY">> <>
311
+ <<byte_size(short_name) + 1, 0x08, short_name::binary-size(byte_size(short_name))>> <>
301
312
<<0x11, 0x06, <<0x42A31ABD030C4D5CA8DF09686DD16CC0::little-128>>::binary>>
302
313
303
314
BlueHeron.Peripheral.set_advertising_data(peripheral, advertising_data)
304
315
316
+ # Complete Name
317
+ scan_response_data =
318
+ <<byte_size(long_name) + 1, 0x09, long_name::binary-size(byte_size(long_name))>>
319
+
320
+ BlueHeron.Peripheral.set_scan_response_data(peripheral, scan_response_data)
321
+
305
322
BlueHeron.Peripheral.start_advertising(peripheral)
306
323
```
changed priv/samples/networking/delta_firmware_update.livemd
 
@@ -31,7 +31,7 @@ Firmware partition: #{Nerves.Runtime.KV.get("nerves_fw_active")}
31
31
```
32
32
33
33
Nerves Livebook delta firmware images are hosted on GitHub under the [releases
34
- tab](https://github.com/livebook-dev/nerves_livebook/releases). They start with the
34
+ tab](https://github.com/nerves-livebook/nerves_livebook/releases). They start with the
35
35
letter `z` and then have the firmware UUID that they can update. The Nerves
36
36
Livebook CI scripts only build delta updates for upgrading the previous
37
37
release, so if you don't see your UUID, load the previous release's firmware on
 
@@ -50,7 +50,7 @@ NervesLivebook.check_internet!()
50
50
51
51
# Setup for below
52
52
alias NervesLivebook.GithubRelease
53
- repo = "livebook-dev/nerves_livebook"
53
+ repo = "nerves-livebook/nerves_livebook"
54
54
firmware_path = "/data/delta.fw"
55
55
firmware_public_key = "IyCnjyE1rrV+W5HFrovC+ZyxrBh9fF7Na4S+7dcGAPw="
56
56
 
@@ -111,7 +111,7 @@ filesystem of one firmware with that of the next one. The process is simple,
111
111
but manual. It consists of unzipping the firmware files (they're just ZIP
112
112
files), running `xdelta3`, and then putting the compressed output back in the
113
113
ZIP file. See
114
- [`create_delta_fw.sh`](https://github.com/livebook-dev/nerves_livebook/blob/main/scripts/create_delta_fw.sh).
114
+ [`create_delta_fw.sh`](https://github.com/nerves-livebook/nerves_livebook/blob/main/scripts/create_delta_fw.sh).
115
115
116
116
The cryptographic checksums and signatures that `fwup` uses will still pass so
117
117
long as the expansion on the `xdelta3`-compressed binary outputs the exact same
changed priv/samples/networking/erlang_distribution.livemd
 
@@ -41,7 +41,7 @@ You can run Livebook on your laptop and connect to the device! This is useful
41
41
if you want to save your code notebooks locally. To do this,
42
42
43
43
1. Follow the [Livebook usage
44
- instructions](https://github.com/livebook-dev/livebook) and start Livebook running
44
+ instructions](https://github.com/nerves-livebook/nerves_livebook) and start Livebook running
45
45
on your laptop.
46
46
2. Open or create a new Livebook
47
47
3. Go to **Settings -> Runtime** and select **Attached Node**
changed priv/samples/networking/firmware_update.livemd
 
@@ -3,10 +3,10 @@
3
3
## Introduction
4
4
5
5
Nerves comes with a tool for handling firmware updates called
6
- [fwup](https://github.com/livebook-dev/fwup). It allows for archival and
6
+ [fwup](https://github.com/fwup-home/fwup). It allows for archival and
7
7
application of firmware updates, however it does not handle distribution of
8
8
updates. This Livebook comes with a module that can fetch a firmware update
9
- from [Github releases](https://github.com/livebook-dev/nerves_livebook/releases).
9
+ from [Github releases](https://github.com/nerves-livebook/nerves_livebook/releases).
10
10
11
11
## Walk through
12
12
 
@@ -24,7 +24,7 @@ Firmware partition: #{Nerves.Runtime.KV.get("nerves_fw_active")}
24
24
```
25
25
26
26
Nerves Livebook firmware images are hosted on GitHub under the [releases
27
- tab](https://github.com/livebook-dev/nerves_livebook/releases). Let's query GitHub
27
+ tab](https://github.com/nerves-livebook/nerves_livebook/releases). Let's query GitHub
28
28
to see what the latest release is:
29
29
30
30
```elixir
 
@@ -32,7 +32,7 @@ NervesLivebook.check_internet!()
32
32
33
33
# Setup for below
34
34
alias NervesLivebook.GithubRelease
35
- repo = "livebook-dev/nerves_livebook"
35
+ repo = "nerves-livebook/nerves_livebook"
36
36
firmware_path = "/data/update.fw"
37
37
firmware_public_key = "IyCnjyE1rrV+W5HFrovC+ZyxrBh9fF7Na4S+7dcGAPw="
38
38
 
@@ -114,7 +114,7 @@ To replicate this, do the following:
114
114
### SSH firmware updates
115
115
116
116
If you've cloned the
117
- [`nerves_livebook`](https://github.com/livebook-dev/nerves_livebook/) repository
117
+ [`nerves_livebook`](https://github.com/nerves-livebook/nerves_livebook/) repository
118
118
and are building your own version of it, it's going to be easier to update your
119
119
device via SSH. The firmware signatures aren't checked on SSH updates, so you
120
120
can do what you want. 🚀
 
@@ -136,7 +136,7 @@ Platform: rpi0
136
136
Uploading to livebook@nerves.local...
137
137
Warning: Permanently added 'nerves.local,172.31.112.97' (RSA) to the list of known hosts.
138
138
Nerves Livebook
139
- https://github.com/livebook-dev/nerves_livebook
139
+ https://github.com/nerves-livebook/nerves_livebook
140
140
141
141
ssh livebook@nerves.local # Use password "nerves"
changed priv/samples/networking/penultimate_update.livemd
 
@@ -28,7 +28,7 @@ NervesLivebook.check_internet!()
28
28
29
29
# Setup for below
30
30
alias NervesLivebook.GithubRelease
31
- repo = "livebook-dev/nerves_livebook"
31
+ repo = "nerves-livebook/nerves_livebook"
32
32
firmware_path = "/data/update.fw"
33
33
firmware_public_key = "IyCnjyE1rrV+W5HFrovC+ZyxrBh9fF7Na4S+7dcGAPw="
changed priv/samples/sensors/bmp280.livemd
 
@@ -8,13 +8,13 @@ This sample demonstrates how to read temperature data from the BMP280 temperatur
8
8
9
9
The explanation below assumes a [Raspberry Pi Zero W](https://www.raspberrypi.org/products/raspberry-pi-zero-w/) as a target device but other [Nerves targets](https://hexdocs.pm/nerves/targets.html) should work as well.
10
10
11
- ![](https://raw.githubusercontent.com/livebook-dev/nerves_livebook/main/assets/bmp280/rpi0.jpg)
11
+ ![](https://raw.githubusercontent.com/nerves-livebook/nerves_livebook/main/assets/bmp280/rpi0.jpg)
12
12
13
13
## Sensor board
14
14
15
15
The [Bosch BMP280 sensor](https://www.bosch-sensortec.com/products/environmental-sensors/pressure-sensors/) itself is so tiny that it might be difficult to handle but some electronics components manufactureres mount it on a [breakout board](https://en.wikipedia.org/wiki/Printed_circuit_board) for our convenience, which is what we look for. Do [Google search by "BMP280 breakout board"](https://www.google.com/search?q=bmp280+breakout+board) and you will find something like [Adafruit BMP280 Sensor board](https://www.adafruit.com/product/2651).
16
16
17
- ![](https://raw.githubusercontent.com/livebook-dev/nerves_livebook/main/assets/bmp280/bme280_breakout.jpg)
17
+ ![](https://raw.githubusercontent.com/nerves-livebook/nerves_livebook/main/assets/bmp280/bme280_breakout.jpg)
18
18
19
19
You can alternatively use [BME280](https://www.bosch-sensortec.com/products/environmental-sensors/humidity-sensors-bme280/) or [BME680](https://www.bosch-sensortec.com/products/environmental-sensors/gas-sensors-bme680/) since the [elixir-sensors/bmp280](https://github.com/elixir-sensors/bmp280) library supports them.
20
20
 
@@ -26,7 +26,7 @@ Roughly speaking, there are typically two ways to hook up a sensor to our Nerves
26
26
27
27
If you already have a [soldering iron](https://en.wikipedia.org/wiki/Soldering_iron) and enjoy using it, this is the go-to option. Even if you have not already, soldering can be fun. This option only requires a [pin header](https://en.wikipedia.org/wiki/Pin_header) and 4 [jumper wires](https://en.wikipedia.org/wiki/Jump_wire)
28
28
29
- ![](https://raw.githubusercontent.com/livebook-dev/nerves_livebook/main/assets/bmp280/rpi0_pin_header_bme280.jpg)
29
+ ![](https://raw.githubusercontent.com/nerves-livebook/nerves_livebook/main/assets/bmp280/rpi0_pin_header_bme280.jpg)
30
30
31
31
[I2C](https://en.wikipedia.org/wiki/I%C2%B2C) protocol uses 4 pins. It is confusing but different products may name the pins differently.
32
32
 
@@ -43,7 +43,7 @@ If you already have a [soldering iron](https://en.wikipedia.org/wiki/Soldering_i
43
43
44
44
Taking advantage of [Qwiic Connect System](https://www.sparkfun.com/qwiic) or similar system, we can remove the need for the soldering. One tradeoff is that we need to get an extra board like [Qwiic HAT for Raspberry Pi](https://www.adafruit.com/product/4688) and special wires.
45
45
46
- ![](https://raw.githubusercontent.com/livebook-dev/nerves_livebook/main/assets/bmp280/rpi0_qwiic_bme280.jpg)
46
+ ![](https://raw.githubusercontent.com/nerves-livebook/nerves_livebook/main/assets/bmp280/rpi0_qwiic_bme280.jpg)
47
47
48
48
## Elixir libraries
added priv/samples/tflite.livemd
 
@@ -0,0 +1,173 @@
1
+ # Use TensorFlow Lite on Nerves Livebook
2
+
3
+ ```elixir
4
+ Mix.install([
5
+ {:tflite_elixir, "~> 0.3.0"},
6
+ {:req, "~> 0.3.0"},
7
+ {:progress_bar, "~> 2.0.0"},
8
+ {:kino, "~> 0.9.0"}
9
+ ])
10
+ ```
11
+
12
+ ## Introduction
13
+
14
+ TensorFlow Lite is a stripped-down version of
15
+ [TensorFlow](https://en.wikipedia.org/wiki/TensorFlow), a free and open-source
16
+ software library for machine learning and artificial intelligence.
17
+
18
+ In Elixir, we can use TensorFlow Lite through the
19
+ [`tflite_elixir`](https://github.com/cocoa-xu/tflite_elixir) package, which
20
+ does the TensorFlow Lite Elixir bindings with optional [Edge
21
+ TPU](https://en.wikipedia.org/wiki/Tensor_Processing_Unit#Edge_TPU) support.
22
+
23
+ In this notebook, we will perform image classification with pre-trained
24
+ [mobilenet_v2_1.0_224_inat_bird_quant.tflite](https://github.com/google-coral/edgetpu/blob/master/test_data/mobilenet_v2_1.0_224_inat_bird_quant.tflite)
25
+ model. The example code below is based on the instructions in the
26
+ [tflite_elixir
27
+ README](https://github.com/cocoa-xu/tflite_elixir/blob/main/README.md). For
28
+ more information, check out the [tflite_elixir API
29
+ reference](https://hexdocs.pm/tflite_elixir/api-reference.html).
30
+
31
+ ## Prepare helper functions
32
+
33
+ ```elixir
34
+ defmodule Utils do
35
+ def download!(source_url, req_options \\ []) do
36
+ Req.get!(source_url, [finch_request: &finch_request/4] ++ req_options).body
37
+ end
38
+
39
+ defp finch_request(req_request, finch_request, finch_name, finch_options) do
40
+ acc = Req.Response.new()
41
+
42
+ case Finch.stream(finch_request, finch_name, acc, &handle_message/2, finch_options) do
43
+ {:ok, response} -> {req_request, response}
44
+ {:error, exception} -> {req_request, exception}
45
+ end
46
+ end
47
+
48
+ defp handle_message({:status, status}, response), do: %{response | status: status}
49
+
50
+ defp handle_message({:headers, headers}, response) do
51
+ {_, total_size} = Enum.find(headers, &match?({"content-length", _}, &1))
52
+
53
+ response
54
+ |> Map.put(:headers, headers)
55
+ |> Map.put(:private, %{total_size: String.to_integer(total_size), downloaded_size: 0})
56
+ end
57
+
58
+ defp handle_message({:data, data}, response) do
59
+ new_downloaded_size = response.private.downloaded_size + byte_size(data)
60
+ ProgressBar.render(new_downloaded_size, response.private.total_size, suffix: :bytes)
61
+
62
+ response
63
+ |> Map.update!(:body, &(&1 <> data))
64
+ |> Map.update!(:private, &%{&1 | downloaded_size: new_downloaded_size})
65
+ end
66
+ end
67
+ ```
68
+
69
+ ## Decide on where downloaded files are saved
70
+
71
+ ```elixir
72
+ downloads_dir = "/data/tmp"
73
+ File.mkdir_p!(downloads_dir)
74
+ ```
75
+
76
+ ## Download pre-trained model
77
+
78
+ ```elixir
79
+ model_source =
80
+ "https://raw.githubusercontent.com/google-coral/test_data/master/mobilenet_v2_1.0_224_inat_bird_quant.tflite"
81
+
82
+ model_file = Path.join(downloads_dir, "mobilenet_v2_1.0_224_inat_bird_quant.tflite")
83
+ Utils.download!(model_source, output: model_file)
84
+ IO.puts("Model saved to #{model_file}")
85
+ ```
86
+
87
+ ## Download labels
88
+
89
+ ```elixir
90
+ label_source =
91
+ "https://raw.githubusercontent.com/google-coral/test_data/master/inat_bird_labels.txt"
92
+
93
+ labels = String.split(Utils.download!(label_source), "\n", trim: true)
94
+ Kino.DataTable.new(Enum.with_index(labels, &%{class_name: &1, class_id: &2}), name: "Labels")
95
+ ```
96
+
97
+ ## Choose image to be classified
98
+
99
+ An input image can be uploaded here, or default parrot image will be used.
100
+
101
+ ```elixir
102
+ image_input = Kino.Input.image("Image", size: {224, 224})
103
+ ```
104
+
105
+ ```elixir
106
+ uploaded_image = Kino.Input.read(image_input)
107
+
108
+ default_input_image_url =
109
+ "https://raw.githubusercontent.com/google-coral/test_data/master/parrot.jpg"
110
+
111
+ input_image =
112
+ if uploaded_image do
113
+ # Build a tensor from the raw pixel data
114
+ uploaded_image.data
115
+ |> Nx.from_binary(:u8)
116
+ |> Nx.reshape({uploaded_image.height, uploaded_image.width, 3})
117
+ else
118
+ IO.puts("Loading default image from #{default_input_image_url}")
119
+
120
+ Utils.download!(default_input_image_url)
121
+ |> StbImage.read_binary!()
122
+ |> StbImage.to_nx()
123
+ end
124
+
125
+ Kino.Image.new(input_image)
126
+ ```
127
+
128
+ ## Classify image
129
+
130
+ ```elixir
131
+ how_many_results = 3
132
+ labels = List.to_tuple(labels)
133
+
134
+ input_nx =
135
+ input_image
136
+ |> StbImage.from_nx()
137
+ |> StbImage.resize(224, 224)
138
+ |> StbImage.to_nx()
139
+
140
+ interpreter = TFLiteElixir.Interpreter.new!(model_file)
141
+ [output_tensor_0] = TFLiteElixir.Interpreter.predict(interpreter, input_nx[[.., .., 0..2]])
142
+ indices_nx = Nx.flatten(output_tensor_0)
143
+
144
+ class_ids =
145
+ indices_nx
146
+ |> Nx.argsort(direction: :desc)
147
+ |> Nx.take(Nx.iota({how_many_results}))
148
+ |> Nx.to_flat_list()
149
+
150
+ class_ids
151
+ |> Enum.map(fn class_id -> %{class_id: class_id, class_name: elem(labels, class_id)} end)
152
+ |> Kino.DataTable.new(name: "Inference results")
153
+ ```
154
+
155
+ ## Next steps
156
+
157
+ ### Run other models
158
+
159
+ You can find a variety of pre-trained open-source models in [TensorFlow
160
+ Hub](https://tfhub.dev). For Elixir code, check out [example
161
+ notebooks](https://github.com/cocoa-xu/tflite_elixir/blob/bda47628e143c860e8cc796f491edd49260b787b/notebooks/README.md)
162
+ in `tflite_elixir` repository.
163
+
164
+ In case some example notebooks require the
165
+ [`evision`](https://github.com/cocoa-xu/evision) package for using
166
+ [OpenCV](https://opencv.org), add it to your Nerves project's `mix.exs` file
167
+ and rebuild Nerves firmware.
168
+
169
+ ### Run inference on Edge TPU
170
+
171
+ You can speed up model inference time, running a TensorFlow Lite model on the
172
+ Edge TPU. Check out `tflite_elixir`'s ["Inference on TPU"
173
+ example](https://github.com/cocoa-xu/tflite_elixir/blob/main/notebooks/tpu.livemd).
changed priv/welcome.livemd
 
@@ -4,7 +4,7 @@
4
4
5
5
Thanks for trying out Nerves Livebook!
6
6
7
- With this [Livebook](https://github.com/livebook-dev/livebook) image, you can
7
+ With this [Livebook](https://github.com/nerves-livebook/nerves_livebook) image, you can
8
8
work through tutorials, create your own code notebooks and save them on device,
9
9
and import notebooks from others. We're just getting started and are super
10
10
excited with what Livebook can already do. We hope that you'll enjoy learning
 
@@ -57,7 +57,7 @@ differences:
57
57
Since you cannot install libraries through hex, we include the libraries listed below.
58
58
59
59
If there is a dependency you want to see included in the `nerves_livebook` distribution,
60
- please file an [issue](https://github.com/livebook-dev/nerves_livebook/issues)
60
+ please file an [issue](https://github.com/nerves-livebook/nerves_livebook/issues)
61
61
or make a PR to include new libraries in the main image.
62
62
63
63
- **[`Kino`](https://hex.pm/packages/kino)**, interactive widgets for Livebook