Tendrl Heartbeat Message Format
This document describes the exact format of heartbeat messages in the Tendrl MicroPython SDK for porting to other SDKs and languages.
Overview
Message Structure
The heartbeat message follows the standard Tendrl message format with specific msg_type and data fields.
Complete Message Format
{
"msg_type": "heartbeat",
"data": {
"mem_free": <integer>,
"mem_total": <integer>,
"disk_free": <integer>,
"disk_size": <integer>
}
"timestamp": "<ISO8601_TIMESTAMP>"
}
Field Specifications
| Field | Type | Required | Description |
|---|---|---|---|
msg_type |
string |
✅ Yes | Must be exactly "heartbeat" |
data |
object |
✅ Yes | System resource information (see below) |
timestamp |
string |
❌ No | Optional ISO8601 formatted timestamp in UTC. If not provided, will be set to time of message ingestion |
Data Object Structure
The data object contains system resource information in bytes (not formatted):
| Field | Type | Description | Units |
|---|---|---|---|
mem_free |
integer |
Available RAM memory | bytes |
mem_total |
integer |
Total RAM memory | bytes |
disk_free |
integer |
Available filesystem space | bytes |
disk_size |
integer |
Total filesystem size | bytes |
Timestamp Format
The timestamp must be in ISO8601 format with UTC timezone:
- Format:
YYYY-MM-DDTHH:MM:SSZ - Example:
"2024-03-15T14:30:45Z" - Always ends with 'Z' indicating UTC
- No fractional seconds
Implementation Details
System Resource Collection
Different platforms will need to adapt the resource collection:
Memory Information
mem_free: Available RAM that can be allocatedmem_total: Total RAM capacity
Filesystem Information
disk_free: Available storage space on the primary filesystemdisk_size: Total capacity of the primary filesystem
Example Implementation Patterns
Python (Standard Library)
import psutil
import time
from datetime import datetime, timezone
def get_system_resources():
memory = psutil.virtual_memory()
disk = psutil.disk_usage('/')
return {
"mem_free": memory.available,
"mem_total": memory.total,
"disk_free": disk.free,
"disk_size": disk.total
}
def create_heartbeat(include_timestamp=False):
heartbeat = {
"msg_type": "heartbeat",
"data": get_system_resources()
}
if include_timestamp:
heartbeat["timestamp"] = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
return heartbeat
JavaScript/Node.js
const os = require('os');
const fs = require('fs');
function getSystemResources() {
const stats = fs.statSync('/');
return {
mem_free: os.freemem(),
mem_total: os.totalmem(),
disk_free: stats.free,
disk_size: stats.size
};
}
function createHeartbeat(includeTimestamp = false) {
const heartbeat = {
msg_type: "heartbeat",
data: getSystemResources()
};
if (includeTimestamp) {
heartbeat.timestamp = new Date().toISOString().slice(0, -5) + 'Z';
}
return heartbeat;
}
Error Handling
Server Response Codes
- 200: Heartbeat received successfully
- 400+: Error codes indicate connection issues - client should disable heartbeat and attempt reconnection
Validation Checklist
When implementing heartbeat messages, verify:
- [ ] Message type is exactly
"heartbeat" - [ ] Data contains all 4 required numeric fields
- [ ] All resource values are positive integers in bytes
- [ ] If timestamp is provided, it must be a valid ISO8601 format with 'Z' suffix
Sample Valid Messages
Minimal Heartbeat
{
"msg_type": "heartbeat",
"data": {
"mem_free": 2097152,
"mem_total": 524288,
"disk_free": 1073741824,
"disk_size": 2147483648
}
}
Real-world Example
{
"msg_type": "heartbeat",
"data": {
"mem_free": 15728640,
"mem_total": 8388608,
"disk_free": 536870912,
"disk_size": 1073741824
}
}