From 8b8e056b7bcce9f4ee3e4256c6c94a724e1d190f Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Fri, 14 Jun 2024 16:27:49 -0500 Subject: [PATCH] Added (excluded) Dropzone Module for more comprehensive module example (#4098) * DropzoneModule hello world * Buttoning things up * Exclude by default * Upstream refs * Cleanup * Add modules folder to path * Case and path matters * Exclude from header * Guard --- platformio.ini | 1 + src/modules/DropzoneModule.cpp | 95 +++++++++++++++++++ src/modules/DropzoneModule.h | 37 ++++++++ src/modules/Modules.cpp | 9 ++ .../Telemetry/Sensor/DFRobotLarkSensor.h | 5 + src/modules/Telemetry/UnitConversions.cpp | 21 ++++ src/modules/Telemetry/UnitConversions.h | 10 ++ 7 files changed, 178 insertions(+) create mode 100644 src/modules/DropzoneModule.cpp create mode 100644 src/modules/DropzoneModule.h create mode 100644 src/modules/Telemetry/UnitConversions.cpp create mode 100644 src/modules/Telemetry/UnitConversions.h diff --git a/platformio.ini b/platformio.ini index 34471fc54..0de3e25c9 100644 --- a/platformio.ini +++ b/platformio.ini @@ -73,6 +73,7 @@ build_flags = -Wno-missing-field-initializers -DRADIOLIB_EXCLUDE_FSK4 -DRADIOLIB_EXCLUDE_APRS -DRADIOLIB_EXCLUDE_LORAWAN + -DMESHTASTIC_EXCLUDE_DROPZONE=1 monitor_speed = 115200 diff --git a/src/modules/DropzoneModule.cpp b/src/modules/DropzoneModule.cpp new file mode 100644 index 000000000..8c5b5dcdd --- /dev/null +++ b/src/modules/DropzoneModule.cpp @@ -0,0 +1,95 @@ +#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 + +#include "modules/Telemetry/Sensor/DFRobotLarkSensor.h" +#include "modules/Telemetry/UnitConversions.h" + +#include + +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(p.payload.bytes); + sprintf(matchCompare, "%s conditions", owner.short_name); + if (strncasecmp(incomingMessage, matchCompare, strlen(matchCompare)) == 0) { + LOG_DEBUG("Received dropzone conditions request\n"); + startSendConditions = millis(); + } + + sprintf(matchCompare, "%s conditions", owner.long_name); + if (strncasecmp(incomingMessage, matchCompare, strlen(matchCompare)) == 0) { + LOG_DEBUG("Received dropzone conditions request\n"); + 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; + + hour = hms / SEC_PER_HOUR; + min = (hms % SEC_PER_HOUR) / SEC_PER_MIN; + sec = (hms % SEC_PER_HOUR) % SEC_PER_MIN; + } + + // 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(); + + 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); + sprintf(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\n"); + sprintf(replyStr, "%s @ %02d:%02d:%02d\nNo sensor found", dropzoneStatus, hour, min, sec); + } + LOG_DEBUG("Conditions reply: %s\n", 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 \ No newline at end of file diff --git a/src/modules/DropzoneModule.h b/src/modules/DropzoneModule.h new file mode 100644 index 000000000..28f54ee0f --- /dev/null +++ b/src/modules/DropzoneModule.h @@ -0,0 +1,37 @@ +#pragma once +#if !MESHTASTIC_EXCLUDE_DROPZONE +#include "SinglePortModule.h" +#include "modules/Telemetry/Sensor/DFRobotLarkSensor.h" + +/** + * An example module that replies to a message with the current conditions + * and status at the dropzone when it receives a text message mentioning it's name followed by "conditions" + */ +class DropzoneModule : public SinglePortModule, private concurrency::OSThread +{ + DFRobotLarkSensor sensor; + + public: + /** Constructor + * name is for debugging output + */ + DropzoneModule() : SinglePortModule("dropzone", meshtastic_PortNum_TEXT_MESSAGE_APP), concurrency::OSThread("DropzoneModule") + { + // Set up the analog pin for reading the dropzone status + pinMode(PIN_A1, INPUT); + } + + virtual int32_t runOnce() override; + + protected: + /** Called to handle a particular incoming message + */ + virtual ProcessMessage handleReceived(const meshtastic_MeshPacket &mp) override; + + private: + meshtastic_MeshPacket *sendConditions(); + uint32_t startSendConditions = 0; +}; + +extern DropzoneModule *dropzoneModule; +#endif \ No newline at end of file diff --git a/src/modules/Modules.cpp b/src/modules/Modules.cpp index e6c44fae6..1b4bbc3b4 100644 --- a/src/modules/Modules.cpp +++ b/src/modules/Modules.cpp @@ -70,6 +70,11 @@ #include "modules/SerialModule.h" #endif #endif + +#if !MESHTASTIC_EXCLUDE_DROPZONE +#include "modules/DropzoneModule.h" +#endif + /** * Create module instances here. If you are adding a new module, you must 'new' it here (or somewhere else) */ @@ -100,6 +105,10 @@ void setupModules() #if !MESHTASTIC_EXCLUDE_ATAK atakPluginModule = new AtakPluginModule(); #endif + +#if !MESHTASTIC_EXCLUDE_DROPZONE + dropzoneModule = new DropzoneModule(); +#endif // Note: if the rest of meshtastic doesn't need to explicitly use your module, you do not need to assign the instance // to a global variable. diff --git a/src/modules/Telemetry/Sensor/DFRobotLarkSensor.h b/src/modules/Telemetry/Sensor/DFRobotLarkSensor.h index b26d690b1..7a988e84a 100644 --- a/src/modules/Telemetry/Sensor/DFRobotLarkSensor.h +++ b/src/modules/Telemetry/Sensor/DFRobotLarkSensor.h @@ -1,3 +1,7 @@ +#pragma once + +#ifndef _MT_DFROBOTLARKSENSOR_H +#define _MT_DFROBOTLARKSENSOR_H #include "configuration.h" #if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR @@ -21,4 +25,5 @@ class DFRobotLarkSensor : public TelemetrySensor virtual bool getMetrics(meshtastic_Telemetry *measurement) override; }; +#endif #endif \ No newline at end of file diff --git a/src/modules/Telemetry/UnitConversions.cpp b/src/modules/Telemetry/UnitConversions.cpp new file mode 100644 index 000000000..9f40de40f --- /dev/null +++ b/src/modules/Telemetry/UnitConversions.cpp @@ -0,0 +1,21 @@ +#include "UnitConversions.h" + +float UnitConversions::CelsiusToFahrenheit(float celcius) +{ + return (celcius * 9) / 5 + 32; +} + +float UnitConversions::MetersPerSecondToKnots(float metersPerSecond) +{ + return metersPerSecond * 1.94384; +} + +float UnitConversions::MetersPerSecondToMilesPerHour(float metersPerSecond) +{ + return metersPerSecond * 2.23694; +} + +float UnitConversions::HectoPascalToInchesOfMercury(float hectoPascal) +{ + return hectoPascal * 0.029529983071445; +} diff --git a/src/modules/Telemetry/UnitConversions.h b/src/modules/Telemetry/UnitConversions.h new file mode 100644 index 000000000..60f9b664a --- /dev/null +++ b/src/modules/Telemetry/UnitConversions.h @@ -0,0 +1,10 @@ +#pragma once + +class UnitConversions +{ + public: + static float CelsiusToFahrenheit(float celcius); + static float MetersPerSecondToKnots(float metersPerSecond); + static float MetersPerSecondToMilesPerHour(float metersPerSecond); + static float HectoPascalToInchesOfMercury(float hectoPascal); +};