Building a Julia-Powered E-Ink Dashboard: A Dev Log

Every great journey starts with a single step. :man_mage:

In the spirit of open source, adventure, and fun, I am making an on-going development log here about building a Julia-powered e-ink dashboard ran on a Raspberry Pi. This was sparked off by the apparent interest folks had for my original post:

As I continue pressing along with this small hobby project, I invite you to tag along as I go on many side-quests, (mis)adventures, and more in this little project! Who knows what we’ll end up making?

~ tcp :deciduous_tree:

14 Likes

Log 01: Undated Sketches

Up until now, I went on a small side-quest to explore weather APIs. A component that I want to make for my dashboard is a weather component to check things like:

  • UV Index :sun:
  • Temperature :thermometer:
  • Humidity :hot_face:
  • Precipitation & Amount :cloud_with_rain:
  • Wind speed & Direction :leaf_fluttering_in_wind:
  • Sunset & Sunrise :waxing_crescent_moon:
  • Air Quality Index :cherry_blossom:

To this end, I found OpenMeteo! I had found GitHub - vnegi10/WeatherReport.jl: A simple weather app for the Julia REPL by @vnegi10 which looked promising but found it’s priority wasn’t to give data from the website but have a nice REPL output of weather. Very cool!

Reading some discussions on issues by Vikas, I found that OpenMeteo had an OpenAPI.yaml spec. Promising! Played with that using OpenAPI.jl but ultimately found that it was extremely limited – they are still in the process of supporting it. So, hit a bit of a wall.

But then! I discovered a strange thing called a flatbuffer spec they use. Turns out flatc can generate a variety of language bindings for an API wrapper package using this spec. And of course, Julia was not supported – until I found an old fork of flatbuffers by @jonalm that purportedly supported Julia. I knew it worked once upon a time thanks to confirmation by @evetion. Buoyed by this promising end to create Julia bindings for OpenMeteo’s flatbuffer spec, I went ahead, cloned it, ran cmake and ran the make pipeline.

It failed.

BUT I WOULD NOT CONCEDE DEFEAT! Using a combination of C++ programming skills I had from years ago and help from ChatGPT, I quickly monkey-patched the fork. And – pow! – I generated Julia bindings for OpenMeteo using the spec!

Now, I am in the process of making a little Julia OpenMeteo package that builds on top of these bindings with direct inspiration from OpenMeteo’s python-requests package.

Do I know what I am doing? Not entirely. Am I motivated? Mostly. Do I want weather data? You betcha.

Stay tuned!

6 Likes

Log 02: July 13th, 2025 - Weather Imagineering

After tinkering further with OpenMeteo, I decided to take a break and determine what data I want exactly. I concluded that basically, this is the information I want from the Weather Forecast API:

Location

  • latitude=42.3751
  • longitude=-71.1056

Daily Variables Requested

  • temperature_2m_max: Daily maximum temperature at 2 meters
  • temperature_2m_min: Daily minimum temperature at 2 meters
  • sunset: Time of sunset
  • sunrise: Time of sunrise
  • wind_speed_10m_max: Maximum wind speed at 10 meters
  • wind_gusts_10m_max: Maximum wind gusts at 10 meters
  • wind_speed_10m_min: Minimum wind speed at 10 meters
  • wind_gusts_10m_min: Minimum wind gusts at 10 meters

Hourly Variables Requested

  • temperature_2m: Temperature at 2 meters
  • uv_index: UV index
  • precipitation_probability: Probability of precipitation
  • precipitation: Amount of precipitation
  • relative_humidity_2m: Relative humidity at 2 meters
  • wind_speed_10m: Wind speed at 10 meters
  • wind_direction_10m: Wind direction at 10 meters

Other Options

  • timezone=America/New_York: Output times in the Eastern Time zone (encoded as %2F)
  • forecast_days=3: Request a 3-day forecast
  • timeformat=unixtime: Timestamps in Unix time format (seconds since epoch)
  • wind_speed_unit=mph: Wind speeds in miles per hour
  • temperature_unit=fahrenheit: Temperatures in Fahrenheit
  • precipitation_unit=inch: Precipitation in inches

