Merge pull request #473 from mc-hamster/master

update dev-https from my fork
This commit is contained in:
Jm Casler 2020-10-11 21:20:50 -07:00 committed by GitHub
commit 9fdef366f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 212 additions and 102 deletions

View File

@ -1,3 +1,3 @@
export VERSION=1.1.3 export VERSION=1.1.4

View File

@ -60,14 +60,13 @@ debug_tool = jlink
lib_deps = lib_deps =
https://github.com/meshtastic/esp8266-oled-ssd1306.git ; ESP8266_SSD1306 https://github.com/meshtastic/esp8266-oled-ssd1306.git ; ESP8266_SSD1306
1260 ; OneButton library for non-blocking button debounce https://github.com/geeksville/OneButton.git ; OneButton library for non-blocking button debounce
1202 ; CRC32, explicitly needed because dependency is missing in the ble ota update lib 1202 ; CRC32, explicitly needed because dependency is missing in the ble ota update lib
https://github.com/meshtastic/arduino-fsm.git#2f106146071fc7bc620e1e8d4b88dc4e0266ce39 https://github.com/meshtastic/arduino-fsm.git#2f106146071fc7bc620e1e8d4b88dc4e0266ce39
https://github.com/meshtastic/SparkFun_Ublox_Arduino_Library.git#31015a55e630a2df77d9d714669c621a5bf355ad https://github.com/meshtastic/SparkFun_Ublox_Arduino_Library.git#31015a55e630a2df77d9d714669c621a5bf355ad
https://github.com/meshtastic/RadioLib.git#8657380241bce681c33aab46598bbf13b11f876c https://github.com/meshtastic/RadioLib.git#8657380241bce681c33aab46598bbf13b11f876c
https://github.com/meshtastic/TinyGPSPlus.git https://github.com/meshtastic/TinyGPSPlus.git
https://github.com/meshtastic/AXP202X_Library.git#8404abb6d4b486748636bc6ad72d2a47baaf5460 https://github.com/meshtastic/AXP202X_Library.git#8404abb6d4b486748636bc6ad72d2a47baaf5460
https://github.com/meshtastic/esp32_https_server.git
Wire ; explicitly needed here because the AXP202 library forgets to add it Wire ; explicitly needed here because the AXP202 library forgets to add it
SPI SPI
https://github.com/geeksville/ArduinoThread.git#333ffd09b596977c217ba25da4258f588b462ac6 https://github.com/geeksville/ArduinoThread.git#333ffd09b596977c217ba25da4258f588b462ac6
@ -96,6 +95,9 @@ build_flags =
${arduino_base.build_flags} -Wall -Wextra -Isrc/esp32 -Isrc/esp32-mfix-esp32-psram-cache-issue -lnimble -std=c++11 ${arduino_base.build_flags} -Wall -Wextra -Isrc/esp32 -Isrc/esp32-mfix-esp32-psram-cache-issue -lnimble -std=c++11
-DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
-DAXP_DEBUG_PORT=Serial -DAXP_DEBUG_PORT=Serial
lib_deps =
${arduino_base.lib_deps}
https://github.com/meshtastic/esp32_https_server.git
# Hmm - this doesn't work yet # Hmm - this doesn't work yet
# board_build.ldscript = linker/esp32.extram.bss.ld # board_build.ldscript = linker/esp32.extram.bss.ld
lib_ignore = segger_rtt lib_ignore = segger_rtt

View File

