2022-02-27 09:27:17 +00:00
|
|
|
#include "SerialModule.h"
|
2021-01-14 04:22:59 +00:00
|
|
|
#include "MeshService.h"
|
|
|
|
#include "NodeDB.h"
|
|
|
|
#include "RTC.h"
|
2022-10-16 14:37:38 +00:00
|
|
|
#include "NMEAWPL.h"
|
2021-01-14 04:22:59 +00:00
|
|
|
#include "Router.h"
|
2022-05-07 10:31:21 +00:00
|
|
|
#include "configuration.h"
|
2021-01-14 04:22:59 +00:00
|
|
|
#include <Arduino.h>
|
|
|
|
|
|
|
|
/*
|
2022-02-27 10:21:02 +00:00
|
|
|
SerialModule
|
2021-01-21 03:02:08 +00:00
|
|
|
A simple interface to send messages over the mesh network by sending strings
|
2021-01-15 02:08:23 +00:00
|
|
|
over a serial port.
|
|
|
|
|
2021-01-17 06:31:56 +00:00
|
|
|
Default is to use RX GPIO 16 and TX GPIO 17.
|
2021-01-14 06:50:02 +00:00
|
|
|
|
2022-02-27 08:29:05 +00:00
|
|
|
Need help with this module? Post your question on the Meshtastic Discourse:
|
2021-01-14 06:50:02 +00:00
|
|
|
https://meshtastic.discourse.group
|
|
|
|
|
|
|
|
Basic Usage:
|
|
|
|
|
2022-05-07 10:31:21 +00:00
|
|
|
1) Enable the module by setting enabled to 1.
|
|
|
|
2) Set the pins (rxd / rxd) for your preferred RX and TX GPIO pins.
|
2021-01-15 06:36:51 +00:00
|
|
|
On tbeam, recommend to use:
|
2021-01-21 03:02:08 +00:00
|
|
|
RXD 35
|
|
|
|
TXD 15
|
2022-05-07 10:31:21 +00:00
|
|
|
3) Set timeout to the amount of time to wait before we consider
|
2021-01-14 06:50:02 +00:00
|
|
|
your packet as "done".
|
2022-10-05 09:39:50 +00:00
|
|
|
4) not applicable any more
|
2021-01-14 06:50:02 +00:00
|
|
|
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.
|
2022-05-07 10:31:21 +00:00
|
|
|
7) (Optional) Set echo to 1 and any message you send out will be echoed back
|
2021-01-14 06:50:02 +00:00
|
|
|
to your device.
|
|
|
|
|
2021-01-14 07:21:55 +00:00
|
|
|
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
|
2022-02-27 08:29:05 +00:00
|
|
|
* Until the module is initilized by the startup sequence, the TX pin is in a floating
|
2021-01-14 07:21:55 +00:00
|
|
|
state. Device connected to that pin may see this as "noise".
|
2022-10-16 14:37:38 +00:00
|
|
|
* Will not work on T-Echo and the Linux device targets.
|
2021-01-14 07:21:55 +00:00
|
|
|
|
2021-01-14 07:02:13 +00:00
|
|
|
|
2021-01-14 04:22:59 +00:00
|
|
|
*/
|
|
|
|
|
2022-12-22 16:43:55 +00:00
|
|
|
#if (defined(ARCH_ESP32) || defined(ARCH_NRF52)) && !defined(TTGO_T_ECHO) && !defined(CONFIG_IDF_TARGET_ESP32S2)
|
|
|
|
|
2021-01-14 04:22:59 +00:00
|
|
|
#define RXD2 16
|
|
|
|
#define TXD2 17
|
2022-05-07 10:31:21 +00:00
|
|
|
#define RX_BUFFER 128
|
|
|
|
#define TIMEOUT 250
|
|
|
|
#define BAUD 38400
|
|
|
|
#define ACK 1
|
2021-01-14 04:22:59 +00:00
|
|
|
|
2022-12-22 16:25:15 +00:00
|
|
|
// API: Defaulting to the formerly removed phone_timeout_secs value of 15 minutes
|
|
|
|
#define SERIAL_CONNECTION_TIMEOUT (15 * 60) * 1000UL
|
|
|
|
|
2022-02-27 10:21:02 +00:00
|
|
|
SerialModule *serialModule;
|
|
|
|
SerialModuleRadio *serialModuleRadio;
|
2021-01-14 04:22:59 +00:00
|
|
|
|
2022-12-22 16:25:15 +00:00
|
|
|
SerialModule::SerialModule() : StreamAPI(&Serial2), concurrency::OSThread("SerialModule") {}
|
2021-01-14 04:22:59 +00:00
|
|
|
|
2023-01-12 18:08:41 +00:00
|
|
|
char serialBytes[Constants_DATA_PAYLOAD_LEN];
|
|
|
|
size_t serialPayloadSize;
|
2021-01-14 04:22:59 +00:00
|
|
|
|
2022-10-05 09:39:50 +00:00
|
|
|
SerialModuleRadio::SerialModuleRadio() : MeshModule("SerialModuleRadio")
|
2021-03-13 05:14:27 +00:00
|
|
|
{
|
2022-10-05 09:39:50 +00:00
|
|
|
|
|
|
|
switch (moduleConfig.serial.mode)
|
|
|
|
{
|
|
|
|
case ModuleConfig_SerialConfig_Serial_Mode_TEXTMSG:
|
|
|
|
ourPortNum = PortNum_TEXT_MESSAGE_APP;
|
|
|
|
break;
|
2022-10-16 14:37:38 +00:00
|
|
|
case ModuleConfig_SerialConfig_Serial_Mode_NMEA:
|
|
|
|
ourPortNum = PortNum_POSITION_APP;
|
|
|
|
break;
|
2022-10-05 09:39:50 +00:00
|
|
|
default:
|
|
|
|
ourPortNum = PortNum_SERIAL_APP;
|
2022-10-16 14:37:38 +00:00
|
|
|
// restrict to the serial channel for rx
|
|
|
|
boundChannel = Channels::serialChannel;
|
2022-10-05 09:39:50 +00:00
|
|
|
break;
|
|
|
|
}
|
2021-03-13 05:14:27 +00:00
|
|
|
}
|
|
|
|
|
2022-12-22 16:25:15 +00:00
|
|
|
// For the serial2 port we can't really detect if any client is on the other side, so instead just look for recent messages
|
|
|
|
bool SerialModule::checkIsConnected()
|
|
|
|
{
|
|
|
|
uint32_t now = millis();
|
|
|
|
return (now - lastContactMsec) < SERIAL_CONNECTION_TIMEOUT;
|
|
|
|
}
|
|
|
|
|
2022-02-27 10:21:02 +00:00
|
|
|
int32_t SerialModule::runOnce()
|
2021-01-14 04:22:59 +00:00
|
|
|
{
|
2021-01-17 23:40:25 +00:00
|
|
|
/*
|
2022-02-27 08:52:25 +00:00
|
|
|
Uncomment the preferences below if you want to use the module
|
2021-01-17 23:40:25 +00:00
|
|
|
without having to configure it from the PythonAPI or WebUI.
|
|
|
|
*/
|
|
|
|
|
2022-05-22 11:27:56 +00:00
|
|
|
// moduleConfig.serial.enabled = 1;
|
|
|
|
// moduleConfig.serial.rxd = 35;
|
|
|
|
// moduleConfig.serial.txd = 15;
|
|
|
|
// moduleConfig.serial.timeout = 1000;
|
|
|
|
// moduleConfig.serial.echo = 1;
|
2021-01-17 23:40:25 +00:00
|
|
|
|
2022-05-22 11:27:56 +00:00
|
|
|
if (moduleConfig.serial.enabled) {
|
2021-01-14 04:22:59 +00:00
|
|
|
|
2021-01-17 06:27:33 +00:00
|
|
|
if (firstTime) {
|
2021-01-14 04:22:59 +00:00
|
|
|
|
2021-01-17 06:27:33 +00:00
|
|
|
// Interface with the serial peripheral from in here.
|
2022-12-30 16:27:07 +00:00
|
|
|
LOG_INFO("Initializing serial peripheral interface\n");
|
2022-05-07 10:31:21 +00:00
|
|
|
|
2022-03-26 16:35:06 +00:00
|
|
|
uint32_t baud = 0;
|
|
|
|
|
2022-09-09 10:51:41 +00:00
|
|
|
if (moduleConfig.serial.baud == ModuleConfig_SerialConfig_Serial_Baud_BAUD_DEFAULT) {
|
2022-03-26 16:35:06 +00:00
|
|
|
baud = 38400;
|
2022-05-07 10:31:21 +00:00
|
|
|
|
2022-05-22 11:27:56 +00:00
|
|
|
} else if (moduleConfig.serial.baud == ModuleConfig_SerialConfig_Serial_Baud_BAUD_110) {
|
2022-04-19 20:37:04 +00:00
|
|
|
baud = 110;
|
|
|
|
|
2022-05-22 11:27:56 +00:00
|
|
|
} else if (moduleConfig.serial.baud == ModuleConfig_SerialConfig_Serial_Baud_BAUD_300) {
|
2022-04-19 20:37:04 +00:00
|
|
|
baud = 300;
|
|
|
|
|
2022-05-22 11:27:56 +00:00
|
|
|
} else if (moduleConfig.serial.baud == ModuleConfig_SerialConfig_Serial_Baud_BAUD_600) {
|
2022-04-19 20:37:04 +00:00
|
|
|
baud = 600;
|
|
|
|
|
2022-05-22 11:27:56 +00:00
|
|
|
} else if (moduleConfig.serial.baud == ModuleConfig_SerialConfig_Serial_Baud_BAUD_1200) {
|
2022-04-19 20:37:04 +00:00
|
|
|
baud = 1200;
|
2022-03-26 16:35:06 +00:00
|
|
|
|
2022-05-22 11:27:56 +00:00
|
|
|
} else if (moduleConfig.serial.baud == ModuleConfig_SerialConfig_Serial_Baud_BAUD_2400) {
|
2022-03-26 16:35:06 +00:00
|
|
|
baud = 2400;
|
|
|
|
|
2022-05-22 11:27:56 +00:00
|
|
|
} else if (moduleConfig.serial.baud == ModuleConfig_SerialConfig_Serial_Baud_BAUD_4800) {
|
2022-03-26 16:35:06 +00:00
|
|
|
baud = 4800;
|
|
|
|
|
2022-05-22 11:27:56 +00:00
|
|
|
} else if (moduleConfig.serial.baud == ModuleConfig_SerialConfig_Serial_Baud_BAUD_9600) {
|
2022-03-26 16:35:06 +00:00
|
|
|
baud = 9600;
|
|
|
|
|
2022-05-22 11:27:56 +00:00
|
|
|
} else if (moduleConfig.serial.baud == ModuleConfig_SerialConfig_Serial_Baud_BAUD_19200) {
|
2022-03-26 16:35:06 +00:00
|
|
|
baud = 19200;
|
|
|
|
|
2022-05-22 11:27:56 +00:00
|
|
|
} else if (moduleConfig.serial.baud == ModuleConfig_SerialConfig_Serial_Baud_BAUD_38400) {
|
2022-03-26 16:35:06 +00:00
|
|
|
baud = 38400;
|
|
|
|
|
2022-05-22 11:27:56 +00:00
|
|
|
} else if (moduleConfig.serial.baud == ModuleConfig_SerialConfig_Serial_Baud_BAUD_57600) {
|
2022-03-26 16:35:06 +00:00
|
|
|
baud = 57600;
|
|
|
|
|
2022-05-22 11:27:56 +00:00
|
|
|
} else if (moduleConfig.serial.baud == ModuleConfig_SerialConfig_Serial_Baud_BAUD_115200) {
|
2022-03-26 16:35:06 +00:00
|
|
|
baud = 115200;
|
|
|
|
|
2022-05-22 11:27:56 +00:00
|
|
|
} else if (moduleConfig.serial.baud == ModuleConfig_SerialConfig_Serial_Baud_BAUD_230400) {
|
2022-03-26 16:35:06 +00:00
|
|
|
baud = 230400;
|
|
|
|
|
2022-05-22 11:27:56 +00:00
|
|
|
} else if (moduleConfig.serial.baud == ModuleConfig_SerialConfig_Serial_Baud_BAUD_460800) {
|
2022-03-26 16:35:06 +00:00
|
|
|
baud = 460800;
|
|
|
|
|
2022-05-22 11:27:56 +00:00
|
|
|
} else if (moduleConfig.serial.baud == ModuleConfig_SerialConfig_Serial_Baud_BAUD_576000) {
|
2022-03-26 16:35:06 +00:00
|
|
|
baud = 576000;
|
|
|
|
|
2022-05-22 11:27:56 +00:00
|
|
|
} else if (moduleConfig.serial.baud == ModuleConfig_SerialConfig_Serial_Baud_BAUD_921600) {
|
2022-03-26 16:35:06 +00:00
|
|
|
baud = 921600;
|
|
|
|
}
|
2021-01-14 04:22:59 +00:00
|
|
|
|
2022-10-05 09:39:50 +00:00
|
|
|
#ifdef ARCH_ESP32
|
|
|
|
Serial2.setRxBufferSize(RX_BUFFER);
|
|
|
|
|
2022-05-22 11:27:56 +00:00
|
|
|
if (moduleConfig.serial.rxd && moduleConfig.serial.txd) {
|
|
|
|
Serial2.begin(baud, SERIAL_8N1, moduleConfig.serial.rxd, moduleConfig.serial.txd);
|
2021-01-14 04:22:59 +00:00
|
|
|
|
2021-01-17 06:27:33 +00:00
|
|
|
} else {
|
2022-03-26 16:35:06 +00:00
|
|
|
Serial2.begin(baud, SERIAL_8N1, RXD2, TXD2);
|
2021-01-17 06:27:33 +00:00
|
|
|
}
|
2022-09-12 08:08:32 +00:00
|
|
|
#else
|
|
|
|
if (moduleConfig.serial.rxd && moduleConfig.serial.txd)
|
|
|
|
Serial2.setPins(moduleConfig.serial.rxd, moduleConfig.serial.txd);
|
2021-01-17 06:39:28 +00:00
|
|
|
|
2022-09-12 08:08:32 +00:00
|
|
|
Serial2.begin(baud, SERIAL_8N1);
|
2021-01-17 06:39:28 +00:00
|
|
|
|
2022-09-12 08:08:32 +00:00
|
|
|
#endif
|
|
|
|
if (moduleConfig.serial.timeout) {
|
|
|
|
Serial2.setTimeout(moduleConfig.serial.timeout); // Number of MS to wait to set the timeout for the string.
|
2021-01-17 06:39:28 +00:00
|
|
|
} else {
|
2022-05-07 10:31:21 +00:00
|
|
|
Serial2.setTimeout(TIMEOUT); // Number of MS to wait to set the timeout for the string.
|
2021-01-17 06:39:28 +00:00
|
|
|
}
|
|
|
|
|
2022-02-27 10:21:02 +00:00
|
|
|
serialModuleRadio = new SerialModuleRadio();
|
2021-01-14 04:22:59 +00:00
|
|
|
|
2021-01-17 06:27:33 +00:00
|
|
|
firstTime = 0;
|
2021-01-14 04:22:59 +00:00
|
|
|
|
2022-12-22 16:25:15 +00:00
|
|
|
// in API mode send rebooted sequence
|
|
|
|
if (moduleConfig.serial.mode == ModuleConfig_SerialConfig_Serial_Mode_PROTO) {
|
|
|
|
emitRebooted();
|
|
|
|
}
|
|
|
|
|
2021-01-17 06:27:33 +00:00
|
|
|
} else {
|
2021-01-14 04:22:59 +00:00
|
|
|
|
2022-12-22 16:25:15 +00:00
|
|
|
if (moduleConfig.serial.mode == ModuleConfig_SerialConfig_Serial_Mode_PROTO) {
|
2022-12-22 17:24:42 +00:00
|
|
|
return runOncePart();
|
2022-12-22 16:25:15 +00:00
|
|
|
} else if (moduleConfig.serial.mode == ModuleConfig_SerialConfig_Serial_Mode_NMEA) {
|
|
|
|
// in NMEA mode send out GGA every 2 seconds, Don't read from Port
|
2022-10-16 14:37:38 +00:00
|
|
|
if (millis() - lastNmeaTime > 2000) {
|
|
|
|
lastNmeaTime = millis();
|
|
|
|
printGGA(outbuf, nodeDB.getNode(myNodeInfo.my_node_num)->position);
|
|
|
|
Serial2.printf("%s", outbuf);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
while (Serial2.available()) {
|
2023-01-12 18:08:41 +00:00
|
|
|
serialPayloadSize = Serial2.readBytes(serialBytes, Constants_DATA_PAYLOAD_LEN);
|
2022-10-16 14:37:38 +00:00
|
|
|
serialModuleRadio->sendPayload();
|
|
|
|
}
|
2021-01-17 06:27:33 +00:00
|
|
|
}
|
2021-01-14 04:22:59 +00:00
|
|
|
}
|
|
|
|
|
2021-01-17 06:27:33 +00:00
|
|
|
return (10);
|
|
|
|
} else {
|
2022-12-30 00:48:33 +00:00
|
|
|
return disable();
|
2021-01-17 06:27:33 +00:00
|
|
|
}
|
2021-01-14 04:22:59 +00:00
|
|
|
}
|
|
|
|
|
2022-02-27 10:21:02 +00:00
|
|
|
MeshPacket *SerialModuleRadio::allocReply()
|
2021-01-14 04:22:59 +00:00
|
|
|
{
|
|
|
|
auto reply = allocDataPacket(); // Allocate a packet for sending
|
|
|
|
|
|
|
|
return reply;
|
|
|
|
}
|
|
|
|
|
2022-02-27 10:21:02 +00:00
|
|
|
void SerialModuleRadio::sendPayload(NodeNum dest, bool wantReplies)
|
2021-01-14 04:22:59 +00:00
|
|
|
{
|
2023-01-12 18:08:41 +00:00
|
|
|
Channel *ch = (boundChannel != NULL) ? &channels.getByName(boundChannel) : NULL;
|
2021-01-14 04:22:59 +00:00
|
|
|
MeshPacket *p = allocReply();
|
|
|
|
p->to = dest;
|
2023-01-12 18:08:41 +00:00
|
|
|
if (ch != NULL) {
|
|
|
|
p->channel = ch->index;
|
|
|
|
}
|
2021-01-14 04:22:59 +00:00
|
|
|
p->decoded.want_response = wantReplies;
|
|
|
|
|
2022-05-07 10:31:21 +00:00
|
|
|
p->want_ack = ACK;
|
2021-01-14 07:21:55 +00:00
|
|
|
|
2023-01-12 18:08:41 +00:00
|
|
|
p->decoded.payload.size = serialPayloadSize; // You must specify how many bytes are in the reply
|
|
|
|
memcpy(p->decoded.payload.bytes, serialBytes, p->decoded.payload.size);
|
2021-01-14 04:22:59 +00:00
|
|
|
|
|
|
|
service.sendToMesh(p);
|
|
|
|
}
|
|
|
|
|
2022-02-27 10:21:02 +00:00
|
|
|
ProcessMessage SerialModuleRadio::handleReceived(const MeshPacket &mp)
|
2021-01-14 04:22:59 +00:00
|
|
|
{
|
2022-05-22 11:27:56 +00:00
|
|
|
if (moduleConfig.serial.enabled) {
|
2022-12-22 16:25:15 +00:00
|
|
|
if (moduleConfig.serial.mode == ModuleConfig_SerialConfig_Serial_Mode_PROTO) {
|
|
|
|
// in API mode we don't care about stuff from radio.
|
|
|
|
return ProcessMessage::CONTINUE;
|
|
|
|
}
|
2021-01-15 05:59:26 +00:00
|
|
|
|
2021-02-17 08:17:46 +00:00
|
|
|
auto &p = mp.decoded;
|
2022-12-30 02:41:37 +00:00
|
|
|
// LOG_DEBUG("Received text msg self=0x%0x, from=0x%0x, to=0x%0x, id=%d, msg=%.*s\n",
|
2021-01-17 23:40:25 +00:00
|
|
|
// nodeDB.getNodeNum(), mp.from, mp.to, mp.id, p.payload.size, p.payload.bytes);
|
2021-01-14 04:22:59 +00:00
|
|
|
|
2021-03-05 02:19:27 +00:00
|
|
|
if (getFrom(&mp) == nodeDB.getNodeNum()) {
|
2021-01-14 04:22:59 +00:00
|
|
|
|
2021-01-17 06:27:33 +00:00
|
|
|
/*
|
2022-05-22 11:27:56 +00:00
|
|
|
* If moduleConfig.serial.echo is true, then echo the packets that are sent out
|
2022-05-07 10:31:21 +00:00
|
|
|
* back to the TX of the serial interface.
|
2021-01-17 06:27:33 +00:00
|
|
|
*/
|
2022-05-22 11:27:56 +00:00
|
|
|
if (moduleConfig.serial.echo) {
|
2021-01-14 04:22:59 +00:00
|
|
|
|
2021-01-17 06:27:33 +00:00
|
|
|
// For some reason, we get the packet back twice when we send out of the radio.
|
|
|
|
// TODO: need to find out why.
|
|
|
|
if (lastRxID != mp.id) {
|
|
|
|
lastRxID = mp.id;
|
2022-12-30 02:41:37 +00:00
|
|
|
// LOG_DEBUG("* * Message came this device\n");
|
2021-01-17 06:27:33 +00:00
|
|
|
// Serial2.println("* * Message came this device");
|
|
|
|
Serial2.printf("%s", p.payload.bytes);
|
|
|
|
}
|
2021-01-14 04:22:59 +00:00
|
|
|
}
|
2021-01-17 06:27:33 +00:00
|
|
|
|
|
|
|
} else {
|
2021-03-18 04:52:30 +00:00
|
|
|
|
2022-09-09 10:51:41 +00:00
|
|
|
if (moduleConfig.serial.mode == ModuleConfig_SerialConfig_Serial_Mode_DEFAULT ||
|
|
|
|
moduleConfig.serial.mode == ModuleConfig_SerialConfig_Serial_Mode_SIMPLE) {
|
2022-12-22 16:25:15 +00:00
|
|
|
Serial2.printf("%s", p.payload.bytes);
|
2022-12-06 15:56:38 +00:00
|
|
|
} else if (moduleConfig.serial.mode == ModuleConfig_SerialConfig_Serial_Mode_TEXTMSG) {
|
|
|
|
NodeInfo *node = nodeDB.getNode(getFrom(&mp));
|
|
|
|
String sender = (node && node->has_user) ? node->user.short_name : "???";
|
|
|
|
Serial2.println();
|
|
|
|
Serial2.printf("%s: %s", sender, p.payload.bytes);
|
|
|
|
Serial2.println();
|
2022-10-16 14:37:38 +00:00
|
|
|
} else if (moduleConfig.serial.mode == ModuleConfig_SerialConfig_Serial_Mode_NMEA) {
|
|
|
|
// Decode the Payload some more
|
|
|
|
Position scratch;
|
|
|
|
Position *decoded = NULL;
|
|
|
|
if (mp.which_payload_variant == MeshPacket_decoded_tag && mp.decoded.portnum == ourPortNum) {
|
|
|
|
memset(&scratch, 0, sizeof(scratch));
|
2022-12-23 09:00:34 +00:00
|
|
|
if (pb_decode_from_bytes(p.payload.bytes, p.payload.size, &Position_msg, &scratch)) {
|
2022-10-16 14:37:38 +00:00
|
|
|
decoded = &scratch;
|
|
|
|
}
|
|
|
|
// send position packet as WPL to the serial port
|
|
|
|
printWPL(outbuf, *decoded, nodeDB.getNode(getFrom(&mp))->user.long_name);
|
|
|
|
Serial2.printf("%s", outbuf);
|
|
|
|
}
|
2021-03-18 04:52:30 +00:00
|
|
|
}
|
2021-01-14 04:22:59 +00:00
|
|
|
}
|
|
|
|
}
|
2021-09-23 01:42:09 +00:00
|
|
|
return ProcessMessage::CONTINUE; // Let others look at this message also if they want
|
2021-01-14 04:22:59 +00:00
|
|
|
}
|
2022-12-22 16:43:55 +00:00
|
|
|
#endif
|