config parsing
This commit is contained in:
@ -1,18 +1,67 @@
|
||||
#include "configuration.h"
|
||||
#include "defines.h"
|
||||
#include "LoRaWan_APP.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <Wire.h>
|
||||
#include "HT_SSD1306Wire.h"
|
||||
|
||||
#include <WiFi.h>
|
||||
#include <WiFiClient.h>
|
||||
#include <WebServer.h>
|
||||
#include <WiFiAP.h>
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <iomanip>
|
||||
|
||||
|
||||
|
||||
|
||||
const uint32_t MAGIC = 0xaffe0001;
|
||||
|
||||
|
||||
config_t myConfig = {
|
||||
.magic = MAGIC,
|
||||
.appEui = { 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
.appKey = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
.modbus_poll_slots = {
|
||||
{ .typ = INPUT_REGISTERS, .id = 7, .address = 0x01 },
|
||||
{ .typ = INPUT_REGISTERS, .id = 7, .address = 0x02 },
|
||||
{ .typ = UNASSIGNED, .id = 0, .address = 0 },
|
||||
}
|
||||
};
|
||||
|
||||
uint8_t devEui[8];
|
||||
uint8_t appEui[8];
|
||||
uint8_t appKey[16];
|
||||
uint8_t nwkSKey[16];
|
||||
uint8_t appSKey[16];
|
||||
uint32_t devAddr;
|
||||
LoRaMacRegion_t loraWanRegion;
|
||||
bool overTheAirActivation;
|
||||
|
||||
|
||||
SSD1306Wire confDisplay(0x3c, 500000, SDA_OLED, SCL_OLED, GEOMETRY_128_64, RST_OLED);; // addr , freq , i2c group , resolution , rst
|
||||
WebServer server(80);
|
||||
|
||||
const char *ssid = "ModbusLoraConf";
|
||||
|
||||
#define TEST_PASSWORD
|
||||
#ifndef TEST_PASSWORD
|
||||
char password[12];
|
||||
#else
|
||||
const char *password = "test1234";
|
||||
#endif
|
||||
|
||||
extern uint8_t devEui[8];
|
||||
|
||||
bool configSaved = false;
|
||||
int configParsingFailed = 0;
|
||||
enum { PARSING_OK, PARSING_INVALID, PARSING_TOO_MANY, PARSING_TOO_FEW } configParsingError;
|
||||
|
||||
static void displayStatus(uint8_t numOfStations) {
|
||||
confDisplay.clear();
|
||||
@ -43,17 +92,142 @@ static void displayInit() {
|
||||
confDisplay.display();
|
||||
}
|
||||
|
||||
|
||||
static void handleRoot() {
|
||||
// bool configValid = (configBlock.magic == MAGIC);
|
||||
std::stringstream buffer;
|
||||
buffer << "<!doctype html"
|
||||
"<html lang=\"en\">"
|
||||
" <head>"
|
||||
" <title>Modbus LoRaWAN Gateway</title>"
|
||||
" </head>"
|
||||
" <body>"
|
||||
" <h1>Modbus LoRaWAN Gateway - Configuration Page</h1>";
|
||||
if (configSaved) {
|
||||
configSaved = false;
|
||||
buffer << "<h2>Configuration saved</h2>";
|
||||
}
|
||||
if (configParsingFailed) {
|
||||
configParsingFailed = 0;
|
||||
buffer << "<h2>Error when parsing field " << configParsingFailed << ", error " << configParsingError << "</h2>";
|
||||
}
|
||||
buffer << " <form action=\"config\" method=\"GET\">"
|
||||
" <table>"
|
||||
" <tr>"
|
||||
" <td>"
|
||||
" DevEui"
|
||||
" </td><td>";
|
||||
buffer << " <input type=\"text\" readonly name=\"DevEui\" id=\"DevEui\" size=\"23\" value=\"";
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (i != 0) {
|
||||
buffer << ":";
|
||||
}
|
||||
buffer << std::uppercase << std::setfill('0') << std::setw(2) << std::hex << (int)devEui[i];
|
||||
}
|
||||
buffer << "\"> (readonly)";
|
||||
buffer << " </td>"
|
||||
" </tr><tr>"
|
||||
" <td>"
|
||||
" AppEui"
|
||||
" </td><td>";
|
||||
buffer << " <input type=\"text\" name=\"AppEui\" id=\"AppEui\" size=\"23\" value=\"";
|
||||
for (int i = 0; i < 8; i++) {
|
||||
if (i != 0) {
|
||||
buffer << ":";
|
||||
}
|
||||
buffer << std::uppercase << std::setfill('0') << std::setw(2) << std::hex << (int)myConfig.appEui[i];
|
||||
}
|
||||
buffer << "\">";
|
||||
buffer << " </td>"
|
||||
" </tr><tr>"
|
||||
" <td>"
|
||||
" AppKey"
|
||||
" </td><td>";
|
||||
buffer << " <input type=\"text\" name=\"AppKey\" id=\"AppKey\" size=\"47\" value=\"";
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (i != 0) {
|
||||
buffer << ":";
|
||||
}
|
||||
buffer << std::uppercase << std::setfill('0') << std::setw(2) << std::hex << (int)myConfig.appKey[i];
|
||||
}
|
||||
buffer << "\">";
|
||||
buffer << " </td>"
|
||||
" </tr>"
|
||||
" <tr><td colspan=\"2\">"
|
||||
" <button type=\"submit\">Save</button>"
|
||||
" </td></tr>"
|
||||
" </table>"
|
||||
" </form>"
|
||||
" </body"
|
||||
"</html";
|
||||
|
||||
server.send(200, "text/html", buffer.str().c_str());
|
||||
}
|
||||
|
||||
static void parseField(char* arg, int fieldNum, int reqTokens, uint8_t *dest) {
|
||||
int i = 0;
|
||||
for (char *part = strtok(arg, ":"); part; part = strtok(NULL, ":")) {
|
||||
Serial.println(part);
|
||||
char *errPtr;
|
||||
long v = strtol(part, &errPtr, 16);
|
||||
if (errPtr && *errPtr) {
|
||||
Serial.printf("some error happened, %p %02x\n\r", errPtr, *errPtr);
|
||||
configParsingFailed = fieldNum;
|
||||
configParsingError = PARSING_INVALID;
|
||||
break;
|
||||
}
|
||||
if (i >= reqTokens) {
|
||||
Serial.println("too many tokens");
|
||||
configParsingFailed = fieldNum;
|
||||
configParsingError = PARSING_TOO_MANY;
|
||||
break;
|
||||
}
|
||||
dest[i] = v;
|
||||
i++;
|
||||
}
|
||||
if ((i != reqTokens) && (configParsingFailed == 0)) {
|
||||
Serial.println("too few tokens");
|
||||
configParsingFailed = fieldNum;
|
||||
configParsingError = PARSING_TOO_FEW;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void handleConfigSave() {
|
||||
char *arg1 = (char*)server.arg("AppEui").c_str();
|
||||
Serial.printf("AppEui: %s\n\r", arg1);
|
||||
parseField(arg1, 1, 8, myConfig.appEui);
|
||||
|
||||
if (!configParsingFailed) {
|
||||
char *arg2 = (char*)server.arg("AppKey").c_str();
|
||||
Serial.printf("AppKey: %s\n\r", arg2);
|
||||
parseField(arg2, 2, 16, myConfig.appKey);
|
||||
}
|
||||
|
||||
configSaved = !configParsingFailed;
|
||||
server.sendHeader("Location", String("/"), true);
|
||||
server.send(302, "text/plain", "");
|
||||
}
|
||||
|
||||
|
||||
void configurationSetup() {
|
||||
#ifndef TEST_PASSWORD
|
||||
memset(password, 0, sizeof(password));
|
||||
for (int i = 0; i < sizeof(password) - 1; i++) {
|
||||
password[i] = random(65, 90);
|
||||
}
|
||||
#endif
|
||||
|
||||
WiFi.softAP(ssid, password);
|
||||
IPAddress myIP = WiFi.softAPIP();
|
||||
|
||||
displayInit();
|
||||
displayStatus(0);
|
||||
|
||||
LoRaWAN.generateDeveuiByChipID();
|
||||
server.on("/", handleRoot);
|
||||
server.on("/config", handleConfigSave);
|
||||
server.begin();
|
||||
}
|
||||
|
||||
|
||||
@ -65,4 +239,14 @@ void configurationLoop() {
|
||||
numOfStations = currentNumOfStations;
|
||||
}
|
||||
|
||||
server.handleClient();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void configLoad() {
|
||||
memcpy(appEui, myConfig.appEui, sizeof(appEui));
|
||||
memcpy(appKey, myConfig.appKey, sizeof(appKey));
|
||||
loraWanRegion = LORAMAC_REGION_EU868;
|
||||
overTheAirActivation = true;
|
||||
}
|
Reference in New Issue
Block a user