Merge pull request #55 from mc-hamster/serial

Update for SerialPlugin and Airtime
This commit is contained in:
Jm Casler 2021-01-14 21:43:28 -08:00 committed by GitHub
commit b963216764
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 228 additions and 17 deletions

View File

@ -5,10 +5,6 @@
AirTime *airTime;
// A reminder that there are 3600 seconds in an hour so I don't have
// to keep googling it.
// This can be changed to a smaller number to speed up testing.
//
uint32_t secondsPerPeriod = 3600;
uint32_t lastMillis = 0;
uint32_t secSinceBoot = 0;
@ -17,25 +13,23 @@ uint32_t secSinceBoot = 0;
// Don't read out of this directly. Use the helper functions.
struct airtimeStruct {
uint16_t periodTX[periodsToLog]; // AirTime transmitted
uint16_t periodRX[periodsToLog]; // AirTime received and repeated (Only valid mesh packets)
uint16_t periodRX_ALL[periodsToLog]; // AirTime received regardless of valid mesh packet. Could include noise.
uint32_t periodTX[periodsToLog]; // AirTime transmitted
uint32_t periodRX[periodsToLog]; // AirTime received and repeated (Only valid mesh packets)
uint32_t periodRX_ALL[periodsToLog]; // AirTime received regardless of valid mesh packet. Could include noise.
uint8_t lastPeriodIndex;
} airtimes;
void AirTime::logAirtime(reportTypes reportType, uint32_t airtime_ms)
{
// DEBUG_MSG("Packet - logAirtime()\n");
if (reportType == TX_LOG) {
DEBUG_MSG("AirTime - Packet transmitted : %us %ums\n", (uint32_t)round((float)airtime_ms / (float)1000), airtime_ms);
airtimes.periodTX[0] = airtimes.periodTX[0] + round(airtime_ms / 1000);
DEBUG_MSG("AirTime - Packet transmitted : %ums\n", airtime_ms);
airtimes.periodTX[0] = airtimes.periodTX[0] + airtime_ms;
} else if (reportType == RX_LOG) {
DEBUG_MSG("AirTime - Packet received : %us %ums\n", (uint32_t)round((float)airtime_ms / (float)1000), airtime_ms);
airtimes.periodRX[0] = airtimes.periodRX[0] + round(airtime_ms / 1000);
DEBUG_MSG("AirTime - Packet received : %ums\n", airtime_ms);
airtimes.periodRX[0] = airtimes.periodRX[0] + airtime_ms;
} else if (reportType == RX_ALL_LOG) {
DEBUG_MSG("AirTime - Packet received (noise?) : %us %ums\n", (uint32_t)round((float)airtime_ms / (float)1000), airtime_ms);
airtimes.periodRX_ALL[0] = airtimes.periodRX_ALL[0] + round(airtime_ms / 1000);
DEBUG_MSG("AirTime - Packet received (noise?) : %ums\n", airtime_ms);
airtimes.periodRX_ALL[0] = airtimes.periodRX_ALL[0] + airtime_ms;
} else {
DEBUG_MSG("AirTime - Unknown report time. This should never happen!!\n");
}
@ -65,7 +59,7 @@ void airtimeRotatePeriod()
}
}
uint16_t *airtimeReport(reportTypes reportType)
uint32_t *airtimeReport(reportTypes reportType)
{
if (reportType == TX_LOG) {

View File

@ -34,7 +34,7 @@ uint8_t getPeriodsToLog();
uint32_t getSecondsSinceBoot();
uint16_t *airtimeReport(reportTypes reportType);
uint32_t *airtimeReport(reportTypes reportType);
uint32_t getSecondsPerPeriod();

View File

@ -1,6 +1,7 @@
#include "plugins/NodeInfoPlugin.h"
#include "plugins/PositionPlugin.h"
#include "plugins/ReplyPlugin.h"
#include "plugins/SerialPlugin.h"
#include "plugins/RemoteHardwarePlugin.h"
#include "plugins/TextMessagePlugin.h"
@ -17,4 +18,5 @@ void setupPlugins() {
new RemoteHardwarePlugin();
new ReplyPlugin();
new SerialPlugin(); // Maintained by MC Hamster (Jm Casler) jm@casler.org
}

View File

@ -0,0 +1,161 @@
#include "SerialPlugin.h"
#include "MeshService.h"
#include "NodeDB.h"
#include "RTC.h"
#include "Router.h"
#include "configuration.h"
#include <Arduino.h>
#include <assert.h>
/*
SerialPlugin
An overly simplistic interface to send messages over the mesh network by sending strings
over a serial port.
Originally designed for lora32 v1.0
Manufacture Info: http://www.lilygo.cn/prod_view.aspx?TypeId=50003&Id=1133&FId=t3:50003:3
Pin Mapping: http://ae01.alicdn.com/kf/HTB1fLBcxkSWBuNjSszdq6zeSpXaJ.jpg
This will probably and most likely work on other esp32 devices, given possible change the RX/TX
selection.
Need help with this plugin? Post your question on the Meshtastic Discourse:
https://meshtastic.discourse.group
Basic Usage:
1) Enable the plugin by setting SERIALPLUGIN_ENABLED to 1.
2) Set the pins (RXD2 / TXD2) for your preferred RX and TX GPIO pins.
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):
* Once protobufs regenerated with the new port, update SerialPlugin.h
* Ensure this works on a tbeam
* 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".
*/
#define RXD2 16
#define TXD2 17
#define SERIALPLUGIN_RX_BUFFER 128
#define SERIALPLUGIN_STRING_MAX Constants_DATA_PAYLOAD_LEN
#define SERIALPLUGIN_TIMEOUT 250
#define SERIALPLUGIN_BAUD 38400
#define SERIALPLUGIN_ENABLED 1
#define SERIALPLUGIN_ECHO 0
#define SERIALPLUGIN_ACK 0
SerialPlugin *serialPlugin;
SerialPluginRadio *serialPluginRadio;
SerialPlugin::SerialPlugin() : concurrency::OSThread("SerialPlugin") {}
char serialStringChar[Constants_DATA_PAYLOAD_LEN];
int32_t SerialPlugin::runOnce()
{
#if SERIALPLUGIN_ENABLED == 1
if (firstTime) {
// Interface with the serial peripheral from in here.
DEBUG_MSG("Initilizing serial peripheral interface\n");
Serial2.begin(SERIALPLUGIN_BAUD, SERIAL_8N1, RXD2, TXD2);
Serial2.setTimeout(SERIALPLUGIN_TIMEOUT); // Number of MS to wait to set the timeout for the string.
Serial2.setRxBufferSize(SERIALPLUGIN_RX_BUFFER);
serialPluginRadio = new SerialPluginRadio();
firstTime = 0;
} else {
String serialString;
while (Serial2.available()) {
serialString = Serial2.readString();
serialString.toCharArray(serialStringChar, Constants_DATA_PAYLOAD_LEN);
serialPluginRadio->sendPayload();
DEBUG_MSG("Received: %s\n", serialStringChar);
}
}
return (10);
#else
DEBUG_MSG("Serial Plugin Disabled\n");
return (INT32_MAX);
#endif
}
MeshPacket *SerialPluginRadio::allocReply()
{
auto reply = allocDataPacket(); // Allocate a packet for sending
return reply;
}
void SerialPluginRadio::sendPayload(NodeNum dest, bool wantReplies)
{
MeshPacket *p = allocReply();
p->to = dest;
p->decoded.want_response = wantReplies;
p->want_ack = SERIALPLUGIN_ACK;
p->decoded.data.payload.size = strlen(serialStringChar); // You must specify how many bytes are in the reply
memcpy(p->decoded.data.payload.bytes, serialStringChar, p->decoded.data.payload.size);
service.sendToMesh(p);
}
bool SerialPluginRadio::handleReceived(const MeshPacket &mp)
{
auto &p = mp.decoded.data;
// DEBUG_MSG("Received text msg self=0x%0x, from=0x%0x, to=0x%0x, id=%d, msg=%.*s\n", nodeDB.getNodeNum(),
// mp.from, mp.to, mp.id, p.payload.size, p.payload.bytes);
if (mp.from == nodeDB.getNodeNum()) {
/*
* If SERIALPLUGIN_ECHO is true, then echo the packets that are sent out back to the TX
* of the serial interface.
*/
if (SERIALPLUGIN_ECHO) {
// 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;
// DEBUG_MSG("* * Message came this device\n");
// Serial2.println("* * Message came this device");
Serial2.printf("%s", p.payload.bytes);
}
}
} else {
// DEBUG_MSG("* * Message came from the mesh\n");
// Serial2.println("* * Message came from the mesh");
Serial2.printf("%s", p.payload.bytes);
}
return true; // Let others look at this message also if they want
}

View File

@ -0,0 +1,54 @@
#pragma once
#include "SinglePortPlugin.h"
#include "concurrency/OSThread.h"
#include "configuration.h"
#include <Arduino.h>
#include <functional>
class SerialPlugin : private concurrency::OSThread
{
bool firstTime = 1;
public:
SerialPlugin();
protected:
virtual int32_t runOnce();
};
extern SerialPlugin *serialPlugin;
/*
* Radio interface for SerialPlugin
*
*/
class SerialPluginRadio : public SinglePortPlugin
{
uint32_t lastRxID;
public:
/*
TODO: Switch this to PortNum_SERIAL_APP once the change is able to be merged back here
from the main code.
*/
SerialPluginRadio() : SinglePortPlugin("SerialPluginRadio", PortNum_TEXT_MESSAGE_APP) {}
// SerialPluginRadio() : SinglePortPlugin("SerialPluginRadio", PortNum_SERIAL_APP) {}
/**
* Send our payload into the mesh
*/
void sendPayload(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false);
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 SerialPluginRadio *serialPluginRadio;