Documentation

Chart File Format

Due to popular demand, we publish our proprietary file format here. However we cannot offer any support for it. Instead we assume you have the necessary programming skills to use it. You can see the file format in action in our UI where we read the historical data and create charts from it.

Downloading the measurement data produces an archive that is a zip file with uncompressed files stored into subfolders corresponding to the device ID or "GD" for the grid demand chart on the start page.

Each folder contains files L0, L1, ... up to L7, with different resolutions of recorded data with up to 400 entries, but usually at least 360:

FileResolutionMax time
L010 s1 hour
L11 min6 hours
L25 min1 day + 6 h
L330 min1 week + 12 h
L42 hour30 days
L51 day1 year
L61 week7 years
L74 week28 years

Each file comes with a header, all values are little-endian:

struct chart_header {
   int32_t magic;   // 0xcf05ca37
   uint8_t version; // 2
   uint8_t level;   // 0-7
   uint16_t hash;   // 0
   tm_t time;       // time after last record (seconds since 2000/01/01)
   uint32_t interval; // resolution in seconds
   uint32_t cnt;    // number of records
};

followed by records:

struct chart_record {
   in32_t energy;     // import-export [Wh / 10]
   power_t power_min; // minimum power in the time frame [W]
   power_t power_max; // maximum power in the time frame [W]
   power_t power_avg; // average power in the time frame [W]
};

where power_t is an 32-bit integer value represented in 16-bit with an accuracy of 11 bits:

struct power_t {
   union {
      int16_t val;
      struct {
         uint16_t mant : 10;
         uint16_t expo : 5;
         uint16_t sign : 1;
      };
   };
   static const int16_t nan_val = int16_t(0x5800); // yields 0x8000'0000 in to_int()
   int32_t to_int() const {
      return (sign ? -1 : 1) * (expo == 0 ? mant : int32_t((1 << 10) | mant) << (expo - 1));
   }
};

Any value in chart_record that evaluates to 0x8000'0000 means that no value is available.