mirror of
https://github.com/alexhopeoconnor/firmware.git
synced 2026-10-13 15:11:20 +10:00
* Checksum NMEA sentences from the $ delimiter The PositionLite printWPL() format begins with a CRLF, so the fixed start offset of 1 folded the newline and the $ into the checksum and every sentence went out with a wrong value. Locate the $ instead and stop at the terminator or a \*. * Clamp truncated writes and harden the remaining fixed buffers snprintf returns the length it would have written, so a truncated NMEA sentence made buf + len point past the buffer and bufsz - len underflow into a huge size for the checksum append. Clamp after each write. Also pulls in the rest of #11236: the two remaining Dropzone sprintf calls, the dead strcpy in mt_sprintf that wrote one byte past a zero-size allocation for an empty format, and the 10-byte errcode buffer that INT32_MIN overflows. Co-Authored-By: Andrew Yong <me@ndoo.sg> * Bail out on a zero-sized buffer and cast err for %ld snprintf writes nothing at all when bufsz is 0, not even a terminator, so the checksum helper would run strchr over whatever the buffer already held. Return before touching it. int32_t is not long on every target, so cast before formatting with %ld. Co-Authored-By: Andrew Yong <me@ndoo.sg> * Add NMEA sentence regression tests Covers checksum computation from the $ delimiter for both printWPL overloads and printGGA, zero-sized buffers, and truncated buffers down to one byte. Co-Authored-By: Andrew Yong <me@ndoo.sg> * Tighten checksum parsing and pin the WPL fixture checksum Require exactly two hex digits followed by the sentence terminator, and assert both WPL overloads against a known checksum instead of comparing them to each other. * Bump native suite count to 43 --------- Co-authored-by: Andrew Yong <me@ndoo.sg>
98 lines
3.7 KiB
C++
98 lines
3.7 KiB
C++
#if !MESHTASTIC_EXCLUDE_DROPZONE
|
|
|
|
#include "DropzoneModule.h"
|
|
#include "Meshservice->h"
|
|
#include "configuration.h"
|
|
#include "gps/GeoCoord.h"
|
|
#include "gps/RTC.h"
|
|
#include "main.h"
|
|
|
|
#include <assert.h>
|
|
|
|
#include "modules/Telemetry/Sensor/DFRobotLarkSensor.h"
|
|
#include "modules/Telemetry/UnitConversions.h"
|
|
|
|
#include <string>
|
|
|
|
DropzoneModule *dropzoneModule;
|
|
|
|
int32_t DropzoneModule::runOnce()
|
|
{
|
|
// Send on a 5 second delay from receiving the matching request
|
|
if (startSendConditions != 0 && (startSendConditions + 5000U) < millis()) {
|
|
service->sendToMesh(sendConditions(), RX_SRC_LOCAL);
|
|
startSendConditions = 0;
|
|
}
|
|
// Run every second to check if we need to send conditions
|
|
return 1000;
|
|
}
|
|
|
|
ProcessMessage DropzoneModule::handleReceived(const meshtastic_MeshPacket &mp)
|
|
{
|
|
auto &p = mp.decoded;
|
|
char matchCompare[54];
|
|
auto incomingMessage = reinterpret_cast<const char *>(p.payload.bytes);
|
|
// payload.bytes is not NUL-terminated, so a comparison longer than the received size would read
|
|
// whatever the previous occupant of the packet left behind.
|
|
const size_t received = p.payload.size;
|
|
snprintf(matchCompare, sizeof(matchCompare), "%s conditions", owner.short_name);
|
|
if (received >= strlen(matchCompare) && strncasecmp(incomingMessage, matchCompare, strlen(matchCompare)) == 0) {
|
|
LOG_DEBUG("Received dropzone conditions request");
|
|
startSendConditions = millis();
|
|
}
|
|
|
|
snprintf(matchCompare, sizeof(matchCompare), "%s conditions", owner.long_name);
|
|
if (received >= strlen(matchCompare) && strncasecmp(incomingMessage, matchCompare, strlen(matchCompare)) == 0) {
|
|
LOG_DEBUG("Received dropzone conditions request");
|
|
startSendConditions = millis();
|
|
}
|
|
return ProcessMessage::CONTINUE;
|
|
}
|
|
|
|
meshtastic_MeshPacket *DropzoneModule::sendConditions()
|
|
{
|
|
char replyStr[200];
|
|
/*
|
|
CLOSED @ {HH:MM:SS}z
|
|
Wind 2 kts @ 125°
|
|
29.25 inHg 72°C
|
|
*/
|
|
uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice, true);
|
|
int hour = 0, min = 0, sec = 0;
|
|
if (rtc_sec > 0) {
|
|
long hms = rtc_sec % SEC_PER_DAY;
|
|
hms = (hms + SEC_PER_DAY) % SEC_PER_DAY;
|
|
|
|
graphics::decomposeTime(rtc_sec, hour, min, sec);
|
|
}
|
|
|
|
// Check if the dropzone is open or closed by reading the analog pin
|
|
// If pin is connected to GND (below 100 should be lower than floating voltage),
|
|
// the dropzone is open
|
|
auto dropzoneStatus = analogRead(A1) < 100 ? "OPEN" : "CLOSED";
|
|
auto reply = allocDataPacket();
|
|
if (!reply)
|
|
return nullptr;
|
|
|
|
auto node = nodeDB->getMeshNode(nodeDB->getNodeNum());
|
|
if (sensor.hasSensor()) {
|
|
meshtastic_Telemetry telemetry = meshtastic_Telemetry_init_zero;
|
|
sensor.getMetrics(&telemetry);
|
|
auto windSpeed = UnitConversions::MetersPerSecondToKnots(telemetry.variant.environment_metrics.wind_speed);
|
|
auto windDirection = telemetry.variant.environment_metrics.wind_direction;
|
|
auto temp = telemetry.variant.environment_metrics.temperature;
|
|
auto baro = UnitConversions::HectoPascalToInchesOfMercury(telemetry.variant.environment_metrics.barometric_pressure);
|
|
snprintf(replyStr, sizeof(replyStr), "%s @ %02d:%02d:%02dz\nWind %.2f kts @ %d°\nBaro %.2f inHg %.2f°C", dropzoneStatus,
|
|
hour, min, sec, windSpeed, windDirection, baro, temp);
|
|
} else {
|
|
LOG_ERROR("No sensor found");
|
|
snprintf(replyStr, sizeof(replyStr), "%s @ %02d:%02d:%02d\nNo sensor found", dropzoneStatus, hour, min, sec);
|
|
}
|
|
LOG_DEBUG("Conditions reply: %s", replyStr);
|
|
reply->decoded.payload.size = strlen(replyStr); // You must specify how many bytes are in the reply
|
|
memcpy(reply->decoded.payload.bytes, replyStr, reply->decoded.payload.size);
|
|
|
|
return reply;
|
|
}
|
|
|
|
#endif |