Skip to content

Message Types

Overview

The SynerWatt platform delivers two types of telemetry messages to Azure IoT Hub: Inverter Telemetry and Boiler Telemetry. All messages follow a standardized format designed for easy integration and consumption.

Common Message Structure

All forwarded messages share a common top-level structure:

typescript
{
  sn: string,          // Required: Device serial number
  uid: string,         // Required: Unique device identifier
  timestamp: number,   // Required: Unix timestamp (seconds)
  data: object         // Required: Device-specific telemetry data
}

Common Field Details

FieldTypeRequiredDescriptionFormat/Constraints
snStringYesDevice serial number extracted from MQTT topic12-character hexadecimal
uidStringYesUnique device identifier64-bit HEX string
timestampIntegerYesUnix timestamp when telemetry was capturedSeconds since epoch
dataObjectYesDevice-specific telemetry payloadVaries by device type

Inverter Telemetry

Inverter devices provide real-time power flow measurements from solar PV systems with battery storage.

Message Specification

typescript
{
  sn: string,                     // Device serial number
  uid: string,                    // Unique device identifier
  timestamp: number,              // Unix timestamp (seconds)
  data: {
    type: "inverter",             // Device type identifier
    production_power: number,     // Solar PV production (W)
    grid_power: number,           // Grid import/export (W)
    battery_power: number,        // Battery charge/discharge (W)
    consumption_power: number,    // Household consumption (W)
    battery_soc: number,          // Battery state of charge (%)
    generator_power: number,      // Generator output (W)
    ups_power: number,            // UPS/Backup power (W)
    service_control: number | null // Server control enabled flag
  }
}
json
{
  "sn": "78390b90a994",
  "uid": "1b2a34",
  "timestamp": 1748862696,
  "data": {
    "type": "inverter",
    "production_power": 2540.0,
    "grid_power": -1200.5,
    "battery_power": 654.5,
    "consumption_power": 892.2,
    "battery_soc": 75,
    "generator_power": 0.0,
    "ups_power": 0.0,
    "service_control": 1
  }
}

Field Details

FieldTypeRequiredDescriptionFormat/Constraints
data.typeStringYesDevice type identifierAlways "inverter"
data.production_powerNumberYesSolar PV production powerWatts (W), decimal allowed
data.grid_powerNumberYesGrid power flowWatts (W), negative = export, positive = import
data.battery_powerNumberYesBattery power flowWatts (W), positive = charging, negative = discharging
data.consumption_powerNumberYesTotal household consumptionWatts (W), decimal allowed
data.battery_socNumberYesBattery state of chargePercentage (0-100)
data.generator_powerNumberYesBackup generator outputWatts (W), decimal allowed
data.ups_powerNumberYesUPS/Backup system powerWatts (W), decimal allowed
data.service_controlNumber/NullNoServer control enabled0 = disabled, 1 = enabled, null = not available

Power Flow Interpretation

Understanding power values and their signs:

  • production_power: Always positive. Amount of power generated by solar panels.
  • grid_power:
    • Positive value: Importing from grid (buying)
    • Negative value: Exporting to grid (selling)
    • Zero: No grid interaction
  • battery_power:
    • Positive value: Battery charging
    • Negative value: Battery discharging
    • Zero: Battery idle
  • consumption_power: Always positive. Total household energy consumption.

Boiler Telemetry

Boiler devices provide temperature and battery state information for smart water heating appliances.

Message Specification

typescript
{
  sn: string,                  // Device serial number
  uid: string,                 // Unique device identifier
  timestamp: number,           // Unix timestamp (seconds)
  data: {
    type: "boiler",            // Device type identifier
    appliance_id: number,      // Appliance index/position within the device
    temperature: number,       // Current water temperature (°C)
    battery_soc: number        // Battery state of charge (%)
  }
}
json
{
  "sn": "4c54d32c01fc",
  "uid": "7f8e9d",
  "timestamp": 1748862796,
  "data": {
    "type": "boiler",
    "appliance_id": 1,
    "temperature": 65.5,
    "battery_soc": 80
  }
}

Field Details

FieldTypeRequiredDescriptionFormat/Constraints
data.typeStringYesDevice type identifierAlways "boiler"
data.appliance_idNumberYesAppliance index/position within the deviceInteger (0-based index)
data.temperatureNumberYesCurrent water temperatureDegrees Celsius (°C), decimal allowed
data.battery_socNumberYesBattery state of chargePercentage (0-100)

Message Frequency & Reliability

Publishing Frequency

  • Inverters: Every 10 seconds (when data changes)
  • Boilers: Every 10 seconds (when data changes)

Change Detection

Messages are only published when telemetry values change. If the device state remains stable, no messages are sent. This optimizes bandwidth and reduces processing overhead.