Curl Request Example:

curl https://api.open-meteo.com/v1/forecast?latitude=42.3751&longitude=-71.1056&daily=temperature_2m_max,temperature_2m_min,sunset,sunrise,wind_speed_10m_max,wind_gusts_10m_max,wind_speed_10m_min,wind_gusts_10m_min&hourly=temperature_2m,uv_index,precipitation_probability,precipitation,relative_humidity_2m,wind_speed_10m,wind_direction_10m&timezone=America%2FNew_York&forecast_days=3&timeformat=unixtime&wind_speed_unit=mph&temperature_unit=fahrenheit&precipitation_unit=inch

And Air Quality API:

Hourly Variables Requested

  • us_aqi: U.S. Air Quality Index (based on EPA standards)

Other Options

  • forecast_days=3: Request a 3-day forecast

Curl Request Example:

curl https://air-quality-api.open-meteo.com/v1/air-quality?latitude=52.52&longitude=13.41&hourly=us_aqi&forecast_days=3

From there, I began tinkering with how to display this data on my display. I sketched out a small draft of this here:

Basically, I am imagining using Makie.jl and a PolarAxis radial chart to display this information (thanks to @asinghvi17 and @sdanisch for the tips here):

You can make multiple polar axes and use PolarAxis | Makie

In my designing, I found this example to be beautiful and something I could base my work off of:

I also found this other example which was also hugely inspiring:

This will be a task for future TCP.


Finally, I decided to put some thoughts to code and began drafting a Jinkies.jl framework for how to β€œchunk” the regions of an e-ink display. As of now, I have two structs called Display and another called Component. Display holds information about the e-ink display and what components are in the display. A Component holds plotting information about what goes into the display and where.

I am imagining making Component’s more like an interface too so I can make any component that could be rendered to an image using tools like Makie, Luxor, and more.

Currently, I have made a PrettyTables.jl interface to represent an e-ink display’s pixels in a coarser granularity than pixel dimensions. Here’s how things look so far:

julia> Jinkies.set_display_grid!(100, 120)

E-Ink Display Grid
β”Œβ”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”
β”‚     β”‚ 001 β”‚ 002 β”‚ 003 β”‚ 004 β”‚ 005 β”‚ 006 β”‚ 007 β”‚ 008 β”‚
β”œβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€
β”‚  1  β”‚  ⬀  β”‚  ⬀  β”‚  ⬀  β”‚  ⬀  β”‚  ⬀  β”‚  ⬀  β”‚  ⬀  β”‚  ⬀  β”‚
β”œβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€
β”‚  2  β”‚  ⬀  β”‚  ⬀  β”‚  ⬀  β”‚  ⬀  β”‚  ⬀  β”‚  ⬀  β”‚  ⬀  β”‚  ⬀  β”‚
β”œβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€
β”‚  3  β”‚  ⬀  β”‚  ⬀  β”‚  ⬀  β”‚  ⬀  β”‚  ⬀  β”‚  ⬀  β”‚  ⬀  β”‚  ⬀  β”‚
β”œβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€
β”‚  4  β”‚  ⬀  β”‚  ⬀  β”‚  ⬀  β”‚  ⬀  β”‚  ⬀  β”‚  ⬀  β”‚  ⬀  β”‚  ⬀  β”‚
β””β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”˜

And then for colors, I can do something like this to say where a part of an e-ink display already has a component:

julia> Jinkies._update_display_grid_colors!(
    [[1,1], [1,2],[2,1],[2,2]]
)

I like the display representation so far, but I need to mess around a bit further with the component and display interplay. Also encoding what information should be stored here and there.


And that is where we shall leave the dev log for now. Nice day of exploring, hacking, and imagineering! Onwards!

2 Likes

Should that be an output only? Let’s invoke a Cloud Seeding API (Cloud seeding - Wikipedia) from the REPL.

2 Likes

I need to create more tutorials for these, but you may find more meteo functions in GMT.jl

