boot, clock, http, log, mqtt, system, wifi, Node, demo, NodeTest
This commit is contained in:
commit
a6fb6af1a9
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
/.pio/
|
||||
/.idea/
|
||||
/src/patrix/library.json
|
||||
/*.tar*
|
||||
29
library.json
Normal file
29
library.json
Normal file
@ -0,0 +1,29 @@
|
||||
{
|
||||
"name": "Patrix",
|
||||
"version": "0.1.0",
|
||||
"description": "Patrix library",
|
||||
"keywords": "patrix",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Patrick Haßel",
|
||||
"email": "development@patrick-hassel.de",
|
||||
"url": "https://patrick-hassel.de/",
|
||||
"maintainer": true
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"homepage": "https://patrick-hassel.de/",
|
||||
"dependencies": {
|
||||
"knolleary/pubsubclient": "2.8",
|
||||
"bblanchon/ArduinoJson": "7.3.0",
|
||||
"me-no-dev/ESPAsyncWebServer": "1.2.4"
|
||||
},
|
||||
"export": {
|
||||
"include": "src/patrix"
|
||||
},
|
||||
"frameworks": "arduino",
|
||||
"platforms": [
|
||||
"espressif8266",
|
||||
"espressif32"
|
||||
]
|
||||
}
|
||||
9
platformio.ini
Normal file
9
platformio.ini
Normal file
@ -0,0 +1,9 @@
|
||||
[env:Patrix]
|
||||
platform = espressif32
|
||||
board = esp32dev
|
||||
framework = arduino
|
||||
lib_deps =
|
||||
knolleary/pubsubclient@2.8
|
||||
bblanchon/ArduinoJson@7.3.0
|
||||
me-no-dev/ESPAsyncWebServer@1.2.4
|
||||
build_flags = -DWIFI_SSID=\"HappyNet\" -DWIFI_PKEY=\"1Grausame!Sackratte7\" -DWIFI_HOST=\"PatrixTest\"
|
||||
21
src/demo/NodeTest.h
Normal file
21
src/demo/NodeTest.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef NODE_TEST_H
|
||||
#define NODE_TEST_H
|
||||
|
||||
#include <public/node/Node.h>
|
||||
#include <patrix/node/Node.h>
|
||||
|
||||
class NodeTest final : public Node {
|
||||
|
||||
public:
|
||||
|
||||
explicit NodeTest() : Node(true, true, true) {
|
||||
//
|
||||
}
|
||||
|
||||
void setup() override {
|
||||
display.printf("Test");
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
7
src/demo/main.cpp
Normal file
7
src/demo/main.cpp
Normal file
@ -0,0 +1,7 @@
|
||||
#include "NodeTest.h"
|
||||
|
||||
auto node = NodeTest();
|
||||
|
||||
Node &patrixGetNode() {
|
||||
return node;
|
||||
}
|
||||
47
src/library.json
Normal file
47
src/library.json
Normal file
@ -0,0 +1,47 @@
|
||||
{
|
||||
"name": "Patrix",
|
||||
"version": "0.1.0",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Patrick Haßel",
|
||||
"email": "development@patrick-hassel.de",
|
||||
"maintainer": true,
|
||||
"url": "https://patrick-hassel.de/"
|
||||
}
|
||||
],
|
||||
"description": "Patrix library",
|
||||
"homepage": "https://patrick-hassel.de/",
|
||||
"license": "MIT",
|
||||
"dependencies": [
|
||||
{
|
||||
"owner": "knolleary",
|
||||
"name": "pubsubclient",
|
||||
"version": "2.8"
|
||||
},
|
||||
{
|
||||
"owner": "bblanchon",
|
||||
"name": "ArduinoJson",
|
||||
"version": "7.3.0"
|
||||
},
|
||||
{
|
||||
"owner": "me-no-dev",
|
||||
"name": "ESPAsyncWebServer",
|
||||
"version": "1.2.4"
|
||||
}
|
||||
],
|
||||
"export": {
|
||||
"exclude": [
|
||||
"src/demo/**"
|
||||
]
|
||||
},
|
||||
"keywords": [
|
||||
"patrix"
|
||||
],
|
||||
"platforms": [
|
||||
"espressif8266",
|
||||
"espressif32"
|
||||
],
|
||||
"frameworks": [
|
||||
"arduino"
|
||||
]
|
||||
}
|
||||
16
src/patrix/Patrix.cpp
Normal file
16
src/patrix/Patrix.cpp
Normal file
@ -0,0 +1,16 @@
|
||||
#include <patrix/Patrix.h>
|
||||
|
||||
void setup() {
|
||||
logSetup();
|
||||
bootDelay();
|
||||
patrixNode.setup();
|
||||
httpSetup();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
wifiLoop();
|
||||
clockLoop();
|
||||
mqttLoop();
|
||||
patrixNode.loop();
|
||||
httpLoop();
|
||||
}
|
||||
17
src/patrix/Patrix.h
Normal file
17
src/patrix/Patrix.h
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef PATRIX_H
|
||||
#define PATRIX_H
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <ESPAsyncWebServer.h>
|
||||
#include <PubSubClient.h>
|
||||
|
||||
#include <patrix/core/boot.h>
|
||||
#include <patrix/core/clock.h>
|
||||
#include <patrix/core/http.h>
|
||||
#include <patrix/core/log.h>
|
||||
#include <patrix/core/mqtt.h>
|
||||
#include <patrix/core/system.h>
|
||||
#include <patrix/core/wifi.h>
|
||||
#include <patrix/node/Node.h>
|
||||
|
||||
#endif
|
||||
95
src/patrix/core/boot.cpp
Normal file
95
src/patrix/core/boot.cpp
Normal file
@ -0,0 +1,95 @@
|
||||
#include <patrix/core/boot.h>
|
||||
#include <patrix/core/clock.h>
|
||||
#include <patrix/core/log.h>
|
||||
#include <patrix/core/wifi.h>
|
||||
#include <patrix/node/Node.h>
|
||||
|
||||
#include "esp32/rom/rtc.h"
|
||||
|
||||
#define BOOT_DELAY_SECONDS 3
|
||||
|
||||
auto failureReset = false;
|
||||
|
||||
const char *getResetReason(const RESET_REASON reason) {
|
||||
switch (reason) {
|
||||
case NO_MEAN: return "NO_MEAN";
|
||||
case POWERON_RESET: return "POWERON_RESET";
|
||||
case SW_RESET: return "SW_RESET";
|
||||
case OWDT_RESET: return "OWDT_RESET";
|
||||
case DEEPSLEEP_RESET: return "DEEPSLEEP_RESET";
|
||||
case SDIO_RESET: return "SDIO_RESET";
|
||||
case TG0WDT_SYS_RESET: return "TG0WDT_SYS_RESET";
|
||||
case TG1WDT_SYS_RESET: return "TG1WDT_SYS_RESET";
|
||||
case RTCWDT_SYS_RESET: return "RTCWDT_SYS_RESET";
|
||||
case INTRUSION_RESET: return "INTRUSION_RESET";
|
||||
case TGWDT_CPU_RESET: return "TGWDT_CPU_RESET";
|
||||
case SW_CPU_RESET: return "SW_CPU_RESET";
|
||||
case RTCWDT_CPU_RESET: return "RTCWDT_CPU_RESET";
|
||||
case EXT_CPU_RESET: return "EXT_CPU_RESET";
|
||||
case RTCWDT_BROWN_OUT_RESET: return "RTCWDT_BROWN_OUT_RESET";
|
||||
case RTCWDT_RTC_RESET: return "RTCWDT_RTC_RESET";
|
||||
default: return "[???]";
|
||||
}
|
||||
}
|
||||
|
||||
void bootReasonLoad() {
|
||||
const auto r0 = rtc_get_reset_reason(0);
|
||||
const auto r1 = rtc_get_reset_reason(1);
|
||||
failureReset = (r0 != POWERON_RESET && r0 != DEEPSLEEP_RESET) || (r1 != POWERON_RESET && r1 != DEEPSLEEP_RESET);
|
||||
if (failureReset) {
|
||||
warn("Forcing OTA delay because of failure-reset: r0=%s, r1=%s", getResetReason(r0), getResetReason(r1));
|
||||
}
|
||||
}
|
||||
|
||||
void boot_waitForWifi() {
|
||||
info("Waiting for WiFi...");
|
||||
while (!isWiFiConnected()) {
|
||||
wifiLoop();
|
||||
yield();
|
||||
}
|
||||
}
|
||||
|
||||
void boot_waitForOTA() {
|
||||
info("Waiting %d seconds for OTA update...", BOOT_DELAY_SECONDS);
|
||||
const auto start = millis();
|
||||
while (millis() - start < BOOT_DELAY_SECONDS * 1000) {
|
||||
wifiLoop();
|
||||
yield();
|
||||
}
|
||||
}
|
||||
|
||||
void boot_waitForClock() {
|
||||
info("Waiting for system time...");
|
||||
while (!isClockSet()) {
|
||||
wifiLoop();
|
||||
clockLoop();
|
||||
yield();
|
||||
}
|
||||
}
|
||||
|
||||
void bootDelay() {
|
||||
bootReasonLoad();
|
||||
|
||||
if (!failureReset && !patrixNode.waitForWiFi && !patrixNode.waitForOTA && !patrixNode.waitForClock) {
|
||||
info("NOT delaying boot.");
|
||||
return;
|
||||
}
|
||||
|
||||
info("Boot delay active...");
|
||||
|
||||
boot_waitForWifi();
|
||||
|
||||
if (failureReset || patrixNode.waitForOTA) {
|
||||
boot_waitForOTA();
|
||||
} else {
|
||||
info("NOT waiting for OTA.");
|
||||
}
|
||||
|
||||
if (patrixNode.waitForClock) {
|
||||
boot_waitForClock();
|
||||
} else {
|
||||
info("NOT waiting for system time.");
|
||||
}
|
||||
|
||||
info("Boot delay complete.");
|
||||
}
|
||||
6
src/patrix/core/boot.h
Normal file
6
src/patrix/core/boot.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef PATRIX_BOOT_H
|
||||
#define PATRIX_BOOT_H
|
||||
|
||||
void bootDelay();
|
||||
|
||||
#endif
|
||||
94
src/patrix/core/clock.cpp
Normal file
94
src/patrix/core/clock.cpp
Normal file
@ -0,0 +1,94 @@
|
||||
#include <WiFi.h>
|
||||
#include <patrix/core/clock.h>
|
||||
#include <patrix/core/log.h>
|
||||
#include <patrix/core/wifi.h>
|
||||
|
||||
#define CLOCK_GMT_OFFSET_SECONDS 3600
|
||||
#define CLOCK_DST_OFFSET_SECONDS 3600
|
||||
#define CLOCK_NTP_SERVER2_URL "de.pool.ntp.org"
|
||||
#define CLOCK_EPOCH_SECONDS_MIN 1735686000
|
||||
|
||||
time_t clockOffset = 0;
|
||||
|
||||
time_t startupTime = 0;
|
||||
|
||||
auto ntpSet = false;
|
||||
|
||||
void clockLoop() {
|
||||
if (isClockSet()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ntpSet && isWiFiConnected()) {
|
||||
configTime(CLOCK_GMT_OFFSET_SECONDS, CLOCK_DST_OFFSET_SECONDS, CLOCK_NTP_SERVER2_URL, WiFi.gatewayIP().toString().c_str());
|
||||
ntpSet = true;
|
||||
}
|
||||
|
||||
const auto now = time(nullptr);
|
||||
if (isCorrectTime(now)) {
|
||||
startupTime = now - clockOffset;
|
||||
info("clock set after %ld seconds! So startup was at %s", clockOffset, getStartupStr());
|
||||
} else {
|
||||
clockOffset = now;
|
||||
}
|
||||
}
|
||||
|
||||
bool isClockSet() {
|
||||
return startupTime != 0;
|
||||
}
|
||||
|
||||
|
||||
char *getClockStr(const time_t epoch) {
|
||||
auto now = epoch;
|
||||
if (now == 0) {
|
||||
now = time(nullptr);
|
||||
}
|
||||
|
||||
tm t{};
|
||||
localtime_r(&now, &t);
|
||||
|
||||
static char buffer[20];
|
||||
snprintf(buffer, sizeof buffer, "%04d-%02d-%02d %02d:%02d:%02d", t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
char *getStartupStr() {
|
||||
return getClockStr(startupTime);
|
||||
}
|
||||
|
||||
time_t getUptimeSeconds() {
|
||||
return time(nullptr) - startupTime;
|
||||
}
|
||||
|
||||
char *getUptimeStr() {
|
||||
const auto totalSeconds = getUptimeSeconds();
|
||||
const auto totalMinutes = totalSeconds / 60;
|
||||
const auto totalHours = totalMinutes / 60;
|
||||
|
||||
const auto partSeconds = totalSeconds % 60;
|
||||
const auto partMinutes = totalMinutes % 60;
|
||||
const auto partHours = totalHours % 24;
|
||||
const auto partDays = totalHours / 24;
|
||||
|
||||
static char buffer[20];
|
||||
snprintf(buffer, sizeof buffer, "%ldd %2ldh %2ldm %2lds", partDays, partHours, partMinutes, partSeconds);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
bool isCorrectTime(const time_t now) {
|
||||
return now >= CLOCK_EPOCH_SECONDS_MIN;
|
||||
}
|
||||
|
||||
time_t clockCorrect(const time_t t) {
|
||||
if (!isClockSet() || isCorrectTime(t)) {
|
||||
return t;
|
||||
}
|
||||
return t + clockOffset;
|
||||
}
|
||||
|
||||
void clockCorrect(time_t *t) {
|
||||
if (!isClockSet() || isCorrectTime(*t)) {
|
||||
return;
|
||||
}
|
||||
*t += clockOffset;
|
||||
}
|
||||
24
src/patrix/core/clock.h
Normal file
24
src/patrix/core/clock.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef PATRIX_CLOCK_H
|
||||
#define PATRIX_CLOCK_H
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
void clockLoop();
|
||||
|
||||
bool isClockSet();
|
||||
|
||||
char *getClockStr(time_t epoch = 0);
|
||||
|
||||
char *getStartupStr();
|
||||
|
||||
time_t getUptimeSeconds();
|
||||
|
||||
char *getUptimeStr();
|
||||
|
||||
bool isCorrectTime(time_t now);
|
||||
|
||||
time_t clockCorrect(time_t t);
|
||||
|
||||
void clockCorrect(time_t *t);
|
||||
|
||||
#endif
|
||||
58
src/patrix/core/http.cpp
Normal file
58
src/patrix/core/http.cpp
Normal file
@ -0,0 +1,58 @@
|
||||
#include <ESPAsyncWebServer.h>
|
||||
#include <patrix/core/log.h>
|
||||
#include <patrix/core/system.h>
|
||||
#include <patrix/node/Node.h>
|
||||
|
||||
AsyncWebServer server(80);
|
||||
|
||||
AsyncWebSocket ws("/ws");
|
||||
|
||||
void httpReboot(AsyncWebServerRequest *request) {
|
||||
info("Rebooting...");
|
||||
request->redirect("/");
|
||||
request->client()->close();
|
||||
yield();
|
||||
delay(500);
|
||||
|
||||
restart();
|
||||
}
|
||||
|
||||
void httpSetup() {
|
||||
ws.onEvent([](AsyncWebSocket *socket, AsyncWebSocketClient *client, AwsEventType type, void *arg, unsigned char *message, unsigned length) {
|
||||
const char *t;
|
||||
switch (type) {
|
||||
case WS_EVT_CONNECT:
|
||||
t = "CONNECT";
|
||||
patrixNode.websocketEvent(socket, client, type, arg, message, length);
|
||||
break;
|
||||
case WS_EVT_DISCONNECT:
|
||||
t = "DISCONNECT";
|
||||
break;
|
||||
case WS_EVT_PONG:
|
||||
t = "PONG";
|
||||
break;
|
||||
case WS_EVT_ERROR:
|
||||
t = "ERROR";
|
||||
break;
|
||||
case WS_EVT_DATA:
|
||||
t = "DATA";
|
||||
break;
|
||||
default:
|
||||
t = "[???]";
|
||||
break;
|
||||
}
|
||||
debug("%s: %s (%d bytes)", client->remoteIP().toString().c_str(), t, length);
|
||||
});
|
||||
server.addHandler(&ws);
|
||||
|
||||
server.on("/reboot", HTTP_GET, httpReboot);
|
||||
server.begin();
|
||||
}
|
||||
|
||||
void httpLoop() {
|
||||
ws.cleanupClients();
|
||||
}
|
||||
|
||||
void websocketSendAll(const String& payload) {
|
||||
ws.textAll(payload);
|
||||
}
|
||||
12
src/patrix/core/http.h
Normal file
12
src/patrix/core/http.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef PATRIX_HTTP_H
|
||||
#define PATRIX_HTTP_H
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
void httpSetup();
|
||||
|
||||
void httpLoop();
|
||||
|
||||
void websocketSendAll(const String& payload);
|
||||
|
||||
#endif
|
||||
75
src/patrix/core/log.cpp
Normal file
75
src/patrix/core/log.cpp
Normal file
@ -0,0 +1,75 @@
|
||||
#include <patrix/core/clock.h>
|
||||
#include <patrix/core/log.h>
|
||||
|
||||
void doLog(LogLevel level, const char *format, va_list args);
|
||||
|
||||
auto logLevel = DEBUG;
|
||||
|
||||
void logSetup() {
|
||||
delay(500);
|
||||
Serial.begin(115200);
|
||||
info("Startup");
|
||||
}
|
||||
|
||||
void log(const LogLevel level, const char *format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
doLog(level, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void error(const char *format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
doLog(ERROR, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void warn(const char *format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
doLog(WARN, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void info(const char *format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
doLog(INFO, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void debug(const char *format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
doLog(DEBUG, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void doLog(const LogLevel level, const char *format, const va_list args) {
|
||||
if (level > logLevel) {
|
||||
return;
|
||||
}
|
||||
Serial.print(getClockStr());
|
||||
switch (level) {
|
||||
case ERROR:
|
||||
Serial.print(" [ERROR] ");
|
||||
break;
|
||||
case WARN:
|
||||
Serial.print(" [WARN ] ");
|
||||
break;
|
||||
case INFO:
|
||||
Serial.print(" [INFO ] ");
|
||||
break;
|
||||
case DEBUG:
|
||||
Serial.print(" [DEBUG] ");
|
||||
break;
|
||||
}
|
||||
|
||||
char message[256];
|
||||
vsnprintf(message, sizeof message, format, args);
|
||||
Serial.print(message);
|
||||
Serial.print("\n");
|
||||
|
||||
yield();
|
||||
}
|
||||
23
src/patrix/core/log.h
Normal file
23
src/patrix/core/log.h
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef PATRIX_LOG_H
|
||||
#define PATRIX_LOG_H
|
||||
|
||||
enum LogLevel {
|
||||
ERROR = 0,
|
||||
WARN = 1,
|
||||
INFO = 2,
|
||||
DEBUG = 3
|
||||
};
|
||||
|
||||
void logSetup();
|
||||
|
||||
void error(const char *format, ...);
|
||||
|
||||
void warn(const char *format, ...);
|
||||
|
||||
void info(const char *format, ...);
|
||||
|
||||
void debug(const char *format, ...);
|
||||
|
||||
void log(LogLevel level, const char *format, ...);
|
||||
|
||||
#endif
|
||||
49
src/patrix/core/mqtt.cpp
Normal file
49
src/patrix/core/mqtt.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
#include <PubSubClient.h>
|
||||
#include <WiFi.h>
|
||||
#include <patrix/core/log.h>
|
||||
#include <patrix/core/mqtt.h>
|
||||
#include <patrix/core/wifi.h>
|
||||
|
||||
#define MQTT_RETRY_DELAY_MILLIS 3000
|
||||
|
||||
WiFiClient wifiClient;
|
||||
|
||||
PubSubClient mqtt(wifiClient);
|
||||
|
||||
auto mqttHost = "10.0.0.50";
|
||||
|
||||
auto mqttPort = 1883;
|
||||
|
||||
auto mqttLastConnectMillis = 0UL;
|
||||
|
||||
char mqttWillTopic[128];
|
||||
|
||||
void mqttLoop() {
|
||||
if (mqtt.loop()) {
|
||||
return;
|
||||
}
|
||||
if (!isWiFiConnected()) {
|
||||
mqttLastConnectMillis = 0;
|
||||
return;
|
||||
}
|
||||
if (mqttLastConnectMillis == 0 || millis() - mqttLastConnectMillis > MQTT_RETRY_DELAY_MILLIS) {
|
||||
snprintf(mqttWillTopic, sizeof(mqttWillTopic), "%s/online", WiFiClass::getHostname());
|
||||
mqtt.setServer(mqttHost, mqttPort);
|
||||
mqtt.setKeepAlive(10);
|
||||
mqtt.setBufferSize(512);
|
||||
mqttLastConnectMillis = millis();
|
||||
info("mqtt connecting: host=%s, port=%d", mqttHost, mqttPort);
|
||||
if (mqtt.connect(WiFiClass::getHostname(), mqttWillTopic, 1, true, "false")) {
|
||||
info("mqtt connected");
|
||||
yield();
|
||||
mqtt.publish(mqttWillTopic, "true", true);
|
||||
yield();
|
||||
} else {
|
||||
error("mqtt failed to connect");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool mqttPublish(const String& topic, const String& payload, const Retain retain) {
|
||||
return mqtt.publish(topic.c_str(), payload.c_str(), retain == RETAIN);
|
||||
}
|
||||
14
src/patrix/core/mqtt.h
Normal file
14
src/patrix/core/mqtt.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef PATRIX_MQTT_H
|
||||
#define PATRIX_MQTT_H
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
enum Retain {
|
||||
NO_RETAIN, RETAIN
|
||||
};
|
||||
|
||||
void mqttLoop();
|
||||
|
||||
bool mqttPublish(const String& topic, const String& payload, Retain retain);
|
||||
|
||||
#endif
|
||||
8
src/patrix/core/system.cpp
Normal file
8
src/patrix/core/system.cpp
Normal file
@ -0,0 +1,8 @@
|
||||
#include <Esp.h>
|
||||
#include <patrix/core/system.h>
|
||||
#include <patrix/core/wifi.h>
|
||||
|
||||
void restart() {
|
||||
wifiOff();
|
||||
ESP.restart();
|
||||
}
|
||||
6
src/patrix/core/system.h
Normal file
6
src/patrix/core/system.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef PATRIX_SYSTEM_H
|
||||
#define PATRIX_SYSTEM_H
|
||||
|
||||
void restart();
|
||||
|
||||
#endif
|
||||
92
src/patrix/core/wifi.cpp
Normal file
92
src/patrix/core/wifi.cpp
Normal file
@ -0,0 +1,92 @@
|
||||
#include <ArduinoOTA.h>
|
||||
#include <patrix/core/log.h>
|
||||
#include <patrix/core/wifi.h>
|
||||
|
||||
#define WIFI_TIMEOUT_MILLIS 10000
|
||||
|
||||
auto wifiEnabled = true;
|
||||
|
||||
auto wifiConnected = false;
|
||||
|
||||
auto wifiTryMillis = 0UL;
|
||||
|
||||
auto wifiSsid = WIFI_SSID;
|
||||
|
||||
auto wifiPkey = WIFI_PKEY;
|
||||
|
||||
auto wifiHost = WIFI_HOST;
|
||||
|
||||
void wifiSetupOTA() {
|
||||
ArduinoOTA.onStart([] {
|
||||
info("beginning ota update...");
|
||||
Serial.print("OTA-UPDATE: 0%");
|
||||
});
|
||||
ArduinoOTA.onProgress([](const unsigned done, const unsigned total) {
|
||||
Serial.printf("\rOTA-UPDATE: %3.0f%%", 100.0 * done / total);
|
||||
});
|
||||
ArduinoOTA.onEnd([] {
|
||||
Serial.print("\rOTA-UPDATE: COMPLETE\n");
|
||||
info("OTA update complete");
|
||||
});
|
||||
ArduinoOTA.onError([](const ota_error_t errorCode) {
|
||||
auto name = "[???]";
|
||||
switch (errorCode) {
|
||||
case OTA_AUTH_ERROR:
|
||||
name = "AUTH";
|
||||
break;
|
||||
case OTA_BEGIN_ERROR:
|
||||
name = "BEGIN";
|
||||
break;
|
||||
case OTA_CONNECT_ERROR:
|
||||
name = "CONNECT";
|
||||
break;
|
||||
case OTA_RECEIVE_ERROR:
|
||||
name = "RECEIVE";
|
||||
break;
|
||||
case OTA_END_ERROR:
|
||||
name = "END";
|
||||
break;
|
||||
}
|
||||
Serial.printf("\nOTA-UPDATE: ERROR #%d=%s\n", errorCode, name);
|
||||
error("OTA update failed: #%d=%s", errorCode, name);
|
||||
});
|
||||
ArduinoOTA.begin();
|
||||
}
|
||||
|
||||
void wifiOff() {
|
||||
info("wifi disabled");
|
||||
wifiEnabled = false;
|
||||
WiFi.disconnect();
|
||||
}
|
||||
|
||||
void wifiLoop() {
|
||||
const auto currentState = WiFi.localIP() != 0;
|
||||
if (wifiConnected != currentState) {
|
||||
wifiConnected = currentState;
|
||||
if (wifiConnected) {
|
||||
info("wifi connected as %s", WiFi.localIP().toString().c_str());
|
||||
wifiSetupOTA();
|
||||
} else {
|
||||
warn("wifi disconnected");
|
||||
ArduinoOTA.end();
|
||||
WiFi.disconnect();
|
||||
}
|
||||
} else if (!wifiConnected) {
|
||||
if (!wifiEnabled) {
|
||||
return;
|
||||
}
|
||||
if (wifiTryMillis == 0 || millis() - wifiTryMillis >= WIFI_TIMEOUT_MILLIS) {
|
||||
wifiTryMillis = millis();
|
||||
WiFiClass::hostname(wifiHost);
|
||||
WiFi.setAutoReconnect(true);
|
||||
info(R"(connecting to SSID "%s" with hostname "%s")", wifiSsid, wifiHost);
|
||||
WiFi.begin(wifiSsid, wifiPkey);
|
||||
}
|
||||
} else {
|
||||
ArduinoOTA.handle();
|
||||
}
|
||||
}
|
||||
|
||||
bool isWiFiConnected() {
|
||||
return wifiConnected;
|
||||
}
|
||||
10
src/patrix/core/wifi.h
Normal file
10
src/patrix/core/wifi.h
Normal file
@ -0,0 +1,10 @@
|
||||
#ifndef PATRIX_WIFI_H
|
||||
#define PATRIX_WIFI_H
|
||||
|
||||
void wifiOff();
|
||||
|
||||
void wifiLoop();
|
||||
|
||||
bool isWiFiConnected();
|
||||
|
||||
#endif
|
||||
4
src/patrix/node/Node.cpp
Normal file
4
src/patrix/node/Node.cpp
Normal file
@ -0,0 +1,4 @@
|
||||
#include <patrix/node/Node.h>
|
||||
|
||||
// ReSharper disable once CppUseAuto
|
||||
Node patrixNode = patrixGetNode();
|
||||
37
src/patrix/node/Node.h
Normal file
37
src/patrix/node/Node.h
Normal file
@ -0,0 +1,37 @@
|
||||
#ifndef NODE_H
|
||||
#define NODE_H
|
||||
|
||||
#include <ESPAsyncWebServer.h>
|
||||
|
||||
class Node {
|
||||
|
||||
public:
|
||||
|
||||
const bool waitForWiFi;
|
||||
|
||||
const bool waitForOTA;
|
||||
|
||||
const bool waitForClock;
|
||||
|
||||
explicit Node(const bool waitForWiFi, const bool waitForOTA, const bool waitForClock)
|
||||
: waitForWiFi(waitForWiFi),
|
||||
waitForOTA(waitForOTA),
|
||||
waitForClock(waitForClock) {
|
||||
//
|
||||
}
|
||||
|
||||
virtual ~Node() = default;
|
||||
|
||||
virtual void setup() {}
|
||||
|
||||
virtual void loop() {}
|
||||
|
||||
virtual void websocketEvent(AsyncWebSocket *socket, AsyncWebSocketClient *client, AwsEventType type, void *arg, unsigned char *message, unsigned length) {}
|
||||
|
||||
};
|
||||
|
||||
extern Node patrixNode;
|
||||
|
||||
Node& patrixGetNode();
|
||||
|
||||
#endif
|
||||
Loading…
Reference in New Issue
Block a user