sforkowany z mirror/meshtastic-firmware
Merge pull request #633 from mc-hamster/master
Fix for #632 (move web server to osthread) and #611 (move airtime to osthread)1.2-legacy
commit
485fec9649
|
@ -9,8 +9,13 @@
|
||||||
; https://docs.platformio.org/page/projectconf.html
|
; https://docs.platformio.org/page/projectconf.html
|
||||||
|
|
||||||
[platformio]
|
[platformio]
|
||||||
|
;default_envs = tbeam
|
||||||
|
;default_envs = tbeam0.7
|
||||||
|
;default_envs = heltec
|
||||||
|
;default_envs = tlora-v1
|
||||||
|
;default_envs = tlora-v2
|
||||||
|
;default_envs = lora-relay-v1 # nrf board
|
||||||
default_envs = linux # lora-relay-v1 # nrf52840dk-geeksville # linux # or if you'd like to change the default to something like lora-relay-v1 put that here
|
default_envs = linux # lora-relay-v1 # nrf52840dk-geeksville # linux # or if you'd like to change the default to something like lora-relay-v1 put that here
|
||||||
;default_envs = heltec # lora-relay-v1 # nrf52840dk-geeksville # linux # or if you'd like to change the default to something like lora-relay-v1 put that here
|
|
||||||
|
|
||||||
[common]
|
[common]
|
||||||
; common is not currently used
|
; common is not currently used
|
||||||
|
@ -183,7 +188,7 @@ build_flags =
|
||||||
-Isdk-nrfxlib/crypto/nrf_oberon/include -Lsdk-nrfxlib/crypto/nrf_oberon/lib/cortex-m4/hard-float/ -lliboberon_3.0.3
|
-Isdk-nrfxlib/crypto/nrf_oberon/include -Lsdk-nrfxlib/crypto/nrf_oberon/lib/cortex-m4/hard-float/ -lliboberon_3.0.3
|
||||||
;-DCFG_DEBUG=3
|
;-DCFG_DEBUG=3
|
||||||
src_filter =
|
src_filter =
|
||||||
${arduino_base.src_filter} -<esp32/> -<nimble/> -<meshwifi/> -<mesh/wifi/>
|
${arduino_base.src_filter} -<esp32/> -<nimble/> -<mesh/wifi/> -<mesh/http/>
|
||||||
lib_ignore =
|
lib_ignore =
|
||||||
BluetoothOTA
|
BluetoothOTA
|
||||||
monitor_port = /dev/ttyACM1
|
monitor_port = /dev/ttyACM1
|
||||||
|
@ -310,7 +315,7 @@ lib_deps =
|
||||||
; The Portduino based sim environment on top of linux
|
; The Portduino based sim environment on top of linux
|
||||||
[env:linux]
|
[env:linux]
|
||||||
platform = https://github.com/geeksville/platform-portduino.git
|
platform = https://github.com/geeksville/platform-portduino.git
|
||||||
src_filter = ${env.src_filter} -<esp32/> -<nimble/> -<nrf52/> -<meshwifi/>
|
src_filter = ${env.src_filter} -<esp32/> -<nimble/> -<nrf52/> -<mesh/http/>
|
||||||
build_flags = ${arduino_base.build_flags} -O0
|
build_flags = ${arduino_base.build_flags} -O0
|
||||||
framework = arduino
|
framework = arduino
|
||||||
board = linux_x86_64
|
board = linux_x86_64
|
||||||
|
|
2
proto
2
proto
|
@ -1 +1 @@
|
||||||
Subproject commit dfe7bc1217a00c23eecb9dfcf1d56fe95ebddc3b
|
Subproject commit 75078afe43934f4ce15ef86ebc6950658a170145
|
|
@ -11,7 +11,7 @@ namespace meshtastic
|
||||||
*/
|
*/
|
||||||
enum OptionalBool { OptFalse = 0, OptTrue = 1, OptUnknown = 2 };
|
enum OptionalBool { OptFalse = 0, OptTrue = 1, OptUnknown = 2 };
|
||||||
|
|
||||||
/// Describes the state of the GPS system.
|
/// Describes the state of the Power system.
|
||||||
class PowerStatus : public Status
|
class PowerStatus : public Status
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
@ -3,33 +3,35 @@
|
||||||
|
|
||||||
#define periodsToLog 48
|
#define periodsToLog 48
|
||||||
|
|
||||||
// A reminder that there are 3600 seconds in an hour so I don't have
|
AirTime *airTime;
|
||||||
// to keep googling it.
|
|
||||||
// This can be changed to a smaller number to speed up testing.
|
|
||||||
//
|
|
||||||
uint32_t secondsPerPeriod = 3600;
|
uint32_t secondsPerPeriod = 3600;
|
||||||
uint32_t lastMillis = 0;
|
uint32_t lastMillis = 0;
|
||||||
uint32_t secSinceBoot = 0;
|
uint32_t secSinceBoot = 0;
|
||||||
|
|
||||||
|
// AirTime at;
|
||||||
|
|
||||||
// Don't read out of this directly. Use the helper functions.
|
// Don't read out of this directly. Use the helper functions.
|
||||||
struct airtimeStruct {
|
struct airtimeStruct {
|
||||||
uint16_t periodTX[periodsToLog];
|
uint32_t periodTX[periodsToLog]; // AirTime transmitted
|
||||||
uint16_t periodRX[periodsToLog];
|
uint32_t periodRX[periodsToLog]; // AirTime received and repeated (Only valid mesh packets)
|
||||||
uint16_t periodRX_ALL[periodsToLog];
|
uint32_t periodRX_ALL[periodsToLog]; // AirTime received regardless of valid mesh packet. Could include noise.
|
||||||
uint8_t lastPeriodIndex;
|
uint8_t lastPeriodIndex;
|
||||||
} airtimes;
|
} airtimes;
|
||||||
|
|
||||||
void logAirtime(reportTypes reportType, uint32_t airtime_ms)
|
void AirTime::logAirtime(reportTypes reportType, uint32_t airtime_ms)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (reportType == TX_LOG) {
|
if (reportType == TX_LOG) {
|
||||||
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) {
|
} else if (reportType == RX_LOG) {
|
||||||
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) {
|
} else if (reportType == RX_ALL_LOG) {
|
||||||
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 {
|
} else {
|
||||||
// Unknown report type
|
DEBUG_MSG("AirTime - Unknown report time. This should never happen!!\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,29 +40,27 @@ uint8_t currentPeriodIndex()
|
||||||
return ((getSecondsSinceBoot() / secondsPerPeriod) % periodsToLog);
|
return ((getSecondsSinceBoot() / secondsPerPeriod) % periodsToLog);
|
||||||
}
|
}
|
||||||
|
|
||||||
void airtimeCalculator()
|
void airtimeRotatePeriod()
|
||||||
{
|
{
|
||||||
if (millis() - lastMillis > 1000) {
|
|
||||||
lastMillis = millis();
|
|
||||||
secSinceBoot++;
|
|
||||||
if (airtimes.lastPeriodIndex != currentPeriodIndex()) {
|
|
||||||
for (int i = periodsToLog - 2; i >= 0; --i) {
|
|
||||||
airtimes.periodTX[i + 1] = airtimes.periodTX[i];
|
|
||||||
airtimes.periodRX[i + 1] = airtimes.periodRX[i];
|
|
||||||
airtimes.periodRX_ALL[i + 1] = airtimes.periodRX_ALL[i];
|
|
||||||
}
|
|
||||||
airtimes.periodTX[0] = 0;
|
|
||||||
airtimes.periodRX[0] = 0;
|
|
||||||
airtimes.periodRX_ALL[0] = 0;
|
|
||||||
|
|
||||||
airtimes.lastPeriodIndex = currentPeriodIndex();
|
if (airtimes.lastPeriodIndex != currentPeriodIndex()) {
|
||||||
|
DEBUG_MSG("Rotating airtimes to a new period = %u\n", currentPeriodIndex());
|
||||||
|
|
||||||
|
for (int i = periodsToLog - 2; i >= 0; --i) {
|
||||||
|
airtimes.periodTX[i + 1] = airtimes.periodTX[i];
|
||||||
|
airtimes.periodRX[i + 1] = airtimes.periodRX[i];
|
||||||
|
airtimes.periodRX_ALL[i + 1] = airtimes.periodRX_ALL[i];
|
||||||
}
|
}
|
||||||
|
airtimes.periodTX[0] = 0;
|
||||||
|
airtimes.periodRX[0] = 0;
|
||||||
|
airtimes.periodRX_ALL[0] = 0;
|
||||||
|
|
||||||
|
airtimes.lastPeriodIndex = currentPeriodIndex();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t *airtimeReport(reportTypes reportType)
|
uint32_t *airtimeReport(reportTypes reportType)
|
||||||
{
|
{
|
||||||
// currentHourIndexReset();
|
|
||||||
|
|
||||||
if (reportType == TX_LOG) {
|
if (reportType == TX_LOG) {
|
||||||
return airtimes.periodTX;
|
return airtimes.periodTX;
|
||||||
|
@ -86,3 +86,22 @@ uint32_t getSecondsSinceBoot()
|
||||||
{
|
{
|
||||||
return secSinceBoot;
|
return secSinceBoot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AirTime::AirTime() : concurrency::OSThread("AirTime") {}
|
||||||
|
|
||||||
|
int32_t AirTime::runOnce()
|
||||||
|
{
|
||||||
|
//DEBUG_MSG("AirTime::runOnce()\n");
|
||||||
|
|
||||||
|
airtimeRotatePeriod();
|
||||||
|
secSinceBoot++;
|
||||||
|
|
||||||
|
/*
|
||||||
|
This actually doesn't need to be run once per second but we currently use it for the
|
||||||
|
secSinceBoot counter.
|
||||||
|
|
||||||
|
If we have a better counter of how long the device has been online (and not millis())
|
||||||
|
then we can change this to something less frequent. Maybe once ever 5 seconds?
|
||||||
|
*/
|
||||||
|
return (1000 * 1);
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "concurrency/OSThread.h"
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
@ -26,13 +27,28 @@ enum reportTypes { TX_LOG, RX_LOG, RX_ALL_LOG };
|
||||||
|
|
||||||
void logAirtime(reportTypes reportType, uint32_t airtime_ms);
|
void logAirtime(reportTypes reportType, uint32_t airtime_ms);
|
||||||
|
|
||||||
void airtimeCalculator();
|
void airtimeRotatePeriod();
|
||||||
|
|
||||||
uint8_t currentPeriodIndex();
|
uint8_t currentPeriodIndex();
|
||||||
uint8_t getPeriodsToLog();
|
uint8_t getPeriodsToLog();
|
||||||
|
|
||||||
uint32_t getSecondsSinceBoot();
|
uint32_t getSecondsSinceBoot();
|
||||||
|
|
||||||
uint16_t *airtimeReport(reportTypes reportType);
|
uint32_t *airtimeReport(reportTypes reportType);
|
||||||
|
|
||||||
uint32_t getSecondsPerPeriod();
|
uint32_t getSecondsPerPeriod();
|
||||||
|
|
||||||
|
class AirTime : private concurrency::OSThread
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
AirTime();
|
||||||
|
|
||||||
|
void logAirtime(reportTypes reportType, uint32_t airtime_ms);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual int32_t runOnce();
|
||||||
|
};
|
||||||
|
|
||||||
|
extern AirTime *airTime;
|
|
@ -4,7 +4,6 @@
|
||||||
#include "EInkDisplay.h"
|
#include "EInkDisplay.h"
|
||||||
#include "SPILock.h"
|
#include "SPILock.h"
|
||||||
#include "epd1in54.h" // Screen specific library
|
#include "epd1in54.h" // Screen specific library
|
||||||
#include "graphics/configs.h"
|
|
||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
#include <TFT_eSPI.h> // Graphics library and Sprite class
|
#include <TFT_eSPI.h> // Graphics library and Sprite class
|
||||||
|
|
||||||
|
|
|
@ -31,11 +31,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#include "graphics/images.h"
|
#include "graphics/images.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "mesh-pb-constants.h"
|
#include "mesh-pb-constants.h"
|
||||||
#include "meshwifi/meshwifi.h"
|
|
||||||
#include "plugins/TextMessagePlugin.h"
|
#include "plugins/TextMessagePlugin.h"
|
||||||
#include "target_specific.h"
|
#include "target_specific.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
|
#ifndef NO_ESP32
|
||||||
|
#include "mesh/http/WiFiAPClient.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace meshtastic; /** @todo remove */
|
using namespace meshtastic; /** @todo remove */
|
||||||
|
|
||||||
namespace graphics
|
namespace graphics
|
||||||
|
@ -895,10 +898,12 @@ void Screen::setFrames()
|
||||||
// call a method on debugInfoScreen object (for more details)
|
// call a method on debugInfoScreen object (for more details)
|
||||||
normalFrames[numframes++] = &Screen::drawDebugInfoSettingsTrampoline;
|
normalFrames[numframes++] = &Screen::drawDebugInfoSettingsTrampoline;
|
||||||
|
|
||||||
|
#ifndef NO_ESP32
|
||||||
if (isWifiAvailable()) {
|
if (isWifiAvailable()) {
|
||||||
// call a method on debugInfoScreen object (for more details)
|
// call a method on debugInfoScreen object (for more details)
|
||||||
normalFrames[numframes++] = &Screen::drawDebugInfoWiFiTrampoline;
|
normalFrames[numframes++] = &Screen::drawDebugInfoWiFiTrampoline;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
ui.setFrames(normalFrames, numframes);
|
ui.setFrames(normalFrames, numframes);
|
||||||
ui.enableAllIndicators();
|
ui.enableAllIndicators();
|
||||||
|
|
20
src/main.cpp
20
src/main.cpp
|
@ -19,16 +19,16 @@
|
||||||
#include "concurrency/Periodic.h"
|
#include "concurrency/Periodic.h"
|
||||||
#include "graphics/Screen.h"
|
#include "graphics/Screen.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "meshwifi/meshhttp.h"
|
|
||||||
#include "meshwifi/meshwifi.h"
|
|
||||||
#include "sleep.h"
|
|
||||||
#include "plugins/Plugins.h"
|
#include "plugins/Plugins.h"
|
||||||
|
#include "sleep.h"
|
||||||
#include "target_specific.h"
|
#include "target_specific.h"
|
||||||
#include <OneButton.h>
|
#include <OneButton.h>
|
||||||
#include <Wire.h>
|
#include <Wire.h>
|
||||||
// #include <driver/rtc_io.h>
|
// #include <driver/rtc_io.h>
|
||||||
|
|
||||||
#ifndef NO_ESP32
|
#ifndef NO_ESP32
|
||||||
|
#include "mesh/http/WebServer.h"
|
||||||
|
#include "mesh/http/WiFiAPClient.h"
|
||||||
#include "nimble/BluetoothUtil.h"
|
#include "nimble/BluetoothUtil.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -513,9 +513,18 @@ void setup()
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef NO_ESP32
|
||||||
// Initialize Wifi
|
// Initialize Wifi
|
||||||
initWifi(forceSoftAP);
|
initWifi(forceSoftAP);
|
||||||
|
|
||||||
|
// Start web server thread.
|
||||||
|
webServerThread = new WebServerThread();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Start airtime logger thread.
|
||||||
|
airTime = new AirTime();
|
||||||
|
|
||||||
if (!rIf)
|
if (!rIf)
|
||||||
recordCriticalError(CriticalErrorCode_NoRadio);
|
recordCriticalError(CriticalErrorCode_NoRadio);
|
||||||
else
|
else
|
||||||
|
@ -576,7 +585,7 @@ void loop()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// TODO: This should go into a thread handled by FreeRTOS.
|
// TODO: This should go into a thread handled by FreeRTOS.
|
||||||
handleWebResponse();
|
// handleWebResponse();
|
||||||
|
|
||||||
service.loop();
|
service.loop();
|
||||||
|
|
||||||
|
@ -589,7 +598,4 @@ void loop()
|
||||||
// We want to sleep as long as possible here - because it saves power
|
// We want to sleep as long as possible here - because it saves power
|
||||||
mainDelay.delay(delayMsec);
|
mainDelay.delay(delayMsec);
|
||||||
// if (didWake) DEBUG_MSG("wake!\n");
|
// if (didWake) DEBUG_MSG("wake!\n");
|
||||||
|
|
||||||
// Handles cleanup for the airtime calculator.
|
|
||||||
airtimeCalculator();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,10 +16,13 @@
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "mesh-pb-constants.h"
|
#include "mesh-pb-constants.h"
|
||||||
#include "meshwifi/meshwifi.h"
|
|
||||||
#include <pb_decode.h>
|
#include <pb_decode.h>
|
||||||
#include <pb_encode.h>
|
#include <pb_encode.h>
|
||||||
|
|
||||||
|
#ifndef NO_ESP32
|
||||||
|
#include "mesh/http/WiFiAPClient.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
NodeDB nodeDB;
|
NodeDB nodeDB;
|
||||||
|
|
||||||
// we have plenty of ram so statically alloc this tempbuf (for now)
|
// we have plenty of ram so statically alloc this tempbuf (for now)
|
||||||
|
|
|
@ -97,7 +97,8 @@ ErrorCode RadioLibInterface::send(MeshPacket *p)
|
||||||
|
|
||||||
// Count the packet toward our TX airtime utilization.
|
// Count the packet toward our TX airtime utilization.
|
||||||
// We only count it if it can be added to the TX queue.
|
// We only count it if it can be added to the TX queue.
|
||||||
logAirtime(TX_LOG, xmitMsec);
|
airTime->logAirtime(TX_LOG, xmitMsec);
|
||||||
|
//airTime.logAirtime(TX_LOG, xmitMsec);
|
||||||
|
|
||||||
// We want all sending/receiving to be done by our daemon thread, We use a delay here because this packet might have been sent
|
// We want all sending/receiving to be done by our daemon thread, We use a delay here because this packet might have been sent
|
||||||
// in response to a packet we just received. So we want to make sure the other side has had a chance to reconfigure its radio
|
// in response to a packet we just received. So we want to make sure the other side has had a chance to reconfigure its radio
|
||||||
|
@ -216,7 +217,8 @@ void RadioLibInterface::handleReceiveInterrupt()
|
||||||
size_t length = iface->getPacketLength();
|
size_t length = iface->getPacketLength();
|
||||||
|
|
||||||
xmitMsec = getPacketTime(length);
|
xmitMsec = getPacketTime(length);
|
||||||
logAirtime(RX_ALL_LOG, xmitMsec);
|
airTime->logAirtime(RX_ALL_LOG, xmitMsec);
|
||||||
|
//airTime.logAirtime(RX_ALL_LOG, xmitMsec);
|
||||||
|
|
||||||
int state = iface->readData(radiobuf, length);
|
int state = iface->readData(radiobuf, length);
|
||||||
if (state != ERR_NONE) {
|
if (state != ERR_NONE) {
|
||||||
|
@ -258,7 +260,8 @@ void RadioLibInterface::handleReceiveInterrupt()
|
||||||
printPacket("Lora RX", mp);
|
printPacket("Lora RX", mp);
|
||||||
|
|
||||||
xmitMsec = getPacketTime(mp);
|
xmitMsec = getPacketTime(mp);
|
||||||
logAirtime(RX_LOG, xmitMsec);
|
airTime->logAirtime(RX_LOG, xmitMsec);
|
||||||
|
//airTime.logAirtime(RX_LOG, xmitMsec);
|
||||||
|
|
||||||
deliverToReceiver(mp);
|
deliverToReceiver(mp);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
#include "mesh/http/ContentHelper.h"
|
||||||
|
//#include <Arduino.h>
|
||||||
|
//#include "main.h"
|
||||||
|
|
||||||
|
void replaceAll(std::string &str, const std::string &from, const std::string &to)
|
||||||
|
{
|
||||||
|
if (from.empty())
|
||||||
|
return;
|
||||||
|
size_t start_pos = 0;
|
||||||
|
while ((start_pos = str.find(from, start_pos)) != std::string::npos) {
|
||||||
|
str.replace(start_pos, from.length(), to);
|
||||||
|
start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void replaceAll(std::string &str, const std::string &from, const std::string &to);
|
||||||
|
|
|
@ -2,14 +2,7 @@
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Steps:
|
This file contains static content.
|
||||||
- Compress the .js file to .js.gz
|
|
||||||
- Convert to hex:
|
|
||||||
http://tomeko.net/online_tools/file_to_hex.php?lang=en
|
|
||||||
- Paste into the array
|
|
||||||
- Note the filesize of your .gz file and write the file
|
|
||||||
size into the length int.
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Length of the binary data
|
// Length of the binary data
|
|
@ -1,12 +1,11 @@
|
||||||
#include "meshwifi/meshhttp.h"
|
#include "mesh/http/WebServer.h"
|
||||||
#include "NodeDB.h"
|
#include "NodeDB.h"
|
||||||
#include "PowerFSM.h"
|
#include "PowerFSM.h"
|
||||||
#include "airtime.h"
|
#include "airtime.h"
|
||||||
#include "configuration.h"
|
|
||||||
#include "esp_task_wdt.h"
|
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "meshhttpStatic.h"
|
#include "mesh/http/ContentHelper.h"
|
||||||
#include "meshwifi/meshwifi.h"
|
#include "mesh/http/ContentStatic.h"
|
||||||
|
#include "mesh/http/WiFiAPClient.h"
|
||||||
#include "sleep.h"
|
#include "sleep.h"
|
||||||
#include <HTTPBodyParser.hpp>
|
#include <HTTPBodyParser.hpp>
|
||||||
#include <HTTPMultipartBodyParser.hpp>
|
#include <HTTPMultipartBodyParser.hpp>
|
||||||
|
@ -15,6 +14,10 @@
|
||||||
#include <WebServer.h>
|
#include <WebServer.h>
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
|
|
||||||
|
#ifndef NO_ESP32
|
||||||
|
#include "esp_task_wdt.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
// Persistant Data Storage
|
// Persistant Data Storage
|
||||||
#include <Preferences.h>
|
#include <Preferences.h>
|
||||||
Preferences prefs;
|
Preferences prefs;
|
||||||
|
@ -196,6 +199,19 @@ void createSSLCert()
|
||||||
DEBUG_MSG("SSL Cert Ready!\n");
|
DEBUG_MSG("SSL Cert Ready!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WebServerThread *webServerThread;
|
||||||
|
|
||||||
|
WebServerThread::WebServerThread() : concurrency::OSThread("WebServerThread") {}
|
||||||
|
|
||||||
|
int32_t WebServerThread::runOnce()
|
||||||
|
{
|
||||||
|
// DEBUG_MSG("WebServerThread::runOnce()\n");
|
||||||
|
handleWebResponse();
|
||||||
|
|
||||||
|
// Loop every 5ms.
|
||||||
|
return (5);
|
||||||
|
}
|
||||||
|
|
||||||
void initWebServer()
|
void initWebServer()
|
||||||
{
|
{
|
||||||
DEBUG_MSG("Initializing Web Server ...\n");
|
DEBUG_MSG("Initializing Web Server ...\n");
|
||||||
|
@ -241,6 +257,7 @@ void initWebServer()
|
||||||
ResourceNode *nodeAPIv1ToRadioOptions = new ResourceNode("/api/v1/toradio", "OPTIONS", &handleAPIv1ToRadio);
|
ResourceNode *nodeAPIv1ToRadioOptions = new ResourceNode("/api/v1/toradio", "OPTIONS", &handleAPIv1ToRadio);
|
||||||
ResourceNode *nodeAPIv1ToRadio = new ResourceNode("/api/v1/toradio", "PUT", &handleAPIv1ToRadio);
|
ResourceNode *nodeAPIv1ToRadio = new ResourceNode("/api/v1/toradio", "PUT", &handleAPIv1ToRadio);
|
||||||
ResourceNode *nodeAPIv1FromRadio = new ResourceNode("/api/v1/fromradio", "GET", &handleAPIv1FromRadio);
|
ResourceNode *nodeAPIv1FromRadio = new ResourceNode("/api/v1/fromradio", "GET", &handleAPIv1FromRadio);
|
||||||
|
|
||||||
ResourceNode *nodeHotspot = new ResourceNode("/hotspot-detect.html", "GET", &handleHotspot);
|
ResourceNode *nodeHotspot = new ResourceNode("/hotspot-detect.html", "GET", &handleHotspot);
|
||||||
ResourceNode *nodeFavicon = new ResourceNode("/favicon.ico", "GET", &handleFavicon);
|
ResourceNode *nodeFavicon = new ResourceNode("/favicon.ico", "GET", &handleFavicon);
|
||||||
ResourceNode *nodeRoot = new ResourceNode("/", "GET", &handleRoot);
|
ResourceNode *nodeRoot = new ResourceNode("/", "GET", &handleRoot);
|
||||||
|
@ -340,6 +357,97 @@ void middlewareSpeedUp160(HTTPRequest *req, HTTPResponse *res, std::function<voi
|
||||||
timeSpeedUp = millis();
|
timeSpeedUp = millis();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void handleAPIv1FromRadio(HTTPRequest *req, HTTPResponse *res)
|
||||||
|
{
|
||||||
|
|
||||||
|
DEBUG_MSG("+++++++++++++++ webAPI handleAPIv1FromRadio\n");
|
||||||
|
|
||||||
|
/*
|
||||||
|
For documentation, see:
|
||||||
|
https://github.com/meshtastic/Meshtastic-device/wiki/HTTP-REST-API-discussion
|
||||||
|
https://github.com/meshtastic/Meshtastic-device/blob/master/docs/software/device-api.md
|
||||||
|
|
||||||
|
Example:
|
||||||
|
http://10.10.30.198/api/v1/fromradio
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Get access to the parameters
|
||||||
|
ResourceParameters *params = req->getParams();
|
||||||
|
|
||||||
|
// std::string paramAll = "all";
|
||||||
|
std::string valueAll;
|
||||||
|
|
||||||
|
// Status code is 200 OK by default.
|
||||||
|
res->setHeader("Content-Type", "application/x-protobuf");
|
||||||
|
res->setHeader("Access-Control-Allow-Origin", "*");
|
||||||
|
res->setHeader("Access-Control-Allow-Methods", "PUT, GET");
|
||||||
|
res->setHeader("X-Protobuf-Schema", "https://raw.githubusercontent.com/meshtastic/Meshtastic-protobufs/master/mesh.proto");
|
||||||
|
|
||||||
|
uint8_t txBuf[MAX_STREAM_BUF_SIZE];
|
||||||
|
uint32_t len = 1;
|
||||||
|
|
||||||
|
if (params->getQueryParameter("all", valueAll)) {
|
||||||
|
|
||||||
|
// If all is ture, return all the buffers we have available
|
||||||
|
// to us at this point in time.
|
||||||
|
if (valueAll == "true") {
|
||||||
|
while (len) {
|
||||||
|
len = webAPI.getFromRadio(txBuf);
|
||||||
|
res->write(txBuf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, just return one protobuf
|
||||||
|
} else {
|
||||||
|
len = webAPI.getFromRadio(txBuf);
|
||||||
|
res->write(txBuf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
// the param "all" was not spcified. Return just one protobuf
|
||||||
|
} else {
|
||||||
|
len = webAPI.getFromRadio(txBuf);
|
||||||
|
res->write(txBuf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_MSG("--------------- webAPI handleAPIv1FromRadio, len %d\n", len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleAPIv1ToRadio(HTTPRequest *req, HTTPResponse *res)
|
||||||
|
{
|
||||||
|
DEBUG_MSG("+++++++++++++++ webAPI handleAPIv1ToRadio\n");
|
||||||
|
|
||||||
|
/*
|
||||||
|
For documentation, see:
|
||||||
|
https://github.com/meshtastic/Meshtastic-device/wiki/HTTP-REST-API-discussion
|
||||||
|
https://github.com/meshtastic/Meshtastic-device/blob/master/docs/software/device-api.md
|
||||||
|
|
||||||
|
Example:
|
||||||
|
http://10.10.30.198/api/v1/toradio
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Status code is 200 OK by default.
|
||||||
|
|
||||||
|
res->setHeader("Content-Type", "application/x-protobuf");
|
||||||
|
res->setHeader("Access-Control-Allow-Headers", "Content-Type");
|
||||||
|
res->setHeader("Access-Control-Allow-Origin", "*");
|
||||||
|
res->setHeader("Access-Control-Allow-Methods", "PUT, OPTIONS");
|
||||||
|
res->setHeader("X-Protobuf-Schema", "https://raw.githubusercontent.com/meshtastic/Meshtastic-protobufs/master/mesh.proto");
|
||||||
|
|
||||||
|
if (req->getMethod() == "OPTIONS") {
|
||||||
|
res->setStatusCode(204); // Success with no content
|
||||||
|
res->print("");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte buffer[MAX_TO_FROM_RADIO_SIZE];
|
||||||
|
size_t s = req->readBytes(buffer, MAX_TO_FROM_RADIO_SIZE);
|
||||||
|
|
||||||
|
DEBUG_MSG("Received %d bytes from PUT request\n", s);
|
||||||
|
webAPI.handleToRadio(buffer, s);
|
||||||
|
|
||||||
|
res->write(buffer, s);
|
||||||
|
DEBUG_MSG("--------------- webAPI handleAPIv1ToRadio\n");
|
||||||
|
}
|
||||||
|
|
||||||
void handleStaticPost(HTTPRequest *req, HTTPResponse *res)
|
void handleStaticPost(HTTPRequest *req, HTTPResponse *res)
|
||||||
{
|
{
|
||||||
// Assume POST request. Contains submitted data.
|
// Assume POST request. Contains submitted data.
|
||||||
|
@ -816,10 +924,10 @@ void handleFormUpload(HTTPRequest *req, HTTPResponse *res)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//if (readLength) {
|
// if (readLength) {
|
||||||
file.write(buf, readLength);
|
file.write(buf, readLength);
|
||||||
fileLength += readLength;
|
fileLength += readLength;
|
||||||
DEBUG_MSG("File Length %i\n", fileLength);
|
DEBUG_MSG("File Length %i\n", fileLength);
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
// enableLoopWDT();
|
// enableLoopWDT();
|
||||||
|
@ -876,97 +984,6 @@ void handleHotspot(HTTPRequest *req, HTTPResponse *res)
|
||||||
res->println("<meta http-equiv=\"refresh\" content=\"0;url=/\" />\n");
|
res->println("<meta http-equiv=\"refresh\" content=\"0;url=/\" />\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleAPIv1FromRadio(HTTPRequest *req, HTTPResponse *res)
|
|
||||||
{
|
|
||||||
|
|
||||||
DEBUG_MSG("+++++++++++++++ webAPI handleAPIv1FromRadio\n");
|
|
||||||
|
|
||||||
/*
|
|
||||||
For documentation, see:
|
|
||||||
https://github.com/meshtastic/Meshtastic-device/wiki/HTTP-REST-API-discussion
|
|
||||||
https://github.com/meshtastic/Meshtastic-device/blob/master/docs/software/device-api.md
|
|
||||||
|
|
||||||
Example:
|
|
||||||
http://10.10.30.198/api/v1/fromradio
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Get access to the parameters
|
|
||||||
ResourceParameters *params = req->getParams();
|
|
||||||
|
|
||||||
// std::string paramAll = "all";
|
|
||||||
std::string valueAll;
|
|
||||||
|
|
||||||
// Status code is 200 OK by default.
|
|
||||||
res->setHeader("Content-Type", "application/x-protobuf");
|
|
||||||
res->setHeader("Access-Control-Allow-Origin", "*");
|
|
||||||
res->setHeader("Access-Control-Allow-Methods", "PUT, GET");
|
|
||||||
res->setHeader("X-Protobuf-Schema", "https://raw.githubusercontent.com/meshtastic/Meshtastic-protobufs/master/mesh.proto");
|
|
||||||
|
|
||||||
uint8_t txBuf[MAX_STREAM_BUF_SIZE];
|
|
||||||
uint32_t len = 1;
|
|
||||||
|
|
||||||
if (params->getQueryParameter("all", valueAll)) {
|
|
||||||
|
|
||||||
// If all is ture, return all the buffers we have available
|
|
||||||
// to us at this point in time.
|
|
||||||
if (valueAll == "true") {
|
|
||||||
while (len) {
|
|
||||||
len = webAPI.getFromRadio(txBuf);
|
|
||||||
res->write(txBuf, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, just return one protobuf
|
|
||||||
} else {
|
|
||||||
len = webAPI.getFromRadio(txBuf);
|
|
||||||
res->write(txBuf, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
// the param "all" was not spcified. Return just one protobuf
|
|
||||||
} else {
|
|
||||||
len = webAPI.getFromRadio(txBuf);
|
|
||||||
res->write(txBuf, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG_MSG("--------------- webAPI handleAPIv1FromRadio, len %d\n", len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void handleAPIv1ToRadio(HTTPRequest *req, HTTPResponse *res)
|
|
||||||
{
|
|
||||||
DEBUG_MSG("+++++++++++++++ webAPI handleAPIv1ToRadio\n");
|
|
||||||
|
|
||||||
/*
|
|
||||||
For documentation, see:
|
|
||||||
https://github.com/meshtastic/Meshtastic-device/wiki/HTTP-REST-API-discussion
|
|
||||||
https://github.com/meshtastic/Meshtastic-device/blob/master/docs/software/device-api.md
|
|
||||||
|
|
||||||
Example:
|
|
||||||
http://10.10.30.198/api/v1/toradio
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Status code is 200 OK by default.
|
|
||||||
|
|
||||||
res->setHeader("Content-Type", "application/x-protobuf");
|
|
||||||
res->setHeader("Access-Control-Allow-Headers", "Content-Type");
|
|
||||||
res->setHeader("Access-Control-Allow-Origin", "*");
|
|
||||||
res->setHeader("Access-Control-Allow-Methods", "PUT, OPTIONS");
|
|
||||||
res->setHeader("X-Protobuf-Schema", "https://raw.githubusercontent.com/meshtastic/Meshtastic-protobufs/master/mesh.proto");
|
|
||||||
|
|
||||||
if (req->getMethod() == "OPTIONS") {
|
|
||||||
res->setStatusCode(204); // Success with no content
|
|
||||||
res->print("");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte buffer[MAX_TO_FROM_RADIO_SIZE];
|
|
||||||
size_t s = req->readBytes(buffer, MAX_TO_FROM_RADIO_SIZE);
|
|
||||||
|
|
||||||
DEBUG_MSG("Received %d bytes from PUT request\n", s);
|
|
||||||
webAPI.handleToRadio(buffer, s);
|
|
||||||
|
|
||||||
res->write(buffer, s);
|
|
||||||
DEBUG_MSG("--------------- webAPI handleAPIv1ToRadio\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
To convert text to c strings:
|
To convert text to c strings:
|
||||||
|
|
||||||
|
@ -996,7 +1013,8 @@ void handleRoot(HTTPRequest *req, HTTPResponse *res)
|
||||||
res->printf("<p></p>\n");
|
res->printf("<p></p>\n");
|
||||||
res->printf("<p>You have gotten this error because the filesystem for the web server has not been loaded.</p>\n");
|
res->printf("<p>You have gotten this error because the filesystem for the web server has not been loaded.</p>\n");
|
||||||
res->printf("<p>Please review the 'Common Problems' section of the <a "
|
res->printf("<p>Please review the 'Common Problems' section of the <a "
|
||||||
"href=https://github.com/meshtastic/Meshtastic-device/wiki/How-to-use-the-Meshtastic-Web-Interface-over-WiFi>web interface</a> documentation.</p>\n");
|
"href=https://github.com/meshtastic/Meshtastic-device/wiki/"
|
||||||
|
"How-to-use-the-Meshtastic-Web-Interface-over-WiFi>web interface</a> documentation.</p>\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1092,13 +1110,13 @@ void handleReport(HTTPRequest *req, HTTPResponse *res)
|
||||||
|
|
||||||
res->println("\"airtime\": {");
|
res->println("\"airtime\": {");
|
||||||
|
|
||||||
uint16_t *logArray;
|
uint32_t *logArray;
|
||||||
|
|
||||||
res->print("\"tx_log\": [");
|
res->print("\"tx_log\": [");
|
||||||
|
|
||||||
logArray = airtimeReport(TX_LOG);
|
logArray = airtimeReport(TX_LOG);
|
||||||
for (int i = 0; i < getPeriodsToLog(); i++) {
|
for (int i = 0; i < getPeriodsToLog(); i++) {
|
||||||
uint16_t tmp;
|
uint32_t tmp;
|
||||||
tmp = *(logArray + i);
|
tmp = *(logArray + i);
|
||||||
res->printf("%d", tmp);
|
res->printf("%d", tmp);
|
||||||
if (i != getPeriodsToLog() - 1) {
|
if (i != getPeriodsToLog() - 1) {
|
||||||
|
@ -1111,7 +1129,7 @@ void handleReport(HTTPRequest *req, HTTPResponse *res)
|
||||||
|
|
||||||
logArray = airtimeReport(RX_LOG);
|
logArray = airtimeReport(RX_LOG);
|
||||||
for (int i = 0; i < getPeriodsToLog(); i++) {
|
for (int i = 0; i < getPeriodsToLog(); i++) {
|
||||||
uint16_t tmp;
|
uint32_t tmp;
|
||||||
tmp = *(logArray + i);
|
tmp = *(logArray + i);
|
||||||
res->printf("%d", tmp);
|
res->printf("%d", tmp);
|
||||||
if (i != getPeriodsToLog() - 1) {
|
if (i != getPeriodsToLog() - 1) {
|
||||||
|
@ -1124,7 +1142,7 @@ void handleReport(HTTPRequest *req, HTTPResponse *res)
|
||||||
|
|
||||||
logArray = airtimeReport(RX_ALL_LOG);
|
logArray = airtimeReport(RX_ALL_LOG);
|
||||||
for (int i = 0; i < getPeriodsToLog(); i++) {
|
for (int i = 0; i < getPeriodsToLog(); i++) {
|
||||||
uint16_t tmp;
|
uint32_t tmp;
|
||||||
tmp = *(logArray + i);
|
tmp = *(logArray + i);
|
||||||
res->printf("%d", tmp);
|
res->printf("%d", tmp);
|
||||||
if (i != getPeriodsToLog() - 1) {
|
if (i != getPeriodsToLog() - 1) {
|
||||||
|
@ -1151,7 +1169,14 @@ void handleReport(HTTPRequest *req, HTTPResponse *res)
|
||||||
|
|
||||||
res->println("},");
|
res->println("},");
|
||||||
|
|
||||||
res->println("\"test\": 123");
|
res->println("\"power\": {");
|
||||||
|
#define BoolToString(x) ((x)?"true":"false")
|
||||||
|
res->printf("\"battery_percent\": %u,\n", powerStatus->getBatteryChargePercent());
|
||||||
|
res->printf("\"battery_voltage_mv\": %u,\n", powerStatus->getBatteryVoltageMv());
|
||||||
|
res->printf("\"has_battery\": %s,\n", BoolToString(powerStatus->getHasBattery()));
|
||||||
|
res->printf("\"has_usb\": %s,\n", BoolToString(powerStatus->getHasUSB()));
|
||||||
|
res->printf("\"is_charging\": %s\n", BoolToString(powerStatus->getIsCharging()));
|
||||||
|
res->println("}");
|
||||||
|
|
||||||
res->println("},");
|
res->println("},");
|
||||||
|
|
||||||
|
@ -1209,14 +1234,3 @@ void handleFavicon(HTTPRequest *req, HTTPResponse *res)
|
||||||
// Write data from header file
|
// Write data from header file
|
||||||
res->write(FAVICON_DATA, FAVICON_LENGTH);
|
res->write(FAVICON_DATA, FAVICON_LENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
void replaceAll(std::string &str, const std::string &from, const std::string &to)
|
|
||||||
{
|
|
||||||
if (from.empty())
|
|
||||||
return;
|
|
||||||
size_t start_pos = 0;
|
|
||||||
while ((start_pos = str.find(from, start_pos)) != std::string::npos) {
|
|
||||||
str.replace(start_pos, from.length(), to);
|
|
||||||
start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "PhoneAPI.h"
|
||||||
|
#include "concurrency/OSThread.h"
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
void initWebServer();
|
||||||
|
void createSSLCert();
|
||||||
|
|
||||||
|
void handleNotFound();
|
||||||
|
|
||||||
|
void handleWebResponse();
|
||||||
|
|
||||||
|
|
||||||
|
//void handleHotspot();
|
||||||
|
|
||||||
|
//void handleStyleCSS();
|
||||||
|
//void handleRoot();
|
||||||
|
|
||||||
|
|
||||||
|
// Interface to the PhoneAPI to access the protobufs with messages
|
||||||
|
class HttpAPI : public PhoneAPI
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Nothing here yet
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Nothing here yet
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Nothing here yet
|
||||||
|
};
|
||||||
|
|
||||||
|
class WebServerThread : private concurrency::OSThread
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
WebServerThread();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual int32_t runOnce();
|
||||||
|
};
|
||||||
|
|
||||||
|
extern WebServerThread *webServerThread;
|
|
@ -1,9 +1,9 @@
|
||||||
#include "meshwifi.h"
|
#include "mesh/http/WiFiAPClient.h"
|
||||||
#include "NodeDB.h"
|
#include "NodeDB.h"
|
||||||
#include "mesh/wifi/WiFiServerAPI.h"
|
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "meshwifi/meshhttp.h"
|
#include "mesh/http/WebServer.h"
|
||||||
|
#include "mesh/wifi/WiFiServerAPI.h"
|
||||||
#include "target_specific.h"
|
#include "target_specific.h"
|
||||||
#include <DNSServer.h>
|
#include <DNSServer.h>
|
||||||
#include <ESPmDNS.h>
|
#include <ESPmDNS.h>
|
|
@ -1,38 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "PhoneAPI.h"
|
|
||||||
#include <Arduino.h>
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
void initWebServer();
|
|
||||||
void createSSLCert();
|
|
||||||
|
|
||||||
void handleNotFound();
|
|
||||||
|
|
||||||
void handleWebResponse();
|
|
||||||
|
|
||||||
void handleJSONChatHistory();
|
|
||||||
|
|
||||||
void notifyWebUI();
|
|
||||||
|
|
||||||
void handleHotspot();
|
|
||||||
|
|
||||||
void handleStyleCSS();
|
|
||||||
void handleRoot();
|
|
||||||
void handleScriptsScriptJS();
|
|
||||||
void handleJSONChatHistoryDummy();
|
|
||||||
|
|
||||||
void replaceAll(std::string& str, const std::string& from, const std::string& to);
|
|
||||||
|
|
||||||
class HttpAPI : public PhoneAPI
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
// Nothing here yet
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Nothing here yet
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// Nothing here yet
|
|
||||||
};
|
|
|
@ -7,13 +7,16 @@
|
||||||
#include "esp_bt.h"
|
#include "esp_bt.h"
|
||||||
#include "host/util/util.h"
|
#include "host/util/util.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "meshwifi/meshwifi.h"
|
|
||||||
#include "nimble/NimbleDefs.h"
|
#include "nimble/NimbleDefs.h"
|
||||||
#include "services/gap/ble_svc_gap.h"
|
#include "services/gap/ble_svc_gap.h"
|
||||||
#include "services/gatt/ble_svc_gatt.h"
|
#include "services/gatt/ble_svc_gatt.h"
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
|
|
||||||
|
#ifndef NO_ESP32
|
||||||
|
#include "mesh/http/WiFiAPClient.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
static bool pinShowing;
|
static bool pinShowing;
|
||||||
static uint32_t doublepressed;
|
static uint32_t doublepressed;
|
||||||
|
|
||||||
|
@ -545,7 +548,9 @@ void setBluetoothEnable(bool on)
|
||||||
if (firstTime) {
|
if (firstTime) {
|
||||||
firstTime = 0;
|
firstTime = 0;
|
||||||
} else {
|
} else {
|
||||||
initWifi(0);
|
#ifndef NO_ESP32
|
||||||
|
initWifi(0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
@ -557,7 +562,9 @@ void setBluetoothEnable(bool on)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// shutdown wifi
|
// shutdown wifi
|
||||||
|
#ifndef NO_ESP32
|
||||||
deinitWifi();
|
deinitWifi();
|
||||||
|
#endif
|
||||||
|
|
||||||
// We have to totally teardown our bluetooth objects to prevent leaks
|
// We have to totally teardown our bluetooth objects to prevent leaks
|
||||||
deinitBLE();
|
deinitBLE();
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
#include "meshwifi/meshhttp.h"
|
//#include "mesh/wifi/WebServer.h"
|
||||||
#include "meshwifi/meshwifi.h"
|
#include "configuration.h"
|
||||||
|
|
||||||
|
#ifndef NO_ESP32
|
||||||
|
|
||||||
|
//#include "mesh/wifi/WiFiAPClient.h"
|
||||||
|
|
||||||
void initWifi(bool forceSoftAP) {}
|
void initWifi(bool forceSoftAP) {}
|
||||||
|
|
||||||
|
@ -10,7 +14,4 @@ bool isWifiAvailable()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleWebResponse() {}
|
#endif
|
||||||
|
|
||||||
/// Perform idle loop processing required by the wifi layer
|
|
||||||
void loopWifi() {}
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "plugins/NodeInfoPlugin.h"
|
#include "plugins/NodeInfoPlugin.h"
|
||||||
#include "plugins/PositionPlugin.h"
|
#include "plugins/PositionPlugin.h"
|
||||||
#include "plugins/ReplyPlugin.h"
|
#include "plugins/ReplyPlugin.h"
|
||||||
|
#include "plugins/SerialPlugin.h"
|
||||||
#include "plugins/RemoteHardwarePlugin.h"
|
#include "plugins/RemoteHardwarePlugin.h"
|
||||||
#include "plugins/TextMessagePlugin.h"
|
#include "plugins/TextMessagePlugin.h"
|
||||||
|
|
||||||
|
@ -17,4 +18,5 @@ void setupPlugins() {
|
||||||
|
|
||||||
new RemoteHardwarePlugin();
|
new RemoteHardwarePlugin();
|
||||||
new ReplyPlugin();
|
new ReplyPlugin();
|
||||||
|
new SerialPlugin(); // Maintained by MC Hamster (Jm Casler) jm@casler.org
|
||||||
}
|
}
|
|
@ -0,0 +1,178 @@
|
||||||
|
#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):
|
||||||
|
* Add check for esp32 and only build code sections for esp32.
|
||||||
|
* 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".
|
||||||
|
* This will not work on the NRF or Linux target.
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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 0
|
||||||
|
#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()
|
||||||
|
{
|
||||||
|
#ifdef NO_ESP32
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
#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)
|
||||||
|
{
|
||||||
|
|
||||||
|
#ifdef NO_ESP32
|
||||||
|
|
||||||
|
#if SERIALPLUGIN_ENABLED == 1
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
DEBUG_MSG("Serial Plugin Disabled\n");
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return true; // Let others look at this message also if they want
|
||||||
|
}
|
|
@ -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;
|
Ładowanie…
Reference in New Issue