Skip to content

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 allocated
  • mem_total: Total RAM capacity

Filesystem Information

  • disk_free: Available storage space on the primary filesystem
  • disk_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
  }
}