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:
{
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
| Field | Type | Required | Description | Format/Constraints |
|---|---|---|---|---|
sn | String | Yes | Device serial number extracted from MQTT topic | 12-character hexadecimal |
uid | String | Yes | Unique device identifier | 64-bit HEX string |
timestamp | Integer | Yes | Unix timestamp when telemetry was captured | Seconds since epoch |
data | Object | Yes | Device-specific telemetry payload | Varies by device type |
Inverter Telemetry
Inverter devices provide real-time power flow measurements from solar PV systems with battery storage.
Message Specification
{
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
}
}{
"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
| Field | Type | Required | Description | Format/Constraints |
|---|---|---|---|---|
data.type | String | Yes | Device type identifier | Always "inverter" |
data.production_power | Number | Yes | Solar PV production power | Watts (W), decimal allowed |
data.grid_power | Number | Yes | Grid power flow | Watts (W), negative = export, positive = import |
data.battery_power | Number | Yes | Battery power flow | Watts (W), positive = charging, negative = discharging |
data.consumption_power | Number | Yes | Total household consumption | Watts (W), decimal allowed |
data.battery_soc | Number | Yes | Battery state of charge | Percentage (0-100) |
data.generator_power | Number | Yes | Backup generator output | Watts (W), decimal allowed |
data.ups_power | Number | Yes | UPS/Backup system power | Watts (W), decimal allowed |
data.service_control | Number/Null | No | Server control enabled | 0 = 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
{
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 (%)
}
}{
"sn": "4c54d32c01fc",
"uid": "7f8e9d",
"timestamp": 1748862796,
"data": {
"type": "boiler",
"appliance_id": 1,
"temperature": 65.5,
"battery_soc": 80
}
}Field Details
| Field | Type | Required | Description | Format/Constraints |
|---|---|---|---|---|
data.type | String | Yes | Device type identifier | Always "boiler" |
data.appliance_id | Number | Yes | Appliance index/position within the device | Integer (0-based index) |
data.temperature | Number | Yes | Current water temperature | Degrees Celsius (°C), decimal allowed |
data.battery_soc | Number | Yes | Battery state of charge | Percentage (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:
- Structure Validation: Ensures all required fields are present
- Type Checking: Verifies field types match specification
- Device Authorization: Confirms device is authorized for your organization
- 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:
{
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
}
}{
"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
| Field | Type | Required | Description | Format/Constraints |
|---|---|---|---|---|
data.type | String | Yes | Device type identifier | Always "unsupported" |
data.original_type | String | Yes | Original device type code | Alphanumeric |
data.raw_data | Object | Yes | Device-specific telemetry payload | Structure 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:
- Check
data.typefield to determine message type - Parse based on device type using appropriate schema
- Handle missing optional fields gracefully (e.g.,
service_control) - Store
timestampfor accurate time-series analysis - Use
snfield to identify device origin
Example Consumer Code
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}`);
}
}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
timestampfield as the primary time index - Use
snfield for device partitioning - Store numeric fields (
production_power,temperature, etc.) in appropriate numeric types - Consider downsampling strategies for long-term storage