and the not yet documented other than docstrings meteostat()

2 Likes

Oh this is great! Not sure if it would be helpful to you, but would you want me to spin up a small repo that has the Julia flatbuffer OpenMeteo bindings now? Could maybe enrich GMT.jl’s OpenMeteo’s functionality even more?

Happy to share here – just on a sidequest for weather data. :sun:

Thanks a lot for the offer but honestly I don’t know the answer right now. You see, I have a strange stubbornness (for the the Julia community habits) that I don’t want, or I’m I’m very reluctant to accept, new dependencies. All the functionality I showed above was achieved without adding any new dependencies to the ones already in GMT.jl (which other than jll and standard libs are very few. Two only).

1 Like

Could it be that those flatbuffers are the same as GDAL driver FlatGeobuf? If yes, it means that perhaps GDAL could be used to access the OpenMeteo data.

1 Like

Hmm, the weather docs say that

Plot and/or retrieve weather data obtained from the Open-Meteo API. Please consult the site for further details. You will find that there are many variables available to plot and with not so obvious names. But confess that didn’t explore much the functionality of this function after writting it (which was inspired in WeatherReport.jl)

1 Like

Log 03: July 17th, 2025 - Weather Wizardry

Relaxed a little this evening and tinkered some more with FlatBuffers.jl, OpenMeteo, and HTTP.jl. After a lot of experimentation and then AI-assisted refactoring, I was able to actually get the flatbuffer spec of OpenMeteo output a Julia interface and have it working to get all the weather information I want!


Here’s a small example:

And with UnicodePlots.jl gives a nice output:


I’ll bundle this prototype together into a small Julia package to work with OpenMeteo more generally. Might be useful more generally in the future, but that means: we have weather data now! :sun:

9 Likes

Log 04: July 20th, 2025 - Polar Pi :pie:

Behold! We have OpenMeteo.jl now! It is undocumented, untested, and unregistered but it exists as a package now and fully utilizes the FlatBuffer specification from OpenMeteo! It supports all endpoints from OpenMeteo including the forecast, air quality, and additional modules here: 🌦️ Docs | Open-Meteo.com

It only has one function right now but here is an example on how to use it:

using OpenMeteo

url = "https://api.open-meteo.com/v1/forecast"
params = Dict(
    "latitude" => "42.3751",
    "longitude" => "-71.1056",
    "daily" => [
        "temperature_2m_max",
        "temperature_2m_min",
        "sunset",
        "sunrise",
        "wind_speed_10m_max",
        "wind_gusts_10m_max",
        "wind_speed_10m_min",
        "wind_gusts_10m_min"
    ],
    "hourly" => [
        "temperature_2m",
        "uv_index",
        "precipitation_probability",
        "precipitation",
        "relative_humidity_2m",
        "wind_speed_10m",
        "wind_direction_10m"
    ],
    "timezone" => "America/New_York",
    "forecast_days" => "1",
    "timeformat" => "unixtime",
    "wind_speed_unit" => "mph",
    "temperature_unit" => "fahrenheit",
    "precipitation_unit" => "inch"
)
method = "GET"
verify = true

resp = OpenMeteo.request_weather_api(url, params = params, method = method, verify = verify)[1]

hourly_vars = Dict(params["hourly"] .=> [resp.hourly.variables[x].values for x in 1:length(params["hourly"])])
daily_vars = Dict(params["daily"] .=> [resp.daily.variables[x].values for x in 1:length(params["daily"])])
sunset = resp.daily.variables[3].values_int64
sunrise = resp.daily.variables[4].values_int64

Which gives an output response like:

