Skip to content

Commit 0e0184f

Browse files
author
maze
committed
Fixing all the livebooks to work well with the 0.7 release
Updating the TODOs
1 parent 7e2ee1f commit 0e0184f

File tree

8 files changed

+90
-52
lines changed

8 files changed

+90
-52
lines changed

TODO.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Even though this library is published, there are things I still want to do befor
1616
- [x] Document the driver options (v0.7)
1717
- [x] Update the cheatsheet with coordinator info (v0.7)
1818
- [x] Resolve all important `doctor` issues (v0.7)
19-
- [ ] Add a livebook with coordinator examples (v0.7) <-- WIP
19+
- [ ] Add a livebook with coordinator examples (v0.8) <-- WIP
2020
- [ ] Update documentation with the Supervision tree (v0.8)
2121
- [ ] hardware setup (analogy with a bus letting 24 passangers off the bus at every led-bus-stop). Create a comprehensive write-up (v0.8)
2222
- [ ] Testing
@@ -45,7 +45,8 @@ Even though this library is published, there are things I still want to do befor
4545
- [x] Rename the job property `pattern` to `schedule` in the DSL created config (v0.7)
4646
- [x] The refactoring made the debug_logging property unnecessary. It's unclear on what to do with it. (v0.7)
4747
- [x] Rename `docs` to `pages`. Some people find it confusing to have a `docs` and a `doc` (created by `ex_doc`) (v0.7)
48-
- [ ] Make sure that all the job options are correctly honored (adjust documentation if necessary) (v0.7)
48+
- [ ] We should be able to replace the `Animation.Manager` config splitting with the `Enum.group_by` function (v0.8)
49+
- [ ] Make sure that all the job options are correctly honored (adjust documentation if necessary) (v0.8)
4950
- [ ] Rethink whether we really want to create a `Fledex.Config.Data` module or we should store the information in a GenServer. The issue with the GenServer is that we need to start a server. But maybe that's not soo bad. (v0.9)
5051
- [x] Change the `start_links` to take just one arg (the parameters) and an `opts` passed as opts to GenServer. Through this we define the name and therefore can move the `via_tuple` outside of the modules.
5152
- [ ] Missing functionality
@@ -54,13 +55,13 @@ Even though this library is published, there are things I still want to do befor
5455
- [x] Allow color modules to not carry more information than just a pre-defined set (v0.7)
5556
- [x] convert the rgb to other color spaces (in the various color name modules). Considering the previous point we might not need to do this, because it should now be optional (v0.7) <-- reduced the generated color functions, and what gets exposed
5657
- [x] we start things through the Supervisor, but we don't shut things down through it (v0.7)
57-
- [ ] Put some more effort into the coordinator to make it work well (v0.7)
5858
- [x] Rework the `:job` implementation (v0.7):
5959
- [x] The Job should (at least appear) to be connected to the LedStrip
6060
- [x] Replace it with a different library (maybe `SchedEx`? https://hexdocs.pm/sched_ex/readme.html) (v0.7)
6161
- [x] Investigate various libraries and how they fit into Fledex. I looked at various different libraries (`erlcron`, `sched_ex`, `exq_scheduler`, `ecron`, ...), but none really fulfils the needs :-( `SchedEx` is the one that is simple and comes closest. Therefore the plan is to take it (it's MIT license), modify it, and integrate it into Fledex
6262
- [x] It's not possible to inject a context to the job, because you either have to provide an `{M, F, [Args]}` or a `(-> any())` function. The former is not possible, since we don't have amodule (but just an anonymous function) and the latter is not possible, because we can't pass in any argument :-(. We would need to extend Quantum to accept an {F, [Args]}
6363
- [x] Switch to a released version of `:fledex_scheduler` (v0.7)
64+
- [ ] Put some more effort into the coordinator to make it work well (v0.8)
6465
- [ ] Enable Telemetry? (v0.8)
6566
- [ ] Switch also the `fledex_scheduler` stats to telemetry (v0.8)
6667
- [ ] Add support for WS2811/12/13/14/15 LED strips controlled through phase modulation. (v0.8)

lib/fledex/animation/animator.ex

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -198,10 +198,22 @@ defmodule Fledex.Animation.Animator do
198198

199199
@impl GenServer
200200
@spec handle_cast({:change_config, config_t}, state_t) :: {:noreply, state_t}
201-
def handle_cast({:change_config, config}, state) do
202-
state = do_update_config(state, config)
201+
def handle_cast(
202+
{:change_config, config},
203+
%{strip_name: strip_name, animation_name: animation_name} = state
204+
) do
205+
Logger.debug(
206+
"changing animation: #{inspect({strip_name, animation_name, self()})}",
207+
Map.filter(state, fn {key, _val} ->
208+
key in [:strip_name, :strip_server, :animation_name, :type]
209+
end)
210+
)
203211

204-
{:noreply, update_leds(state)}
212+
state = state
213+
|> do_update_config(config)
214+
|> update_leds()
215+
216+
{:noreply, state}
205217
end
206218

207219
@impl GenServer

livebooks/2_fledex_first_steps.livemd

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,12 @@ Now we are ready to send some data to the led_strip. Before we send some color i
5656
For now we use a hex code to define colors. You can learn more about colors and how to define them in [chapter 3b](3b_fledex_everything_about_colors.livemd).
5757

5858
```elixir
59-
LedStrip.define_namespace(:john, :default)
60-
LedStrip.set_leds(:john, :default, [0xFF0000, 0x00FF00, 0x0000FF], 3)
59+
server = AnimationSystem.get_strip_server(:john)
60+
LedStrip.define_namespace(server, :default)
61+
LedStrip.set_leds(server, :default, [0xFF0000, 0x00FF00, 0x0000FF], 3)
6162
```
6263

63-
> #### Note {: .info}
64+
> #### Note
6465
>
6566
> If you don't see your led strip displayed, then you might have to scroll up a bit. It
6667
> should be just after the code block where you defined your led_strip.
@@ -74,23 +75,25 @@ All functions are trying to create a simple animation by configuring the leds, s
7475
```elixir
7576
defmodule Helpers do
7677
def red(namespace) do
78+
server = AnimationSystem.get_strip_server(:john)
7779
Enum.each(1..10, fn _index ->
78-
LedStrip.set_leds(:john, namespace, [0xFF0000, 0x000000, 0x000000, 0x000000, 0x000000], 5)
80+
LedStrip.set_leds(server, namespace, [0xFF0000, 0x000000, 0x000000, 0x000000, 0x000000], 5)
7981
Process.sleep(600)
80-
LedStrip.set_leds(:john, namespace, [0x000000, 0xFF0000, 0x000000, 0x000000, 0x000000], 5)
82+
LedStrip.set_leds(server, namespace, [0x000000, 0xFF0000, 0x000000, 0x000000, 0x000000], 5)
8183
Process.sleep(600)
82-
LedStrip.set_leds(:john, namespace, [0x000000, 0x000000, 0xFF0000, 0x000000, 0x000000], 5)
84+
LedStrip.set_leds(server, namespace, [0x000000, 0x000000, 0xFF0000, 0x000000, 0x000000], 5)
8385
Process.sleep(600)
84-
LedStrip.set_leds(:john, namespace, [0x000000, 0x000000, 0x000000, 0xFF0000, 0x000000], 5)
86+
LedStrip.set_leds(server, namespace, [0x000000, 0x000000, 0x000000, 0xFF0000, 0x000000], 5)
8587
Process.sleep(600)
86-
LedStrip.set_leds(:john, namespace, [0x000000, 0x000000, 0x000000, 0x000000, 0xFF0000], 5)
88+
LedStrip.set_leds(server, namespace, [0x000000, 0x000000, 0x000000, 0x000000, 0xFF0000], 5)
8789
Process.sleep(600)
8890
end)
8991
end
9092

9193
def blue(namespace) do
94+
server = AnimationSystem.get_strip_server(:john)
9295
Enum.each(1..10, fn _index ->
93-
LedStrip.set_leds(:john, namespace, [
96+
LedStrip.set_leds(server, namespace, [
9497
0x000000,
9598
0x000000,
9699
0x000000,
@@ -101,7 +104,7 @@ defmodule Helpers do
101104

102105
Process.sleep(600)
103106

104-
LedStrip.set_leds(:john, namespace, [
107+
LedStrip.set_leds(server, namespace, [
105108
0x000000,
106109
0x000000,
107110
0x000000,
@@ -112,7 +115,7 @@ defmodule Helpers do
112115

113116
Process.sleep(600)
114117

115-
LedStrip.set_leds(:john, namespace, [
118+
LedStrip.set_leds(server, namespace, [
116119
0x000000,
117120
0x000000,
118121
0x0000FF,
@@ -123,7 +126,7 @@ defmodule Helpers do
123126

124127
Process.sleep(600)
125128

126-
LedStrip.set_leds(:john, namespace, [
129+
LedStrip.set_leds(server, namespace, [
127130
0x000000,
128131
0x0000FF,
129132
0x000000,
@@ -134,7 +137,7 @@ defmodule Helpers do
134137

135138
Process.sleep(600)
136139

137-
LedStrip.set_leds(:john, namespace, [
140+
LedStrip.set_leds(server, namespace, [
138141
0x0000FF,
139142
0x000000,
140143
0x000000,
@@ -148,14 +151,15 @@ defmodule Helpers do
148151
end
149152

150153
def rainbow(namespace) do
154+
server = AnimationSystem.get_strip_server(:john)
151155
Enum.each(0..10000, fn index ->
152156
config = [
153157
num_leds: 50,
154158
reversed: true
155159
]
156160

157161
Leds.leds(50)
158-
|> Leds.set_led_strip_info(:john, namespace)
162+
|> Leds.set_led_strip_info(server, namespace)
159163
|> Leds.rainbow(config)
160164
|> Leds.send(offset: index)
161165

@@ -165,9 +169,10 @@ defmodule Helpers do
165169
end
166170

167171
def gradient(namespace) do
172+
server = AnimationSystem.get_strip_server(:john)
168173
Enum.each(0..10000, fn index ->
169174
Leds.leds(50)
170-
|> Leds.set_led_strip_info(:john, namespace)
175+
|> Leds.set_led_strip_info(server, namespace)
171176
|> Leds.gradient(0xFF0000, 0x0000FF, %{num_leds: 50})
172177
|> Leds.send(
173178
offset: index,
@@ -189,12 +194,12 @@ Take note, that our functions create sequences of different length.
189194

190195
Now we can try it out with one of the first functions. Let's call our `red/1` function. We spawn it in a separate process. The reason for that you'll see in a second.
191196

192-
> #### Note {: .info}
197+
> #### Note
193198
>
194199
> You might have to scroll up to see the animation
195200
196201
```elixir
197-
LedStrip.define_namespace(:john, :red)
202+
LedStrip.define_namespace(server, :red)
198203

199204
spawn(fn ->
200205
Helpers.red(:red)
@@ -203,14 +208,14 @@ end)
203208

204209
Similarly you can do the same with the `blue/1` function. Where it gets interesting is, when you start first the red function and then start the blue function while the red function is still running.
205210

206-
> #### Note {: .info}
211+
> #### Note
207212
>
208213
> Don't forget to use a differnt namespace name compared to the above function, otherwise
209214
> one function would constantly overwrite what the other function has defined. We want them
210215
> to live in parallel and get merged.
211216
212217
```elixir
213-
LedStrip.define_namespace(:john, :blue)
218+
LedStrip.define_namespace(server, :blue)
214219

215220
spawn(fn ->
216221
Helpers.blue(:blue)
@@ -226,7 +231,7 @@ While both functions are running, they will
226231
Now we can use the above functions with our trip. We can run the functions by spawning a new thread. This allows to also see what happens if another thread works in parallel. Here we create a rainbow effect that will be send with a changing offset so that the rainbow rotates through the LEDs
227232

228233
```elixir
229-
LedStrip.define_namespace(:john, :rainbow)
234+
LedStrip.define_namespace(server, :rainbow)
230235
spawn(fn -> Helpers.rainbow(:rainbow) end)
231236
```
232237

@@ -237,14 +242,14 @@ spawn(fn -> Helpers.rainbow(:rainbow) end)
237242
Here we create a gradient between red and blue. Also this one we let rotate through. Note, depending on whether you started the rainbow above or not, you might see different results. Try this section with and without running the Rainbow section.
238243

239244
```elixir
240-
LedStrip.define_namespace(:john, :gradient)
245+
LedStrip.define_namespace(server, :gradient)
241246
spawn(fn -> Helpers.gradient(:gradient) end)
242247
```
243248

244249
We can drop the namespaces to see what happens
245250

246251
```elixir
247-
LedStrip.drop_namespace(:john, :gradient)
252+
LedStrip.drop_namespace(server, :gradient)
248253
```
249254

250255
As we can see our animation stops to be visible and our calls to `set_leds` will fail (but we swallow those errors).
@@ -256,9 +261,9 @@ As we can see our animation stops to be visible and our calls to `set_leds` will
256261
This test is running a couple of different ligth definitions in parallel.
257262

258263
```elixir
259-
LedStrip.define_namespace(:john, :john)
260-
LedStrip.define_namespace(:john, :jane)
261-
LedStrip.define_namespace(:john, :default)
264+
LedStrip.define_namespace(server, :john)
265+
LedStrip.define_namespace(server, :jane)
266+
LedStrip.define_namespace(server, :default)
262267

263268
spawn(fn -> Helpers.blue(:jane) end)
264269
spawn(fn -> Helpers.red(:john) end)

livebooks/3_fledex_animations.livemd

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,12 @@ alias Fledex.Driver.Impl.Kino
2828
alias Fledex.Color.Correction
2929
alias Fledex.Supervisor.AnimationSystem
3030

31+
# to use our color aliases (like :red) we need to configure them
32+
use Fledex.Config
33+
34+
# now we start our animation system
3135
AnimationSystem.start_link()
36+
3237
```
3338

3439
## Helper functions
@@ -68,6 +73,7 @@ We call our led strip `:john`. In this example we will only use the simple kino
6873
We then define an animation configuration that consists of a map with the key being the name of the animation and the value being the configuration of that animation. Each animation configuration needs to specify the `:type` as `:animation`, because (as we will see later) other types exist, and a `:def_func` that defines our animation (potentially with an additional `:send_config_func` as shown here. We'll look at this in more detail in a later section).
6974

7075
```elixir
76+
7177
Manager.register_strip(:john, [{Kino, []}], [])
7278

7379
Manager.register_config(:john, %{

livebooks/3b_fledex_everything_about_colors.livemd

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ Mix.install([
1212
])
1313
```
1414

15-
## Setup
16-
1715
## Colors and different drivers
1816

1917
Different drivers have different color characteristics. Therefore you might have to adjust the colors when migrating from one output to another. Some drivers allow some color correction to try to adjust for those issues (see also the 'Color Correction' section.
@@ -34,7 +32,7 @@ We don't specify anything and thereby go with the default color set of `:wiki`,
3432
use Fledex
3533
```
3634

37-
Fledex has an extensive set of predefined colors from [Wikipedia](https://en.wikipedia.org/wiki/List_of_colors:_A%E2%80%93F), [CSS](https://drafts.csswg.org/css-color/#named-colors), [SVG](https://www.w3.org/TR/SVG11/types.html#ColorKeywords), and [RAL](https://en.wikipedia.org/wiki/List_of_RAL_colours).Apart from the last list (which is not so commonly used), they are all combined together to a single Names module. You can retrieve those names by calling:
35+
Fledex has an extensive set of predefined colors from [Wikipedia](https://en.wikipedia.org/wiki/List_of_colors:_A%E2%80%93F), [CSS](https://drafts.csswg.org/css-color/#named-colors), [SVG](https://www.w3.org/TR/SVG11/types.html#ColorKeywords), and [RAL](https://en.wikipedia.org/wiki/List_of_RAL_colours). Apart from the last list (which is not so commonly used), they are all combined together to a single Names module. You can retrieve those names by calling:
3836

3937
<!-- livebook:{"force_markdown":true} -->
4038

@@ -54,11 +52,17 @@ Fledex.Color.Names.info(name, :all)
5452
Here a list of all the defined colors (extra colors can still be used, but need to be called explicitly, like the RAL colors through `Fledex.Color.Names.RAL`):
5553

5654
```elixir
57-
colors = Enum.map(Fledex.Color.Names.names() |> Enum.sort(), fn name ->
58-
Fledex.Color.Names.info(name, :all)
59-
end)
55+
fields = [:descriptive_name, :name, :rgb, :hex, :source, :module]
56+
colors = Enum.map(
57+
Fledex.Color.Names.names() |> Enum.sort(),
58+
fn name ->
59+
Fledex.Color.Names.info(name, :all)
60+
|> Map.take(fields)
61+
end
62+
)
63+
6064
Elixir.Kino.DataTable.new(colors,
61-
keys: [:descriptive_name, :name, :rgb, :hex, :hsv, :hsl, :source, :module],
65+
keys: [:descriptive_name, :name, :rgb, :hex, :source, :module],
6266
sorting_enabled: true
6367
)
6468
```
@@ -108,9 +112,10 @@ Before we look at the Fledex features regarding color correction we first need t
108112
> the colors, making the whites appear white, the blacks appear black, and making sure that
109113
> everything is even.
110114
111-
The color correction consists of two parts. First to compensate the physical mis-coloring of the LEDs. The basic colors on the classical 5050 LED chip are not shown in the same intensity. So we need to compensate this.
115+
The color correction consists of two parts:
112116

113-
The second color coorection we might want to perform is to bring the color into the correct "temperature" (named due to the [black body radiator](https://en.wikipedia.org/wiki/Black-body_radiation)) with a relatively continuous spectrum, or approach the light of a gaseous light source with more discrete spectral band (see [gas discharge lamp](https://en.wikipedia.org/wiki/Gas-discharge_lamp)).
117+
1. First to compensate the physical mis-coloring of the LEDs. The basic colors on the classical 5050 LED chip are not shown in the same intensity. So we need to compensate this.
118+
2. The second color correction we might want to perform is to bring the color into the correct "temperature" (named due to the [black body radiator](https://en.wikipedia.org/wiki/Black-body_radiation)) with a relatively continuous spectrum, or approach the light of a gaseous light source with more discrete spectral band (see [gas discharge lamp](https://en.wikipedia.org/wiki/Gas-discharge_lamp)).
114119

115120
Color correction is provided in Fledex through the modules under `Fledex.Color.Correction`.
116121

livebooks/4_fledex_clock_example.livemd

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ alias Fledex.Leds
1818
alias Fledex.LedStrip
1919
alias Fledex.Supervisor.AnimationSystem
2020

21-
AnimationSystem.start_link()
22-
2321
:ok
2422
```
2523

@@ -32,7 +30,14 @@ But before we get there, we first initiate our led strip.
3230

3331
## Preparational steps
3432

35-
First we register a strip (we name it `:clock`) with our `Fledex.Animation.Manager` and we use the default settings for the `Kino` driver.
33+
First we need to define our config and start our AnimationSystem
34+
35+
```elixir
36+
use Fledex.Config
37+
AnimationSystem.start_link()
38+
```
39+
40+
Then we register a strip (we name it `:clock`) with our `Fledex.Animation.Manager` and we use the default settings for the `Kino` driver.
3641

3742
Then we modify the led strip to update with a very low frequency. Our clock only updates every second and therefore it's unnecessary that we update it more often than that. To avoid any issues due to some runtime delays, we update it twice every second. Thereby the second indicator will never jump an led.
3843

livebooks/5_fledex_weather_example.livemd

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,6 @@ alias Fledex.Color.Correction
2121
alias Fledex.Utils.PubSub
2222
alias Fledex.Supervisor.AnimationSystem
2323

24-
AnimationSystem.start_link()
25-
26-
2724
:ok
2825
```
2926

@@ -67,6 +64,13 @@ As can be seen we get the information we are interested in, the current temperat
6764

6865
## Configuring the led strip
6966

67+
Again, we configure our System and start our AnimationSystem
68+
69+
```elixir
70+
use Fledex.Config
71+
AnimationSystem.start_link()
72+
```
73+
7074
Now it's time to prepare our led strip. First we define our strip and we set a very low refresh rate. An update every 10 sec is enough.
7175

7276
```elixir

livebooks/8_fledex_component.livemd

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ end
5050
To test our animation we fake again the temperature by simply publishing the desired temperature.
5151

5252
```elixir
53-
Fledex.Utils.PubSub.broadcast(:fledex, "trigger", {:trigger, %{temperature: 17.2}})
53+
broadcast_trigger(%{temperature: 17.2})
5454
```
5555

5656
## What is a component
@@ -96,11 +96,11 @@ The interesting thing in the `Fledex.Component.Dot` component is that it actuall
9696

9797
but that almost equal to importing.
9898

99-
> #### Note {: .info}
100-
>
101-
> We want to leave the definition of color names to the user of our component. In a component you
102-
> should ideally define colors as hex values and not by name. If you still want to use color
103-
> names, then specify the color name module explicitly (example: `Fledex.Color.Names.Wiki.red()`)
99+
> #### Note
100+
>
101+
> We want to leave the definition of color names to the user of our component. In a component you
102+
> should ideally define colors as hex values and not by name. If you still want to use color
103+
> names, then specify the color name module explicitly (example: `Fledex.Color.Names.Wiki.red()`)
104104
105105
The code looks like the following
106106

0 commit comments

Comments
 (0)