1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
//! Local-first dashboard for a pamoja node.
//!
//! A node serves its own dashboard over its own WiFi hotspot, so a clinic worker, a
//! farmer, or a water committee sees their own data with no internet at all, in their
//! own language, on whatever cheap phone they have. This crate is the host side of
//! that: it turns the state a node already holds into a small, language-neutral
//! snapshot and serves a hand-built, localized page that renders it.
//!
//! The design rests on one split. The device emits only a [`State`] - stable keys,
//! stable codes, raw values, and canonical units, identical in every locale - and the
//! page does all rendering, formatting, and translation at the surface. That keeps the
//! device's job tiny enough for constrained hardware and the page's job rich enough to
//! be beautiful, and it means localization is a property of the page, not a fork of
//! the data.
//!
//! The pieces:
//!
//! - [`State`] is the language-neutral fleet snapshot served at `GET /state`:
//! [`Org`]s of [`Group`]s of [`Sensor`]s, each group on its own [`Link`].
//! - [`StateSource`] is the one seam between the dashboard and its data; a real
//! gateway and the `Mock` both implement it.
//! - `Mock` serves a deterministic `Scenario` so the whole dashboard runs and is
//! debugged with no hardware.
//! - [`Server`] serves the page, the snapshot, and a live event stream over plain TCP.
//!
//! # Capability tiers
//!
//! One design serves hardware from a Raspberry Pi to a microcontroller, chosen with a
//! compile-time tier feature. The `/state` contract is identical across all of them, so a
//! page written for one tier reads another tier's data:
//!
//! - Tiers A and B (`tier-a`, the default, and `tier-b`) embed the full localized app: the
//! hand-built visuals, history, authenticated control, and the seed locales. A Tier B build
//! trims flash by embedding only the locales it needs (the `locale-*` features, English
//! always included); the page learns the embedded set from `GET /locales` and offers only
//! those languages.
//! - Tier C (`tier-c`) embeds only a single self-contained floor page for the smallest
//! hardware. It renders the status table with the smallest possible script, and when
//! scripting is off entirely it falls back to `GET /lite`, a server-rendered,
//! meta-refreshing table with no script at all. It is plain, but it is legible and it
//! works on any browser.
//!
//! Build a non-default tier with `--no-default-features`, for example
//! `--no-default-features --features "serve,tier-c"`. Each tier's gzipped page-load budget
//! is enforced by `cargo xtask dashboard footprint`.
//!
//! # Examples
//!
//! A device turns the state it holds into the language-neutral snapshot the page fetches:
//!
//! ```
//! use pamoja_dashboard::{State, Status};
//!
//! let state = State {
//! orgs: Vec::new(),
//! status: Status::Alarm,
//! uptime_secs: Some(3600),
//! demo: false,
//! };
//!
//! let json = state.to_json().expect("serialize");
//! assert!(json.contains("\"status\":\"alarm\""));
//! ```
//!
//! The hardware-free `Mock` fleet (the `mock` feature) implements [`StateSource`] the same
//! way a real node does, so the whole dashboard runs and is debugged with no hardware.
// Capability tier is a compile-time choice. The full bundle ships unless `tier-c` is set, so
// the documented real build (`--no-default-features --features serve`) keeps the full page;
// `tier-c` embeds only the minimal floor page. Selecting `tier-c` alongside a full tier is
// ambiguous about which page to embed, so it is rejected with a clear pointer.
compile_error!;
pub use Assets;
pub use ;
// The presentation vocabulary a profile uses to declare custom dashboard elements, so a
// gateway can build a catalog and pin a reading's graphic from this one crate.
pub use ;
pub use StateSource;
pub use ;
pub use ;
pub use ;
pub use Catalog;
pub use ;
pub use Server;