Decoded Block 0 status (0x40) and report (0x47) of a Schema 1 device.

Classes

  Name
struct NW_Report
The two Block 0 bytes that describe a reading’s health, with their decoding.

Functions

  Name
size_t nwPrintHex(Print & out, const uint8_t * b, uint8_t n)
Print n bytes as upper-case hex pairs, no separators.
size_t nwPrintCommit(Print & out, const uint8_t * b)
Print a build commit from Page 0 Block 3: bytes 0x18-0x1B as 8 hex characters, “+” when byte 0x1C bit 0 marks a dirty tree; nothing when the four bytes are zero (no build wrapper).
size_t nwPrintPage(Print & out, const uint8_t * page)
Print a 32-byte page as four 8-byte blocks in hex, a space between blocks: the status file’s page columns.

Functions Documentation

function nwPrintHex

inline size_t nwPrintHex(
    Print & out,
    const uint8_t * b,
    uint8_t n
)

Print n bytes as upper-case hex pairs, no separators.

function nwPrintCommit

inline size_t nwPrintCommit(
    Print & out,
    const uint8_t * b
)

Print a build commit from Page 0 Block 3: bytes 0x18-0x1B as 8 hex characters, “+” when byte 0x1C bit 0 marks a dirty tree; nothing when the four bytes are zero (no build wrapper).

Parameters:

  • b the five bytes at Page 0 offset 0x18

function nwPrintPage

inline size_t nwPrintPage(
    Print & out,
    const uint8_t * page
)

Print a 32-byte page as four 8-byte blocks in hex, a space between blocks: the status file’s page columns.

Source code


#ifndef NW_Report_h
#define NW_Report_h

#include <Arduino.h>

inline size_t nwPrintHex(Print& out, const uint8_t* b, uint8_t n) {
  static const char digits[] = "0123456789ABCDEF";
  size_t k = 0;
  for (uint8_t i = 0; i < n; i++) { k += out.print(digits[b[i] >> 4]); k += out.print(digits[b[i] & 0x0F]); }
  return k;
}

inline size_t nwPrintCommit(Print& out, const uint8_t* b) {
  if (!(b[0] | b[1] | b[2] | b[3])) return 0;
  size_t k = nwPrintHex(out, b, 4);
  if (b[4] & 0x01) k += out.print('+');
  return k;
}

inline size_t nwPrintPage(Print& out, const uint8_t* page) {
  size_t k = 0;
  for (uint8_t b = 0; b < 4; b++) { if (b) k += out.print(' '); k += nwPrintHex(out, page + 8 * b, 8); }
  return k;
}

struct NW_Report {
  uint8_t status = 0;   
  uint8_t code   = 0;   

  bool ready() const                    { return status & 0x01; }
  bool chipFaulted(uint8_t chip) const  { return status & (1 << (chip + 1)); }   
  bool any() const                      { return status & 0x80; }               
  uint8_t chip() const                  { return code >> 5; }                   
  uint8_t kind() const                  { return code & 0x1F; }
  bool isUnit() const                   { return chip() == 7; }
  bool isFault() const                  { return kind() != 0 && (isUnit() ? any() : chipFaulted(chip())); }
  bool isNotice() const                 { return kind() != 0 && !isFault(); }

  size_t printKind(Print& out) const {
    switch (kind()) {
      case 0: return out.print(F("none"));
      case 1: return out.print(F("not answering"));
      case 2: return out.print(F("timed out"));
      case 3: return out.print(isUnit() ? F("Page 0 invalid") : F("checksum failed"));
      case 4: return out.print(F("out of range"));
      case 5: return out.print(F("self-test failed"));
      case 6: return out.print(F("restarted since configured"));
      case 7: return out.print(F("configuration rejected"));
      case 8: return out.print(F("power fault"));
      case 9: return out.print(F("calibration stored"));
      case 10: return out.print(F("batch abandoned"));
      default: { size_t n = out.print(F("kind ")); return n + out.print(kind()); }
    }
  }
  String kindWord() const {
    switch (kind()) {
      case 0: return String(F("None"));
      case 1: return String(F("NotAnswering"));
      case 2: return String(F("Timeout"));
      case 3: return String(isUnit() ? F("Page0Invalid") : F("ChecksumFailed"));
      case 4: return String(F("OutOfRange"));
      case 5: return String(F("SelfTestFailed"));
      case 6: return String(F("Restarted"));
      case 7: return String(F("ConfigRejected"));
      case 8: return String(F("PowerFault"));
      case 9: return String(F("CalibrationStored"));
      case 10: return String(F("BatchAbandoned"));
      default: { String w = F("Kind"); w += String(kind()); return w; }
    }
  }
  size_t print(Print& out, const char* const* chipNames, uint8_t nChips, const char* const* kindWords = nullptr, uint8_t nKindWords = 0) const {
    uint8_t c = chip(), k = kind();
    if (k == 0) return out.print(F("none"));
    if (k >= 16 && kindWords && (uint8_t)(k - 16) < nKindWords) return out.print(kindWords[k - 16]);   // a device-specific kind: its own word says it all
    size_t n = 0;
    if (c == 7) n += out.print(F("unit"));
    else if (c < nChips) n += out.print(chipNames[c]);
    else { n += out.print(F("chip ")); n += out.print(c); }
    n += out.print(F(": "));
    return n + printKind(out);
  }
  String note(const char* const* chipNames, uint8_t nChips, const char* const* kindWords = nullptr, uint8_t nKindWords = 0) const {
    uint8_t c = chip();
    String w;
    if (kind() == 0) return String(F("UnitNone"));
    if (kind() >= 16 && kindWords && (uint8_t)(kind() - 16) < nKindWords) return String(kindWords[kind() - 16]);   // device-specific: the appendix's word alone
    if (c == 7) w = F("Unit");
    else if (c < nChips) w = chipNames[c];
    else { w = F("Chip"); w += String(c); }
    w += kindWord();
    return w;
  }
  bool chipAbsent() const               { return kind() == 1 || kind() == 5; }
};

#endif

Updated on 2026-09-29 at 05:58:59 +0000