julia> resp
OpenMeteo.WeatherApiResponse{OpenMeteo.VariablesWithTime{OpenMeteo.VariableWithValues}, OpenMeteo.VariablesWithTime{OpenMeteo.VariableWithValues}, OpenMeteo.Vari
ablesWithTime{OpenMeteo.VariableWithValues}, OpenMeteo.VariablesWithTime{OpenMeteo.VariableWithValues}, OpenMeteo.VariablesWithTime{OpenMeteo.VariableWithValues}
}
  latitude: Float32 42.372776f0
  longitude: Float32 -71.09675f0
  elevation: Float32 12.0f0
  generation_time_milliseconds: Float32 0.106573105f0
  location_id: Int64 0
  model: OpenMeteo.Model OpenMeteo.Modelbest_match
  utc_offset_seconds: Int32 -14400
  timezone: String "America/New_York"
  timezone_abbreviation: String "GMT-4"
  current: Nothing nothing
  daily: OpenMeteo.VariablesWithTime{OpenMeteo.VariableWithValues}
  hourly: OpenMeteo.VariablesWithTime{OpenMeteo.VariableWithValues}
  minutely_15: Nothing nothing
  six_hourly: Nothing nothing

On this occasion, I celebrate with a gif:

So what do I do with this unstoppable power? Well, visualize it of course!


Here are some rough cut attempts at the moment:

using CairoMakie
using OpenMeteo

url = "https://api.open-meteo.com/v1/forecast"
params = Dict(
    "latitude" => "42.3751",
    "longitude" => "-71.1056",
    "daily" => [
        "temperature_2m_max",
        "temperature_2m_min",
        "sunset",
        "sunrise",
        "wind_speed_10m_max",
        "wind_gusts_10m_max",
        "wind_speed_10m_min",
        "wind_gusts_10m_min"
    ],
    "hourly" => [
        "temperature_2m",
        "uv_index",
        "precipitation_probability",
        "precipitation",
        "relative_humidity_2m",
        "wind_speed_10m",
        "wind_direction_10m"
    ],
    "timezone" => "America/New_York",
    "forecast_days" => "1",
    "timeformat" => "unixtime",
    "wind_speed_unit" => "mph",
    "temperature_unit" => "fahrenheit",
    "precipitation_unit" => "inch"
)
method = "GET"
verify = true

resp = OpenMeteo.request_weather_api(url, params = params, method = method, verify = verify)[1]

hourly_vars = Dict(params["hourly"] .=> [resp.hourly.variables[x].values for x in 1:length(params["hourly"])])
daily_vars = Dict(params["daily"] .=> [resp.daily.variables[x].values for x in 1:length(params["daily"])])
sunset = resp.daily.variables[3].values_int64
sunrise = resp.daily.variables[4].values_int64

f = Figure(size = (400, 240));

ax = PolarAxis(
    f[1, 1], 
    rminorgridvisible = false,
    rminorticksvisible = false,
    rgridvisible = false,
    rticks = LinearTicks(2),
    rticklabelsize = 10,
    rticklabelsvisible = false,
    rgridcolor = :blue,
    rlimits = (minimum(hourly_vars["temperature_2m"]) - 5, maximum(hourly_vars["temperature_2m"]) + 5),
    thetaminorticksvisible = false,
    thetaticks = (collect(-3pi/2:15 * pi / 180:pi/2)[1:end-1], vcat("0", ["$x" for x in 23:-1:1])),
    thetaticklabelsize = 10,
    thetaminorticks = IntervalsBetween(3),
    thetagridcolor = :lightgray
)

lines!(ax, collect(-3pi/2:15 * pi / 180:pi/2), vcat(reverse(hourly_vars["temperature_2m"]), hourly_vars["temperature_2m"][1]), color = :dimgray)

markers = []
for val in reverse(hourly_vars["uv_index"])
    println(val)
    if 0 <= val < 3
        push!(markers, :circle)
    elseif 3 <= val < 6
        push!(markers, :utriangle)
    elseif 6 <= val < 8
        push!(markers, :diamond)
    elseif 8 <= val < 11
        push!(markers, :star4)
    elseif 11 <= val 
        push!(markers, :xcross)
    end
end

scatter!(ax, collect(-3pi/2:15 * pi / 180:pi/2)[1:end-1], reverse(hourly_vars["temperature_2m"]), color = :black, markersize = 12, marker = markers) 

Which gives the following:

