mirror of
https://github.com/mikecarper/MeshCore.git
synced 2026-09-26 18:47:56 +00:00
Refactor timestamp handling in MQTTMessageBuilder
- Introduced a new method `formatIsoTimestampForMqtt` to centralize ISO-like timestamp formatting for MQTT messages, applying timezone preferences. - Updated `buildStatusMessage`, `buildPacketJSON`, `buildPacketJSONFromRaw`, and `buildRawJSON` methods to utilize the new timestamp formatting function, improving code clarity and reducing redundancy. - Adjusted `publishStatusToSlot` and `publishStatus` in MQTTBridge to use the new timestamp formatting method, ensuring consistent timestamp handling across status messages.
This commit is contained in:
@@ -1,9 +1,21 @@
|
||||
#include "MQTTMessageBuilder.h"
|
||||
#include <ArduinoJson.h>
|
||||
#include <cstring>
|
||||
#include <time.h>
|
||||
#include <Timezone.h>
|
||||
#include "MeshCore.h"
|
||||
|
||||
void MQTTMessageBuilder::formatIsoTimestampForMqtt(time_t now, Timezone* timezone, char* buffer, size_t buffer_size) {
|
||||
if (!buffer || buffer_size == 0) return;
|
||||
time_t local_wall = timezone ? timezone->toLocal(now) : now;
|
||||
struct tm* tm_info = localtime(&local_wall);
|
||||
if (tm_info && strftime(buffer, buffer_size, "%Y-%m-%dT%H:%M:%S.000000", tm_info) > 0) {
|
||||
return;
|
||||
}
|
||||
strncpy(buffer, "2024-01-01T12:00:00.000000", buffer_size - 1);
|
||||
buffer[buffer_size - 1] = '\0';
|
||||
}
|
||||
|
||||
int MQTTMessageBuilder::buildStatusMessage(
|
||||
JsonDocument& doc,
|
||||
const char* origin,
|
||||
@@ -182,22 +194,11 @@ int MQTTMessageBuilder::buildPacketJSON(
|
||||
) {
|
||||
if (!packet) return 0;
|
||||
|
||||
// Get current device time (should be UTC since system timezone is set to UTC)
|
||||
time_t now = time(nullptr);
|
||||
|
||||
// Convert to local time using timezone library (for timestamp field only)
|
||||
time_t local_time = timezone ? timezone->toLocal(now) : now;
|
||||
struct tm* local_timeinfo = localtime(&local_time);
|
||||
|
||||
// Format timestamp in ISO 8601 format (LOCAL TIME)
|
||||
char timestamp[32];
|
||||
if (local_timeinfo) {
|
||||
strftime(timestamp, sizeof(timestamp), "%Y-%m-%dT%H:%M:%S.000000", local_timeinfo);
|
||||
} else {
|
||||
strcpy(timestamp, "2024-01-01T12:00:00.000000");
|
||||
}
|
||||
formatIsoTimestampForMqtt(now, timezone, timestamp, sizeof(timestamp));
|
||||
|
||||
// Get UTC time (since system timezone is UTC, time() returns UTC)
|
||||
// Packet time/date: UTC (gmtime), same family as meshcoretomqtt serial fields
|
||||
struct tm* utc_timeinfo = gmtime(&now);
|
||||
|
||||
// Format time and date (ALWAYS UTC)
|
||||
@@ -266,22 +267,10 @@ int MQTTMessageBuilder::buildPacketJSONFromRaw(
|
||||
) {
|
||||
if (!packet || !raw_data || raw_len <= 0) return 0;
|
||||
|
||||
// Get current device time (should be UTC since system timezone is set to UTC)
|
||||
time_t now = time(nullptr);
|
||||
|
||||
// Convert to local time using timezone library (for timestamp field only)
|
||||
time_t local_time = timezone ? timezone->toLocal(now) : now;
|
||||
struct tm* local_timeinfo = localtime(&local_time);
|
||||
|
||||
// Format timestamp in ISO 8601 format (LOCAL TIME)
|
||||
char timestamp[32];
|
||||
if (local_timeinfo) {
|
||||
strftime(timestamp, sizeof(timestamp), "%Y-%m-%dT%H:%M:%S.000000", local_timeinfo);
|
||||
} else {
|
||||
strcpy(timestamp, "2024-01-01T12:00:00.000000");
|
||||
}
|
||||
formatIsoTimestampForMqtt(now, timezone, timestamp, sizeof(timestamp));
|
||||
|
||||
// Get UTC time (since system timezone is UTC, time() returns UTC)
|
||||
struct tm* utc_timeinfo = gmtime(&now);
|
||||
|
||||
// Format time and date (ALWAYS UTC)
|
||||
@@ -344,20 +333,9 @@ int MQTTMessageBuilder::buildRawJSON(
|
||||
) {
|
||||
if (!packet) return 0;
|
||||
|
||||
// Get current device time
|
||||
time_t now = time(nullptr);
|
||||
|
||||
// Convert to local time using timezone library
|
||||
time_t local_time = timezone ? timezone->toLocal(now) : now;
|
||||
struct tm* timeinfo = localtime(&local_time);
|
||||
|
||||
// Format timestamp in ISO 8601 format
|
||||
char timestamp[32];
|
||||
if (timeinfo) {
|
||||
strftime(timestamp, sizeof(timestamp), "%Y-%m-%dT%H:%M:%S.000000", timeinfo);
|
||||
} else {
|
||||
strcpy(timestamp, "2024-01-01T12:00:00.000000");
|
||||
}
|
||||
formatIsoTimestampForMqtt(now, timezone, timestamp, sizeof(timestamp));
|
||||
|
||||
// Convert packet to hex
|
||||
// MAX_TRANS_UNIT is 255, so max hex size is 510 chars + null = 511 bytes
|
||||
|
||||
@@ -11,12 +11,24 @@
|
||||
* This class handles the formatting of mesh packets and device status
|
||||
* into JSON messages for MQTT publishing according to the MeshCore
|
||||
* packet capture specification.
|
||||
*
|
||||
* Timestamps in JSON use the configured Timezone (prefs) for status, packet, and
|
||||
* raw topics. Packet payloads also include separate `time` and `date` strings in
|
||||
* UTC (gmtime) so they stay aligned with meshcoretomqtt serial regex fields.
|
||||
*/
|
||||
class MQTTMessageBuilder {
|
||||
private:
|
||||
static const int JSON_BUFFER_SIZE = 1024;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Format the MQTT JSON `timestamp` field (same rule for status, packet, raw).
|
||||
* Applies Timezone prefs via `timezone->toLocal(now)`; if timezone is nullptr,
|
||||
* uses `now` unchanged. Output is naive local wall time, ISO-like
|
||||
* "%Y-%m-%dT%H:%M:%S.000000".
|
||||
*/
|
||||
static void formatIsoTimestampForMqtt(time_t now, Timezone* timezone, char* buffer, size_t buffer_size);
|
||||
|
||||
/**
|
||||
* Build status message JSON
|
||||
*
|
||||
@@ -27,7 +39,7 @@ public:
|
||||
* @param radio Radio information
|
||||
* @param client_version Client version
|
||||
* @param status Connection status ("online" or "offline")
|
||||
* @param timestamp ISO 8601 timestamp
|
||||
* @param timestamp ISO-like timestamp (see formatIsoTimestampForMqtt)
|
||||
* @param buffer Output buffer for JSON string
|
||||
* @param buffer_size Size of output buffer
|
||||
* @param battery_mv Battery voltage in millivolts (optional, -1 to omit)
|
||||
@@ -71,10 +83,10 @@ public:
|
||||
*
|
||||
* @param origin Device name
|
||||
* @param origin_id Device public key (hex string)
|
||||
* @param timestamp ISO 8601 timestamp
|
||||
* @param timestamp ISO-like timestamp (see formatIsoTimestampForMqtt)
|
||||
* @param direction Packet direction ("rx" or "tx")
|
||||
* @param time Time in HH:MM:SS format
|
||||
* @param date Date in DD/MM/YYYY format
|
||||
* @param time Time in HH:MM:SS (UTC, gmtime; meshcoretomqtt serial parity)
|
||||
* @param date Date in DD/MM/YYYY (UTC, gmtime)
|
||||
* @param len Total packet length
|
||||
* @param packet_type Packet type code
|
||||
* @param route Routing type
|
||||
@@ -114,7 +126,7 @@ public:
|
||||
*
|
||||
* @param origin Device name
|
||||
* @param origin_id Device public key (hex string)
|
||||
* @param timestamp ISO 8601 timestamp
|
||||
* @param timestamp ISO-like timestamp (see formatIsoTimestampForMqtt)
|
||||
* @param raw Raw packet data (hex string)
|
||||
* @param buffer Output buffer for JSON string
|
||||
* @param buffer_size Size of output buffer
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <NTPClient.h>
|
||||
#include <WiFiUdp.h>
|
||||
#include <Timezone.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef WITH_SNMP
|
||||
#include "../SNMPAgent.h"
|
||||
@@ -1676,13 +1677,9 @@ void MQTTBridge::publishStatusToSlot(int index) {
|
||||
char timestamp[32];
|
||||
char radio_info[64];
|
||||
|
||||
// Get current timestamp in ISO 8601 format
|
||||
struct tm timeinfo;
|
||||
if (getLocalTime(&timeinfo)) {
|
||||
strftime(timestamp, sizeof(timestamp), "%Y-%m-%dT%H:%M:%S.000000", &timeinfo);
|
||||
} else {
|
||||
strcpy(timestamp, "2024-01-01T12:00:00.000000");
|
||||
}
|
||||
// Status timestamp: same prefs-based wall clock as packet/raw JSON `timestamp`
|
||||
// (not libc getLocalTime — SNTP uses UTC offset 0; prefs Timezone is separate).
|
||||
MQTTMessageBuilder::formatIsoTimestampForMqtt(time(nullptr), _timezone, timestamp, sizeof(timestamp));
|
||||
|
||||
snprintf(radio_info, sizeof(radio_info), "%.6f,%.1f,%d,%d",
|
||||
_prefs->freq, _prefs->bw, _prefs->sf, _prefs->cr);
|
||||
@@ -2370,13 +2367,9 @@ bool MQTTBridge::publishStatus() {
|
||||
char timestamp[32];
|
||||
char radio_info[64];
|
||||
|
||||
// Get current timestamp in ISO 8601 format
|
||||
struct tm timeinfo;
|
||||
if (getLocalTime(&timeinfo)) {
|
||||
strftime(timestamp, sizeof(timestamp), "%Y-%m-%dT%H:%M:%S.000000", &timeinfo);
|
||||
} else {
|
||||
strcpy(timestamp, "2024-01-01T12:00:00.000000");
|
||||
}
|
||||
// Status timestamp: same prefs-based wall clock as packet/raw JSON `timestamp`
|
||||
// (not libc getLocalTime — SNTP uses UTC offset 0; prefs Timezone is separate).
|
||||
MQTTMessageBuilder::formatIsoTimestampForMqtt(time(nullptr), _timezone, timestamp, sizeof(timestamp));
|
||||
|
||||
snprintf(radio_info, sizeof(radio_info), "%.6f,%.1f,%d,%d",
|
||||
_prefs->freq, _prefs->bw, _prefs->sf, _prefs->cr);
|
||||
|
||||
Reference in New Issue
Block a user