Fixed #19: Implement exception handler

This commit is contained in:
Mark van Renswoude 2018-02-13 21:52:24 +01:00
parent 7b823b7cff
commit 7010e83554
11 changed files with 1227 additions and 1108 deletions

35
API.md
View File

@ -1,6 +1,6 @@
# API
- [GET /api/apply](#get-apiapply)
- [GET /api/set](#get-apiset)
- [GET /api/status](#get-apistatus)
- [GET /api/connection/status](#get-apiconnectionstatus)
- [GET /api/connection](#get-apiconnection)
@ -14,6 +14,13 @@
- [GET /api/triggers/motion](#get-apitriggersmotion)
- [POST /api/triggers/motion](#post-apitriggersmotion)
- [POST /api/firmware](#post-apifirmware)
- [GET /api/stacktrace/get](#get-apistacktraceget)
- [GET /api/stacktrace/delete](#get-apistacktracedelete)
#### Debug API
- [GET /api/crash/exception](#get-apicrashexception)
- [GET /api/crash/softwdt](#get-apicrashsoftwdt)
- [GET /api/crash/wdt](#get-apicrashwdt)
## GET /api/set
@ -290,4 +297,28 @@ If the "triggers" array is omitted entirely, the items will not be cleared or ov
## POST /api/firmware
Uploads new firmware. The bin file should be posted as a multipart/form-data file attachment. Name is not relevant.
Uploads new firmware. The bin file should be posted as a multipart/form-data file attachment. Name is not relevant.
## GET /api/stacktrace/get
If an exception occurs and the stack trace was recorded before the device reset, this will return the stack trace as a file named "stacktrace.txt".
## GET /api/stacktrace/delete
Removes any recorded stack trace.
# Debug API
These APIs are hopefully never enabled unless you've changed the config.h for the purpose of testing the exception handler. Don't forget to turn it back off afterwards.
## GET /api/crash/exception
Causes a crash due to an unhandled exception. Should provide a stack trace afterwards.
## GET /api/crash/softwdt
Causes the software watchdog to reset.
## GET /api/crash/wdt
Disables the software watchdog and causes the hardware watchdog.

View File

@ -19,4 +19,5 @@ lib_deps =
NTPClient
Time
Dusk2Dawn
EspSaveCrash
build_flags = !platformio-buildflags.bat

File diff suppressed because it is too large Load Diff

View File

@ -4,10 +4,10 @@
const uint8_t VersionMajor = 2;
const uint8_t VersionMinor = 0;
const uint8_t VersionPatch = 0;
const uint8_t VersionMetadata = 41;
const uint8_t VersionMetadata = 42;
const char VersionBranch[] = "release/2.0";
const char VersionSemVer[] = "2.0.0-beta.1";
const char VersionFullSemVer[] = "2.0.0-beta.1+41";
const char VersionFullSemVer[] = "2.0.0-beta.1+42";
const char VersionCommitDate[] = "2018-02-13";
#endif

View File

@ -4,7 +4,14 @@
#include <stdint.h>
#define SerialDebug
// Enables debug information to be output through the standard
// Serial connection, disable in production units to improve performance
//#define SerialDebug
// Enables the crash API methods to cause crashes, you probably never
// want to leave this on unless you're debugging the exception handler
//#define EnableCrashAPI
#ifdef SerialDebug
static const uint32_t SerialDebugBaudrate = 115200;

View File

@ -6,12 +6,12 @@
*/
#include <Arduino.h>
#include <ESP8266WiFi.h>
//#include <ESPAsyncTCP.h>
#include <WiFiUDP.h>
#include <ESPAsyncWebServer.h>
#include <ESPAsyncTCP.h>
#include <TimeLib.h>
#include <ArduinoJson.h>
#include <EspSaveCrash.h>
extern "C" {
#include <user_interface.h>

View File

@ -8,12 +8,18 @@
#include <ArduinoJson.h>
#include <IPAddress.h>
#include <ESP8266WiFi.h>
#include <EspSaveCrash.h>
#include "./shared.h"
#include "../assets/version.h"
#include "../config.h"
#include "../debug.h"
#include "../global.h"
#include "../settings/connection.h"
extern "C" {
#include <user_interface.h>
}
void handleStatus(AsyncWebServerRequest *request)
{
@ -36,8 +42,8 @@ void handleStatus(AsyncWebServerRequest *request)
root["timeOffset"] = 0;
}
root["resetReason"] = ESP.getResetReason();
root["stackTrace"] = false; // TODO implement as part of #19
root["resetReason"] = ESP.getResetInfoPtr()->reason;
root["stackTrace"] = SaveCrash.count() > 0;
AsyncResponseStream *response = request->beginResponseStream("application/json");
root.printTo(*response);
@ -159,6 +165,60 @@ void handlePostSteps(AsyncWebServerRequest *request, uint8_t *data, size_t len,
}
void handleGetStackTrace(AsyncWebServerRequest *request)
{
_dln("API :: get stack trace");
if (SaveCrash.count() == 0)
{
request->send(404);
return;
}
AsyncResponseStream *response = request->beginResponseStream("application/octet-stream");
response->addHeader("Content-Disposition", "attachment; filename=\"stacktrace.txt\"");
SaveCrash.print(*response);
request->send(response);
}
void handleDeleteStackTrace(AsyncWebServerRequest *request)
{
_dln("API :: delete stack trace");
SaveCrash.clear();
request->send(200);
}
#ifdef EnableCrashAPI
#pragma "!!! Crash API is enabled on this build !!!"
void handleCrashException(AsyncWebServerRequest *request)
{
_dln("API :: crash exception");
int* i = nullptr;
*i = 42;
}
void handleCrashSoftWDT(AsyncWebServerRequest *request)
{
_dln("API :: crash soft WDT");
while (true);
}
void handleCrashWDT(AsyncWebServerRequest *request)
{
_dln("API :: crash WDT");
ESP.wdtDisable();
while (true);
}
#endif
void registerSettingsRoutes(AsyncWebServer* server)
{
server->on("/api/status", HTTP_GET, handleStatus);
@ -173,4 +233,13 @@ void registerSettingsRoutes(AsyncWebServer* server)
server->on("/api/steps", HTTP_GET, handleGetSteps);
server->on("/api/steps", HTTP_POST, devNullRequest, devNullFileUpload, handlePostSteps);
server->on("/api/stacktrace/get", HTTP_GET, handleGetStackTrace);
server->on("/api/stacktrace/delete", HTTP_GET, handleDeleteStackTrace);
#ifdef EnableCrashAPI
server->on("/api/crash/exception", HTTP_GET, handleCrashException);
server->on("/api/crash/softwdt", HTTP_GET, handleCrashSoftWDT);
server->on("/api/crash/wdt", HTTP_GET, handleCrashWDT);
#endif
}

View File

@ -33,6 +33,7 @@ void AbstractJsonSettings::read()
std::unique_ptr<char[]> buf(new char[size]);
settingsFile.readBytes(buf.get(), size);
settingsFile.close();
_dln(buf.get());
@ -60,6 +61,7 @@ void AbstractJsonSettings::write()
}
toJson(settingsFile);
settingsFile.close();
_d(getDebugPrefix()); _dln(" :: written to file");
}

View File

@ -823,7 +823,7 @@ function startApp()
brightness: 0,
enabled: true,
pin: 2,
direction: 0
direction: 1
});
},
@ -959,10 +959,13 @@ function startApp()
{
var self = this;
// TODO call /api/stacktrace/delete
self.status.resetReason = 0;
self.status.stackTrace = false;
return axios.get('/api/stacktrace/delete')
.then(function(response)
{
self.status.resetReason = 0;
self.status.stackTrace = false;
})
.catch(self.handleAPIError.bind(self, 'error.stackTraceDeleteError'));
}
},

2
web/dist/bundle.js vendored

File diff suppressed because one or more lines are too long

View File

@ -163,7 +163,9 @@ var messages = {
},
stackTrace: 'A stack trace is available. Please send it to your nearest developer and/or delete it from this Stairs device to remove this message.',
stackTraceDownload: 'Download',
stackTraceDelete: 'Remove'
stackTraceDelete: 'Remove',
stackTraceDeleteError: 'Could not remove stack trace'
},
calibration: {
@ -342,7 +344,9 @@ var messages = {
},
stackTrace: 'Een stack trace is beschikbaar. Stuur het naar de dichtsbijzijnde ontwikkelaar en/of verwijder het van deze Trap module om dit bericht te verbergen.',
stackTraceDownload: 'Downloaden',
stackTraceDelete: 'Verwijderen'
stackTraceDelete: 'Verwijderen',
stackTraceDeleteError: 'Kan stack trace niet verwijderen'
},
calibration: {