@ -138,38 +138,39 @@ int32_t Power::runOnce()
{ {
readPowerStatus(); readPowerStatus();
#ifdef PMU_IRQ #ifdef TBEAM_V10
if (pmu_irq) { // WE no longer use the IRQ line to wake the CPU (due to false wakes from sleep), but we do poll
pmu_irq = false; // the IRQ status by reading the registers over I2C
axp.readIRQ(); axp.readIRQ();
DEBUG_MSG("pmu irq!\n"); if (axp.isVbusRemoveIRQ()) {
DEBUG_MSG("USB unplugged\n");
if (axp.isChargingIRQ()) { powerFSM.trigger(EVENT_POWER_DISCONNECTED);
DEBUG_MSG("Battery start charging\n");
}
if (axp.isChargingDoneIRQ()) {
DEBUG_MSG("Battery fully charged\n");
}
if (axp.isVbusRemoveIRQ()) {
DEBUG_MSG("USB unplugged\n");
powerFSM.trigger(EVENT_POWER_DISCONNECTED);
}
if (axp.isVbusPlugInIRQ()) {
DEBUG_MSG("USB plugged In\n");
powerFSM.trigger(EVENT_POWER_CONNECTED);
}
if (axp.isBattPlugInIRQ()) {
DEBUG_MSG("Battery inserted\n");
}
if (axp.isBattRemoveIRQ()) {
DEBUG_MSG("Battery removed\n");
}
if (axp.isPEKShortPressIRQ()) {
DEBUG_MSG("PEK short button press\n");
}
axp.clearIRQ();
} }
if (axp.isVbusPlugInIRQ()) {
DEBUG_MSG("USB plugged In\n");
powerFSM.trigger(EVENT_POWER_CONNECTED);
}
/*
Other things we could check if we cared...
if (axp.isChargingIRQ()) {
DEBUG_MSG("Battery start charging\n");
}
if (axp.isChargingDoneIRQ()) {
DEBUG_MSG("Battery fully charged\n");
}
if (axp.isBattPlugInIRQ()) {
DEBUG_MSG("Battery inserted\n");
}
if (axp.isBattRemoveIRQ()) {
DEBUG_MSG("Battery removed\n");
}
if (axp.isPEKShortPressIRQ()) {
DEBUG_MSG("PEK short button press\n");
}
*/
axp.clearIRQ();
#endif #endif
// Only read once every 20 seconds once the power status for the app has been initialized // Only read once every 20 seconds once the power status for the app has been initialized

View File

@ -118,13 +118,21 @@ static void serialEnter()
{ {
setBluetoothEnable(false); setBluetoothEnable(false);
screen->setOn(true); screen->setOn(true);
screen->print("Using API...\n");
} }
static void powerEnter() static void powerEnter()
{ {
screen->setOn(true); screen->setOn(true);
setBluetoothEnable(true); setBluetoothEnable(true);
setCPUFast(true); // Set CPU to 240mhz when we're plugged in to wall power. screen->print("Powered...\n");
}
static void powerExit()
{
screen->setOn(true);
setBluetoothEnable(true);
screen->print("Unpowered...\n");
} }
static void onEnter() static void onEnter()
@ -158,8 +166,7 @@ State stateDARK(darkEnter, NULL, NULL, "DARK");
State stateSERIAL(serialEnter, NULL, NULL, "SERIAL"); State stateSERIAL(serialEnter, NULL, NULL, "SERIAL");
State stateBOOT(bootEnter, NULL, NULL, "BOOT"); State stateBOOT(bootEnter, NULL, NULL, "BOOT");
State stateON(onEnter, NULL, NULL, "ON"); State stateON(onEnter, NULL, NULL, "ON");
State statePOWER(powerEnter, NULL, NULL, "POWER"); State statePOWER(powerEnter, NULL, powerExit, "POWER");
Fsm powerFSM(&stateBOOT); Fsm powerFSM(&stateBOOT);
void PowerFSM_setup() void PowerFSM_setup()

View File

@ -20,6 +20,6 @@
#define EVENT_POWER_DISCONNECTED 14 #define EVENT_POWER_DISCONNECTED 14
extern Fsm powerFSM; extern Fsm powerFSM;
extern State statePOWER; extern State statePOWER, stateSERIAL;
void PowerFSM_setup(); void PowerFSM_setup();

View File

@ -4,30 +4,22 @@
namespace concurrency namespace concurrency
{ {
InterruptableDelay::InterruptableDelay() InterruptableDelay::InterruptableDelay() {}
{
}
InterruptableDelay::~InterruptableDelay() InterruptableDelay::~InterruptableDelay() {}
{
}
/** /**
* Returns false if we were interrupted * Returns false if we were interrupted
*/ */
bool InterruptableDelay::delay(uint32_t msec) bool InterruptableDelay::delay(uint32_t msec)
{ {
if (msec) { // DEBUG_MSG("delay %u ", msec);
// DEBUG_MSG("delay %u ", msec);
// sem take will return false if we timed out (i.e. were not interrupted) // sem take will return false if we timed out (i.e. were not interrupted)
bool r = semaphore.take(msec); bool r = semaphore.take(msec);
// DEBUG_MSG("interrupt=%d\n", r); // DEBUG_MSG("interrupt=%d\n", r);
return !r; return !r;
} else {
return true;
}
} }
void InterruptableDelay::interrupt() void InterruptableDelay::interrupt()

View File

@ -202,7 +202,7 @@ class Screen : public concurrency::OSThread
return true; // claim success if our display is not in use return true; // claim success if our display is not in use
else { else {
bool success = cmdQueue.enqueue(cmd, 0); bool success = cmdQueue.enqueue(cmd, 0);
setInterval(0); // handle ASAP enabled = true; // handle ASAP (we are the registered reader for cmdQueue, but might have been disabled)
return success; return success;
} }
} }

View File

@ -128,31 +128,13 @@ class PowerFSMThread : public OSThread
/// If we are in power state we force the CPU to wake every 10ms to check for serial characters (we don't yet wake /// If we are in power state we force the CPU to wake every 10ms to check for serial characters (we don't yet wake
/// cpu for serial rx - FIXME) /// cpu for serial rx - FIXME)
canSleep = (powerFSM.getState() != &statePOWER); auto state = powerFSM.getState();
canSleep = (state != &statePOWER) && (state != &stateSERIAL);
return 10; return 10;
} }
}; };
static Periodic *ledPeriodic;
static OSThread *powerFSMthread;
// Prepare for button presses
#ifdef BUTTON_PIN
OneButton userButton;
#endif
#ifdef BUTTON_PIN_ALT
OneButton userButtonAlt;
#endif
void userButtonPressed()
{
powerFSM.trigger(EVENT_PRESS);
}
void userButtonPressedLong()
{
screen->adjustBrightness();
}
/** /**
* Watch a GPIO and if we get an IRQ, wake the main thread. * Watch a GPIO and if we get an IRQ, wake the main thread.
* Use to add wake on button press * Use to add wake on button press
@ -168,6 +150,65 @@ void wakeOnIrq(int irq, int mode)
FALLING); FALLING);
} }
class ButtonThread : public OSThread
{
// Prepare for button presses
#ifdef BUTTON_PIN
OneButton userButton;
#endif
#ifdef BUTTON_PIN_ALT
OneButton userButtonAlt;
#endif
public:
// callback returns the period for the next callback invocation (or 0 if we should no longer be called)
ButtonThread() : OSThread("Button")
{
#ifdef BUTTON_PIN
userButton = OneButton(BUTTON_PIN, true, true);
userButton.attachClick(userButtonPressed);
userButton.attachDuringLongPress(userButtonPressedLong);
wakeOnIrq(BUTTON_PIN, FALLING);
#endif
#ifdef BUTTON_PIN_ALT
userButtonAlt = OneButton(BUTTON_PIN_ALT, true, true);
userButtonAlt.attachClick(userButtonPressed);
userButton.attachDuringLongPress(userButtonPressedLong);
wakeOnIrq(BUTTON_PIN_ALT, FALLING);
#endif
}
protected:
/// If the button is pressed we suppress CPU sleep until release
int32_t runOnce()
{
canSleep = true; // Assume we should not keep the board awake
#ifdef BUTTON_PIN
userButton.tick();
canSleep &= userButton.isIdle();
#endif
#ifdef BUTTON_PIN_ALT
userButtonAlt.tick();
canSleep &= userButton.isIdle();
#endif
// if(!canSleep) DEBUG_MSG("Supressing sleep!\n");
return 5;
}
private:
static void userButtonPressed()
{
// DEBUG_MSG("press!\n");
powerFSM.trigger(EVENT_PRESS);
}
static void userButtonPressedLong() { screen->adjustBrightness(); }
};
static Periodic *ledPeriodic;
static OSThread *powerFSMthread, *buttonThread;
RadioInterface *rIf = NULL; RadioInterface *rIf = NULL;
void setup() void setup()
@ -210,18 +251,7 @@ void setup()
#endif #endif
// Buttons & LED // Buttons & LED
#ifdef BUTTON_PIN buttonThread = new ButtonThread();
userButton = OneButton(BUTTON_PIN, true, true);
userButton.attachClick(userButtonPressed);
userButton.attachDuringLongPress(userButtonPressedLong);
wakeOnIrq(BUTTON_PIN, FALLING);
#endif
#ifdef BUTTON_PIN_ALT
userButtonAlt = OneButton(BUTTON_PIN_ALT, true, true);
userButtonAlt.attachClick(userButtonPressed);
userButton.attachDuringLongPress(userButtonPressedLong);
wakeOnIrq(BUTTON_PIN_ALT, FALLING);
#endif
#ifdef LED_PIN #ifdef LED_PIN
pinMode(LED_PIN, OUTPUT); pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, 1 ^ LED_INVERTED); // turn on for now digitalWrite(LED_PIN, 1 ^ LED_INVERTED); // turn on for now
@ -411,13 +441,6 @@ void loop()
esp32Loop(); esp32Loop();
#endif #endif
#ifdef BUTTON_PIN
userButton.tick();
#endif
#ifdef BUTTON_PIN_ALT
userButtonAlt.tick();
#endif
// For debugging // For debugging
// if (rIf) ((RadioLibInterface *)rIf)->isActivelyReceiving(); // if (rIf) ((RadioLibInterface *)rIf)->isActivelyReceiving();
@ -438,9 +461,9 @@ void loop()
/* if (mainController.nextThread && delayMsec) /* if (mainController.nextThread && delayMsec)
DEBUG_MSG("Next %s in %ld\n", mainController.nextThread->ThreadName.c_str(), DEBUG_MSG("Next %s in %ld\n", mainController.nextThread->ThreadName.c_str(),
mainController.nextThread->tillRun(millis())); mainController.nextThread->tillRun(millis())); */
*/
// 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");
} }