Message Validation

The SynerWatt platform validates all messages before delivery:

  1. Structure Validation: Ensures all required fields are present
  2. Type Checking: Verifies field types match specification
  3. Device Authorization: Confirms device is authorized for your organization
  4. Data Integrity: Validates message content and format

Quality Guarantee

Only messages that pass all validation checks are forwarded to Azure IoT Hub. Your integration will never receive malformed or invalid messages.

Unsupported Device Types

In rare cases, you may receive messages from device types that are not yet fully supported or documented. These messages follow a fallback format:

typescript
{
  sn: string,                  // Device serial number
  uid: string,                 // Unique device identifier
  timestamp: number,           // Unix timestamp (seconds)
  data: {
    type: "unsupported",       // Device type identifier
    original_type: string,     // Original device type code
    raw_data: object           // Device-specific data payload
  }
}
json
{
  "sn": "device123",
  "uid": "abc123",
  "timestamp": 1748862896,
  "data": {
    "type": "unsupported",
    "original_type": "heatpump-v1",
    "raw_data": {
      "temp_in": 22.5,
      "temp_out": 45.0,
      "power": 1200
    }
  }
}

Field Details

FieldTypeRequiredDescriptionFormat/Constraints
data.typeStringYesDevice type identifierAlways "unsupported"
data.original_typeStringYesOriginal device type codeAlphanumeric
data.raw_dataObjectYesDevice-specific telemetry payloadStructure varies by device

Important

The structure of raw_data is not guaranteed and may vary by device type. If you receive unsupported device messages regularly, contact SynerWatt support to request proper documentation and standardization for that device type.

Do not build production integrations based on raw_data structure - it may change without notice.

Future Device Types

The SynerWatt platform is continuously expanding to support additional device types. New device types will be documented here as they become available.

Roadmap

Upcoming device types planned for full support:

  • Heat pumps
  • Electric vehicle chargers
  • Smart meters

Contact support@synerwatt.eu for early access to beta device types or to request support for specific devices.

Integration Best Practices

Message Consumption

When consuming messages from Azure IoT Hub:

  1. Check data.type field to determine message type
  2. Parse based on device type using appropriate schema
  3. Handle missing optional fields gracefully (e.g., service_control)
  4. Store timestamp for accurate time-series analysis
  5. Use sn field to identify device origin

Example Consumer Code

typescript
interface BaseTelemetry {
  sn: string;
  uid: string;
  timestamp: number;
  data: {
    type: string;
    [key: string]: any;
  };
}

interface InverterData {
  type: "inverter";
  production_power: number;
  grid_power: number;
  battery_power: number;
  consumption_power: number;
  battery_soc: number;
  generator_power: number;
  ups_power: number;
  service_control?: number | null;
}

interface BoilerData {
  type: "boiler";
  appliance_id: number;
  temperature: number;
  battery_soc: number;
}

function processTelemetry(message: BaseTelemetry) {
  switch (message.data.type) {
    case "inverter":
      const inverterData = message.data as InverterData;
      // Process inverter telemetry
      console.log(`Device ${message.sn}: PV=${inverterData.production_power}W, Grid=${inverterData.grid_power}W`);
      break;

    case "boiler":
      const boilerData = message.data as BoilerData;
      // Process boiler telemetry
      console.log(`Boiler ${message.sn}: Temp=${boilerData.temperature}°C`);
      break;

    default:
      console.warn(`Unsupported device type: ${message.data.type}`);
  }
}
python
from typing import Dict, Any

def process_telemetry(message: Dict[str, Any]) -> None:
    """Process telemetry message from Azure IoT Hub"""

    device_type = message.get('data', {}).get('type')

    if device_type == 'inverter':
        process_inverter(message)
    elif device_type == 'boiler':
        process_boiler(message)
    else:
        print(f"Unsupported device type: {device_type}")

def process_inverter(message: Dict[str, Any]) -> None:
    """Process inverter telemetry"""
    sn = message['sn']
    data = message['data']

    print(f"Device {sn}: "
          f"PV={data['production_power']}W, "
          f"Grid={data['grid_power']}W, "
          f"Battery={data['battery_soc']}%")

def process_boiler(message: Dict[str, Any]) -> None:
    """Process boiler telemetry"""
    sn = message['sn']
    data = message['data']

    print(f"Boiler {sn}: "
          f"Temp={data['temperature']}°C, "
          f"Battery={data['battery_soc']}%")

Time-Series Data Storage

For optimal time-series storage and analysis:

  • Use timestamp field as the primary time index
  • Use sn field for device partitioning
  • Store numeric fields (production_power, temperature, etc.) in appropriate numeric types
  • Consider downsampling strategies for long-term storage