gabe /presentato-mf
public · Issues · Pulls · Labels · Forks · Compare · Actions success · Badges · Packages
⭐
Log in to mark this repository.
acme-camera: assumptions, build & OS, security, event anatomy, power budget, risks; components to appendix
10112a6 · Gabriel Morell · 2026-10-13 19:19
Files changed
modified
content/presentations/acme-camera.md
+327
−121
@@ -18,6 +18,27 @@ reveal_transition = "slide"
| 18 | 18 | |
| 19 | 19 | A wireless security system architecture supporting long operational life |
| 20 | 20 | |
| 21 | +Note: | |
| 22 | +The pitch: months on a charge, a person-confirmed alert in seconds, and fleet data that proves both | |
| 23 | + | |
| 24 | +--- | |
| 25 | + | |
| 26 | +# Assumptions | |
| 27 | + | |
| 28 | +| Area | Assumption | | |
| 29 | +|---|---| | |
| 30 | +| Battery | ~6000 mAh Li-ion pack | | |
| 31 | +| External power | regulated 5 V, solar included | | |
| 32 | +| Activity | ~20 events/day, ~10 s clips | | |
| 33 | +| Network | 2.4 GHz Wi-Fi to a home AP | | |
| 34 | +| Recording | event clips, live view on demand | | |
| 35 | +| Backend | exists, we own the device side | | |
| 36 | + | |
| 37 | +Note: | |
| 38 | +These drive every number later in the deck, so happy to rerun the math if Acme's are different | |
| 39 | +Solar is just another 5 V source, the panel's own controller handles MPPT | |
| 40 | +No continuous recording, a battery camera can't afford it | |
| 41 | + | |
| 21 | 42 | --- |
| 22 | 43 | |
| 23 | 44 | # Hardware Design |
@@ -132,6 +153,39 @@ infctl: inference controller for on-chip npus to load models (bonus)
| 132 | 153 | |
| 133 | 154 | --- |
| 134 | 155 | |
| 156 | +# Build & OS | |
| 157 | + | |
| 158 | +- Yocto on the SOC vendor's BSP | |
| 159 | +- Read-only rootfs in A/B slots, writable `/data` | |
| 160 | +- Signed images, built reproducibly in CI | |
| 161 | +- Rust daemons as sandboxed systemd units | |
| 162 | + | |
| 163 | +Note: | |
| 164 | +Yocto for layers, an SDK for app developers, and license manifests / SBOM for free; Buildroot if the chosen vendor only supports that | |
| 165 | +Kernel trimmed to what the board needs, suspend-to-RAM tuned so a wake is a resume, not a boot | |
| 166 | +Read-only rootfs means an update is a whole-slot swap, nothing drifts between devices | |
| 167 | +/data holds config, credentials and the clip buffer, and is the only thing a factory reset wipes | |
| 168 | + | |
| 169 | +-- | |
| 170 | + | |
| 171 | +## Process Model | |
| 172 | + | |
| 173 | +| Unit | Can reach | | |
| 174 | +|---|---| | |
| 175 | +| broker | `/run/broker.sock` | | |
| 176 | +| mcuctl | UART to the MCU | | |
| 177 | +| powerctl | PMIC over I²C | | |
| 178 | +| cameractl | sensor, ISP, clip buffer | | |
| 179 | +| portalctl | soft-AP, HTTP | | |
| 180 | +| configctl | `/data/config` | | |
| 181 | + | |
| 182 | +Note: | |
| 183 | +Each unit runs as its own user with ProtectSystem=strict and DeviceAllow for only its hardware | |
| 184 | +The broker checks the connecting uid (SO_PEERCRED) against per-topic ACLs, so portalctl can request config but never write it | |
| 185 | +A crashed daemon is restarted by systemd and counted in telemetry | |
| 186 | + | |
| 187 | +--- | |
| 188 | + | |
| 135 | 189 | # Boot Plan |
| 136 | 190 | |
| 137 | 191 | <iframe src="https://diogramos.neiam.co/embed/C0ICOZGl94HAS7JuVHy8OjPN?mode=frame" |
@@ -143,6 +197,267 @@ Uses an A+B boot that only changes the boot target once we've booted successfull
| 143 | 197 | |
| 144 | 198 | --- |
| 145 | 199 | |
| 200 | +# Security | |
| 201 | + | |
| 202 | +Trust from boot to cloud | |
| 203 | + | |
| 204 | +Note: | |
| 205 | +Home security buyers ask about this first, and a compromised camera is a camera pointed into someone's home | |
| 206 | + | |
| 207 | +-- | |
| 208 | + | |
| 209 | +## Layers | |
| 210 | + | |
| 211 | +| Layer | Measure | | |
| 212 | +|---|---| | |
| 213 | +| Boot | secure boot, signed A/B images | | |
| 214 | +| Keys | secure element / OTP, never in rootfs | | |
| 215 | +| Storage | encrypted `/data` and clips | | |
| 216 | +| Processes | per-service users, sandboxed units | | |
| 217 | +| Broker | per-topic ACLs by peer uid | | |
| 218 | +| Setup | soft-AP only while unprovisioned | | |
| 219 | +| Cloud | per-device certs, mutual TLS | | |
| 220 | + | |
| 221 | +Note: | |
| 222 | +The claim token from setup is exchanged for a per-device cert, nothing shared across the fleet | |
| 223 | +Telemetry carries metrics only, no video and nothing personal beyond the display name | |
| 224 | +Factory reset wipes /data and revokes the device cert server side | |
| 225 | + | |
| 226 | +--- | |
| 227 | + | |
| 228 | +# Components | |
| 229 | + | |
| 230 | +| Component | Role | | |
| 231 | +|---|---| | |
| 232 | +| <a href="#/broker">broker</a> | MQTT on a Unix socket | | |
| 233 | +| <a href="#/mcuctl">mcuctl</a> | motion and lights via the MCU | | |
| 234 | +| <a href="#/powerctl">powerctl</a> | power modes, PMIC telemetry | | |
| 235 | +| <a href="#/portalctl">portalctl</a> | setup and status portals | | |
| 236 | +| <a href="#/cameractl">cameractl</a> | frames to storage and cloud | | |
| 237 | +| <a href="#/configctl">configctl</a> | source of truth for settings | | |
| 238 | +| <a href="#/infctl">infctl</a> | on-device inference (bonus) | | |
| 239 | + | |
| 240 | +Note: | |
| 241 | +Details and types for each are in the appendix, the links jump there | |
| 242 | + | |
| 243 | +--- | |
| 244 | + | |
| 245 | +# Anatomy of an Event | |
| 246 | + | |
| 247 | +| Step | t | | |
| 248 | +|---|---| | |
| 249 | +| PIR trips, MCU wakes the SOC | 0 | | |
| 250 | +| SOC resumes from suspend | ~200 ms | | |
| 251 | +| Radar confirms a person | ~300 ms | | |
| 252 | +| First frame from the sensor | ~700 ms | | |
| 253 | +| Wi-Fi reconnects | ~1.5 s | | |
| 254 | +| Notification sent | ~2 s | | |
| 255 | +| Clip uploaded, back to sleep | ~15 s | | |
| 256 | + | |
| 257 | +Note: | |
| 258 | +The SOC resumes in parallel with the radar check, if the radar doesn't confirm it goes straight back to sleep | |
| 259 | +Capture starts before the network is up, frames go to the local clip buffer first, so the first frame isn't waiting on Wi-Fi | |
| 260 | +~15 s at ~400 mA is the ~1.5 mAh per event the power budget uses | |
| 261 | +Keeping Wi-Fi associated while asleep would cut 1.5 s but costs standby current, a config trade-off | |
| 262 | + | |
| 263 | +--- | |
| 264 | + | |
| 265 | +# Metrics | |
| 266 | + | |
| 267 | +- Performance within the configured power envelope | |
| 268 | + | |
| 269 | +_leading to insights for better defaults_ <!-- .element: class="fragment" --> | |
| 270 | + | |
| 271 | +- Battery life across the fleet <!-- .element: class="fragment" --> | |
| 272 | + | |
| 273 | +Note: | |
| 274 | +Every config choice (motion mode, light mode, schedules) trades responsiveness for battery, | |
| 275 | +so the metrics are about how well a device does inside the envelope its owner picked, | |
| 276 | +and fleet data tells us which defaults to ship | |
| 277 | + | |
| 278 | +-- | |
| 279 | + | |
| 280 | +## Targets | |
| 281 | + | |
| 282 | +| Metric | Target | | |
| 283 | +|---|---| | |
| 284 | +| Battery life, default config | ≥ 3 months | | |
| 285 | +| Standby draw, SOC asleep | ≤ 100 µA | | |
| 286 | +| Motion → first frame | < 1 s p95 | | |
| 287 | +| Motion → notification | < 5 s p95 | | |
| 288 | +| False wakes (no person) | < 20% | | |
| 289 | +| Crash-free wakes | > 99.9% | | |
| 290 | +| OTA success, first try | > 99.5% | | |
| 291 | + | |
| 292 | +Note: | |
| 293 | +Assumptions: ~6000 mAh pack, 20 events/day, 10 s clips, ~400 mA while the SOC, Wi-Fi and IR are up | |
| 294 | +Each event costs roughly 1.5 mAh, so events dominate and standby has to stay tiny | |
| 295 | +Wake latency is the user-visible one: a late first frame means a clip of someone's back | |
| 296 | +False wakes are PIR triggers the radar doesn't confirm, they cost battery for nothing | |
| 297 | +A/B boot means a failed OTA rolls back rather than bricks, the target is about not needing to | |
| 298 | + | |
| 299 | +-- | |
| 300 | + | |
| 301 | +## Power Budget | |
| 302 | + | |
| 303 | +| Item | mAh/day | | |
| 304 | +|---|---| | |
| 305 | +| Standby, 100 µA × 24 h | 2.4 | | |
| 306 | +| Events, 20 × 1.5 mAh | 30 | | |
| 307 | +| Heartbeat + telemetry | ~0.5 | | |
| 308 | +| Self-discharge, ~2%/month | ~4 | | |
| 309 | +| **Total** | **~37** | | |
| 310 | +| **6000 mAh × 80% usable** | **~130 days** | | |
| 311 | + | |
| 312 | +Note: | |
| 313 | +Events are ~80% of the budget, so the false wake target and clip length matter more than standby | |
| 314 | +40 events/day halves it to ~65 days, cold weather takes another chunk off usable capacity | |
| 315 | +This is the table the fleet data should confirm or correct | |
| 316 | + | |
| 317 | +-- | |
| 318 | + | |
| 319 | +## Slicing the Fleet | |
| 320 | + | |
| 321 | +- Firmware version | |
| 322 | +- Motion / light / power mode | |
| 323 | +- Battery vs solar vs external | |
| 324 | +- Temperature and Wi-Fi signal | |
| 325 | + | |
| 326 | +Note: | |
| 327 | +Averages hide problems: a battery life drop on one firmware, or in cold climates, or on weak Wi-Fi | |
| 328 | +These are the dimensions every metric gets broken down by | |
| 329 | +Firmware cohorts gate staged OTA rollouts: a regression in one cohort halts the rollout | |
| 330 | + | |
| 331 | +--- | |
| 332 | + | |
| 333 | +# Instrumentation | |
| 334 | + | |
| 335 | +What we measure, how it leaves the device, and how often | |
| 336 | + | |
| 337 | +Note: | |
| 338 | +Combines environmental and fuel gauge data with what each component already knows | |
| 339 | + | |
| 340 | +-- | |
| 341 | + | |
| 342 | +## Signals | |
| 343 | + | |
| 344 | +| Source | Signals | | |
| 345 | +|---|---| | |
| 346 | +| powerctl | voltage, current, charge | | |
| 347 | +| mcuctl | wake reason, radar confirm | | |
| 348 | +| cameractl | wake → frame latency | | |
| 349 | +| network | connect time, RSSI | | |
| 350 | +| system | fw, boot slot, crashes | | |
| 351 | +| environment | temperature, light | | |
| 352 | + | |
| 353 | +Note: | |
| 354 | +powerctl also reports time to empty, mcuctl how long the lights were on, cameractl clip length, network upload time, system the reboot reason | |
| 355 | +Each component publishes its own metrics to the broker, so nothing new has to reach into another process | |
| 356 | +Energy per wake comes from the fuel gauge before and after, which ties every event to its battery cost | |
| 357 | + | |
| 358 | +-- | |
| 359 | + | |
| 360 | +## Collection | |
| 361 | + | |
| 362 | +- Components publish metrics to the broker | |
| 363 | +- A telemetry agent aggregates and buffers to flash | |
| 364 | +- MCU logs hourly samples while the SOC sleeps | |
| 365 | +- Uploads ride along when Wi-Fi is already up | |
| 366 | + | |
| 367 | +Note: | |
| 368 | +Never wake the radio just to report, telemetry should be well under 1% of the energy budget | |
| 369 | +The MCU keeps a small ring buffer of sleep samples (battery, temperature, wake counts) that the SOC drains on its next wake | |
| 370 | +Buffered to flash so a dead battery or lost network doesn't lose history | |
| 371 | +Upload is MQTT over TLS to the backend, the same connection the device already holds for events | |
| 372 | + | |
| 373 | +-- | |
| 374 | + | |
| 375 | +## Reporting Cadence | |
| 376 | + | |
| 377 | +| When | What | | |
| 378 | +|---|---| | |
| 379 | +| Every event | wake summary: reason, latency, energy | | |
| 380 | +| Daily heartbeat | counters, battery state, sleep samples | | |
| 381 | +| After a crash or rollback | coredump and reboot reason | | |
| 382 | +| On demand | debug logs, per device | | |
| 383 | + | |
| 384 | +Note: | |
| 385 | +The heartbeat goes out even with no events, so a silent device is a signal on its own | |
| 386 | +Coredumps are symbolicated server side, the device only ships the raw dump | |
| 387 | +On demand logs are for support cases, off by default to save power and bandwidth | |
| 388 | + | |
| 389 | +-- | |
| 390 | + | |
| 391 | +## Fleet Dashboards | |
| 392 | + | |
| 393 | +- Projected battery life per device vs target | |
| 394 | +- Latency and false wake rate per cohort | |
| 395 | +- Alerts: projected life below target, missed heartbeat, crash spikes after OTA | |
| 396 | + | |
| 397 | +Note: | |
| 398 | +Projected life comes from the measured drain rate, so we can flag a device months before it dies | |
| 399 | +Missed heartbeat for 48 h means dead, offline or stuck, worth an owner notification | |
| 400 | +A crash spike in a new firmware cohort pauses the rollout automatically | |
| 401 | + | |
| 402 | +--- | |
| 403 | + | |
| 404 | +# Risks | |
| 405 | + | |
| 406 | +| Risk | Mitigation | | |
| 407 | +|---|---| | |
| 408 | +| SOC vendor BSP quality | evaluate two SOCs early | | |
| 409 | +| Battery life misses target | measure from the first prototype | | |
| 410 | +| Wake latency | resume, don't boot | | |
| 411 | +| Weak Wi-Fi | local clip buffer, RSSI telemetry | | |
| 412 | +| RF certification | pre-certified Wi-Fi module | | |
| 413 | +| Fleet regressions | staged OTA, A/B rollback | | |
| 414 | + | |
| 415 | +Note: | |
| 416 | +BSP quality is the biggest schedule risk for camera SOCs, kernel age and ISP blobs vary a lot between vendors | |
| 417 | +Battery life is the product, so it's measured on every build, not at the end | |
| 418 | + | |
| 419 | +-- | |
| 420 | + | |
| 421 | +## Trade-offs | |
| 422 | + | |
| 423 | +| Choice | Gains | Costs | | |
| 424 | +|---|---|---| | |
| 425 | +| PIR wakes radar | fewer false alerts | ~100 ms | | |
| 426 | +| Radar only | catches still people | standby draw | | |
| 427 | +| Lights on motion | color night video | battery | | |
| 428 | +| Longer clips | more context | battery, upload | | |
| 429 | +| Wi-Fi kept up | faster live view | standby draw | | |
| 430 | +| On-device inference | smarter alerts | NPU power, BOM | | |
| 431 | + | |
| 432 | +Note: | |
| 433 | +Every row is a battery-life knob, which is why the metrics are per configuration | |
| 434 | +The defaults are a product decision, fleet data tells us whether they were the right ones | |
| 435 | + | |
| 436 | +-- | |
| 437 | + | |
| 438 | +## Delivery Plan | |
| 439 | + | |
| 440 | +| Phase | Outcome | | |
| 441 | +|---|---| | |
| 442 | +| EVT, ~2 mo | dev kits, BSP up, power measured | | |
| 443 | +| DVT, ~3 mo | custom board, all daemons, OTA | | |
| 444 | +| PVT, ~3 mo | certification, ~100 device pilot | | |
| 445 | +| Launch | staged rollout, dashboards live | | |
| 446 | + | |
| 447 | +Note: | |
| 448 | +Rough durations, mostly gated by the board spins and certification | |
| 449 | +Telemetry ships in EVT firmware, the pilot fleet is where the targets get validated | |
| 450 | + | |
| 451 | +--- | |
| 452 | + | |
| 453 | +# Appendix | |
| 454 | + | |
| 455 | +Component details and types | |
| 456 | + | |
| 457 | +--- | |
| 458 | + | |
| 459 | +<!-- .slide: id="broker" --> | |
| 460 | + | |
| 146 | 461 | # Component : Broker |
| 147 | 462 | |
| 148 | 463 | - MQTT |
@@ -153,6 +468,8 @@ TODO: topic layout and which components publish/subscribe
| 153 | 468 | |
| 154 | 469 | --- |
| 155 | 470 | |
| 471 | +<!-- .slide: id="mcuctl" --> | |
| 472 | + | |
| 156 | 473 | # Component : MCUctl |
| 157 | 474 | |
| 158 | 475 | Owns the MCU link: motion sensing and lighting |
@@ -191,6 +508,8 @@ enum LightControlMode {
| 191 | 508 | |
| 192 | 509 | --- |
| 193 | 510 | |
| 511 | +<!-- .slide: id="powerctl" --> | |
| 512 | + | |
| 194 | 513 | # Component: Powerctl |
| 195 | 514 | |
| 196 | 515 | Power modes, schedules and PMIC telemetry |
@@ -241,6 +560,8 @@ struct PowerReading {
| 241 | 560 | |
| 242 | 561 | --- |
| 243 | 562 | |
| 563 | +<!-- .slide: id="portalctl" --> | |
| 564 | + | |
| 244 | 565 | # Component: Portalctl |
| 245 | 566 | |
| 246 | 567 | First-boot setup, then a status portal |
@@ -337,6 +658,8 @@ Read-only view assembled from the other components via the broker
| 337 | 658 | |
| 338 | 659 | --- |
| 339 | 660 | |
| 661 | +<!-- .slide: id="cameractl" --> | |
| 662 | + | |
| 340 | 663 | # Component: Cameractl |
| 341 | 664 | |
| 342 | 665 | Note: |
@@ -344,6 +667,8 @@ Reads frames from the camera and decides to do further processing depending on c
| 344 | 667 | |
| 345 | 668 | --- |
| 346 | 669 | |
| 670 | +<!-- .slide: id="configctl" --> | |
| 671 | + | |
| 347 | 672 | # Component: Configctl |
| 348 | 673 | |
| 349 | 674 | Note: |
@@ -355,129 +680,10 @@ Source of truth for various configurations set from the portal
| 355 | 680 | |
| 356 | 681 | -- |
| 357 | 682 | |
| 683 | +<!-- .slide: id="infctl" --> | |
| 684 | + | |
| 358 | 685 | # Component: Infctl |
| 359 | 686 | |
| 360 | 687 | Note: |
| 361 | 688 | This one is -- because it's a bonus one that we may not get into |
| 362 | 689 | Configures on-device inference using NPU hardware available in modern camera SOCs |
| 363 | − | |
| 364 | −--- | |
| 365 | − | |
| 366 | −# Metrics | |
| 367 | − | |
| 368 | −- Performance within the configured power envelope | |
| 369 | − | |
| 370 | −_leading to insights for better defaults_ <!-- .element: class="fragment" --> | |
| 371 | − | |
| 372 | −- Battery life across the fleet <!-- .element: class="fragment" --> | |
| 373 | − | |
| 374 | −Note: | |
| 375 | −Every config choice (motion mode, light mode, schedules) trades responsiveness for battery, | |
| 376 | −so the metrics are about how well a device does inside the envelope its owner picked, | |
| 377 | −and fleet data tells us which defaults to ship | |
| 378 | − | |
| 379 | −-- | |
| 380 | − | |
| 381 | −## Targets | |
| 382 | − | |
| 383 | −| Metric | Target | | |
| 384 | −|---|---| | |
| 385 | −| Battery life, default config | ≥ 3 months | | |
| 386 | −| Standby draw, SOC asleep | ≤ 100 µA | | |
| 387 | −| Motion → first frame | < 1 s p95 | | |
| 388 | −| Motion → notification | < 5 s p95 | | |
| 389 | −| False wakes (no person) | < 20% | | |
| 390 | −| Crash-free wakes | > 99.9% | | |
| 391 | −| OTA success, first try | > 99.5% | | |
| 392 | − | |
| 393 | −Note: | |
| 394 | −Assumptions: ~6000 mAh pack, 20 events/day, 10 s clips, ~400 mA while the SOC, Wi-Fi and IR are up | |
| 395 | −Each event costs roughly 1.5 mAh, so events dominate and standby has to stay tiny | |
| 396 | −Wake latency is the user-visible one: a late first frame means a clip of someone's back | |
| 397 | −False wakes are PIR triggers the radar doesn't confirm, they cost battery for nothing | |
| 398 | −A/B boot means a failed OTA rolls back rather than bricks, the target is about not needing to | |
| 399 | − | |
| 400 | −-- | |
| 401 | − | |
| 402 | −## Slicing the Fleet | |
| 403 | − | |
| 404 | −- Firmware version | |
| 405 | −- Motion / light / power mode | |
| 406 | −- Battery vs solar vs external | |
| 407 | −- Temperature and Wi-Fi signal | |
| 408 | − | |
| 409 | −Note: | |
| 410 | −Averages hide problems: a battery life drop on one firmware, or in cold climates, or on weak Wi-Fi | |
| 411 | −These are the dimensions every metric gets broken down by | |
| 412 | −Firmware cohorts gate staged OTA rollouts: a regression in one cohort halts the rollout | |
| 413 | − | |
| 414 | −--- | |
| 415 | − | |
| 416 | −# Instrumentation | |
| 417 | − | |
| 418 | −What we measure, how it leaves the device, and how often | |
| 419 | − | |
| 420 | −Note: | |
| 421 | −Combines environmental and fuel gauge data with what each component already knows | |
| 422 | − | |
| 423 | −-- | |
| 424 | − | |
| 425 | −## Signals | |
| 426 | − | |
| 427 | −| Source | Signals | | |
| 428 | −|---|---| | |
| 429 | −| powerctl | voltage, current, charge | | |
| 430 | −| mcuctl | wake reason, radar confirm | | |
| 431 | −| cameractl | wake → frame latency | | |
| 432 | −| network | connect time, RSSI | | |
| 433 | −| system | fw, boot slot, crashes | | |
| 434 | −| environment | temperature, light | | |
| 435 | − | |
| 436 | −Note: | |
| 437 | −powerctl also reports time to empty, mcuctl how long the lights were on, cameractl clip length, network upload time, system the reboot reason | |
| 438 | −Each component publishes its own metrics to the broker, so nothing new has to reach into another process | |
| 439 | −Energy per wake comes from the fuel gauge before and after, which ties every event to its battery cost | |
| 440 | − | |
| 441 | −-- | |
| 442 | − | |
| 443 | −## Collection | |
| 444 | − | |
| 445 | −- Components publish metrics to the broker | |
| 446 | −- A telemetry agent aggregates and buffers to flash | |
| 447 | −- MCU logs hourly samples while the SOC sleeps | |
| 448 | −- Uploads ride along when Wi-Fi is already up | |
| 449 | − | |
| 450 | −Note: | |
| 451 | −Never wake the radio just to report, telemetry should be well under 1% of the energy budget | |
| 452 | −The MCU keeps a small ring buffer of sleep samples (battery, temperature, wake counts) that the SOC drains on its next wake | |
| 453 | −Buffered to flash so a dead battery or lost network doesn't lose history | |
| 454 | −Upload is MQTT over TLS to the backend, the same connection the device already holds for events | |
| 455 | − | |
| 456 | −-- | |
| 457 | − | |
| 458 | −## Reporting Cadence | |
| 459 | − | |
| 460 | −| When | What | | |
| 461 | −|---|---| | |
| 462 | −| Every event | wake summary: reason, latency, energy | | |
| 463 | −| Daily heartbeat | counters, battery state, sleep samples | | |
| 464 | −| After a crash or rollback | coredump and reboot reason | | |
| 465 | −| On demand | debug logs, per device | | |
| 466 | − | |
| 467 | −Note: | |
| 468 | −The heartbeat goes out even with no events, so a silent device is a signal on its own | |
| 469 | −Coredumps are symbolicated server side, the device only ships the raw dump | |
| 470 | −On demand logs are for support cases, off by default to save power and bandwidth | |
| 471 | − | |
| 472 | −-- | |
| 473 | − | |
| 474 | −## Fleet Dashboards | |
| 475 | − | |
| 476 | −- Projected battery life per device vs target | |
| 477 | −- Latency and false wake rate per cohort | |
| 478 | −- Alerts: projected life below target, missed heartbeat, crash spikes after OTA | |
| 479 | − | |
| 480 | −Note: | |
| 481 | −Projected life comes from the measured drain rate, so we can flag a device months before it dies | |
| 482 | −Missed heartbeat for 48 h means dead, offline or stuck, worth an owner notification | |
| 483 | −A crash spike in a new firmware cohort pauses the rollout automatically |
modified
sass/reveal-neiam.scss
+3
−0
@@ -58,7 +58,10 @@
| 58 | 58 | } |
| 59 | 59 | } |
| 60 | 60 | |
| 61 | + // Tables carry the dense slides (targets, budgets, risks), so set them a | |
| 62 | + // little smaller than body text to fit 6-7 rows under a heading. | |
| 61 | 63 | table { |
| 64 | + font-size: 0.75em; | |
| 62 | 65 | th { color: var(--accent); } |
| 63 | 66 | th, td { border-bottom: var(--border) solid var(--base-300); } |
| 64 | 67 | } |
Parents: 663be22