Change analogWrite to ledcWrite, configuration improvements
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
#include <Preferences.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include <variant>
|
||||
@@ -45,8 +44,8 @@ static const ConfigDef configdefs[] = {
|
||||
{"apMask", ConfigType::STRING, String("255.255.255.0")},
|
||||
{"stopApTime", ConfigType::SHORT, int16_t(0)},
|
||||
{"cpuSpeed", ConfigType::SHORT, int16_t(160)},
|
||||
{"ledBrightness", ConfigType::BYTE, uint8_t(96)},
|
||||
{"ledRgbBrightness", ConfigType::BYTE, uint8_t(96)},
|
||||
{"ledBrightness", ConfigType::SHORT, int16_t(96)},
|
||||
{"ledRgbBrightness", ConfigType::SHORT, int16_t(96)},
|
||||
{"tempFormat", ConfigType::CHAR, 'C'},
|
||||
{"switchBank", ConfigType::BYTE, uint8_t(0)},
|
||||
{"key1", ConfigType::BYTE, uint8_t(1)},
|
||||
@@ -76,6 +75,7 @@ private:
|
||||
Preferences& prefs;
|
||||
std::map<String, ConfigValue> values;
|
||||
std::map<String, const ConfigDef*> defs;
|
||||
[[noreturn]] void error_abort() const;
|
||||
public:
|
||||
explicit Config(Preferences& prefs);
|
||||
void load();
|
||||
@@ -92,4 +92,8 @@ public:
|
||||
float getFloat(const char* key) const;
|
||||
char getChar(const char* key) const;
|
||||
const String& getString(const char* key) const;
|
||||
const char* getCString(const char* key) const;
|
||||
|
||||
};
|
||||
|
||||
extern Config config;
|
||||
|
||||
4
include/hash.h
Normal file
4
include/hash.h
Normal file
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
#include <Arduino.h>
|
||||
|
||||
String get_sha256(String payload);
|
||||
8
include/led.h
Normal file
8
include/led.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
extern int16_t led_brightness;
|
||||
extern int16_t rgb_brightness;
|
||||
|
||||
void led_init();
|
||||
void led_test();
|
||||
void led_blink(uint8_t channel, uint8_t count, int16_t brightness, uint32_t interval_ms);
|
||||
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
#include <Arduino.h>
|
||||
#include "Nmea2kTwai.h"
|
||||
#include "N2kDeviceList.h"
|
||||
|
||||
#define STRINGIFY_IMPL(x) #x
|
||||
#define STRINGIFY(x) STRINGIFY_IMPL(x)
|
||||
@@ -40,11 +42,23 @@
|
||||
#define KEY_6 GPIO_NUM_10 // D7
|
||||
#define KEY_DST GPIO_NUM_17 // D8
|
||||
|
||||
// LEDC / PWM channels
|
||||
#define LEDC_BUZZER 0
|
||||
#define LEDC_LED_A 1
|
||||
#define LEDC_LED_B 2
|
||||
#define LEDC_LED_C 3
|
||||
#define LEDC_RGBLED_R 4
|
||||
#define LEDC_RGBLED_G 5
|
||||
#define LEDC_RGBLED_B 6
|
||||
|
||||
#define LEDC_BASE_FREQ 5000
|
||||
#define LEDC_RES_BUZZER 8 // 8bit: 0..255
|
||||
#define LEDC_RES_LED 12 // 12bit: 0..4095
|
||||
|
||||
// #define LEDC_TIMER_8_BIT 8
|
||||
|
||||
// Buzzer
|
||||
#define BUZZER GPIO_NUM_43 // TX
|
||||
#define LEDC_CHANNEL 0
|
||||
#define LEDC_TIMER_8_BIT 8
|
||||
#define LEDC_BASE_FREQ 5000
|
||||
|
||||
// LEDS
|
||||
#define LED_A GPIO_NUM_3 // A2
|
||||
@@ -99,13 +113,17 @@ struct ButtonEvent {
|
||||
ButtonPressType pressType;
|
||||
};
|
||||
|
||||
extern Nmea2kTwai &NMEA2000;
|
||||
extern tN2kDeviceList *pN2kDeviceList;
|
||||
|
||||
extern char globalmode;
|
||||
|
||||
extern uint64_t chipid;
|
||||
extern uint8_t led_brightness;
|
||||
extern uint8_t rgb_brightness;
|
||||
extern int16_t led_brightness;
|
||||
extern int16_t rgb_brightness;
|
||||
extern uint8_t keycode[6];
|
||||
extern uint8_t longcode[6];
|
||||
|
||||
extern float temp;
|
||||
extern float hum;
|
||||
|
||||
String uptime_with_unit();
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include <ESPAsyncWebServer.h>
|
||||
|
||||
extern AsyncWebServer server;
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
#include "config.h"
|
||||
#include "esp_rom_uart.h" // for uart wait idle
|
||||
|
||||
// Logging
|
||||
static const char* TAG = "CFG";
|
||||
|
||||
Preferences preferences; // persistent storage for configuration
|
||||
Config config(preferences); // configuration object
|
||||
|
||||
Config::Config(Preferences& prefs)
|
||||
: prefs(prefs) {
|
||||
|
||||
@@ -13,12 +17,19 @@ Config::Config(Preferences& prefs)
|
||||
|
||||
}
|
||||
|
||||
[[noreturn]] void Config::error_abort() const {
|
||||
ESP_LOGD(TAG, "Rebooting in about 2 seconds");
|
||||
esp_rom_uart_tx_wait_idle(0);
|
||||
delay(2000); // to have a chance to read
|
||||
abort();
|
||||
}
|
||||
|
||||
void Config::load() {
|
||||
ESP_LOGI(TAG, "Loading configuration");
|
||||
ESP_LOGD(TAG, "Loading configuration");
|
||||
prefs.begin(PREF_NAME, true);
|
||||
for (const auto& def : configdefs) {
|
||||
if (prefs.isKey(def.key)) {
|
||||
ESP_LOGI(TAG, "Config option '%s' loaded from NVS", def.key);
|
||||
ESP_LOGD(TAG, "Config option '%s' loaded from NVS", def.key);
|
||||
switch (def.type) {
|
||||
case ConfigType::BYTE:
|
||||
values[def.key] = (uint8_t)prefs.getUChar(def.key, std::get<uint8_t>(def.defval));
|
||||
@@ -43,7 +54,7 @@ void Config::load() {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Using default for '%s'", def.key);
|
||||
ESP_LOGD(TAG, "Using default for '%s'", def.key);
|
||||
switch (def.type) {
|
||||
case ConfigType::BYTE:
|
||||
values[def.key] = std::get<uint8_t>(def.defval);
|
||||
@@ -204,36 +215,36 @@ uint8_t Config::getByte(const char* key) const {
|
||||
auto it = values.find(key);
|
||||
if (it == values.end()) {
|
||||
ESP_LOGE(TAG, "Missing config key: %s", key);
|
||||
abort();
|
||||
error_abort();
|
||||
}
|
||||
if (auto v = std::get_if<uint8_t>(&it->second))
|
||||
return *v;
|
||||
ESP_LOGE(TAG, "Type mismatch for key: %s", key);
|
||||
abort();
|
||||
error_abort();
|
||||
}
|
||||
|
||||
int16_t Config::getShort(const char* key) const {
|
||||
auto it = values.find(key);
|
||||
if (it == values.end()) {
|
||||
ESP_LOGE(TAG, "Missing config key: %s", key);
|
||||
abort();
|
||||
error_abort();
|
||||
}
|
||||
if (auto v = std::get_if<int16_t>(&it->second))
|
||||
return *v;
|
||||
ESP_LOGE(TAG, "Type mismatch for key: %s", key);
|
||||
abort();
|
||||
error_abort();
|
||||
}
|
||||
|
||||
int32_t Config::getInt(const char* key) const {
|
||||
auto it = values.find(key);
|
||||
if (it == values.end()) {
|
||||
ESP_LOGE(TAG, "Missing config key: %s", key);
|
||||
abort();
|
||||
error_abort();
|
||||
}
|
||||
if (auto v = std::get_if<int32_t>(&it->second))
|
||||
return *v;
|
||||
ESP_LOGE(TAG, "Type mismatch for key: %s", key);
|
||||
abort();
|
||||
error_abort();
|
||||
}
|
||||
|
||||
bool Config::getBool(const char* key) const {
|
||||
@@ -251,34 +262,38 @@ float Config::getFloat(const char* key) const {
|
||||
auto it = values.find(key);
|
||||
if (it == values.end()) {
|
||||
ESP_LOGE(TAG, "Missing config key: %s", key);
|
||||
abort();
|
||||
error_abort();
|
||||
}
|
||||
if (auto v = std::get_if<float>(&it->second))
|
||||
return *v;
|
||||
ESP_LOGE(TAG, "Type mismatch for key: %s", key);
|
||||
abort();
|
||||
error_abort();
|
||||
}
|
||||
|
||||
char Config::getChar(const char* key) const {
|
||||
auto it = values.find(key);
|
||||
if (it == values.end()) {
|
||||
ESP_LOGE(TAG, "Missing config key: %s", key);
|
||||
abort();
|
||||
error_abort();
|
||||
}
|
||||
if (auto v = std::get_if<char>(&it->second))
|
||||
return *v;
|
||||
ESP_LOGE(TAG, "Type mismatch for key: %s", key);
|
||||
abort();
|
||||
error_abort();
|
||||
}
|
||||
|
||||
const String& Config::getString(const char* key) const {
|
||||
auto it = values.find(key);
|
||||
if (it == values.end()) {
|
||||
ESP_LOGE(TAG, "Missing config key: %s", key);
|
||||
abort();
|
||||
error_abort();
|
||||
}
|
||||
if (auto v = std::get_if<String>(&it->second))
|
||||
return *v;
|
||||
ESP_LOGE(TAG, "Type mismatch for key: %s", key);
|
||||
abort();
|
||||
error_abort();
|
||||
}
|
||||
|
||||
const char* Config::getCString(const char* key) const {
|
||||
return getString(key).c_str();
|
||||
}
|
||||
|
||||
32
src/hash.cpp
Normal file
32
src/hash.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
#include "hash.h"
|
||||
#include "mbedtls/md.h" // for SHA256
|
||||
|
||||
String get_sha256(String payload) {
|
||||
byte shaResult[32];
|
||||
mbedtls_md_context_t ctx;
|
||||
mbedtls_md_type_t md_type = MBEDTLS_MD_SHA256;
|
||||
mbedtls_md_init(&ctx);
|
||||
mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(md_type), 0);
|
||||
mbedtls_md_starts(&ctx);
|
||||
mbedtls_md_update(&ctx, (const unsigned char *) payload.c_str(), payload.length());
|
||||
mbedtls_md_finish(&ctx, shaResult);
|
||||
mbedtls_md_free(&ctx);
|
||||
// convert to hex string
|
||||
char buffer[sizeof(shaResult)*2 + 1];
|
||||
const char hexmap[] = "0123456789abcdef";
|
||||
for (int i = 0; i < sizeof(shaResult); i++) {
|
||||
buffer[i*2] = hexmap[(shaResult[i] >> 4) & 0x0F];
|
||||
buffer[i*2+1] = hexmap[shaResult[i] & 0x0F];
|
||||
}
|
||||
buffer[sizeof(buffer) - 1] = '\0';
|
||||
String hash = String(buffer);
|
||||
|
||||
Serial.print("SHA256 payload: ");
|
||||
Serial.print(payload);
|
||||
Serial.println();
|
||||
Serial.print("SHA256-Hash: ");
|
||||
Serial.print(hash);
|
||||
Serial.println();
|
||||
|
||||
return hash;
|
||||
}
|
||||
95
src/led.cpp
Normal file
95
src/led.cpp
Normal file
@@ -0,0 +1,95 @@
|
||||
#include "main.h"
|
||||
#include "led.h"
|
||||
|
||||
// Logging
|
||||
static const char* TAG = "LED";
|
||||
|
||||
int16_t led_brightness = 512; // analog pin with ledc: 0 .. 4095
|
||||
int16_t rgb_brightness = 768;
|
||||
|
||||
void led_init() {
|
||||
|
||||
// internal user led (red)
|
||||
digitalWrite(LED_USER, HIGH);
|
||||
delay(1000);
|
||||
digitalWrite(LED_USER, LOW);
|
||||
|
||||
// LEDC
|
||||
ledcSetup(LEDC_BUZZER, LEDC_BASE_FREQ, LEDC_RES_BUZZER);
|
||||
ledcSetup(LEDC_LED_A, LEDC_BASE_FREQ, LEDC_RES_LED);
|
||||
ledcSetup(LEDC_LED_B, LEDC_BASE_FREQ, LEDC_RES_LED);
|
||||
ledcSetup(LEDC_LED_C, LEDC_BASE_FREQ, LEDC_RES_LED);
|
||||
ledcSetup(LEDC_RGBLED_R, LEDC_BASE_FREQ, LEDC_RES_LED);
|
||||
ledcSetup(LEDC_RGBLED_G, LEDC_BASE_FREQ, LEDC_RES_LED);
|
||||
ledcSetup(LEDC_RGBLED_B, LEDC_BASE_FREQ, LEDC_RES_LED);
|
||||
|
||||
ledcAttachPin(LED_A, LEDC_LED_A);
|
||||
ledcAttachPin(LED_B, LEDC_LED_B);
|
||||
ledcAttachPin(LED_C, LEDC_LED_C);
|
||||
ledcAttachPin(RGBLED_R, LEDC_RGBLED_R);
|
||||
ledcAttachPin(RGBLED_G, LEDC_RGBLED_G);
|
||||
ledcAttachPin(RGBLED_B, LEDC_RGBLED_B);
|
||||
|
||||
}
|
||||
|
||||
void led_test() {
|
||||
// all led one after another to test functionality
|
||||
|
||||
ESP_LOGI(TAG, "LED test started");
|
||||
|
||||
// Onbard RGB LED, inverted mode
|
||||
digitalWrite(LED_IR, LOW);
|
||||
digitalWrite(LED_IG, HIGH);
|
||||
digitalWrite(LED_IB, HIGH);
|
||||
delay(500);
|
||||
digitalWrite(LED_IR, HIGH);
|
||||
digitalWrite(LED_IG, LOW);
|
||||
delay(500);
|
||||
digitalWrite(LED_IG, HIGH);
|
||||
digitalWrite(LED_IB, LOW);
|
||||
delay(500);
|
||||
digitalWrite(LED_IB, HIGH);
|
||||
|
||||
// destination leds
|
||||
ledcWrite(LEDC_LED_A, 0);
|
||||
delay(250);
|
||||
// test every led
|
||||
ledcWrite(LEDC_LED_A, led_brightness);
|
||||
ledcWrite(LEDC_LED_B, 0);
|
||||
ledcWrite(LEDC_LED_C, 0);
|
||||
delay(500);
|
||||
ledcWrite(LEDC_LED_A, 0);
|
||||
ledcWrite(LEDC_LED_B, led_brightness);
|
||||
delay(500);
|
||||
ledcWrite(LEDC_LED_B, 0);
|
||||
ledcWrite(LEDC_LED_C, led_brightness);
|
||||
delay(500);
|
||||
ledcWrite(LEDC_LED_C, 0);
|
||||
|
||||
// enclosure rgb led (common cathode, so low is off)
|
||||
ledcWrite(LEDC_RGBLED_R, rgb_brightness);
|
||||
ledcWrite(LEDC_RGBLED_G, 0);
|
||||
ledcWrite(LEDC_RGBLED_B, 0);
|
||||
delay(700);
|
||||
ledcWrite(LEDC_RGBLED_R, 0);
|
||||
ledcWrite(LEDC_RGBLED_G, rgb_brightness);
|
||||
delay(700);
|
||||
ledcWrite(LEDC_RGBLED_G, 0);
|
||||
ledcWrite(LEDC_RGBLED_B, rgb_brightness);
|
||||
delay(700);
|
||||
ledcWrite(LEDC_RGBLED_B, 0);
|
||||
|
||||
ESP_LOGI(TAG, "LED test finished");
|
||||
|
||||
}
|
||||
|
||||
void led_blink(uint8_t channel, uint8_t count, int16_t brightness, uint32_t interval_ms) {
|
||||
ledcWrite(channel, 0);
|
||||
for (uint16_t i = 0; i < count; i++) {
|
||||
delay(interval_ms);
|
||||
ledcWrite(channel, brightness);
|
||||
delay(interval_ms);
|
||||
ledcWrite(channel, 0);
|
||||
}
|
||||
delay(interval_ms);
|
||||
}
|
||||
340
src/main.cpp
340
src/main.cpp
@@ -1,6 +1,8 @@
|
||||
#include "main.h"
|
||||
#include "config.h"
|
||||
#include "webserver.h"
|
||||
#include "led.h"
|
||||
#include "hash.h"
|
||||
#include <ArduinoJson.h>
|
||||
#include <WiFi.h>
|
||||
#include <Wire.h>
|
||||
@@ -8,14 +10,12 @@
|
||||
#include <NMEA2000.h>
|
||||
#include <N2kMsg.h>
|
||||
#include <N2kMessages.h>
|
||||
#include "Nmea2kTwai.h"
|
||||
#include "N2kDeviceList.h"
|
||||
#include <map>
|
||||
|
||||
#include "mbedtls/md.h" // for SHA256
|
||||
#include <esp32/clk.h> // for cpu frequency
|
||||
#include "driver/rtc_io.h" // for wakeup from deep sleep
|
||||
#include "esp_app_format.h" // for custom fw descriptor
|
||||
#include "esp_rom_uart.h" // for uart wait idle
|
||||
|
||||
// ESP-IDF firmware descriptor
|
||||
__attribute__((section(".rodata_custom_desc"))) esp_app_desc_t custom_app_desc = {
|
||||
@@ -31,53 +31,18 @@ __attribute__((section(".rodata_custom_desc"))) esp_app_desc_t custom_app_desc =
|
||||
{}
|
||||
};
|
||||
|
||||
String get_sha256(String payload) {
|
||||
byte shaResult[32];
|
||||
mbedtls_md_context_t ctx;
|
||||
mbedtls_md_type_t md_type = MBEDTLS_MD_SHA256;
|
||||
mbedtls_md_init(&ctx);
|
||||
mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(md_type), 0);
|
||||
mbedtls_md_starts(&ctx);
|
||||
mbedtls_md_update(&ctx, (const unsigned char *) payload.c_str(), payload.length());
|
||||
mbedtls_md_finish(&ctx, shaResult);
|
||||
mbedtls_md_free(&ctx);
|
||||
// convert to hex string
|
||||
char buffer[sizeof(shaResult)*2 + 1];
|
||||
const char hexmap[] = "0123456789abcdef";
|
||||
for (int i = 0; i < sizeof(shaResult); i++) {
|
||||
buffer[i*2] = hexmap[(shaResult[i] >> 4) & 0x0F];
|
||||
buffer[i*2+1] = hexmap[shaResult[i] & 0x0F];
|
||||
}
|
||||
buffer[sizeof(buffer) - 1] = '\0';
|
||||
String hash = String(buffer);
|
||||
|
||||
Serial.print("SHA256 payload: ");
|
||||
Serial.print(payload);
|
||||
Serial.println();
|
||||
Serial.print("SHA256-Hash: ");
|
||||
Serial.print(hash);
|
||||
Serial.println();
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
// Logging
|
||||
static const char* TAG = "MAIN";
|
||||
|
||||
Preferences preferences; // persistent storage for configuration
|
||||
Config config(preferences); // configuration object
|
||||
|
||||
uint64_t chipid = ESP.getEfuseMac();
|
||||
|
||||
const char* wifi_ssid = "OBPKP61";
|
||||
const char* wifi_pass = "keypad61";
|
||||
bool apEnabled = false;
|
||||
// AsyncWebServer server(80);
|
||||
bool ap_enabled = false;
|
||||
|
||||
unsigned long firstStart = 0;
|
||||
unsigned long lastSensor = 0;
|
||||
unsigned long lastPrint = 0;
|
||||
unsigned long counter = 0;
|
||||
|
||||
bool rgb_r = false;
|
||||
bool rgb_g = false;
|
||||
@@ -85,13 +50,11 @@ bool rgb_b = false;
|
||||
|
||||
int cpuspeed = 240; // MHz
|
||||
|
||||
char globalmode = 'K'; // (K)eyboard | (A)utopilot | (L)ogbook
|
||||
char mode = 'N'; // (N)ormal | (C)onfig
|
||||
char ledmode = 'D'; // (D)ay | (N)ight
|
||||
char audiomode = 'E'; // (E)nabled | (D)isabled
|
||||
RTC_DATA_ATTR char globalmode = 'K'; // (K)eyboard | (A)utopilot | (L)ogbook
|
||||
char mode = 'N'; // (N)ormal | (C)onfig -> do not store for reset!
|
||||
RTC_DATA_ATTR char ledmode = 'D'; // (D)ay | (N)ight
|
||||
RTC_DATA_ATTR char audiomode = 'E'; // (E)nabled | (D)isabled
|
||||
RTC_DATA_ATTR char destination = 'A'; // A | B | C im RTC-Speicher überlebt deep sleep
|
||||
uint8_t led_brightness = 16; // analog pin: 0 .. 255
|
||||
uint8_t rgb_brightness = 64;
|
||||
|
||||
uint buzzerpower = 50; // TBD make use of this
|
||||
|
||||
@@ -103,7 +66,7 @@ bool sht_available = false;
|
||||
float temp = 0.0;
|
||||
float hum = 0.0;
|
||||
|
||||
int nodeid; // NMEA2000 id on bus
|
||||
uint8_t nodeid; // NMEA2000 id on bus
|
||||
Nmea2kTwai &NMEA2000=*(new Nmea2kTwai(CAN_TX, CAN_RX, CAN_RECOVERY_PERIOD));
|
||||
tN2kDeviceList *pN2kDeviceList;
|
||||
|
||||
@@ -112,77 +75,6 @@ String processor(const String& var) {
|
||||
return "";
|
||||
}
|
||||
|
||||
String uptime_with_unit() {
|
||||
int64_t uptime = esp_timer_get_time() / 1000000;
|
||||
String uptime_unit;
|
||||
if (uptime < 120) {
|
||||
uptime_unit = " seconds";
|
||||
} else {
|
||||
if (uptime < 2 * 3600) {
|
||||
uptime /= 60;
|
||||
uptime_unit = " minutes";
|
||||
} else if (uptime < 2 * 3600 * 24) {
|
||||
uptime /= 3600;
|
||||
uptime_unit = " hours";
|
||||
} else {
|
||||
uptime /= 86400;
|
||||
uptime_unit = " days";
|
||||
}
|
||||
}
|
||||
return String(uptime) + " " + uptime_unit;
|
||||
}
|
||||
|
||||
void ledtest() {
|
||||
// all led one after another to test functionality
|
||||
|
||||
Serial.println("LED test started");
|
||||
|
||||
// Onbard RGB LED, inverted mode
|
||||
digitalWrite(LED_IR, LOW);
|
||||
digitalWrite(LED_IG, HIGH);
|
||||
digitalWrite(LED_IB, HIGH);
|
||||
delay(500);
|
||||
digitalWrite(LED_IR, HIGH);
|
||||
digitalWrite(LED_IG, LOW);
|
||||
delay(500);
|
||||
digitalWrite(LED_IG, HIGH);
|
||||
digitalWrite(LED_IB, LOW);
|
||||
delay(500);
|
||||
digitalWrite(LED_IB, HIGH);
|
||||
|
||||
// destination leds
|
||||
analogWrite(LED_A, 0);
|
||||
delay(250);
|
||||
// test every led
|
||||
analogWrite(LED_A, led_brightness);
|
||||
analogWrite(LED_B, 0);
|
||||
analogWrite(LED_C, 0);
|
||||
delay(500);
|
||||
analogWrite(LED_A, 0);
|
||||
analogWrite(LED_B, led_brightness);
|
||||
delay(500);
|
||||
analogWrite(LED_B, 0);
|
||||
analogWrite(LED_C, led_brightness);
|
||||
delay(500);
|
||||
analogWrite(LED_C, 0);
|
||||
|
||||
// enclosure rgb led (common cathode, so low is off)
|
||||
analogWrite(RGBLED_R, rgb_brightness);
|
||||
analogWrite(RGBLED_G, 0);
|
||||
analogWrite(RGBLED_B, 0);
|
||||
delay(700);
|
||||
analogWrite(RGBLED_R, 0);
|
||||
analogWrite(RGBLED_G, rgb_brightness);
|
||||
delay(700);
|
||||
analogWrite(RGBLED_G, 0);
|
||||
analogWrite(RGBLED_B, rgb_brightness);
|
||||
delay(700);
|
||||
analogWrite(RGBLED_B, 0);
|
||||
|
||||
Serial.println("LED test finished");
|
||||
|
||||
}
|
||||
|
||||
TaskHandle_t ledTaskHandle = NULL;
|
||||
TaskHandle_t sensorTaskHandle = NULL;
|
||||
TaskHandle_t keyTaskHandle = NULL;
|
||||
@@ -191,17 +83,17 @@ QueueHandle_t ledQueue = NULL;
|
||||
QueueHandle_t keyQueue = NULL;
|
||||
|
||||
void ledTask(void *parameter) {
|
||||
Serial.println("Starting LED task");
|
||||
ESP_LOGI(TAG, "Starting LED task");
|
||||
for (;;) {
|
||||
vTaskDelay(5000);
|
||||
analogWrite(RGBLED_G, 10); // a short activity flash
|
||||
ledcWrite(LEDC_RGBLED_G, 160); // a short activity flash
|
||||
vTaskDelay(20);
|
||||
analogWrite(RGBLED_G, 0);
|
||||
ledcWrite(LEDC_RGBLED_G, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void sensorTask(void *parameter) {
|
||||
Serial.println("Starting sensor task");
|
||||
ESP_LOGI(TAG, "Starting sensor task");
|
||||
for (;;) {
|
||||
vTaskDelay(10000); // nothing yet
|
||||
}
|
||||
@@ -211,7 +103,7 @@ void keyTask(void *parameter) {
|
||||
// short key press <= 1s
|
||||
// medium key press >1s and < 3s
|
||||
// long key press >= 3s
|
||||
Serial.println("Starting keyboard task");
|
||||
ESP_LOGI(TAG, "Starting keyboard task");
|
||||
|
||||
constexpr uint8_t NUM_BUTTONS = 7;
|
||||
constexpr gpio_num_t buttonPins[NUM_BUTTONS] = {
|
||||
@@ -268,12 +160,12 @@ void keyTask(void *parameter) {
|
||||
}
|
||||
|
||||
void stopApTimerCallback(TimerHandle_t xTimer) {
|
||||
Serial.println("reached AP switchoff time: accesspoint switched off ");
|
||||
ESP_LOGI(TAG, "reached AP switchoff time: accesspoint switched off ");
|
||||
WiFi.softAPdisconnect(true);
|
||||
}
|
||||
|
||||
void cpuFreqTimerCallback(TimerHandle_t xTimer) {
|
||||
Serial.println("after 3 minutes: set CPU frequency to 160MHz");
|
||||
ESP_LOGI(TAG, "after 3 minutes: set CPU frequency to 160MHz");
|
||||
setCpuFrequencyMhz(cpuspeed);
|
||||
}
|
||||
|
||||
@@ -315,10 +207,10 @@ void setup() {
|
||||
pinMode(KEY_6, INPUT_PULLUP);
|
||||
pinMode(KEY_DST, INPUT_PULLUP);
|
||||
|
||||
// Early signal system activity
|
||||
analogWrite(RGBLED_R, 255);
|
||||
analogWrite(RGBLED_G, 0);
|
||||
analogWrite(RGBLED_B, 0);
|
||||
// Early signal system activity, red while booting
|
||||
digitalWrite(RGBLED_R, HIGH);
|
||||
digitalWrite(RGBLED_G, LOW);
|
||||
digitalWrite(RGBLED_B, LOW);
|
||||
|
||||
// Arduino ESP32 logging
|
||||
esp_log_level_set("*", ESP_LOG_INFO);
|
||||
@@ -348,7 +240,7 @@ void setup() {
|
||||
|
||||
esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
|
||||
if (cause == ESP_SLEEP_WAKEUP_EXT0) {
|
||||
ESP_LOGI(TAG, " Wake up by key");
|
||||
ESP_LOGI(TAG, "Wake up by key");
|
||||
} else {
|
||||
destination = 'A';
|
||||
}
|
||||
@@ -356,9 +248,10 @@ void setup() {
|
||||
// N2K basics
|
||||
nodeid = N2K_DEFAULT_NODEID;
|
||||
ESP_LOGI(TAG, "N2K default node is %d", nodeid);
|
||||
preferences.begin(PREF_NAME, false);
|
||||
nodeid = preferences.getInt("LastNodeId", N2K_DEFAULT_NODEID);
|
||||
preferences.end();
|
||||
//preferences.begin(PREF_NAME, false);
|
||||
//nodeid = preferences.getInt("LastNodeId", N2K_DEFAULT_NODEID);
|
||||
//preferences.end();
|
||||
nodeid = config.getByte("LastNodeId");
|
||||
ESP_LOGI(TAG, "N2K node id set to %d from preferences", nodeid);
|
||||
|
||||
//cpuspeed = preferences.getInt("cpuSpeed", 160);
|
||||
@@ -392,37 +285,10 @@ void setup() {
|
||||
IPAddress ap_gateway(ap_addr);
|
||||
|
||||
WiFi.softAPConfig(ap_addr, ap_gateway, ap_subnet);
|
||||
apEnabled = true;
|
||||
ap_enabled = true;
|
||||
|
||||
// Initialize WebGUI
|
||||
webserver_init();
|
||||
|
||||
server.on("/api/devicelist", HTTP_GET, [](AsyncWebServerRequest *request){
|
||||
// NMEA2000 device list
|
||||
AsyncResponseStream *response = request->beginResponseStream("application/json");
|
||||
response->print("[");
|
||||
bool first = true;
|
||||
for (int i = 0; i <= 252; i++) {
|
||||
const tNMEA2000::tDevice *d = pN2kDeviceList->FindDeviceBySource(i);
|
||||
if (d == nullptr) {
|
||||
continue;
|
||||
}
|
||||
uint64_t NAME = d->GetName();
|
||||
char hex_name[17];
|
||||
snprintf(hex_name, sizeof(hex_name), "%08X%08X", (uint32_t)(NAME >> 32), (uint32_t)(NAME & 0xFFFFFFFF));
|
||||
if (!first) {
|
||||
response->print(",");
|
||||
} else {
|
||||
first = false;
|
||||
}
|
||||
// TODO last seen?
|
||||
response->printf("{\"source\":%d,\"name\":\"%s\",\"manuf\":\"%d\",\"model\":\"%s\"}",
|
||||
i, hex_name, d->GetManufacturerCode(), d->GetModelID());
|
||||
}
|
||||
response->print("]");
|
||||
request->send(response);
|
||||
});
|
||||
|
||||
// Start HTTP Webserver
|
||||
server.begin();
|
||||
|
||||
@@ -486,52 +352,50 @@ void setup() {
|
||||
// Debug: NMEA2000.EnableForward(true);
|
||||
NMEA2000.Open();
|
||||
|
||||
// internal user led (red)
|
||||
digitalWrite(LED_USER, HIGH);
|
||||
delay(1000);
|
||||
digitalWrite(LED_USER, LOW);
|
||||
|
||||
|
||||
led_init();
|
||||
|
||||
// Buzzer
|
||||
ledcSetup(LEDC_CHANNEL, LEDC_BASE_FREQ, LEDC_TIMER_8_BIT);
|
||||
ledcAttachPin(BUZZER, LEDC_CHANNEL);
|
||||
ledcAttachPin(BUZZER, LEDC_BUZZER);
|
||||
// Test tone while booting
|
||||
// Buzzer 12V, 2500Hz +/- 200Hz, 30mA, ca. 90dB
|
||||
if (ledcWriteTone(LEDC_CHANNEL, 2300) == 0) {
|
||||
if (ledcWriteTone(LEDC_BUZZER, 2300) == 0) {
|
||||
Serial.println("Error setting buzzer tone");
|
||||
} else {
|
||||
delay(50);
|
||||
ledcWriteTone(LEDC_CHANNEL, 0); // Buzzer off
|
||||
ledcWriteTone(LEDC_BUZZER, 0); // Buzzer off
|
||||
}
|
||||
|
||||
// Startup sequence: test all led and short beep buzzer
|
||||
analogWrite(RGBLED_R, 0); // boot status off
|
||||
digitalWrite(RGBLED_R, LOW); // boot status off
|
||||
delay(500);
|
||||
ledtest();
|
||||
led_test();
|
||||
|
||||
// select current destination
|
||||
switch (destination) {
|
||||
case 'A':
|
||||
analogWrite(LED_A, led_brightness);
|
||||
ledcWrite(LEDC_LED_A, led_brightness);
|
||||
break;
|
||||
case 'B':
|
||||
analogWrite(LED_B, led_brightness);
|
||||
ledcWrite(LEDC_LED_B, led_brightness);
|
||||
break;
|
||||
case 'C':
|
||||
analogWrite(LED_C, led_brightness);
|
||||
ledcWrite(LEDC_LED_C, led_brightness);
|
||||
break;
|
||||
}
|
||||
|
||||
// I²C
|
||||
Serial.print("SHT31_LIB_VERSION: ");
|
||||
Serial.println(SHT31_LIB_VERSION);
|
||||
// Serial.print("SHT31_LIB_VERSION: ");
|
||||
// Serial.println(SHT31_LIB_VERSION);
|
||||
ESP_LOGI(TAG, "SHT31_LIB_VERSION: %s", SHT31_LIB_VERSION);
|
||||
Wire.begin(I2C_SDA, I2C_SCL);
|
||||
Wire.setClock(I2C_SPEED);
|
||||
uint16_t stat = sht.readStatus();
|
||||
// stat = ffff anscheinend Fehler
|
||||
// = 8010 läuft anscheinend
|
||||
sht_available = (stat == 0x8010);
|
||||
Serial.print(stat, HEX);
|
||||
Serial.println();
|
||||
ESP_LOGI(TAG, "SHT31 state=0x%X", stat);
|
||||
|
||||
// Additional tests
|
||||
String passhash = get_sha256("secretTEST");
|
||||
@@ -553,10 +417,10 @@ void setup() {
|
||||
ledQueue = xQueueCreate(5, sizeof(uint8_t));
|
||||
|
||||
if (esp_sleep_is_valid_wakeup_gpio(KEY_DST)) {
|
||||
Serial.println("DST-Taste ist als Wakeup-Pin konfiguriert");
|
||||
ESP_LOGI(TAG, "DST-key configured as wakeup-pin");
|
||||
esp_sleep_enable_ext0_wakeup(KEY_DST, 0);
|
||||
} else {
|
||||
Serial.println("Keine Wakeup-Funktion vorhanden! Deep-sleep deaktiviert.");
|
||||
ESP_LOGI(TAG, "No wakeup feature available! Deep-sleep disabled.");
|
||||
}
|
||||
|
||||
if (cpuspeed < 240) {
|
||||
@@ -584,19 +448,19 @@ void setup() {
|
||||
}
|
||||
|
||||
void shortBeep() {
|
||||
ledcWriteTone(LEDC_CHANNEL, 2500);
|
||||
ledcWriteTone(LEDC_BUZZER, 2500);
|
||||
delay(15);
|
||||
ledcWriteTone(LEDC_CHANNEL, 0);
|
||||
ledcWriteTone(LEDC_BUZZER, 0);
|
||||
}
|
||||
|
||||
void atariKeyclick() {
|
||||
ledcWriteTone(LEDC_CHANNEL, 3200);
|
||||
ledcWriteTone(LEDC_BUZZER, 3200);
|
||||
delayMicroseconds(3000);
|
||||
ledcWriteTone(LEDC_CHANNEL, 0);
|
||||
ledcWriteTone(LEDC_BUZZER, 0);
|
||||
delayMicroseconds(800);
|
||||
ledcWriteTone(LEDC_CHANNEL, 3200);
|
||||
ledcWriteTone(LEDC_BUZZER, 3200);
|
||||
delayMicroseconds(2000);
|
||||
ledcWriteTone(LEDC_CHANNEL, 0);
|
||||
ledcWriteTone(LEDC_BUZZER, 0);
|
||||
}
|
||||
|
||||
void print_n2k_devicelist() {
|
||||
@@ -658,7 +522,7 @@ void send_sensor_temphum(float temp_k, float hum_perc) {
|
||||
unsigned char instance = 0;
|
||||
tN2kTempSource temp_src = N2kts_OutsideTemperature; // 1=outside, 2=inside
|
||||
tN2kHumiditySource hum_src = N2khs_OutsideHumidity; // 0=inside, 1=outside
|
||||
Serial.printf("Sending temp=%f K, hum=%f %%\n", temp_k, hum_perc);
|
||||
ESP_LOGI(TAG, "Sending temp=%f K, hum=%f %%", temp_k, hum_perc);
|
||||
SetN2kPGN130312(N2kMsg, SID, instance, temp_src, temp_k);
|
||||
NMEA2000.SendMsg(N2kMsg);
|
||||
SetN2kPGN130313(N2kMsg, SID, instance, hum_src, hum_perc);
|
||||
@@ -670,55 +534,37 @@ void loop() {
|
||||
|
||||
ButtonEvent event;
|
||||
if (xQueueReceive(keyQueue, &event, 0) == pdPASS) {
|
||||
Serial.print("Button ");
|
||||
Serial.print(event.buttonId);
|
||||
Serial.print(" -> ");
|
||||
switch (event.pressType) {
|
||||
case ButtonPressType::SHORT:
|
||||
Serial.println("SHORT");
|
||||
break;
|
||||
case ButtonPressType::MEDIUM:
|
||||
Serial.println("MEDIUM");
|
||||
break;
|
||||
case ButtonPressType::LONG:
|
||||
Serial.println("LONG");
|
||||
break;
|
||||
default:
|
||||
Serial.print("UNBEKANNT: ");
|
||||
Serial.println(static_cast<uint8_t>(event.pressType));
|
||||
break;
|
||||
}
|
||||
if (event.buttonId == BUTTON_DST) {
|
||||
// destination / mode button
|
||||
if (event.pressType == ButtonPressType::SHORT) {
|
||||
if (mode == 'N') {
|
||||
// switch destination only in normal mode
|
||||
if (destination == 'A') {
|
||||
destination = 'B';
|
||||
analogWrite(LED_A, 0);
|
||||
analogWrite(LED_B, led_brightness);
|
||||
ledcWrite(LEDC_LED_A, 0);
|
||||
ledcWrite(LEDC_LED_B, led_brightness);
|
||||
} else if (destination == 'B') {
|
||||
destination = 'C';
|
||||
analogWrite(LED_B, 0);
|
||||
analogWrite(LED_C, led_brightness);
|
||||
ledcWrite(LEDC_LED_B, 0);
|
||||
ledcWrite(LEDC_LED_C, led_brightness);
|
||||
} else {
|
||||
destination = 'A';
|
||||
analogWrite(LED_C, 0);
|
||||
analogWrite(LED_A, led_brightness);
|
||||
ledcWrite(LEDC_LED_C, 0);
|
||||
ledcWrite(LEDC_LED_A, led_brightness);
|
||||
}
|
||||
Serial.print("New destination=");
|
||||
Serial.println(destination);
|
||||
ESP_LOGI(TAG, "New destination=%s", destination);
|
||||
}
|
||||
} else if (event.pressType == ButtonPressType::LONG) {
|
||||
shortBeep();
|
||||
// switch config mode
|
||||
if (mode == 'N') {
|
||||
mode = 'C';
|
||||
analogWrite(RGBLED_B, rgb_brightness); // blue status indicator
|
||||
Serial.println("Entering config mode");
|
||||
ledcWrite(LEDC_RGBLED_B, rgb_brightness); // blue status indicator
|
||||
ESP_LOGI(TAG, "Entering config mode");
|
||||
} else {
|
||||
mode = 'N';
|
||||
analogWrite(RGBLED_B, 0);
|
||||
Serial.println("Leaving config mode");
|
||||
ledcWrite(LEDC_RGBLED_B, 0);
|
||||
ESP_LOGI(TAG, "Leaving config mode");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -742,71 +588,48 @@ void loop() {
|
||||
switch (event.buttonId) {
|
||||
case BUTTON_1: // switch day/night mode
|
||||
if (ledmode == 'D') {
|
||||
Serial.println("Night mode enabled");
|
||||
ESP_LOGI(TAG, "Night mode enabled");
|
||||
ledmode = 'N';
|
||||
} else {
|
||||
Serial.println("Day mode enabled");
|
||||
ESP_LOGI(TAG, "Day mode enabled");
|
||||
ledmode = 'D';
|
||||
}
|
||||
break;
|
||||
case BUTTON_2: // switch audio on/off
|
||||
if (audiomode == 'E') {
|
||||
Serial.println("Disabled audio");
|
||||
ESP_LOGI(TAG, "Disabled audio");
|
||||
audiomode = 'D';
|
||||
} else {
|
||||
Serial.println("Enabled audio");
|
||||
ESP_LOGI(TAG, "Enabled audio");
|
||||
audiomode = 'E';
|
||||
}
|
||||
break;
|
||||
case BUTTON_3: // switch accesspoint on/off
|
||||
if (apEnabled) {
|
||||
Serial.println("Disable Accesspoint");
|
||||
if (ap_enabled) {
|
||||
ESP_LOGI(TAG, "Disable Accesspoint");
|
||||
WiFi.softAPdisconnect(true);
|
||||
apEnabled = false;
|
||||
ap_enabled = false;
|
||||
} else {
|
||||
Serial.println("Enable Accesspoint");
|
||||
WiFi.softAP(wifi_ssid, wifi_pass);
|
||||
apEnabled = true;
|
||||
ap_enabled = true;
|
||||
}
|
||||
break;
|
||||
case BUTTON_4: // reserved
|
||||
break;
|
||||
case BUTTON_5: // reset
|
||||
Serial.println("Device reset");
|
||||
analogWrite(RGBLED_B, 0);
|
||||
delay(500);
|
||||
analogWrite(RGBLED_G, 255);
|
||||
delay(500);
|
||||
analogWrite(RGBLED_G, 0);
|
||||
delay(500);
|
||||
analogWrite(RGBLED_G, 255);
|
||||
delay(500);
|
||||
analogWrite(RGBLED_G, 0);
|
||||
delay(500);
|
||||
analogWrite(RGBLED_G, 255);
|
||||
delay(500);
|
||||
ESP_LOGI(TAG, "Device reset");
|
||||
esp_rom_uart_tx_wait_idle(0);
|
||||
led_blink(LEDC_RGBLED_G, 3, 4095, 500);
|
||||
ESP.restart();
|
||||
break;
|
||||
case BUTTON_6: // deep sleep
|
||||
Serial.println("Going into deep sleep");
|
||||
Serial.flush();
|
||||
analogWrite(RGBLED_B, 0);
|
||||
delay(500);
|
||||
analogWrite(RGBLED_B, 255);
|
||||
delay(500);
|
||||
analogWrite(RGBLED_B, 0);
|
||||
delay(500);
|
||||
analogWrite(RGBLED_B, 255);
|
||||
delay(500);
|
||||
analogWrite(RGBLED_B, 0);
|
||||
delay(500);
|
||||
analogWrite(RGBLED_B, 255);
|
||||
delay(500);
|
||||
|
||||
ESP_LOGI(TAG, "Going into deep sleep");
|
||||
esp_rom_uart_tx_wait_idle(0);
|
||||
led_blink(LEDC_RGBLED_B, 3, 4095, 500);
|
||||
rtc_gpio_pullup_en(KEY_DST);
|
||||
rtc_gpio_pulldown_dis(KEY_DST);
|
||||
esp_deep_sleep_start();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -816,7 +639,7 @@ void loop() {
|
||||
NMEA2000.loop();
|
||||
NMEA2000.ParseMessages();
|
||||
|
||||
if (millis() - lastSensor >= 5000) {
|
||||
if ((millis() - lastSensor >= 5000) and sht_available) {
|
||||
lastSensor = millis();
|
||||
sht.read();
|
||||
temp = sht.getTemperature(); // °C
|
||||
@@ -826,12 +649,5 @@ void loop() {
|
||||
send_sensor_temphum(temp + 273.15, hum);
|
||||
}
|
||||
|
||||
// development heartbeat
|
||||
if (millis() - lastPrint >= 1000) {
|
||||
lastPrint = millis();
|
||||
counter++;
|
||||
Serial.printf("Loop counter: %lu\n", counter);
|
||||
}
|
||||
|
||||
delay(1); // 1ms für freertos
|
||||
delay(1); // 1ms for FreeRTOS
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "main.h"
|
||||
#include "config.h"
|
||||
#include "webserver.h"
|
||||
#include <map>
|
||||
#include <AsyncTCP.h>
|
||||
@@ -42,6 +43,26 @@ void send_embedded_file(String name, AsyncWebServerRequest *request)
|
||||
}
|
||||
}
|
||||
|
||||
String uptime_with_unit() {
|
||||
int64_t uptime = esp_timer_get_time() / 1000000;
|
||||
String uptime_unit;
|
||||
if (uptime < 120) {
|
||||
uptime_unit = " seconds";
|
||||
} else {
|
||||
if (uptime < 2 * 3600) {
|
||||
uptime /= 60;
|
||||
uptime_unit = " minutes";
|
||||
} else if (uptime < 2 * 3600 * 24) {
|
||||
uptime /= 3600;
|
||||
uptime_unit = " hours";
|
||||
} else {
|
||||
uptime /= 86400;
|
||||
uptime_unit = " days";
|
||||
}
|
||||
}
|
||||
return String(uptime) + " " + uptime_unit;
|
||||
}
|
||||
|
||||
void webserver_init() {
|
||||
|
||||
// Route for root / web page
|
||||
@@ -76,24 +97,24 @@ void webserver_init() {
|
||||
|
||||
server.on("/api/config", HTTP_GET, [](AsyncWebServerRequest *request){
|
||||
StaticJsonDocument<512> doc;
|
||||
doc["systemName"] = "Keypad1";
|
||||
doc["systemName"] = config.getString("systemName");
|
||||
doc["systemMode"] = String(config.getChar("systemMode"));
|
||||
doc["logLevel"] = 0;
|
||||
doc["version"] = VERSION;
|
||||
doc["fwtype"] = "unknown";
|
||||
doc["fwtype"] = "unknown"; // TODO ?
|
||||
doc["salt"] = "secret";
|
||||
doc["AdminPassword"] = "********";
|
||||
doc["useAdminPass"] = false;
|
||||
doc["apEnable"] = true;
|
||||
doc["apIp"] = "192.168.15.1";
|
||||
doc["apMask"] = "255.255.255.0";
|
||||
doc["useAdminPass"] = "false"; //config.getBool("useAdminPass") ? "true" : "false";
|
||||
doc["apEnable"] = "true";
|
||||
doc["apIp"] = config.getString("apIp");
|
||||
doc["apMask"] = config.getString("apMask");
|
||||
doc["apPassword"] = "********";
|
||||
doc["stopApTime"] = 0;
|
||||
doc["stopApTime"] = config.getShort("stopApTime");
|
||||
doc["cpuSpeed"] = 160;
|
||||
doc["tempFormat"] = "C";
|
||||
doc["tempFormat"] = String(config.getChar("tempFormat"));
|
||||
doc["ledBrightness"] = led_brightness;
|
||||
doc["ledRgbBrightness"] = rgb_brightness;
|
||||
doc["tempFormat"] = "C";
|
||||
doc["switchBank"] = 0;
|
||||
doc["switchBank"] = config.getByte("switchBank");
|
||||
doc["key1"] = keycode[BUTTON_1];
|
||||
doc["key2"] = keycode[BUTTON_2];
|
||||
doc["key3"] = keycode[BUTTON_3];
|
||||
@@ -106,7 +127,7 @@ void webserver_init() {
|
||||
doc["key4long"] = longcode[BUTTON_4];
|
||||
doc["key5long"] = longcode[BUTTON_5];
|
||||
doc["key6long"] = longcode[BUTTON_6];
|
||||
doc["envInterval"] = 5;
|
||||
doc["envInterval"] = 5; // config.getShort("envInterval");
|
||||
String out;
|
||||
serializeJson(doc, out);
|
||||
request->send(200, "application/json", out);
|
||||
@@ -122,16 +143,12 @@ void webserver_init() {
|
||||
|
||||
server.on("/api/status", HTTP_GET, [](AsyncWebServerRequest *request){
|
||||
StaticJsonDocument<200> doc;
|
||||
|
||||
doc["version"] = VERSION;
|
||||
|
||||
int cpu_freq = esp_clk_cpu_freq() / 1000000;
|
||||
doc["cpuspeed"] = String(cpu_freq) + "MHz";
|
||||
|
||||
char ssid[13];
|
||||
snprintf(ssid, 13, "%04X%08X", (uint16_t)(chipid >> 32), (uint32_t)chipid);
|
||||
doc["chipid"] = String(ssid);
|
||||
|
||||
doc["uptime"] = uptime_with_unit();
|
||||
doc["heap"]=(long)xPortGetFreeHeapSize();
|
||||
doc["temp"] = String(temp, 1);
|
||||
@@ -147,6 +164,9 @@ void webserver_init() {
|
||||
doc["version"] = VERSION;
|
||||
doc["build_date"] = BUILD_DATE;
|
||||
doc["build_time"] = BUILD_TIME;
|
||||
String out;
|
||||
serializeJson(doc, out);
|
||||
request->send(200, "application/json", out);
|
||||
});
|
||||
|
||||
server.on("/api/setconfig", HTTP_POST, [](AsyncWebServerRequest *request){
|
||||
@@ -187,4 +207,30 @@ void webserver_init() {
|
||||
|
||||
});
|
||||
|
||||
server.on("/api/devicelist", HTTP_GET, [](AsyncWebServerRequest *request){
|
||||
// NMEA2000 device list
|
||||
AsyncResponseStream *response = request->beginResponseStream("application/json");
|
||||
response->print("[");
|
||||
bool first = true;
|
||||
for (int i = 0; i <= 252; i++) {
|
||||
const tNMEA2000::tDevice *d = pN2kDeviceList->FindDeviceBySource(i);
|
||||
if (d == nullptr) {
|
||||
continue;
|
||||
}
|
||||
uint64_t NAME = d->GetName();
|
||||
char hex_name[17];
|
||||
snprintf(hex_name, sizeof(hex_name), "%08X%08X", (uint32_t)(NAME >> 32), (uint32_t)(NAME & 0xFFFFFFFF));
|
||||
if (!first) {
|
||||
response->print(",");
|
||||
} else {
|
||||
first = false;
|
||||
}
|
||||
// TODO last seen?
|
||||
response->printf("{\"source\":%d,\"name\":\"%s\",\"manuf\":\"%d\",\"model\":\"%s\"}",
|
||||
i, hex_name, d->GetManufacturerCode(), d->GetModelID());
|
||||
}
|
||||
response->print("]");
|
||||
request->send(response);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
"name": "logLevel",
|
||||
"label": "Log level",
|
||||
"type": "list",
|
||||
"default": "0",
|
||||
"default": 0,
|
||||
"list": [
|
||||
{"l":"Off (0)","v":0},
|
||||
{"l":"Error (1)","v":1},
|
||||
|
||||
Reference in New Issue
Block a user