mirror of
https://github.com/meshtastic/firmware.git
synced 2025-04-28 18:47:40 +00:00
Merge pull request #2060 from meshtastic/protobuf-serial
ProtobufAPI in SerialModule
This commit is contained in:
commit
adb8d773d4
@ -25,7 +25,7 @@ void consolePrintf(const char *format, ...)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SerialConsole::SerialConsole() : StreamAPI(&Port), RedirectablePrint(&Port)
|
SerialConsole::SerialConsole() : StreamAPI(&Port), RedirectablePrint(&Port), concurrency::OSThread("SerialConsole")
|
||||||
{
|
{
|
||||||
assert(!console);
|
assert(!console);
|
||||||
console = this;
|
console = this;
|
||||||
@ -46,6 +46,10 @@ SerialConsole::SerialConsole() : StreamAPI(&Port), RedirectablePrint(&Port)
|
|||||||
emitRebooted();
|
emitRebooted();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t SerialConsole::runOnce()
|
||||||
|
{
|
||||||
|
return runOncePart();
|
||||||
|
}
|
||||||
|
|
||||||
// For the serial port we can't really detect if any client is on the other side, so instead just look for recent messages
|
// For the serial port we can't really detect if any client is on the other side, so instead just look for recent messages
|
||||||
bool SerialConsole::checkIsConnected()
|
bool SerialConsole::checkIsConnected()
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* Provides both debug printing and, if the client starts sending protobufs to us, switches to send/receive protobufs
|
* Provides both debug printing and, if the client starts sending protobufs to us, switches to send/receive protobufs
|
||||||
* (and starts dropping debug printing - FIXME, eventually those prints should be encapsulated in protobufs).
|
* (and starts dropping debug printing - FIXME, eventually those prints should be encapsulated in protobufs).
|
||||||
*/
|
*/
|
||||||
class SerialConsole : public StreamAPI, public RedirectablePrint
|
class SerialConsole : public StreamAPI, public RedirectablePrint, private concurrency::OSThread
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SerialConsole();
|
SerialConsole();
|
||||||
@ -24,6 +24,8 @@ class SerialConsole : public StreamAPI, public RedirectablePrint
|
|||||||
return RedirectablePrint::write(c);
|
return RedirectablePrint::write(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual int32_t runOnce() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/// Check the current underlying physical link to see if the client is currently connected
|
/// Check the current underlying physical link to see if the client is currently connected
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
#define START2 0xc3
|
#define START2 0xc3
|
||||||
#define HEADER_LEN 4
|
#define HEADER_LEN 4
|
||||||
|
|
||||||
int32_t StreamAPI::runOnce()
|
int32_t StreamAPI::runOncePart()
|
||||||
{
|
{
|
||||||
auto result = readStream();
|
auto result = readStream();
|
||||||
writeStream();
|
writeStream();
|
||||||
|
@ -28,7 +28,7 @@ valid utf8 encoding. This makes it a bit easier to start a device outputting reg
|
|||||||
after it has received a valid packet from the PC, turn off unencoded debug printing and switch to this packet encoding.
|
after it has received a valid packet from the PC, turn off unencoded debug printing and switch to this packet encoding.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
class StreamAPI : public PhoneAPI, protected concurrency::OSThread
|
class StreamAPI : public PhoneAPI
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* The stream we read/write from
|
* The stream we read/write from
|
||||||
@ -42,13 +42,13 @@ class StreamAPI : public PhoneAPI, protected concurrency::OSThread
|
|||||||
uint32_t lastRxMsec = 0;
|
uint32_t lastRxMsec = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
StreamAPI(Stream *_stream) : concurrency::OSThread("StreamAPI"), stream(_stream) {}
|
StreamAPI(Stream *_stream) : stream(_stream) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Currently we require frequent invocation from loop() to check for arrived serial packets and to send new packets to the
|
* Currently we require frequent invocation from loop() to check for arrived serial packets and to send new packets to the
|
||||||
* phone.
|
* phone.
|
||||||
*/
|
*/
|
||||||
virtual int32_t runOnce() override;
|
virtual int32_t runOncePart();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
|
@ -14,7 +14,7 @@ void initApiServer(int port)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ethServerAPI::ethServerAPI(EthernetClient &_client) : StreamAPI(&client), client(_client)
|
ethServerAPI::ethServerAPI(EthernetClient &_client) : StreamAPI(&client), concurrency::OSThread("ethServerAPI"), client(_client)
|
||||||
{
|
{
|
||||||
DEBUG_MSG("Incoming ethernet connection\n");
|
DEBUG_MSG("Incoming ethernet connection\n");
|
||||||
}
|
}
|
||||||
@ -42,7 +42,7 @@ bool ethServerAPI::checkIsConnected()
|
|||||||
int32_t ethServerAPI::runOnce()
|
int32_t ethServerAPI::runOnce()
|
||||||
{
|
{
|
||||||
if (client.connected()) {
|
if (client.connected()) {
|
||||||
return StreamAPI::runOnce();
|
return StreamAPI::runOncePart();
|
||||||
} else {
|
} else {
|
||||||
DEBUG_MSG("Client dropped connection, suspending API service\n");
|
DEBUG_MSG("Client dropped connection, suspending API service\n");
|
||||||
enabled = false; // we no longer need to run
|
enabled = false; // we no longer need to run
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Provides both debug printing and, if the client starts sending protobufs to us, switches to send/receive protobufs
|
* Provides both debug printing and, if the client starts sending protobufs to us, switches to send/receive protobufs
|
||||||
* (and starts dropping debug printing - FIXME, eventually those prints should be encapsulated in protobufs).
|
* (and starts dropping debug printing - FIXME, eventually those prints should be encapsulated in protobufs).
|
||||||
*/
|
*/
|
||||||
class ethServerAPI : public StreamAPI
|
class ethServerAPI : public StreamAPI, private concurrency::OSThread
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
EthernetClient client;
|
EthernetClient client;
|
||||||
|
@ -14,7 +14,7 @@ void initApiServer(int port)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WiFiServerAPI::WiFiServerAPI(WiFiClient &_client) : StreamAPI(&client), client(_client)
|
WiFiServerAPI::WiFiServerAPI(WiFiClient &_client) : StreamAPI(&client), concurrency::OSThread("WiFiServerAPI"), client(_client)
|
||||||
{
|
{
|
||||||
DEBUG_MSG("Incoming wifi connection\n");
|
DEBUG_MSG("Incoming wifi connection\n");
|
||||||
}
|
}
|
||||||
@ -42,7 +42,7 @@ bool WiFiServerAPI::checkIsConnected()
|
|||||||
int32_t WiFiServerAPI::runOnce()
|
int32_t WiFiServerAPI::runOnce()
|
||||||
{
|
{
|
||||||
if (client.connected()) {
|
if (client.connected()) {
|
||||||
return StreamAPI::runOnce();
|
return StreamAPI::runOncePart();
|
||||||
} else {
|
} else {
|
||||||
DEBUG_MSG("Client dropped connection, suspending API service\n");
|
DEBUG_MSG("Client dropped connection, suspending API service\n");
|
||||||
enabled = false; // we no longer need to run
|
enabled = false; // we no longer need to run
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Provides both debug printing and, if the client starts sending protobufs to us, switches to send/receive protobufs
|
* Provides both debug printing and, if the client starts sending protobufs to us, switches to send/receive protobufs
|
||||||
* (and starts dropping debug printing - FIXME, eventually those prints should be encapsulated in protobufs).
|
* (and starts dropping debug printing - FIXME, eventually those prints should be encapsulated in protobufs).
|
||||||
*/
|
*/
|
||||||
class WiFiServerAPI : public StreamAPI
|
class WiFiServerAPI : public StreamAPI, private concurrency::OSThread
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
WiFiClient client;
|
WiFiClient client;
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#if defined(ARCH_ESP32) || defined(ARCH_NRF52)
|
#if defined(ARCH_ESP32) || defined(ARCH_NRF52)
|
||||||
#include "modules/ExternalNotificationModule.h"
|
#include "modules/ExternalNotificationModule.h"
|
||||||
#if !defined(TTGO_T_ECHO)
|
#if (defined(ARCH_ESP32) || defined(ARCH_NRF52)) && !defined(TTGO_T_ECHO) && !defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||||
#include "modules/SerialModule.h"
|
#include "modules/SerialModule.h"
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
@ -63,7 +63,7 @@ void setupModules()
|
|||||||
new DeviceTelemetryModule();
|
new DeviceTelemetryModule();
|
||||||
new EnvironmentTelemetryModule();
|
new EnvironmentTelemetryModule();
|
||||||
#endif
|
#endif
|
||||||
#if (defined(ARCH_ESP32) || defined(ARCH_NRF52)) && !defined(TTGO_T_ECHO)
|
#if (defined(ARCH_ESP32) || defined(ARCH_NRF52)) && !defined(TTGO_T_ECHO) && !defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||||
new SerialModule();
|
new SerialModule();
|
||||||
#endif
|
#endif
|
||||||
#ifdef ARCH_ESP32
|
#ifdef ARCH_ESP32
|
||||||
|
@ -46,20 +46,25 @@
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#if (defined(ARCH_ESP32) || defined(ARCH_NRF52)) && !defined(TTGO_T_ECHO) && !defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||||
|
|
||||||
#define RXD2 16
|
#define RXD2 16
|
||||||
#define TXD2 17
|
#define TXD2 17
|
||||||
#define RX_BUFFER 128
|
#define RX_BUFFER 128
|
||||||
|
#define STRING_MAX Constants_DATA_PAYLOAD_LEN
|
||||||
#define TIMEOUT 250
|
#define TIMEOUT 250
|
||||||
#define BAUD 38400
|
#define BAUD 38400
|
||||||
#define ACK 1
|
#define ACK 1
|
||||||
|
|
||||||
|
// API: Defaulting to the formerly removed phone_timeout_secs value of 15 minutes
|
||||||
|
#define SERIAL_CONNECTION_TIMEOUT (15 * 60) * 1000UL
|
||||||
|
|
||||||
SerialModule *serialModule;
|
SerialModule *serialModule;
|
||||||
SerialModuleRadio *serialModuleRadio;
|
SerialModuleRadio *serialModuleRadio;
|
||||||
|
|
||||||
SerialModule::SerialModule() : concurrency::OSThread("SerialModule") {}
|
SerialModule::SerialModule() : StreamAPI(&Serial2), concurrency::OSThread("SerialModule") {}
|
||||||
|
|
||||||
char serialBytes[Constants_DATA_PAYLOAD_LEN];
|
char serialStringChar[Constants_DATA_PAYLOAD_LEN];
|
||||||
size_t serialPayloadSize;
|
|
||||||
|
|
||||||
SerialModuleRadio::SerialModuleRadio() : MeshModule("SerialModuleRadio")
|
SerialModuleRadio::SerialModuleRadio() : MeshModule("SerialModuleRadio")
|
||||||
{
|
{
|
||||||
@ -80,9 +85,15 @@ SerialModuleRadio::SerialModuleRadio() : MeshModule("SerialModuleRadio")
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
int32_t SerialModule::runOnce()
|
int32_t SerialModule::runOnce()
|
||||||
{
|
{
|
||||||
#if (defined(ARCH_ESP32) || defined(ARCH_NRF52)) && !defined(TTGO_T_ECHO) && !defined(CONFIG_IDF_TARGET_ESP32S2)
|
|
||||||
/*
|
/*
|
||||||
Uncomment the preferences below if you want to use the module
|
Uncomment the preferences below if you want to use the module
|
||||||
without having to configure it from the PythonAPI or WebUI.
|
without having to configure it from the PythonAPI or WebUI.
|
||||||
@ -178,19 +189,32 @@ int32_t SerialModule::runOnce()
|
|||||||
|
|
||||||
firstTime = 0;
|
firstTime = 0;
|
||||||
|
|
||||||
|
// in API mode send rebooted sequence
|
||||||
|
if (moduleConfig.serial.mode == ModuleConfig_SerialConfig_Serial_Mode_PROTO) {
|
||||||
|
emitRebooted();
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// in NMEA mode send out GGA every 2 seconds, Don't read from Port
|
if (moduleConfig.serial.mode == ModuleConfig_SerialConfig_Serial_Mode_PROTO) {
|
||||||
if (moduleConfig.serial.mode == ModuleConfig_SerialConfig_Serial_Mode_NMEA) {
|
return runOncePart();
|
||||||
|
} else if (moduleConfig.serial.mode == ModuleConfig_SerialConfig_Serial_Mode_NMEA) {
|
||||||
|
// in NMEA mode send out GGA every 2 seconds, Don't read from Port
|
||||||
if (millis() - lastNmeaTime > 2000) {
|
if (millis() - lastNmeaTime > 2000) {
|
||||||
lastNmeaTime = millis();
|
lastNmeaTime = millis();
|
||||||
printGGA(outbuf, nodeDB.getNode(myNodeInfo.my_node_num)->position);
|
printGGA(outbuf, nodeDB.getNode(myNodeInfo.my_node_num)->position);
|
||||||
Serial2.printf("%s", outbuf);
|
Serial2.printf("%s", outbuf);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
String serialString;
|
||||||
|
|
||||||
while (Serial2.available()) {
|
while (Serial2.available()) {
|
||||||
serialPayloadSize = Serial2.readBytes(serialBytes, Constants_DATA_PAYLOAD_LEN);
|
serialString = Serial2.readString();
|
||||||
|
serialString.toCharArray(serialStringChar, Constants_DATA_PAYLOAD_LEN);
|
||||||
|
|
||||||
serialModuleRadio->sendPayload();
|
serialModuleRadio->sendPayload();
|
||||||
|
|
||||||
|
DEBUG_MSG("Received: %s\n", serialStringChar);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -201,9 +225,6 @@ int32_t SerialModule::runOnce()
|
|||||||
|
|
||||||
return INT32_MAX;
|
return INT32_MAX;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
return INT32_MAX;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MeshPacket *SerialModuleRadio::allocReply()
|
MeshPacket *SerialModuleRadio::allocReply()
|
||||||
@ -221,16 +242,19 @@ void SerialModuleRadio::sendPayload(NodeNum dest, bool wantReplies)
|
|||||||
|
|
||||||
p->want_ack = ACK;
|
p->want_ack = ACK;
|
||||||
|
|
||||||
p->decoded.payload.size = serialPayloadSize; // You must specify how many bytes are in the reply
|
p->decoded.payload.size = strlen(serialStringChar); // You must specify how many bytes are in the reply
|
||||||
memcpy(p->decoded.payload.bytes, serialBytes, p->decoded.payload.size);
|
memcpy(p->decoded.payload.bytes, serialStringChar, p->decoded.payload.size);
|
||||||
|
|
||||||
service.sendToMesh(p);
|
service.sendToMesh(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcessMessage SerialModuleRadio::handleReceived(const MeshPacket &mp)
|
ProcessMessage SerialModuleRadio::handleReceived(const MeshPacket &mp)
|
||||||
{
|
{
|
||||||
#if (defined(ARCH_ESP32) || defined(ARCH_NRF52)) && !defined(TTGO_T_ECHO) && !defined(CONFIG_IDF_TARGET_ESP32S2)
|
|
||||||
if (moduleConfig.serial.enabled) {
|
if (moduleConfig.serial.enabled) {
|
||||||
|
if (moduleConfig.serial.mode == ModuleConfig_SerialConfig_Serial_Mode_PROTO) {
|
||||||
|
// in API mode we don't care about stuff from radio.
|
||||||
|
return ProcessMessage::CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
auto &p = mp.decoded;
|
auto &p = mp.decoded;
|
||||||
// DEBUG_MSG("Received text msg self=0x%0x, from=0x%0x, to=0x%0x, id=%d, msg=%.*s\n",
|
// DEBUG_MSG("Received text msg self=0x%0x, from=0x%0x, to=0x%0x, id=%d, msg=%.*s\n",
|
||||||
@ -258,15 +282,13 @@ ProcessMessage SerialModuleRadio::handleReceived(const MeshPacket &mp)
|
|||||||
|
|
||||||
if (moduleConfig.serial.mode == ModuleConfig_SerialConfig_Serial_Mode_DEFAULT ||
|
if (moduleConfig.serial.mode == ModuleConfig_SerialConfig_Serial_Mode_DEFAULT ||
|
||||||
moduleConfig.serial.mode == ModuleConfig_SerialConfig_Serial_Mode_SIMPLE) {
|
moduleConfig.serial.mode == ModuleConfig_SerialConfig_Serial_Mode_SIMPLE) {
|
||||||
Serial2.write(p.payload.bytes, p.payload.size);
|
Serial2.printf("%s", p.payload.bytes);
|
||||||
} else if (moduleConfig.serial.mode == ModuleConfig_SerialConfig_Serial_Mode_TEXTMSG) {
|
} else if (moduleConfig.serial.mode == ModuleConfig_SerialConfig_Serial_Mode_TEXTMSG) {
|
||||||
NodeInfo *node = nodeDB.getNode(getFrom(&mp));
|
NodeInfo *node = nodeDB.getNode(getFrom(&mp));
|
||||||
String sender = (node && node->has_user) ? node->user.short_name : "???";
|
String sender = (node && node->has_user) ? node->user.short_name : "???";
|
||||||
Serial2.println();
|
Serial2.println();
|
||||||
Serial2.printf("%s: %s", sender, p.payload.bytes);
|
Serial2.printf("%s: %s", sender, p.payload.bytes);
|
||||||
Serial2.println();
|
Serial2.println();
|
||||||
} else if (moduleConfig.serial.mode == ModuleConfig_SerialConfig_Serial_Mode_PROTO) {
|
|
||||||
// TODO this needs to be implemented
|
|
||||||
} else if (moduleConfig.serial.mode == ModuleConfig_SerialConfig_Serial_Mode_NMEA) {
|
} else if (moduleConfig.serial.mode == ModuleConfig_SerialConfig_Serial_Mode_NMEA) {
|
||||||
// Decode the Payload some more
|
// Decode the Payload some more
|
||||||
Position scratch;
|
Position scratch;
|
||||||
@ -286,8 +308,6 @@ ProcessMessage SerialModuleRadio::handleReceived(const MeshPacket &mp)
|
|||||||
} else {
|
} else {
|
||||||
DEBUG_MSG("Serial Module Disabled\n");
|
DEBUG_MSG("Serial Module Disabled\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return ProcessMessage::CONTINUE; // Let others look at this message also if they want
|
return ProcessMessage::CONTINUE; // Let others look at this message also if they want
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
@ -8,7 +8,9 @@
|
|||||||
#include "Router.h"
|
#include "Router.h"
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
class SerialModule : private concurrency::OSThread
|
#if (defined(ARCH_ESP32) || defined(ARCH_NRF52)) && !defined(TTGO_T_ECHO) && !defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||||
|
|
||||||
|
class SerialModule : public StreamAPI, private concurrency::OSThread
|
||||||
{
|
{
|
||||||
bool firstTime = 1;
|
bool firstTime = 1;
|
||||||
unsigned long lastNmeaTime = millis();
|
unsigned long lastNmeaTime = millis();
|
||||||
@ -19,6 +21,9 @@ class SerialModule : private concurrency::OSThread
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual int32_t runOnce() override;
|
virtual int32_t runOnce() override;
|
||||||
|
|
||||||
|
/// Check the current underlying physical link to see if the client is currently connected
|
||||||
|
virtual bool checkIsConnected() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern SerialModule *serialModule;
|
extern SerialModule *serialModule;
|
||||||
@ -65,3 +70,5 @@ class SerialModuleRadio : public MeshModule
|
|||||||
};
|
};
|
||||||
|
|
||||||
extern SerialModuleRadio *serialModuleRadio;
|
extern SerialModuleRadio *serialModuleRadio;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user