Update firmware build date format and enhance MQTT timestamp handling to always emit UTC with "+00:00" offset. Adjusted buffer sizes for timestamps in MQTTMessageBuilder and MQTTBridge to accommodate new format.

This commit is contained in:
agessaman committed 2026-06-06 20:29:52 -07:00
1 parent c29ede054b
commit b45373a31f
4 files changed
+47 -26

No files matched your search

+14 -4
View File
@@ -124,8 +124,8 @@ build_firmware() {
# get git commit sha
COMMIT_HASH=$(git rev-parse --short HEAD)
# set firmware build date
FIRMWARE_BUILD_DATE=$(date '+%d-%b-%Y')
# set firmware build date (e.g. "6 Jun 2026"; %-d drops the leading zero on GNU date / the Linux CI runner)
FIRMWARE_BUILD_DATE=$(date '+%-d %b %Y')
# get FIRMWARE_VERSION, which should be provided by the environment
if [ -z "$FIRMWARE_VERSION" ]; then
@@ -133,7 +133,7 @@ build_firmware() {
exit 1
fi
# set firmware version string
# set firmware version string (used for the output filename)
# e.g: v1.0.0-abcdef
FIRMWARE_VERSION_STRING="${FIRMWARE_VERSION}-${COMMIT_HASH}"
@@ -141,8 +141,18 @@ build_firmware() {
# e.g: RAK_4631_Repeater-v1.0.0-SHA
FIRMWARE_FILENAME="$1-${FIRMWARE_VERSION_STRING}"
# Tag the *embedded* version for observer builds, e.g. v1.0.0-observer-abcdef,
# so `ver`, the MQTT firmware_version/client_version, and SNMP all identify the
# fork. The filename above is intentionally left untagged: the env name already
# contains "observer", and the web flasher keys off that existing pattern.
VARIANT_TAG=""
case "$1" in
*observer*) VARIANT_TAG="-observer" ;;
esac
EMBEDDED_VERSION_STRING="${FIRMWARE_VERSION}${VARIANT_TAG}-${COMMIT_HASH}"
# add firmware version info to end of existing platformio build flags in environment vars
export PLATFORMIO_BUILD_FLAGS="${PLATFORMIO_BUILD_FLAGS} -DFIRMWARE_BUILD_DATE='\"${FIRMWARE_BUILD_DATE}\"' -DFIRMWARE_VERSION='\"${FIRMWARE_VERSION_STRING}\"'"
export PLATFORMIO_BUILD_FLAGS="${PLATFORMIO_BUILD_FLAGS} -DFIRMWARE_BUILD_DATE='\"${FIRMWARE_BUILD_DATE}\"' -DFIRMWARE_VERSION='\"${EMBEDDED_VERSION_STRING}\"'"
# disable debug flags if requested
disable_debug_flags
+10 -7
View File
@@ -7,12 +7,15 @@
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) {
// Always emit UTC with an explicit "+00:00" offset, matching Python's
// datetime.now(timezone.utc).isoformat(). The system clock is UTC (SNTP offset 0),
// so gmtime() is correct regardless of the prefs Timezone (now unused here).
(void)timezone;
struct tm* tm_info = gmtime(&now);
if (tm_info && strftime(buffer, buffer_size, "%Y-%m-%dT%H:%M:%S.000000+00:00", tm_info) > 0) {
return;
}
strncpy(buffer, "2024-01-01T12:00:00.000000", buffer_size - 1);
strncpy(buffer, "2024-01-01T12:00:00.000000+00:00", buffer_size - 1);
buffer[buffer_size - 1] = '\0';
}
@@ -195,7 +198,7 @@ int MQTTMessageBuilder::buildPacketJSON(
if (!packet) return 0;
time_t now = time(nullptr);
char timestamp[32];
char timestamp[40];
formatIsoTimestampForMqtt(now, timezone, timestamp, sizeof(timestamp));
// Packet time/date: UTC (gmtime), same family as meshcoretomqtt serial fields
@@ -268,7 +271,7 @@ int MQTTMessageBuilder::buildPacketJSONFromRaw(
if (!packet || !raw_data || raw_len <= 0) return 0;
time_t now = time(nullptr);
char timestamp[32];
char timestamp[40];
formatIsoTimestampForMqtt(now, timezone, timestamp, sizeof(timestamp));
struct tm* utc_timeinfo = gmtime(&now);
@@ -334,7 +337,7 @@ int MQTTMessageBuilder::buildRawJSON(
if (!packet) return 0;
time_t now = time(nullptr);
char timestamp[32];
char timestamp[40];
formatIsoTimestampForMqtt(now, timezone, timestamp, sizeof(timestamp));
// Convert packet to hex
+9 -6
View File
@@ -12,9 +12,11 @@
* 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.
* Timestamps in the JSON `timestamp` field are emitted in UTC with an explicit
* "+00:00" offset (equivalent to Python datetime.now(timezone.utc).isoformat()) 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:
@@ -23,9 +25,10 @@ private:
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".
* Always UTC with an explicit "+00:00" offset, ISO-8601
* "%Y-%m-%dT%H:%M:%S.000000+00:00" (matches Python
* datetime.now(timezone.utc).isoformat()). The `timezone` parameter is retained
* for API compatibility but ignored — the system clock is UTC.
*/
static void formatIsoTimestampForMqtt(time_t now, Timezone* timezone, char* buffer, size_t buffer_size);
+14 -9
View File
@@ -1706,11 +1706,11 @@ void MQTTBridge::publishStatusToSlot(int index) {
#endif
char origin_id[65];
char timestamp[32];
char timestamp[40];
char radio_info[64];
// Status timestamp: same prefs-based wall clock as packet/raw JSON `timestamp`
// (not libc getLocalTime — SNTP uses UTC offset 0; prefs Timezone is separate).
// Status timestamp: UTC with explicit +00:00 offset, same as packet/raw JSON
// `timestamp` (system clock is UTC — SNTP offset 0; prefs Timezone is separate).
MQTTMessageBuilder::formatIsoTimestampForMqtt(time(nullptr), _timezone, timestamp, sizeof(timestamp));
snprintf(radio_info, sizeof(radio_info), "%.6f,%.1f,%d,%d",
@@ -2412,11 +2412,11 @@ bool MQTTBridge::publishStatus() {
char* json_buffer = _status_json_buffer;
#endif
char origin_id[65];
char timestamp[32];
char timestamp[40];
char radio_info[64];
// Status timestamp: same prefs-based wall clock as packet/raw JSON `timestamp`
// (not libc getLocalTime — SNTP uses UTC offset 0; prefs Timezone is separate).
// Status timestamp: UTC with explicit +00:00 offset, same as packet/raw JSON
// `timestamp` (system clock is UTC — SNTP offset 0; prefs Timezone is separate).
MQTTMessageBuilder::formatIsoTimestampForMqtt(time(nullptr), _timezone, timestamp, sizeof(timestamp));
snprintf(radio_info, sizeof(radio_info), "%.6f,%.1f,%d,%d",
@@ -3085,9 +3085,14 @@ void MQTTBridge::optimizeMqttClientConfig(PsychicMqttClient* client, bool needs_
esp_mqtt_client_config_t* config = client->getMqttConfig();
if (config) {
#if defined(ESP_IDF_VERSION_MAJOR) && ESP_IDF_VERSION_MAJOR >= 5
if (config->buffer.out_size == 0 || config->buffer.out_size > MQTT_CLIENT_BUFFER_SIZE) {
config->buffer.out_size = MQTT_CLIENT_BUFFER_SIZE;
}
// Keep the output buffer (used to build the CONNECT/PUBLISH frames) in lockstep
// with the input buffer. setBufferSize() above only sets buffer.size, so out_size
// must be set here. The previous conditional only ever shrank out_size or set it
// from 0 — when a slot was reconfigured from a small non-JWT buffer (512) up to
// the JWT buffer (896), out_size stayed at 512 and the JWT CONNECT frame (username
// + ~537-768B token) overflowed it, producing esp-mqtt "Connect message cannot be
// created". Always matching MQTT_CLIENT_BUFFER_SIZE fixes the grow case.
config->buffer.out_size = MQTT_CLIENT_BUFFER_SIZE;
#endif
}
}