MODBUS MASTER MONITOR 1.0
Loading...
Searching...
No Matches
Data Format & Payload

Classes

struct  ResponseFormat
 Intermediate structure to pass data from the Modbus callback to tasks. More...
struct  BitPacker
 Utility for packing arbitrary bits into a byte stream. More...
struct  SensorDataPayload
 Container for processed sensor data, ready for aggregation. More...

Macros

#define MAX_SENSOR_PAYLOAD   128
 Maximum size of an individual sensor payload.
#define AGGREGATION_INTERVAL_MS   6100
 Aggregation interval (ms).
#define AGGREGATION_INTERVAL_MS   6100
 Aggregation interval (ms).

Functions

static bool formatAndEnqueueSensorData (const ResponseFormat &response, const ModbusRequestInfo &request, std::vector< uint8_t > &values)
 Extracts and formats data from a sampling Modbus response.
void DataFormatter (void *pvParameters)
 Data Formatter task.
std::vector< uint8_t > construirPayloadUnificado (uint8_t id_mensaje, const std::vector< SensorDataPayload > &collectedPayloads)
 Builds a unified payload from a collection of sensor data.
void DataAggregatorTask (void *pvParameters)
 Proactive task that collects and packages sensor data at a fixed rate.

Detailed Description

Overview

This module is responsible for:

  • Parsing raw Modbus responses from queueRespuestas.
  • Normalizing data per sensor and generating SensorDataPayload.
  • Aggregating multiple payloads into a compact message with Activate Byte and metadata.
  • Delivering ready-for-transmission fragments to the external layer (LMIC) via queueFragmentos.

Structure and components

Main API

Usage

Flow summary:

1) Response formatting

2) Payload aggregation

3) Delivery to transmission

  • The aggregated fragment is ready to be taken by the external transmission task.

Structure and payload encoding

The firmware uses an optimized binary scheme to maximize transmission efficiency over LoRaWAN. This section describes the payload structure to facilitate decoder implementation.

Payload components:

  • Header (1 byte): Message identifier to maintain reception order.
  • Timestamp (4 bytes): Time mark since system startup in UNIX format.
  • Activate byte (1 byte): Flags indicating operation by sensor type, encoded bit by bit (Bit 0 = battery, Bit 1 = voltage, Bit 2 = current; rest reserved).
  • Data length bytes (depend on Activate byte): Define quantity and encoding format for each active sensor type. The number of these bytes equals the number of active sensors indicated in the Activate byte.

Structure of each length byte (8 bits):

Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0
------|-------|-------|-------|-------|-------|-------|-------
PKD | 2BIT | DATA_LENGTH (5 bits)

Field descriptions:

  • Bits 0-4 (DATA_LENGTH): Number of sensor readings (0–31 samples).
  • Bit 6 (2BIT):
    • 0: Standard encoding (1 bit per sample).
    • 1: 2-bit per sample encoding.
  • Bit 7 (PKD):
    • 0: Byte-aligned format.
    • 1: Bit-level packed format.

Length byte order:

Length bytes follow the same order as the Activate byte flags (LSB → MSB):

  • Bit 0: Battery (if active)
  • Bit 1: Voltage (if active)
  • Bit 2: Current (if active)

Example: If Activate byte = 0x06 (voltage + current active), there will be 2 length bytes: first for voltage, second for current.

  • Data bytes: Bytes with sensor data; both the Activate byte and length bytes are necessary to decode this data.

Macro Definition Documentation

◆ AGGREGATION_INTERVAL_MS [1/2]

#define AGGREGATION_INTERVAL_MS   6100

Aggregation interval (ms).

Aggregation interval (6s + 100ms margin).

◆ AGGREGATION_INTERVAL_MS [2/2]

#define AGGREGATION_INTERVAL_MS   6100

Aggregation interval (ms).

Aggregation interval (6s + 100ms margin).

Function Documentation

◆ construirPayloadUnificado()

std::vector< uint8_t > construirPayloadUnificado ( uint8_t id_mensaje,
const std::vector< SensorDataPayload > & collectedPayloads )

Builds a unified payload from a collection of sensor data.

Payload Structure: [ID_MSG][TIMESTAMP][ACTIVATE_BYTE][LEN_BYTES...][DATA_BLOCKS...]

Parameters
id_mensajeThe message ID byte (Header).
collectedPayloadsThe vector with the collected data.
Returns
std::vector<uint8_t> The binary payload ready to be sent.

◆ DataAggregatorTask()

void DataAggregatorTask ( void * pvParameters)

Proactive task that collects and packages sensor data at a fixed rate.

Wakes up every AGGREGATION_INTERVAL_MS, empties the data queue, and sends a single LoRaWAN payload if it has collected anything.

◆ DataFormatter()

void DataFormatter ( void * pvParameters)

Data Formatter task.

Consumes responses from queueRespuestas, processes them according to their type (Discovery or Sampling) and enqueues the formatted results.

◆ formatAndEnqueueSensorData()

bool formatAndEnqueueSensorData ( const ResponseFormat & response,
const ModbusRequestInfo & request,
std::vector< uint8_t > & values )
static

Extracts and formats data from a sampling Modbus response.

Parameters
responseRaw response received.
requestInformation from the original request.
valuesOutput vector where the processed bytes will be stored.
Returns
true if the process was successful.