View File

@ -3,6 +3,7 @@
#include "configuration.h" #include "configuration.h"
#include "main.h" #include "main.h"
#include "meshwifi/meshwifi.h" #include "meshwifi/meshwifi.h"
#include "sleep.h"
#include <WebServer.h> #include <WebServer.h>
#include <WiFi.h> #include <WiFi.h>
@ -30,6 +31,8 @@ Preferences prefs;
#include <HTTPServer.hpp> #include <HTTPServer.hpp>
#include <SSLCert.hpp> #include <SSLCert.hpp>
#define HEADER_LEN 4
// The HTTPS Server comes in a separate namespace. For easier use, include it here. // The HTTPS Server comes in a separate namespace. For easier use, include it here.
using namespace httpsserver; using namespace httpsserver;
@ -37,16 +40,25 @@ SSLCert *cert;
HTTPSServer *secureServer; HTTPSServer *secureServer;
HTTPServer *insecureServer; HTTPServer *insecureServer;
// Our API to handle messages to and from the radio.
httpAPI webAPI;
// Declare some handler functions for the various URLs on the server // Declare some handler functions for the various URLs on the server
void handleAPIv1FromRadio(HTTPRequest *req, HTTPResponse *res);
void handleAPIv1ToRadio(HTTPRequest *req, HTTPResponse *res);
void handleStyleCSS(HTTPRequest *req, HTTPResponse *res); void handleStyleCSS(HTTPRequest *req, HTTPResponse *res);
void handleJSONChatHistoryDummy(HTTPRequest *req, HTTPResponse *res); void handleJSONChatHistoryDummy(HTTPRequest *req, HTTPResponse *res);
void handleHotspot(HTTPRequest *req, HTTPResponse *res); void handleHotspot(HTTPRequest *req, HTTPResponse *res);
void handleRoot(HTTPRequest *req, HTTPResponse *res); void handleRoot(HTTPRequest *req, HTTPResponse *res);
void handle404(HTTPRequest *req, HTTPResponse *res); void handle404(HTTPRequest *req, HTTPResponse *res);
void middlewareLogging(HTTPRequest *req, HTTPResponse *res, std::function<void()> next);
bool isWebServerReady = 0; bool isWebServerReady = 0;
bool isCertReady = 0; bool isCertReady = 0;
uint32_t timeSpeedUp = 0;
void handleWebResponse() void handleWebResponse()
{ {
if (isWifiAvailable() == 0) { if (isWifiAvailable() == 0) {
@ -61,6 +73,14 @@ void handleWebResponse()
secureServer->loop(); secureServer->loop();
insecureServer->loop(); insecureServer->loop();
} }
// Slow down the CPU if we have not received a request within the last
// 2 minutes.
if (millis () - timeSpeedUp >= (2 * 60 * 1000)) {
setCPUFast(false); // Set CPU to 80mhz
timeSpeedUp = millis();
}
} }
void taskCreateCert(void *parameter) void taskCreateCert(void *parameter)
@ -87,10 +107,10 @@ void taskCreateCert(void *parameter)
DEBUG_MSG("Creating the certificate. This may take a while. Please wait...\n"); DEBUG_MSG("Creating the certificate. This may take a while. Please wait...\n");
cert = new SSLCert(); cert = new SSLCert();
//disableCore1WDT(); // disableCore1WDT();
int createCertResult = createSelfSignedCert(*cert, KEYSIZE_2048, "CN=meshtastic.local,O=Meshtastic,C=US", int createCertResult = createSelfSignedCert(*cert, KEYSIZE_2048, "CN=meshtastic.local,O=Meshtastic,C=US",
"20190101000000", "20300101000000"); "20190101000000", "20300101000000");
//enableCore1WDT(); // enableCore1WDT();
if (createCertResult != 0) { if (createCertResult != 0) {
DEBUG_MSG("Creating the certificate failed\n"); DEBUG_MSG("Creating the certificate failed\n");
@ -188,6 +208,8 @@ void initWebServer()
// For every resource available on the server, we need to create a ResourceNode // For every resource available on the server, we need to create a ResourceNode
// The ResourceNode links URL and HTTP method to a handler function // The ResourceNode links URL and HTTP method to a handler function
ResourceNode *nodeAPIv1ToRadio = new ResourceNode("/api/v1/toradio", "GET", &handleAPIv1ToRadio);
ResourceNode *nodeAPIv1FromRadio = new ResourceNode("/api/v1/fromradio", "GET", &handleAPIv1FromRadio);
ResourceNode *nodeCSS = new ResourceNode("/css/style.css", "GET", &handleStyleCSS); ResourceNode *nodeCSS = new ResourceNode("/css/style.css", "GET", &handleStyleCSS);
ResourceNode *nodeJS = new ResourceNode("/scripts/script.js", "GET", &handleJSONChatHistoryDummy); ResourceNode *nodeJS = new ResourceNode("/scripts/script.js", "GET", &handleJSONChatHistoryDummy);
ResourceNode *nodeHotspot = new ResourceNode("/hotspot-detect.html", "GET", &handleHotspot); ResourceNode *nodeHotspot = new ResourceNode("/hotspot-detect.html", "GET", &handleHotspot);
@ -195,13 +217,19 @@ void initWebServer()
ResourceNode *node404 = new ResourceNode("", "GET", &handle404); ResourceNode *node404 = new ResourceNode("", "GET", &handle404);
// Secure nodes // Secure nodes
secureServer->registerNode(nodeAPIv1ToRadio);
secureServer->registerNode(nodeAPIv1FromRadio);
secureServer->registerNode(nodeCSS); secureServer->registerNode(nodeCSS);
secureServer->registerNode(nodeJS); secureServer->registerNode(nodeJS);
secureServer->registerNode(nodeHotspot); secureServer->registerNode(nodeHotspot);
secureServer->registerNode(nodeRoot); secureServer->registerNode(nodeRoot);
secureServer->setDefaultNode(node404); secureServer->setDefaultNode(node404);
secureServer->addMiddleware(&middlewareLogging);
// Insecure nodes // Insecure nodes
insecureServer->registerNode(nodeAPIv1ToRadio);
insecureServer->registerNode(nodeAPIv1FromRadio);
insecureServer->registerNode(nodeCSS); insecureServer->registerNode(nodeCSS);
insecureServer->registerNode(nodeJS); insecureServer->registerNode(nodeJS);
insecureServer->registerNode(nodeHotspot); insecureServer->registerNode(nodeHotspot);
@ -217,6 +245,16 @@ void initWebServer()
} }
} }
void middlewareLogging(HTTPRequest *req, HTTPResponse *res, std::function<void()> next)
{
// We want to print the response status, so we need to call next() first.
next();
setCPUFast(true); // Set CPU to 240mhz when we're plugged in to wall power.
timeSpeedUp = millis();
}
void handle404(HTTPRequest *req, HTTPResponse *res) void handle404(HTTPRequest *req, HTTPResponse *res)
{ {
@ -261,6 +299,40 @@ void handleHotspot(HTTPRequest *req, HTTPResponse *res)
res->println("<meta http-equiv=\"refresh\" content=\"0;url=http://meshtastic.org/\" />\n"); res->println("<meta http-equiv=\"refresh\" content=\"0;url=http://meshtastic.org/\" />\n");
} }
void handleAPIv1FromRadio(HTTPRequest *req, HTTPResponse *res)
{
DEBUG_MSG("+++++++++++++++ webAPI handleAPIv1FromRadio\n");
/*
http://10.10.30.198/api/v1/fromradio
*/
// Status code is 200 OK by default.
// We want to deliver a simple HTML page, so we send a corresponding content type:
res->setHeader("Content-Type", "application/x-protobuf");
uint8_t txBuf[MAX_STREAM_BUF_SIZE];
uint32_t len = webAPI.getFromRadio(txBuf + HEADER_LEN);
res->write(txBuf, len);
DEBUG_MSG("--------------- webAPI handleAPIv1FromRadio, len %d\n", len);
}
void handleAPIv1ToRadio(HTTPRequest *req, HTTPResponse *res)
{
DEBUG_MSG("webAPI handleAPIv1ToRadio\n");
// Status code is 200 OK by default.
// We want to deliver a simple HTML page, so we send a corresponding content type:
res->setHeader("Content-Type", "application/x-protobuf");
// The response implements the Print interface, so you can use it just like
// you would write to Serial etc.
res->print("<!DOCTYPE html>");
}
/* /*
To convert text to c strings: To convert text to c strings:

View File

@ -2,11 +2,11 @@
#include <Arduino.h> #include <Arduino.h>
#include <functional> #include <functional>
#include "PhoneAPI.h"
void initWebServer(); void initWebServer();
void createSSLCert(); void createSSLCert();
void handleNotFound(); void handleNotFound();
void handleWebResponse(); void handleWebResponse();
@ -17,8 +17,21 @@ void notifyWebUI();
void handleHotspot(); void handleHotspot();
void handleStyleCSS(); void handleStyleCSS();
void handleRoot(); void handleRoot();
void handleScriptsScriptJS(); void handleScriptsScriptJS();
void handleJSONChatHistoryDummy(); void handleJSONChatHistoryDummy();
class httpAPI : public PhoneAPI
{
public:
// Nothing here yet
private:
// Nothing here yet
protected:
// Nothing here yet
};

View File

@ -17,7 +17,7 @@ static WiFiServerPort *apiPort;
uint8_t wifiDisconnectReason = 0; uint8_t wifiDisconnectReason = 0;
// Stores the last 4 of our hardware ID, to make finding the device for pairing easier // Stores our hostname
static char ourHost[16]; static char ourHost[16];
bool isWifiAvailable() bool isWifiAvailable()