mirror of
https://github.com/meshtastic/firmware.git
synced 2026-01-03 16:41:56 +00:00
Initial Detection sensor module feature (#2722)
* WIP * Updates * Doh! * Move it out of the macro guard so portduino can build * Changes from feedback
This commit is contained in:
@@ -373,6 +373,11 @@ void AdminModule::handleSetModuleConfig(const meshtastic_ModuleConfig &c)
|
||||
moduleConfig.has_neighbor_info = true;
|
||||
moduleConfig.neighbor_info = c.payload_variant.neighbor_info;
|
||||
break;
|
||||
case meshtastic_ModuleConfig_detection_sensor_tag:
|
||||
LOG_INFO("Setting module config: Detection Sensor\n");
|
||||
moduleConfig.has_detection_sensor = true;
|
||||
moduleConfig.detection_sensor = c.payload_variant.detection_sensor;
|
||||
break;
|
||||
}
|
||||
|
||||
saveChanges(SEGMENT_MODULECONFIG);
|
||||
@@ -513,6 +518,11 @@ void AdminModule::handleGetModuleConfig(const meshtastic_MeshPacket &req, const
|
||||
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_neighbor_info_tag;
|
||||
res.get_module_config_response.payload_variant.neighbor_info = moduleConfig.neighbor_info;
|
||||
break;
|
||||
case meshtastic_AdminMessage_ModuleConfigType_DETECTIONSENSOR_CONFIG:
|
||||
LOG_INFO("Getting module config: Detection Sensor\n");
|
||||
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_detection_sensor_tag;
|
||||
res.get_module_config_response.payload_variant.detection_sensor = moduleConfig.detection_sensor;
|
||||
break;
|
||||
}
|
||||
|
||||
// NOTE: The phone app needs to know the ls_secsvalue so it can properly expect sleep behavior.
|
||||
|
||||
99
src/modules/DetectionSensorModule.cpp
Normal file
99
src/modules/DetectionSensorModule.cpp
Normal file
@@ -0,0 +1,99 @@
|
||||
#include "DetectionSensorModule.h"
|
||||
#include "MeshService.h"
|
||||
#include "NodeDB.h"
|
||||
#include "PowerFSM.h"
|
||||
#include "configuration.h"
|
||||
#include "main.h"
|
||||
|
||||
DetectionSensorModule *detectionSensorModule;
|
||||
|
||||
#define GPIO_POLLING_INTERVAL 100
|
||||
#define DELAYED_INTERVAL 1000
|
||||
|
||||
int32_t DetectionSensorModule::runOnce()
|
||||
{
|
||||
/*
|
||||
Uncomment the preferences below if you want to use the module
|
||||
without having to configure it from the PythonAPI or WebUI.
|
||||
*/
|
||||
// moduleConfig.detection_sensor.enabled = true;
|
||||
// moduleConfig.detection_sensor.monitor_pin = 10; // WisBlock PIR IO6
|
||||
// moduleConfig.detection_sensor.minimum_broadcast_secs = 60;
|
||||
// moduleConfig.detection_sensor.state_broadcast_secs = 120;
|
||||
// moduleConfig.detection_sensor.detection_triggered_high = false;
|
||||
// strcpy(moduleConfig.detection_sensor.name, "Motion");
|
||||
|
||||
if (moduleConfig.detection_sensor.enabled == false)
|
||||
return disable();
|
||||
|
||||
if (firstTime) {
|
||||
// This is the first time the OSThread library has called this function, so do some setup
|
||||
firstTime = false;
|
||||
if (moduleConfig.detection_sensor.monitor_pin > 0) {
|
||||
pinMode(moduleConfig.detection_sensor.monitor_pin, moduleConfig.detection_sensor.use_pullup ? INPUT_PULLUP : INPUT);
|
||||
} else {
|
||||
LOG_WARN("Detection Sensor Module: Set to enabled but no monitor pin is set. Disabling module...\n");
|
||||
return disable();
|
||||
}
|
||||
LOG_INFO("Detection Sensor Module: Initializing\n");
|
||||
|
||||
return DELAYED_INTERVAL;
|
||||
}
|
||||
|
||||
if ((millis() - lastSentToMesh) >= getConfiguredOrDefaultMs(moduleConfig.detection_sensor.minimum_broadcast_secs) &&
|
||||
hasDetectionEvent()) {
|
||||
sendDetectionMessage();
|
||||
return DELAYED_INTERVAL;
|
||||
}
|
||||
// Even if we haven't detected an event, broadcast our current state to the mesh on the scheduled interval as a sort
|
||||
// of heartbeat. We only do this if the minimum broadcast interval is greater than zero, otherwise we'll only broadcast state
|
||||
// change detections.
|
||||
else if (moduleConfig.detection_sensor.state_broadcast_secs > 0 &&
|
||||
(millis() - lastSentToMesh) >= getConfiguredOrDefaultMs(moduleConfig.detection_sensor.state_broadcast_secs)) {
|
||||
sendCurrentStateMessage();
|
||||
return DELAYED_INTERVAL;
|
||||
}
|
||||
return GPIO_POLLING_INTERVAL;
|
||||
}
|
||||
|
||||
void DetectionSensorModule::sendDetectionMessage()
|
||||
{
|
||||
LOG_DEBUG("Detected event observed. Sending message\n");
|
||||
char *message = new char[40];
|
||||
sprintf(message, "%s detected", moduleConfig.detection_sensor.name);
|
||||
meshtastic_MeshPacket *p = allocDataPacket();
|
||||
p->want_ack = false;
|
||||
p->decoded.payload.size = strlen(message);
|
||||
memcpy(p->decoded.payload.bytes, message, p->decoded.payload.size);
|
||||
if (moduleConfig.detection_sensor.send_bell && p->decoded.payload.size < meshtastic_Constants_DATA_PAYLOAD_LEN) {
|
||||
p->decoded.payload.bytes[p->decoded.payload.size] = 7; // Bell character
|
||||
p->decoded.payload.bytes[p->decoded.payload.size + 1] = '\0'; // Bell character
|
||||
p->decoded.payload.size++;
|
||||
}
|
||||
LOG_INFO("Sending message id=%d, dest=%x, msg=%.*s\n", p->id, p->to, p->decoded.payload.size, p->decoded.payload.bytes);
|
||||
lastSentToMesh = millis();
|
||||
service.sendToMesh(p);
|
||||
delete[] message;
|
||||
}
|
||||
|
||||
void DetectionSensorModule::sendCurrentStateMessage()
|
||||
{
|
||||
char *message = new char[40];
|
||||
sprintf(message, "%s state: %i", moduleConfig.detection_sensor.name, hasDetectionEvent());
|
||||
|
||||
meshtastic_MeshPacket *p = allocDataPacket();
|
||||
p->want_ack = false;
|
||||
p->decoded.payload.size = strlen(message);
|
||||
memcpy(p->decoded.payload.bytes, message, p->decoded.payload.size);
|
||||
LOG_INFO("Sending message id=%d, dest=%x, msg=%.*s\n", p->id, p->to, p->decoded.payload.size, p->decoded.payload.bytes);
|
||||
lastSentToMesh = millis();
|
||||
service.sendToMesh(p);
|
||||
delete[] message;
|
||||
}
|
||||
|
||||
bool DetectionSensorModule::hasDetectionEvent()
|
||||
{
|
||||
bool currentState = digitalRead(moduleConfig.detection_sensor.monitor_pin);
|
||||
// LOG_DEBUG("Detection Sensor Module: Current state: %i\n", currentState);
|
||||
return moduleConfig.detection_sensor.detection_triggered_high ? currentState : !currentState;
|
||||
}
|
||||
23
src/modules/DetectionSensorModule.h
Normal file
23
src/modules/DetectionSensorModule.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
#include "SinglePortModule.h"
|
||||
|
||||
class DetectionSensorModule : public SinglePortModule, private concurrency::OSThread
|
||||
{
|
||||
public:
|
||||
DetectionSensorModule()
|
||||
: SinglePortModule("detection", meshtastic_PortNum_TEXT_MESSAGE_APP), OSThread("DetectionSensorModule")
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual int32_t runOnce() override;
|
||||
|
||||
private:
|
||||
bool firstTime = true;
|
||||
uint32_t lastSentToMesh = 0;
|
||||
void sendDetectionMessage();
|
||||
void sendCurrentStateMessage();
|
||||
bool hasDetectionEvent();
|
||||
};
|
||||
|
||||
extern DetectionSensorModule *detectionSensorModule;
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "input/kbMatrixImpl.h"
|
||||
#include "modules/AdminModule.h"
|
||||
#include "modules/CannedMessageModule.h"
|
||||
#include "modules/DetectionSensorModule.h"
|
||||
#include "modules/NeighborInfoModule.h"
|
||||
#include "modules/NodeInfoModule.h"
|
||||
#include "modules/PositionModule.h"
|
||||
@@ -50,6 +51,7 @@ void setupModules()
|
||||
textMessageModule = new TextMessageModule();
|
||||
traceRouteModule = new TraceRouteModule();
|
||||
neighborInfoModule = new NeighborInfoModule();
|
||||
detectionSensorModule = new DetectionSensorModule();
|
||||
|
||||
// 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.
|
||||
|
||||
Reference in New Issue
Block a user