The symbols correspond to UV index (with circle being least dangerous and xcross being the most dangerous) and this represents temperature change over 24 hours. I still need a better way to display the band minimum and maximum weather temperatures. Don’t know an elegant way yet…

From there, we have windspeed and direction!

f = Figure(size = (400, 240));

ax = PolarAxis(
    f[1, 1], 
    rminorgridvisible = false,
    rminorticksvisible = false,
    rgridvisible = false,
    rticks = LinearTicks(2),
    rticklabelsize = 10,
    rticklabelsvisible = true,
    rgridcolor = :blue,
    rlimits = (minimum(hourly_vars["wind_speed_10m"]), maximum(hourly_vars["wind_speed_10m"]) + 2),
    thetaminorticksvisible = false,
    thetaticks = (collect(-3pi/2:15 * pi / 180:pi/2)[1:end-1], vcat("0", ["$x" for x in 23:-1:1])),
    thetaticklabelsize = 10,
    thetaminorticks = IntervalsBetween(3),
    thetagridcolor = :lightgray
)

lines!(ax, collect(-3pi/2:15 * pi / 180:pi/2), vcat(reverse(hourly_vars["wind_speed_10m"]), hourly_vars["wind_speed_10m"][1]), color = :dimgray)
scatter!(ax, collect(-3pi/2:15 * pi / 180:pi/2)[1:end-1], reverse(hourly_vars["wind_speed_10m"]), color = :black, markersize = 12, marker = '↑', rotation = hourly_vars["wind_direction_10m"] .* (pi / 180))

It’s not quite so clean yet, but we are getting there.


Now, I need to figure out how to plot a radial bar chart with probabilities of precipitation and precipitation amount. Additionally, I have no idea how to make this into one figure that shares concentric rings. Ideally, windspeed would be inside the temperature and UV plot. Does anyone know how to do this?

At any rate, we are progressing quite well! Until the next adventurous hacking – maybe at JuliaCon with @mitiemannn? :thinking: I’ll be bringing my Pi and display with me. :smiley: Happy to hack when not engaged with JuliaHealth shenanigans or AlgebraicJulia stuff too! Just grab me!

~ tcp :deciduous_tree:

2 Likes

I’m gonna be honest - I don’t like it. I don’t like that is not already featured at this year’s JuliaCon :winking_face_with_tongue: All the other stuff: I love it! If you promise to submit it as a talk, I’ll promise to submit β€œRecreational Julia, Vol. 2” as another mini next year.

1 Like

Lemme make it through this JuliaCon and then I can have brain capacity for JuliaCon '26. :joy:

1 Like

Log 05: August 3rd, 2025 - Seeing the Vision :magnifying_glass_tilted_left:

AT LAST! I posted another discussion over
in Discourse about How To Make Concentric Polar Axes with Custom Band Size in Makie? and thanks to some pointers from @jules and tinkering by @JonasWickman, I was able to get the vision of my Polar weather plot working:

Many thanks for the support from folks on the help! Also, I had to update and figure out how to hack out the radial bar plot hack using CairoMakie.jl based on the following post: Wind Rose 'hard' stacked barplot edges in GLMakie - #2 by ffreyer and solution by @ffreyer. To create a figure like this, the code (with updates to the Makie interface) is here:

using CairoMakie
using Luxor

f = Figure(
    size = (240, 240)
);

function scale_vals(data, r)
    r_min = minimum(data)
    r_max = maximum(data)
    t_min = r[1]
    t_max = r[2]

    [(m - r_min)/(r_max - r_min) * (t_max - t_min) + t_min for m in data]
end

# Outside ring
ax = PolarAxis(
    f[1, 1], 
    width = 200,
    height = 240,
    rminorgridvisible = false,
    rminorticksvisible = false,
    rgridvisible = false,
    rticks = LinearTicks(2),
    rticklabelsize = 10,
    rticklabelsvisible = false,
    rgridcolor = :blue,
    rlimits = (6.66, 10),
    thetaminorticksvisible = false,
    thetaticks = (collect(-3pi/2:15 * pi / 180:pi/2)[1:end-1], vcat("0", ["$x" for x in 23:-1:1])),
    thetaticklabelsize = 14,
    thetaminorticks = IntervalsBetween(3),
    thetagridcolor = :black,
    thetagridvisible = false,
    thetagridwidth = 1,
    clip = false
)

