diff --git a/docs/software/plugins/ExternalNotificationPlugin.md b/docs/software/plugins/ExternalNotificationPlugin.md new file mode 100644 index 000000000..c0814b6c3 --- /dev/null +++ b/docs/software/plugins/ExternalNotificationPlugin.md @@ -0,0 +1,89 @@ +# About + +The ExternalNotification Plugin will allow you to connect a speaker, LED or other device to notify you when a message has been received from the mesh network. + +# Configuration + +These are the settings that can be configured. + + ext_notification_plugin_enabled + Is the plugin enabled? + + 0 = Disabled (Default) + 1 = Enabled + + ext_notification_plugin_active + Is your external circuit triggered when our GPIO is low or high? + + 0 = Active Low (Default) + 1 = Active High + + ext_notification_plugin_alert_message + Do you want to be notified on an incoming message? + + 0 = Disabled (Default) + 1 = Alert when a text message comes + + ext_notification_plugin_alert_bell + Do you want to be notified on an incoming bell? + + 0 = Disabled (Default) + 1 = Alert when the bell character is received + + ext_notification_plugin_output + What GPIO is your external circuit attached? + + GPIO of the output. (Default = 13) + + ext_notification_plugin_output_ms + How long do you want us to trigger your external circuit? + + Amount of time in ms for the alert. Default is 1000. + + +# Usage Notes + +For basic usage, start with: + + ext_notification_plugin_enabled = 1 + ext_notification_plugin_alert_message = 1 + +Depending on how your external cirtcuit configured is configured, you may need to set the active state to true. + + ext_notification_plugin_active = 1 + +## Alert Types + +We support being alerted on two events: + +1) Incoming Text Message + +2) Incoming Text Message that contains the ascii bell character. At present, only the Python API can send an ascii bell character, but more support may be added in the future. + +### Bell Character + +The bell character is ASCII 0x07. Include 0x07 anywhere in the text message and with ext_notification_plugin_alert_bell enabled, we will issue an external notification. + +# External Hardware + +Be mindful of the max current sink and source of the esp32 GPIO. The easiest devices to interface with would be either an LED or Active Buzzer. + +Ideas for external hardware: + +* LED +* Active Buzzer +* Flame thrower +* Strobe Light +* Siren + +# Known Problems + +* This won't directly support an passive (normal) speaker as it does not generate any audio wave forms. +* This currently only supports the esp32. Other targets may be possible, I just don't have to test with. +* This plugin only monitors text messages. We won't trigger on any other packet types. + +# Need more help? + +Go to the Meshtastic Discourse Group if you have any questions or to share how you have used this. + +https://meshtastic.discourse.group diff --git a/docs/software/plugins/SerialPlugin.md b/docs/software/plugins/SerialPlugin.md new file mode 100644 index 000000000..acd777e35 --- /dev/null +++ b/docs/software/plugins/SerialPlugin.md @@ -0,0 +1,40 @@ +# About + +A simple interface to send messages over the mesh network by sending strings +over a serial port. + +Default is to use RX GPIO 16 and TX GPIO 17. + + +# Basic Usage: + + 1) Enable the plugin by setting serialplugin_enabled to 1. + 2) Set the pins (serialplugin_rxd / serialplugin_rxd) for your preferred RX and TX GPIO pins. + On tbeam, recommend to use: + RXD 35 + TXD 15 + 3) Set serialplugin_timeout to the amount of time to wait before we consider + your packet as "done". + 4) (Optional) In SerialPlugin.h set the port to PortNum_TEXT_MESSAGE_APP if you want to + send messages to/from the general text message channel. + 5) Connect to your device over the serial interface at 38400 8N1. + 6) Send a packet up to 240 bytes in length. This will get relayed over the mesh network. + 7) (Optional) Set serialplugin_echo to 1 and any message you send out will be echoed back + to your device. + +# TODO (in this order): + +* Define a verbose RX mode to report on mesh and packet infomration. + - This won't happen any time soon. + +# Known Problems + + * Until the plugin is initilized by the startup sequence, the TX pin is in a floating + state. Device connected to that pin may see this as "noise". + * Will not work on NRF and the Linux device targets. + +# Need help? + +Need help with this plugin? Post your question on the Meshtastic Discourse: + +https://meshtastic.discourse.group diff --git a/docs/software/plugins/StoreRequestPlugin.md b/docs/software/plugins/StoreRequestPlugin.md new file mode 100644 index 000000000..239a00de8 --- /dev/null +++ b/docs/software/plugins/StoreRequestPlugin.md @@ -0,0 +1,6 @@ +# About + + + +# Running notes + diff --git a/src/nimble/BluetoothUtil.cpp b/src/nimble/BluetoothUtil.cpp index f5f1f77ec..1416453b1 100644 --- a/src/nimble/BluetoothUtil.cpp +++ b/src/nimble/BluetoothUtil.cpp @@ -10,6 +10,7 @@ #include "nimble/NimbleDefs.h" #include "services/gap/ble_svc_gap.h" #include "services/gatt/ble_svc_gatt.h" +#include "sleep.h" #include #include @@ -226,16 +227,14 @@ static int gap_event(struct ble_gap_event *event, void *arg) if (event->passkey.params.action == BLE_SM_IOACT_DISP) { pkey.action = event->passkey.params.action; - DEBUG_MSG("dp: %d now:%d\n",doublepressed, now); - if (doublepressed > 0 && (doublepressed + (30*1000)) > now) - { + DEBUG_MSG("dp: %d now:%d\n", doublepressed, now); + if (doublepressed > 0 && (doublepressed + (30 * 1000)) > now) { DEBUG_MSG("User has overridden passkey or no display available\n"); - pkey.passkey = defaultBLEPin; - } - else { + pkey.passkey = defaultBLEPin; + } else { DEBUG_MSG("Using random passkey\n"); pkey.passkey = random( - 100000, 999999); // This is the passkey to be entered on peer - we pick a number >100,000 to ensure 6 digits + 100000, 999999); // This is the passkey to be entered on peer - we pick a number >100,000 to ensure 6 digits } DEBUG_MSG("*** Enter passkey %d on the peer side ***\n", pkey.passkey); @@ -395,7 +394,6 @@ void gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg) } } - /** * A helper function that implements simple read and write handling for a uint32_t * @@ -449,8 +447,7 @@ int chr_readwrite8(uint8_t *v, size_t vlen, struct ble_gatt_access_ctxt *ctxt) if (len < vlen) { DEBUG_MSG("Error: wrongsized write\n"); return BLE_ATT_ERR_UNLIKELY; - } - else { + } else { DEBUG_MSG("BLE writing bytes\n"); } } else { @@ -465,7 +462,21 @@ void disablePin() { DEBUG_MSG("User Override, disabling bluetooth pin requirement\n"); // keep track of when it was pressed, so we know it was within X seconds - doublepressed = millis(); + + // Flash the LED + setLed(true); + delay(100); + setLed(false); + delay(100); + setLed(true); + delay(100); + setLed(false); + delay(100); + setLed(true); + delay(100); + setLed(false); + + doublepressed = millis(); } // This routine is called multiple times, once each time we come back from sleep @@ -549,7 +560,7 @@ void setBluetoothEnable(bool on) firstTime = 0; } else { #ifndef NO_ESP32 - initWifi(0); + initWifi(0); #endif } } else { diff --git a/src/plugins/ExternalNotificationPlugin.cpp b/src/plugins/ExternalNotificationPlugin.cpp new file mode 100644 index 000000000..b4f3c801c --- /dev/null +++ b/src/plugins/ExternalNotificationPlugin.cpp @@ -0,0 +1,176 @@ +#include "ExternalNotificationPlugin.h" +#include "MeshService.h" +#include "NodeDB.h" +#include "RTC.h" +#include "Router.h" +#include "configuration.h" +#include + +#include + +/* + + Documentation: + https://github.com/mc-hamster/Meshtastic-device/blob/master/docs/software/plugins/ExternalNotificationPlugin.md + + This plugin supports: + https://github.com/meshtastic/Meshtastic-device/issues/654 + + + Quick reference: + + radioConfig.preferences.ext_notification_plugin_enabled + 0 = Disabled (Default) + 1 = Enabled + + radioConfig.preferences.ext_notification_plugin_active + 0 = Active Low (Default) + 1 = Active High + + radioConfig.preferences.ext_notification_plugin_alert_message + 0 = Disabled (Default) + 1 = Alert when a text message comes + + radioConfig.preferences.ext_notification_plugin_alert_bell + 0 = Disabled (Default) + 1 = Alert when the bell character is received + + radioConfig.preferences.ext_notification_plugin_output + GPIO of the output. (Default = 13) + + radioConfig.preferences.ext_notification_plugin_output_ms + Amount of time in ms for the alert. Default is 1000. + +*/ + + +// Default configurations +#define EXT_NOTIFICATION_PLUGIN_OUTPUT 13 +#define EXT_NOTIFICATION_PLUGIN_OUTPUT_MS 1000 + +#define ASCII_BELL 0x07 + +ExternalNotificationPlugin *externalNotificationPlugin; +ExternalNotificationPluginRadio *externalNotificationPluginRadio; + +ExternalNotificationPlugin::ExternalNotificationPlugin() : concurrency::OSThread("ExternalNotificationPlugin") {} + +bool externalCurrentState = 0; +uint32_t externalTurnedOn = 0; + +int32_t ExternalNotificationPlugin::runOnce() +{ +#ifndef NO_ESP32 + + /* + Uncomment the preferences below if you want to use the plugin + without having to configure it from the PythonAPI or WebUI. + */ + + // radioConfig.preferences.ext_notification_plugin_enabled = 1; + // radioConfig.preferences.ext_notification_plugin_alert_message = 1; + + // radioConfig.preferences.ext_notification_plugin_active = 1; + // radioConfig.preferences.ext_notification_plugin_alert_bell = 1; + // radioConfig.preferences.ext_notification_plugin_output_ms = 1000; + // radioConfig.preferences.ext_notification_plugin_output = 13; + + if (radioConfig.preferences.ext_notification_plugin_enabled) { + + if (firstTime) { + + DEBUG_MSG("Initializing External Notification Plugin\n"); + + // Set the direction of a pin + pinMode((radioConfig.preferences.ext_notification_plugin_output + ? radioConfig.preferences.ext_notification_plugin_output + : EXT_NOTIFICATION_PLUGIN_OUTPUT), + OUTPUT); + + // Turn off the pin + setExternalOff(); + + externalNotificationPluginRadio = new ExternalNotificationPluginRadio(); + + firstTime = 0; + + } else { + if (externalCurrentState) { + + // If the output is turned on, turn it back off after the given period of time. + if (externalTurnedOn + (radioConfig.preferences.ext_notification_plugin_output_ms + ? radioConfig.preferences.ext_notification_plugin_output_ms + : EXT_NOTIFICATION_PLUGIN_OUTPUT_MS) < + millis()) { + DEBUG_MSG("Turning off external notification\n"); + setExternalOff(); + } + } + } + + return (25); + } else { + DEBUG_MSG("External Notification Plugin Disabled\n"); + + return (INT32_MAX); + } + +#endif +} + +void ExternalNotificationPlugin::setExternalOn() +{ + externalCurrentState = 1; + externalTurnedOn = millis(); + + digitalWrite((radioConfig.preferences.ext_notification_plugin_output ? radioConfig.preferences.ext_notification_plugin_output + : EXT_NOTIFICATION_PLUGIN_OUTPUT), + (radioConfig.preferences.ext_notification_plugin_active ? true : false)); +} + +void ExternalNotificationPlugin::setExternalOff() +{ + externalCurrentState = 0; + + digitalWrite((radioConfig.preferences.ext_notification_plugin_output ? radioConfig.preferences.ext_notification_plugin_output + : EXT_NOTIFICATION_PLUGIN_OUTPUT), + (radioConfig.preferences.ext_notification_plugin_active ? false : true)); +} + +// -------- + +bool ExternalNotificationPluginRadio::handleReceived(const MeshPacket &mp) +{ +#ifndef NO_ESP32 + + if (radioConfig.preferences.ext_notification_plugin_enabled) { + + auto &p = mp.decoded.data; + + if (mp.from != nodeDB.getNodeNum()) { + + // TODO: This may be a problem if messages are sent in unicide, but I'm not sure if it will. + // Need to know if and how this could be a problem. + if (radioConfig.preferences.ext_notification_plugin_alert_bell) { + DEBUG_MSG("externalNotificationPlugin - Notification Bell\n"); + for (int i = 0; i < p.payload.size; i++) { + if (p.payload.bytes[i] == ASCII_BELL) { + externalNotificationPlugin->setExternalOn(); + } + } + } + + if (radioConfig.preferences.ext_notification_plugin_alert_message) { + DEBUG_MSG("externalNotificationPlugin - Notification Plugin\n"); + externalNotificationPlugin->setExternalOn(); + } + } + + } else { + DEBUG_MSG("External Notification Plugin Disabled\n"); + } + +#endif + + return true; // Let others look at this message also if they want +} diff --git a/src/plugins/ExternalNotificationPlugin.h b/src/plugins/ExternalNotificationPlugin.h new file mode 100644 index 000000000..a9ef58d04 --- /dev/null +++ b/src/plugins/ExternalNotificationPlugin.h @@ -0,0 +1,47 @@ +#pragma once + +#include "SinglePortPlugin.h" +#include "concurrency/OSThread.h" +#include "configuration.h" +#include +#include + + +class ExternalNotificationPlugin : private concurrency::OSThread +{ + bool firstTime = 1; + + public: + ExternalNotificationPlugin(); + + void setExternalOn(); + void setExternalOff(); + void getExternal(); + + protected: + virtual int32_t runOnce(); +}; + +extern ExternalNotificationPlugin *externalNotificationPlugin; + +/* + * Radio interface for ExternalNotificationPlugin + * + */ +class ExternalNotificationPluginRadio : public SinglePortPlugin +{ + + public: + ExternalNotificationPluginRadio() : SinglePortPlugin("ExternalNotificationPluginRadio", PortNum_TEXT_MESSAGE_APP) {} + + protected: + //virtual MeshPacket *allocReply(); + + /** Called to handle a particular incoming message + + @return true if you've guaranteed you've handled this message and no other handlers should be considered for it + */ + virtual bool handleReceived(const MeshPacket &mp); +}; + +extern ExternalNotificationPluginRadio *externalNotificationPluginRadio; \ No newline at end of file diff --git a/src/plugins/Plugins.cpp b/src/plugins/Plugins.cpp index 096b9cf5d..90a1b554f 100644 --- a/src/plugins/Plugins.cpp +++ b/src/plugins/Plugins.cpp @@ -1,3 +1,4 @@ +#include "plugins/ExternalNotificationPlugin.h" #include "plugins/NodeInfoPlugin.h" #include "plugins/PositionPlugin.h" #include "plugins/RemoteHardwarePlugin.h" @@ -23,7 +24,7 @@ void setupPlugins() #ifndef NO_ESP32 // Only run on an esp32 based device. - new SerialPlugin(); // Maintained by MC Hamster (Jm Casler) jm@casler.org + new SerialPlugin(); // Maintained by MC Hamster (Jm Casler) jm@casler.org + new ExternalNotificationPlugin(); // Maintained by MC Hamster (Jm Casler) jm@casler.org #endif - } \ No newline at end of file