Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
f2cca8a
feat(deps): adopt ex_ratatui for cell-based rendering
mcass19 May 7, 2026
5cfb4c6
feat(ex_ratatui): add embedded 6×8 ASCII bitmap font
mcass19 May 7, 2026
f730f09
feat(ex_ratatui): rasterise CellSession buffers to grayscale PNG
mcass19 May 7, 2026
8da5ace
feat(screen): add generic Screen.ExRatatui adapter
mcass19 May 7, 2026
e150cdf
feat(screen): add Counter demo ExRatatui app
mcass19 May 7, 2026
cf23a77
feat(screen): register Counter in the top-level menu
mcass19 May 7, 2026
136efd2
fix(screen): use ExRatatui.App so __runtime__/0 is injected
mcass19 May 7, 2026
aeaa08d
fix(screen): raise on missing use ExRatatui.App at mount
mcass19 May 7, 2026
42ca143
test(screen): cover Screen.ExRatatui server boot path
mcass19 May 7, 2026
8032ace
feat(screen): trap exits and render crash + initial frames
mcass19 May 7, 2026
30cdc31
feat(ex_ratatui): invert reversed cells in the rasteriser
mcass19 May 7, 2026
1e757e4
feat(ex_ratatui): extend font with lowercase, box, and block glyphs
mcass19 May 7, 2026
2a1154f
refactor(screen): polish Counter to exercise borders and reversed chips
mcass19 May 7, 2026
4fdd504
feat(screen): add Goatmire animated greeting demo
mcass19 May 10, 2026
13ab41e
feat(screen): add Stats BEAM system monitor demo
mcass19 May 10, 2026
075cd45
feat(screen): register Goatmire and Stats in the top-level menu
mcass19 May 10, 2026
f153b7b
fix(ex_ratatui): invert cells only on bg :black or :reversed modifier
mcass19 May 10, 2026
24ea681
feat(screen): brand demos with ex_ratatui on top border
mcass19 May 10, 2026
c0079e2
feat(ex_ratatui): add DemoFrame helper for shared screen chrome
mcass19 May 10, 2026
e8b3b77
refactor(screen): use DemoFrame across Counter and Stats
mcass19 May 10, 2026
f99d5a0
feat(screen): switch Goatmire to ASCII pixel-art frames
mcass19 May 10, 2026
1ad7a4c
feat(ex_ratatui): polish demos
mcass19 May 10, 2026
b91f04e
feat: system monitor ssh subsystem
mcass19 May 10, 2026
01dfb93
docs(screen): add README for the ex_ratatui demo collection
mcass19 May 10, 2026
9bfefc2
feat(screen): replace Goathi side-view with a front-view face that winks
mcass19 May 10, 2026
bcc36b7
refactor(ex_ratatui): code-review pass before opening contribution
mcass19 May 11, 2026
8692683
perf(ex_ratatui): hot-path tweaks + configurability pass
mcass19 May 11, 2026
6649350
refactor(ex_ratatui): precompute Goathi art + tighten SystemMonitor loop
mcass19 May 11, 2026
799cd38
refactor(ex_ratatui): async stats refresh + crash-safe collectors
mcass19 May 11, 2026
a3dce93
fix(ex_ratatui): honour Stats pause for samples already in flight
mcass19 May 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@ erl_crash.dump
.mise.local.toml

# ignore macOS files
.DS_Store
.DS_Store
34 changes: 34 additions & 0 deletions config/runtime.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import Config

# Register the live system monitor TUI as a `nerves_ssh` subsystem so
# you can drop into a full-color dashboard from your laptop without
# disturbing the badge's e-ink screen:
#
# ssh -t nerves@wisteria.local -s Elixir.NameBadge.ExRatatui.SystemMonitorTui
#
# Plain `ssh nerves@wisteria.local` still gives you the regular IEx
# prompt — the subsystem only kicks in when you pass `-s`.
#
# This config lives in `runtime.exs` on purpose: `ExRatatui.SSH.subsystem/1`
# is a normal function call, and on a fresh `MIX_TARGET=trellis mix
# compile` the compile-time config files (`config.exs`, `target.exs`)
# run before Mix has compiled deps for the target — `ExRatatui.SSH`
# isn't on the code path yet, so calling it there crashes with
# `module ExRatatui.SSH is not available`.
#
# `runtime.exs` is evaluated on device boot, after every beam file in
# the release is loaded but before the OTP application controller
# starts `:nerves_ssh`, so the config it writes is in place by the
# time the daemon reads it. Standard Elixir release pattern for any
# config that can't be a pure data literal.
#
# On host builds (`MIX_TARGET=host mix run`, tests, etc.) this file
# still runs but it's harmless: `:nerves_ssh` isn't a host dep, so no
# one ever reads the env key we're writing.
if Application.spec(:nerves_ssh) do
config :nerves_ssh,
subsystems: [
:ssh_sftpd.subsystem_spec(cwd: ~c"/"),
ExRatatui.SSH.subsystem(NameBadge.ExRatatui.SystemMonitorTui)
]
end
12 changes: 11 additions & 1 deletion config/target.exs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,17 @@ config :nerves, :erlinit, update_clock: true
# set tzdata dir for Nerves device
config :tzdata, :data_dir, "/data/tzdata"

# Configure the device for SSH IEx prompt access and firmware updates
# Configure the device for SSH IEx prompt access and firmware updates.
#
# ssh nerves@wisteria.local # IEx shell
# cat name_badge.fw | ssh -s nerves@... fwup # via fwup subsystem
# ssh -t nerves@wisteria.local \ # live system monitor TUI
# -s Elixir.NameBadge.ExRatatui.SystemMonitorTui
#
# The TUI subsystem is registered in `config/runtime.exs` because
# `ExRatatui.SSH.subsystem/1` is a function call and target deps
# aren't compiled when this file is evaluated. Authorized keys, by
# contrast, are baked in at build time so you never need a password.
#
# * See https://hexdocs.pm/nerves_ssh/readme.html for general SSH configuration
# * See https://hexdocs.pm/ssh_subsystem_fwup/readme.html for firmware updates
Expand Down
9 changes: 5 additions & 4 deletions lib/name_badge/battery.ex
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@ defmodule NameBadge.Battery do
min_voltage = 3.0
max_voltage = 4.2

percentage = ((v - min_voltage) / (max_voltage - min_voltage) * 100)
|> max(0)
|> min(100)
|> round()
percentage =
((v - min_voltage) / (max_voltage - min_voltage) * 100)
|> max(0)
|> min(100)
|> round()

percentage
end
Expand Down
Loading