scatter!(ax, collect(-3pi/2:15 * pi / 180:pi/2)[1:end-1], scale_vals(reverse(hourly_vars["wind_speed_10m"]), ax.rlimits.val), color = :black, markersize = 12, marker = '↑', rotation = hourly_vars["wind_direction_10m"] .* (pi / 180))

# Middle ring
ax = PolarAxis(
    f[1, 1],
    width=120,
    height=120,
    rminorgridvisible = false,
    rminorticksvisible = false,
    rgridvisible = false,
    rticks = LinearTicks(2),
    rticklabelsize = 10,
    rticklabelsvisible = false,
    rgridcolor = :blue,
    rlimits = (3.33, 6.66),
    thetaminorticksvisible = false,
    thetaticks = (collect(-3pi/2:15 * pi / 180:pi/2)[1:end-1], vcat("0", ["$x" for x in 23:-1:1])),
    thetaticklabelsize = 10,
    thetaticklabelsvisible = false,
    thetaminorticks = IntervalsBetween(3),
    thetagridcolor = :black,
    thetagridvisible = false,
    thetagridwidth = 1,
    clip = false,
)

norm_val = ax.rlimits.val[1] / minimum(hourly_vars["temperature_2m"]) 

scatter!(ax, collect(-3pi/2:15 * pi / 180:pi/2)[1:end-1], scale_vals(reverse(hourly_vars["temperature_2m"]), ax.rlimits.val), color = :black, markersize = 8, marker = markers)

# Inside ring
ax = PolarAxis(
    f[1,1];
    width=70,
    height=70,
    rlimits = (0, 3.33),
    rminorgridvisible = false,
    rminorticksvisible = false,
    rgridvisible = false,
    rticks = LinearTicks(2),
    rticklabelsize = 10,
    rticklabelsvisible = false,
    rgridcolor = :blue,
    thetaminorticksvisible = false,
    thetaticks = (collect(-3pi/2:15 * pi / 180:pi/2)[1:end-1], vcat("0", ["$x" for x in 23:-1:1])),
    thetaticklabelsvisible = false,
    thetaminorticks = IntervalsBetween(3),
    thetagridcolor = :black,
    thetagridvisible = false,
    thetagridwidth = 1,
    clip = false,
);

p = barplot!(ax, collect(-3pi/2:15 * pi / 180:pi/2)[1:end-1], rand(0:.1:3.33, 24))
pp = popat!(p.plots, findfirst(x -> x isa Poly, p.plots))
polys = map(pp[1].value) do rects
    map(rects) do rect
        N_steps = 100
        mini = minimum(rect); maxi = maximum(rect)
        ps = Point2f[mini, Point2f(mini[1], maxi[2]), maxi, Point2f(maxi[1], mini[2]), mini]
        ps = map(range(0, 4, length = N_steps)) do f
            ps[1] * max(0, 1-f) + 
            ps[2] * max(0, 1 - abs(f-1)) + 
            ps[3] * max(0, 1 - abs(f-2)) + 
            ps[4] * max(0, 1 - abs(f-3)) + 
            ps[5] * max(0, 1 - abs(f-4))
        end
        Makie.Polygon(ps)
    end
end
poly!(p, attributes(pp), polys[1], strokecolor = :black, strokewidth = 2, color = :black)

Here’s how it looks on my eink display:


With this part out of the way, I think we now dip back more into software engineering. Basically, what I need to figure out is how to best create a layout-ing engine for my eink display that:

  • Keeps track of where components are in a display
  • Segments out the display into a grid
  • Handles components

The biggest question I have is where to put my tinkerings for components. Probably I’ll make a package like JinkiesComponents that has a bunch of extensions to load different components like for weather, todo lists, calendars, etc.

And with that! We are back to hackings!

6 Likes