mqtt and system tabs
This commit is contained in:
parent
0c74411808
commit
3aabf4f8c1
@ -20,7 +20,6 @@ board_build.filesystem = littlefs
|
|||||||
extra_scripts =
|
extra_scripts =
|
||||||
post:scripts/build_interface.py
|
post:scripts/build_interface.py
|
||||||
lib_deps =
|
lib_deps =
|
||||||
adafruit/Adafruit NeoPixel@^1.11.0
|
|
||||||
ottowinter/AsyncMqttClient-esphome@^0.8.6
|
ottowinter/AsyncMqttClient-esphome@^0.8.6
|
||||||
ottowinter/ESPAsyncWebServer-esphome@^3.1.0
|
ottowinter/ESPAsyncWebServer-esphome@^3.1.0
|
||||||
bblanchon/ArduinoJson@^6.21.3
|
bblanchon/ArduinoJson@^6.21.3
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
#include "app/routes.h"
|
#include "app/routes.h"
|
||||||
#include "infra/eth.h"
|
#include "infra/eth.h"
|
||||||
#include "infra/httpServer.h"
|
#include "infra/httpServer.h"
|
||||||
|
#include "infra/mqtt.h"
|
||||||
#include "infra/relay.h"
|
#include "infra/relay.h"
|
||||||
#include "infra/fs.h"
|
#include "infra/fs.h"
|
||||||
#include "config/config.h"
|
#include "config/config.h"
|
||||||
#include "utils/print.h"
|
#include "utils/print.h"
|
||||||
|
#include "utils/settings.h"
|
||||||
|
#include "utils/utils.h"
|
||||||
|
|
||||||
void handleDoorOpen(AsyncWebServerRequest *request) {
|
void handleDoorOpen(AsyncWebServerRequest *request) {
|
||||||
relayTurnOn();
|
relayTurnOn();
|
||||||
@ -31,7 +34,7 @@ void getFeatures(AsyncWebServerRequest *request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void intercomStatus(AsyncWebServerRequest* request) {
|
void intercomStatus(AsyncWebServerRequest* request) {
|
||||||
AsyncJsonResponse* response = new AsyncJsonResponse(false, MAX_AP_STATUS_SIZE);
|
AsyncJsonResponse* response = new AsyncJsonResponse(false, MAX_INTERCOM_STATUS_SIZE);
|
||||||
JsonObject root = response->getRoot();
|
JsonObject root = response->getRoot();
|
||||||
|
|
||||||
root["status"] = 0;
|
root["status"] = 0;
|
||||||
@ -46,25 +49,8 @@ void intercomStatus(AsyncWebServerRequest* request) {
|
|||||||
void networkStatus(AsyncWebServerRequest* request) {
|
void networkStatus(AsyncWebServerRequest* request) {
|
||||||
AsyncJsonResponse* response = new AsyncJsonResponse(false, MAX_NETWORK_STATUS_SIZE);
|
AsyncJsonResponse* response = new AsyncJsonResponse(false, MAX_NETWORK_STATUS_SIZE);
|
||||||
JsonObject root = response->getRoot();
|
JsonObject root = response->getRoot();
|
||||||
wl_status_t status = WL_CONNECTED;
|
|
||||||
|
|
||||||
root["status"] = (uint8_t)status;
|
getEthStatus(root);
|
||||||
if (status == WL_CONNECTED) {
|
|
||||||
root["local_ip"] = ETH.localIP().toString();
|
|
||||||
IPv6Address localIPv6 = ETH.localIPv6();
|
|
||||||
if (!(localIPv6 == IPv6Address()))
|
|
||||||
root["local_ip_v6"] = ETH.localIPv6().toString();
|
|
||||||
root["mac_address"] = ETH.macAddress();
|
|
||||||
root["full_duplex"] = ETH.fullDuplex();
|
|
||||||
root["link_speed"] = ETH.linkSpeed();
|
|
||||||
root["link_up"] = ETH.linkUp();
|
|
||||||
root["network_id"] = ETH.networkID();
|
|
||||||
root["subnet_mask"] = ETH.subnetMask().toString();
|
|
||||||
root["gateway_ip"] = ETH.gatewayIP().toString();
|
|
||||||
IPAddress dnsIP = ETH.dnsIP();
|
|
||||||
if (dnsIP)
|
|
||||||
root["dns_ip"] = dnsIP.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
response->setLength();
|
response->setLength();
|
||||||
request->send(response);
|
request->send(response);
|
||||||
@ -79,20 +65,14 @@ void scanNetworks(AsyncWebServerRequest* request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void networkSettingsRead(AsyncWebServerRequest* request) {
|
static void networkSettingsRead(AsyncWebServerRequest* request) {
|
||||||
AsyncJsonResponse* response = new AsyncJsonResponse(false, MAX_NETWORK_STATUS_SIZE);
|
AsyncJsonResponse* response = new AsyncJsonResponse(false, MAX_NETWORK_SETTINGS_SIZE);
|
||||||
DynamicJsonDocument doc(1024);
|
DynamicJsonDocument doc(1024);
|
||||||
|
|
||||||
bool success = readJsonVariantFromFile(NETWORK_SETTINGS_PATH, doc);
|
bool success = readJsonVariantFromFile(NETWORK_SETTINGS_PATH, doc);
|
||||||
JsonVariant root = doc.as<JsonVariant>();
|
JsonVariant root = doc.as<JsonVariant>();
|
||||||
|
|
||||||
if (!success) {
|
if (!success)
|
||||||
root["static_ip_config"] = false;
|
getDefaultEthConf(root);
|
||||||
root["local_ip"] = ETH.localIP().toString();
|
|
||||||
root["gateway_ip"] = ETH.gatewayIP().toString();
|
|
||||||
root["subnet_mask"] = ETH.subnetMask().toString();
|
|
||||||
root["dns_ip"] = ETH.dnsIP().toString();
|
|
||||||
root["dns_ip_2"] = ETH.dnsIP(1).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
response->setLength();
|
response->setLength();
|
||||||
|
|
||||||
@ -101,24 +81,21 @@ static void networkSettingsRead(AsyncWebServerRequest* request) {
|
|||||||
request->send(200, "application/json", jsonString.c_str());
|
request->send(200, "application/json", jsonString.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void networkSettingsUpdate(AsyncWebServerRequest* request, JsonVariant &json) {
|
static void networkSettingsUpdate(AsyncWebServerRequest *request,
|
||||||
if (!json.is<JsonVariant>()) {
|
uint8_t *data, size_t len, size_t index, size_t total) {
|
||||||
|
DynamicJsonDocument jsonDoc(MAX_NETWORK_SETTINGS_SIZE);
|
||||||
|
String jsonStr = requestDataToStr(data, len);
|
||||||
|
DeserializationError error = deserializeJson(jsonDoc, jsonStr);
|
||||||
|
|
||||||
|
if (!jsonDoc.is<JsonVariant>()) {
|
||||||
request->send(400);
|
request->send(400);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonVariant root = json.as<JsonVariant>();
|
JsonVariant root = jsonDoc.as<JsonVariant>();
|
||||||
|
|
||||||
bool success = writeJsonVariantToFile(NETWORK_SETTINGS_PATH, root);
|
bool success = writeJsonVariantToFile(NETWORK_SETTINGS_PATH, root);
|
||||||
|
|
||||||
setEthConfig(
|
|
||||||
root["static_ip_config"].as<bool>(),
|
|
||||||
root["local_ip"].as<String>(),
|
|
||||||
root["gateway_ip"].as<String>(),
|
|
||||||
root["subnet_mask"].as<String>(),
|
|
||||||
root["dns_ip"].as<String>()
|
|
||||||
);
|
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
String jsonString;
|
String jsonString;
|
||||||
serializeJson(root, jsonString);
|
serializeJson(root, jsonString);
|
||||||
@ -126,6 +103,106 @@ static void networkSettingsUpdate(AsyncWebServerRequest* request, JsonVariant &j
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
request->send(500, "text/plain", "Network settings not updated");
|
request->send(500, "text/plain", "Network settings not updated");
|
||||||
|
|
||||||
|
configureEth(
|
||||||
|
root["static_ip_config"].as<bool>(),
|
||||||
|
root["local_ip"].as<String>(),
|
||||||
|
root["gateway_ip"].as<String>(),
|
||||||
|
root["subnet_mask"].as<String>(),
|
||||||
|
root["dns_ip"].as<String>()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mqttStatus(AsyncWebServerRequest* request) {
|
||||||
|
AsyncJsonResponse* response = new AsyncJsonResponse(false, MAX_MQTT_STATUS_SIZE);
|
||||||
|
JsonObject root = response->getRoot();
|
||||||
|
|
||||||
|
root["enabled"] = getMqttEnabled();
|
||||||
|
root["connected"] = getMqttClient().connected();
|
||||||
|
root["client_id"] = getMqttClient().getClientId();
|
||||||
|
root["disconnect_reason"] = (uint8_t)getMqttDisconnectReason();
|
||||||
|
|
||||||
|
response->setLength();
|
||||||
|
request->send(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mqttSettingsRead(AsyncWebServerRequest* request) {
|
||||||
|
AsyncJsonResponse* response = new AsyncJsonResponse(false, MAX_MQTT_SETTINGS_SIZE);
|
||||||
|
DynamicJsonDocument doc(1024);
|
||||||
|
|
||||||
|
bool success = readJsonVariantFromFile(MQTT_SETTINGS_PATH, doc);
|
||||||
|
JsonVariant root = doc.as<JsonVariant>();
|
||||||
|
|
||||||
|
if (!success)
|
||||||
|
getDefaultMqttConf(root);
|
||||||
|
|
||||||
|
response->setLength();
|
||||||
|
|
||||||
|
String jsonString;
|
||||||
|
serializeJson(root, jsonString);
|
||||||
|
request->send(200, "application/json", jsonString.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mqttSettingsUpdate(AsyncWebServerRequest *request,
|
||||||
|
uint8_t *data, size_t len, size_t index, size_t total) {
|
||||||
|
DynamicJsonDocument jsonDoc(MAX_MQTT_SETTINGS_SIZE);
|
||||||
|
String jsonStr = requestDataToStr(data, len);
|
||||||
|
DeserializationError error = deserializeJson(jsonDoc, jsonStr);
|
||||||
|
|
||||||
|
if (!jsonDoc.is<JsonVariant>() || error) {
|
||||||
|
request->send(400);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonVariant root = jsonDoc.as<JsonVariant>();
|
||||||
|
|
||||||
|
bool fileLoaded = writeJsonVariantToFile(MQTT_SETTINGS_PATH, root);
|
||||||
|
bool enabled = root["enabled"].as<bool>();
|
||||||
|
|
||||||
|
bool mqttConfigured = configureMqtt(
|
||||||
|
root["enabled"].as<bool>(),
|
||||||
|
root["host"].as<String>(),
|
||||||
|
root["port"].as<uint16_t>(),
|
||||||
|
root["username"].as<String>(),
|
||||||
|
root["password"].as<String>(),
|
||||||
|
root["client_id"].as<String>(),
|
||||||
|
root["keep_alive"].as<uint16_t>(),
|
||||||
|
root["clean_session"].as<bool>(),
|
||||||
|
root["max_topic_length"].as<uint16_t>()
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!fileLoaded) {
|
||||||
|
request->send(500, "text/plain", "MQTT settings not updated");
|
||||||
|
} else if (!mqttConfigured && enabled) {
|
||||||
|
request->send(404, "text/plain", "MQTT settings not configured");
|
||||||
|
} else {
|
||||||
|
String jsonString;
|
||||||
|
serializeJson(root, jsonString);
|
||||||
|
request->send(200, "application/json", jsonString.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void systemStatus(AsyncWebServerRequest* request) {
|
||||||
|
AsyncJsonResponse* response = new AsyncJsonResponse(false, MAX_ESP_STATUS_SIZE);
|
||||||
|
JsonObject root = response->getRoot();
|
||||||
|
|
||||||
|
root["esp_platform"] = "esp32";
|
||||||
|
root["max_alloc_heap"] = ESP.getMaxAllocHeap();
|
||||||
|
root["psram_size"] = ESP.getPsramSize();
|
||||||
|
root["free_psram"] = ESP.getFreePsram();
|
||||||
|
root["cpu_freq_mhz"] = ESP.getCpuFreqMHz();
|
||||||
|
root["free_heap"] = ESP.getFreeHeap();
|
||||||
|
root["sketch_size"] = ESP.getSketchSize();
|
||||||
|
root["free_sketch_space"] = ESP.getFreeSketchSpace();
|
||||||
|
root["sdk_version"] = ESP.getSdkVersion();
|
||||||
|
root["flash_chip_size"] = ESP.getFlashChipSize();
|
||||||
|
root["flash_chip_speed"] = ESP.getFlashChipSpeed();
|
||||||
|
|
||||||
|
root["fs_total"] = LittleFS.totalBytes();
|
||||||
|
root["fs_used"] = LittleFS.usedBytes();
|
||||||
|
|
||||||
|
response->setLength();
|
||||||
|
request->send(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleDoorStatus(AsyncWebServerRequest *request) {
|
void handleDoorStatus(AsyncWebServerRequest *request) {
|
||||||
@ -133,14 +210,25 @@ void handleDoorStatus(AsyncWebServerRequest *request) {
|
|||||||
request->send(200, "text/plain", "OK");
|
request->send(200, "text/plain", "OK");
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleBodyRequest(AsyncWebServer& server, const char* uri, WebRequestMethodComposite method, \
|
|
||||||
|
void handleBodyRequest(AsyncWebServer& server, const char* uri, WebRequestMethodComposite method,
|
||||||
ArJsonRequestHandlerFunction onRequest) {
|
ArJsonRequestHandlerFunction onRequest) {
|
||||||
AsyncCallbackJsonWebHandler* handler = \
|
AsyncCallbackJsonWebHandler* handler = \
|
||||||
new AsyncCallbackJsonWebHandler(uri, networkSettingsUpdate);
|
new AsyncCallbackJsonWebHandler(uri, onRequest);
|
||||||
handler->setMethod(method);
|
handler->setMethod(method);
|
||||||
server.addHandler(handler);
|
server.addHandler(handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void restartNow(AsyncWebServerRequest *request) {
|
||||||
|
request->send(200, "text/plain", "OK");
|
||||||
|
ESP.restart();
|
||||||
|
}
|
||||||
|
|
||||||
|
void factoryReset(AsyncWebServerRequest *request) {
|
||||||
|
deleteFilesInDir(FS_CONFIG_DIRECTORY);
|
||||||
|
restartNow(request);
|
||||||
|
}
|
||||||
|
|
||||||
void initRoutes() {
|
void initRoutes() {
|
||||||
AsyncWebServer& server = getServer();
|
AsyncWebServer& server = getServer();
|
||||||
server.on("/api/v1/door/open", handleDoorOpen);
|
server.on("/api/v1/door/open", handleDoorOpen);
|
||||||
@ -150,7 +238,15 @@ void initRoutes() {
|
|||||||
|
|
||||||
server.on("/api/v1/networkStatus", networkStatus);
|
server.on("/api/v1/networkStatus", networkStatus);
|
||||||
server.on("/api/v1/networkSettings", HTTP_GET, networkSettingsRead);
|
server.on("/api/v1/networkSettings", HTTP_GET, networkSettingsRead);
|
||||||
handleBodyRequest(server, "/api/v1/networkSettings", HTTP_POST, networkSettingsUpdate);
|
server.on("/api/v1/networkSettings", HTTP_POST, [](AsyncWebServerRequest *request) {}, NULL, networkSettingsUpdate);
|
||||||
|
|
||||||
server.on("/api/v1/intercomStatus", intercomStatus);
|
server.on("/api/v1/intercomStatus", intercomStatus);
|
||||||
|
|
||||||
|
server.on("/api/v1/mqttStatus", mqttStatus);
|
||||||
|
server.on("/api/v1/mqttSettings", HTTP_GET, mqttSettingsRead);
|
||||||
|
server.on("/api/v1/mqttSettings", HTTP_POST, [](AsyncWebServerRequest *request) {}, NULL, mqttSettingsUpdate);
|
||||||
|
|
||||||
|
server.on("/api/v1/systemStatus", systemStatus);
|
||||||
|
server.on("/api/v1/restart", restartNow);
|
||||||
|
server.on("/api/v1/factoryReset", factoryReset);
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <AsyncJson.h>
|
#include <AsyncJson.h>
|
||||||
|
#include <FS.h>
|
||||||
|
|
||||||
void initRoutes();
|
void initRoutes();
|
@ -1,11 +1,18 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define DEFAULT_STATIC_LOCAL_IP IPAddress(192, 168, 1, 150)
|
#define FACTORY_STATIC_LOCAL_IP IPAddress(192, 168, 1, 150)
|
||||||
#define DEFAULT_STATIC_GATEWAY IPAddress(192, 168, 1, 1)
|
#define FACTORY_STATIC_GATEWAY IPAddress(192, 168, 1, 1)
|
||||||
#define DEFAULT_STATIC_SUBNET IPAddress(255, 255, 255, 0)
|
#define FACTORY_STATIC_SUBNET IPAddress(255, 255, 255, 0)
|
||||||
|
|
||||||
#define MQTT_HOST IPAddress(192, 168, 1, 173)
|
#define FACTORY_MQTT_ENABLED false
|
||||||
#define MQTT_PORT 1883
|
#define FACTORY_MQTT_HOST ""
|
||||||
|
#define FACTORY_MQTT_PORT 1883
|
||||||
|
#define FACTORY_MQTT_USERNAME ""
|
||||||
|
#define FACTORY_MQTT_PASSWORD ""
|
||||||
|
#define FACTORY_MQTT_CLIENT_ID "#{platform}-#{unique_id}"
|
||||||
|
#define FACTORY_MQTT_KEEP_ALIVE 16
|
||||||
|
#define FACTORY_MQTT_CLEAN_SESSION true
|
||||||
|
#define FACTORY_MQTT_MAX_TOPIC_LENGTH 128
|
||||||
|
|
||||||
#define SERIAL_NUMBER "4823"
|
#define SERIAL_NUMBER "4823"
|
||||||
|
|
||||||
@ -21,13 +28,18 @@
|
|||||||
#define DOOR_SENS_PIN 114
|
#define DOOR_SENS_PIN 114
|
||||||
|
|
||||||
#define DATA_PIN 12
|
#define DATA_PIN 12
|
||||||
#define DATA_PERIOD 240 // microseconds
|
#define DATA_PERIOD 120 // microseconds
|
||||||
|
|
||||||
#define PRINT_RAW_SIGNAL_FLAG 0
|
#define PRINT_RAW_SIGNAL_FLAG 1
|
||||||
|
|
||||||
#define MAX_FEATURES_SIZE 256
|
#define MAX_FEATURES_SIZE 256
|
||||||
#define MAX_AP_STATUS_SIZE 1024
|
|
||||||
#define MAX_NETWORK_STATUS_SIZE 1024
|
#define MAX_NETWORK_STATUS_SIZE 1024
|
||||||
#define MAX_NETWORK_SETTINGS_SIZE 1024
|
#define MAX_NETWORK_SETTINGS_SIZE 1024
|
||||||
|
#define MAX_INTERCOM_STATUS_SIZE 1024
|
||||||
|
#define MAX_MQTT_STATUS_SIZE 1024
|
||||||
|
#define MAX_MQTT_SETTINGS_SIZE 1024
|
||||||
|
#define MAX_ESP_STATUS_SIZE 1024
|
||||||
|
|
||||||
|
#define FS_CONFIG_DIRECTORY "/config"
|
||||||
#define NETWORK_SETTINGS_PATH "/config/networkSettings.json"
|
#define NETWORK_SETTINGS_PATH "/config/networkSettings.json"
|
||||||
|
#define MQTT_SETTINGS_PATH "/config/mqttSettings.json"
|
@ -38,7 +38,7 @@ void receiveData(int data) {
|
|||||||
previousData = data;
|
previousData = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void changeState(State state, bool resetCountersFlag=true) {
|
void changeState(State state, bool resetCountersFlag) {
|
||||||
currentState = state;
|
currentState = state;
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
@ -140,3 +140,7 @@ void updateStateMachine(int data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void initStateMachine() {
|
||||||
|
changeState(CONNECTED);
|
||||||
|
}
|
@ -19,5 +19,7 @@ enum State {
|
|||||||
|
|
||||||
void resetCounters();
|
void resetCounters();
|
||||||
void updateStateMachine(int data);
|
void updateStateMachine(int data);
|
||||||
|
void initStateMachine();
|
||||||
|
void changeState(State state, bool resetCountersFlag=true);
|
||||||
|
|
||||||
#endif // STATE_MACHINE_H
|
#endif // STATE_MACHINE_H
|
@ -1,12 +1,11 @@
|
|||||||
#include <ArduinoJson.h>
|
|
||||||
#include "infra/eth.h"
|
#include "infra/eth.h"
|
||||||
#include "infra/fs.h"
|
#include "infra/fs.h"
|
||||||
#include "infra/mqtt.h"
|
#include "infra/mqtt.h"
|
||||||
#include "config/config.h"
|
#include "config/config.h"
|
||||||
#include "utils/print.h"
|
#include "utils/print.h"
|
||||||
|
|
||||||
extern bool eth_connected;
|
|
||||||
TimerHandle_t ethReconnectTimer;
|
TimerHandle_t ethReconnectTimer;
|
||||||
|
wl_status_t status;
|
||||||
|
|
||||||
void WiFiEvent(WiFiEvent_t event)
|
void WiFiEvent(WiFiEvent_t event)
|
||||||
{
|
{
|
||||||
@ -19,6 +18,7 @@ void WiFiEvent(WiFiEvent_t event)
|
|||||||
break;
|
break;
|
||||||
case ARDUINO_EVENT_ETH_CONNECTED:
|
case ARDUINO_EVENT_ETH_CONNECTED:
|
||||||
Serial.println("ETH Connected");
|
Serial.println("ETH Connected");
|
||||||
|
status = WL_CONNECTED;
|
||||||
break;
|
break;
|
||||||
case ARDUINO_EVENT_ETH_GOT_IP:
|
case ARDUINO_EVENT_ETH_GOT_IP:
|
||||||
Serial.print("ETH MAC: ");
|
Serial.print("ETH MAC: ");
|
||||||
@ -31,17 +31,14 @@ void WiFiEvent(WiFiEvent_t event)
|
|||||||
Serial.print(", ");
|
Serial.print(", ");
|
||||||
Serial.print(ETH.linkSpeed());
|
Serial.print(ETH.linkSpeed());
|
||||||
Serial.println("Mbps");
|
Serial.println("Mbps");
|
||||||
eth_connected = true;
|
|
||||||
delay(2000);
|
delay(2000);
|
||||||
connectToMqtt();
|
|
||||||
break;
|
break;
|
||||||
case ARDUINO_EVENT_ETH_DISCONNECTED:
|
case ARDUINO_EVENT_ETH_DISCONNECTED:
|
||||||
Serial.println("ETH Disconnected");
|
Serial.println("ETH Disconnected");
|
||||||
eth_connected = false;
|
status = WL_DISCONNECTED;
|
||||||
break;
|
break;
|
||||||
case ARDUINO_EVENT_ETH_STOP:
|
case ARDUINO_EVENT_ETH_STOP:
|
||||||
Serial.println("ETH Stopped");
|
Serial.println("ETH Stopped");
|
||||||
eth_connected = false;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -67,15 +64,12 @@ void WiFiEvent(WiFiEvent_t event)
|
|||||||
Serial.print(", ");
|
Serial.print(", ");
|
||||||
Serial.print(ETH.linkSpeed());
|
Serial.print(ETH.linkSpeed());
|
||||||
Serial.println("Mbps");
|
Serial.println("Mbps");
|
||||||
eth_connected = true;
|
|
||||||
break;
|
break;
|
||||||
case SYSTEM_EVENT_ETH_DISCONNECTED:
|
case SYSTEM_EVENT_ETH_DISCONNECTED:
|
||||||
Serial.println("ETH Disconnected");
|
Serial.println("ETH Disconnected");
|
||||||
eth_connected = false;
|
|
||||||
break;
|
break;
|
||||||
case SYSTEM_EVENT_ETH_STOP:
|
case SYSTEM_EVENT_ETH_STOP:
|
||||||
Serial.println("ETH Stopped");
|
Serial.println("ETH Stopped");
|
||||||
eth_connected = false;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -83,75 +77,7 @@ void WiFiEvent(WiFiEvent_t event)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool loadEthConfig() {
|
void configureEth(bool isStatic, String localIp, String gateway,
|
||||||
DynamicJsonDocument doc(1024);
|
|
||||||
|
|
||||||
bool success = readJsonVariantFromFile(NETWORK_SETTINGS_PATH, doc);
|
|
||||||
|
|
||||||
if (!success)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
JsonVariant root = doc.as<JsonVariant>();
|
|
||||||
|
|
||||||
setEthConfig(
|
|
||||||
root["static_ip_config"].as<bool>(),
|
|
||||||
root["local_ip"].as<String>(),
|
|
||||||
root["gateway_ip"].as<String>(),
|
|
||||||
root["subnet_mask"].as<String>(),
|
|
||||||
root["dns_ip"].as<String>()
|
|
||||||
);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void initEth() {
|
|
||||||
pinMode(NRST, OUTPUT);
|
|
||||||
digitalWrite(NRST, 0);
|
|
||||||
delay(200);
|
|
||||||
digitalWrite(NRST, 1);
|
|
||||||
delay(200);
|
|
||||||
digitalWrite(NRST, 0);
|
|
||||||
delay(200);
|
|
||||||
digitalWrite(NRST, 1);
|
|
||||||
delay(200);
|
|
||||||
|
|
||||||
ETH.begin(ETH_ADDR,
|
|
||||||
ETH_POWER_PIN,
|
|
||||||
ETH_MDC_PIN,
|
|
||||||
ETH_MDIO_PIN,
|
|
||||||
ETH_TYPE,
|
|
||||||
ETH_CLK_MODE);
|
|
||||||
|
|
||||||
if (!loadEthConfig() && DEFAULT_STATIC_LOCAL_IP) {
|
|
||||||
ETH.config(
|
|
||||||
DEFAULT_STATIC_LOCAL_IP,
|
|
||||||
DEFAULT_STATIC_GATEWAY,
|
|
||||||
DEFAULT_STATIC_SUBNET
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void testClient(const char * host, uint16_t port)
|
|
||||||
{
|
|
||||||
Serial.print("\nconnecting to ");
|
|
||||||
Serial.println(host);
|
|
||||||
|
|
||||||
WiFiClient client;
|
|
||||||
if (!client.connect(host, port)) {
|
|
||||||
Serial.println("connection failed");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
client.printf("GET / HTTP/1.1\r\nHost: %s\r\n\r\n", host);
|
|
||||||
while (client.connected() && !client.available());
|
|
||||||
while (client.available()) {
|
|
||||||
Serial.write(client.read());
|
|
||||||
}
|
|
||||||
|
|
||||||
Serial.println("closing connection\n");
|
|
||||||
client.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
void setEthConfig(bool isStatic, String localIp, String gateway,
|
|
||||||
String subnet, String dns1, String dns2) {
|
String subnet, String dns1, String dns2) {
|
||||||
IPAddress newLocalIp = IPAddress();
|
IPAddress newLocalIp = IPAddress();
|
||||||
IPAddress newGateway = IPAddress();
|
IPAddress newGateway = IPAddress();
|
||||||
@ -174,6 +100,120 @@ String subnet, String dns1, String dns2) {
|
|||||||
newDns2
|
newDns2
|
||||||
);
|
);
|
||||||
else {
|
else {
|
||||||
|
//ESP.restart();
|
||||||
ETH.config((uint32_t)0, (uint32_t)0, (uint32_t)0);
|
ETH.config((uint32_t)0, (uint32_t)0, (uint32_t)0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void configureEth(JsonVariant& root) {
|
||||||
|
configureEth(
|
||||||
|
root["static_ip_config"].as<bool>(),
|
||||||
|
root["local_ip"].as<String>(),
|
||||||
|
root["gateway_ip"].as<String>(),
|
||||||
|
root["subnet_mask"].as<String>(),
|
||||||
|
root["dns_ip"].as<String>()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void getDefaultEthConf(JsonVariant& root) {
|
||||||
|
root["static_ip_config"] = true;
|
||||||
|
root["local_ip"] = ETH.localIP().toString();
|
||||||
|
root["gateway_ip"] = ETH.gatewayIP().toString();
|
||||||
|
root["subnet_mask"] = ETH.subnetMask().toString();
|
||||||
|
root["dns_ip"] = ETH.dnsIP().toString();
|
||||||
|
root["dns_ip_2"] = ETH.dnsIP(1).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void getEthStatus(JsonObject& root) {
|
||||||
|
root["status"] = (uint8_t)status;
|
||||||
|
|
||||||
|
if (status == WL_CONNECTED) {
|
||||||
|
root["local_ip"] = ETH.localIP().toString();
|
||||||
|
IPv6Address localIPv6 = ETH.localIPv6();
|
||||||
|
if (!(localIPv6 == IPv6Address()))
|
||||||
|
root["local_ip_v6"] = ETH.localIPv6().toString();
|
||||||
|
root["mac_address"] = ETH.macAddress();
|
||||||
|
root["full_duplex"] = ETH.fullDuplex();
|
||||||
|
root["link_speed"] = ETH.linkSpeed();
|
||||||
|
root["link_up"] = ETH.linkUp();
|
||||||
|
root["network_id"] = ETH.networkID();
|
||||||
|
root["subnet_mask"] = ETH.subnetMask().toString();
|
||||||
|
root["gateway_ip"] = ETH.gatewayIP().toString();
|
||||||
|
|
||||||
|
IPAddress dnsIP = ETH.dnsIP();
|
||||||
|
if (dnsIP)
|
||||||
|
root["dns_ip"] = dnsIP.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool loadEthConfig() {
|
||||||
|
DynamicJsonDocument doc(1024);
|
||||||
|
|
||||||
|
bool success = readJsonVariantFromFile(NETWORK_SETTINGS_PATH, doc);
|
||||||
|
|
||||||
|
if (!success)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
JsonVariant root = doc.as<JsonVariant>();
|
||||||
|
|
||||||
|
configureEth(root);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void initEth() {
|
||||||
|
pinMode(NRST, OUTPUT);
|
||||||
|
digitalWrite(NRST, 0);
|
||||||
|
delay(200);
|
||||||
|
digitalWrite(NRST, 1);
|
||||||
|
delay(200);
|
||||||
|
digitalWrite(NRST, 0);
|
||||||
|
delay(200);
|
||||||
|
digitalWrite(NRST, 1);
|
||||||
|
delay(200);
|
||||||
|
|
||||||
|
ETH.begin(ETH_ADDR,
|
||||||
|
ETH_POWER_PIN,
|
||||||
|
ETH_MDC_PIN,
|
||||||
|
ETH_MDIO_PIN,
|
||||||
|
ETH_TYPE,
|
||||||
|
ETH_CLK_MODE);
|
||||||
|
|
||||||
|
if (!loadEthConfig() && FACTORY_STATIC_LOCAL_IP) {
|
||||||
|
ETH.config(
|
||||||
|
FACTORY_STATIC_LOCAL_IP,
|
||||||
|
FACTORY_STATIC_GATEWAY,
|
||||||
|
FACTORY_STATIC_SUBNET
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void testClient(const char * host, uint16_t port) {
|
||||||
|
Serial.print("\nconnecting to ");
|
||||||
|
Serial.println(host);
|
||||||
|
|
||||||
|
WiFiClient client;
|
||||||
|
if (!client.connect(host, port)) {
|
||||||
|
Serial.println("connection failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
client.printf("GET / HTTP/1.1\r\nHost: %s\r\n\r\n", host);
|
||||||
|
while (client.connected() && !client.available());
|
||||||
|
while (client.available()) {
|
||||||
|
Serial.write(client.read());
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.println("closing connection\n");
|
||||||
|
client.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool checkHost(const char* host, uint16_t port) {
|
||||||
|
WiFiClient client;
|
||||||
|
|
||||||
|
if (client.connect(host, port)) {
|
||||||
|
client.stop();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <ETH.h>
|
#include <ETH.h>
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ETH_CLOCK_GPIO0_IN - default: external clock from crystal oscillator
|
* ETH_CLOCK_GPIO0_IN - default: external clock from crystal oscillator
|
||||||
@ -30,7 +31,9 @@
|
|||||||
void WiFiEvent(WiFiEvent_t event);
|
void WiFiEvent(WiFiEvent_t event);
|
||||||
void initEth();
|
void initEth();
|
||||||
void testClient(const char * host, uint16_t port);
|
void testClient(const char * host, uint16_t port);
|
||||||
void setEthConfig(
|
bool checkHost(const char* host, uint16_t port);
|
||||||
|
void getEthStatus(JsonObject& root);
|
||||||
|
void configureEth(
|
||||||
bool isStatic,
|
bool isStatic,
|
||||||
String localIp,
|
String localIp,
|
||||||
String gateway,
|
String gateway,
|
||||||
@ -38,3 +41,5 @@ void setEthConfig(
|
|||||||
String dns1="",
|
String dns1="",
|
||||||
String dns2=""
|
String dns2=""
|
||||||
);
|
);
|
||||||
|
void configureEth(JsonVariant& root);
|
||||||
|
void getDefaultEthConf(JsonVariant& root);
|
@ -24,7 +24,7 @@ bool readJsonVariantFromFile(const char* file_path, DynamicJsonDocument& jsonDoc
|
|||||||
}
|
}
|
||||||
|
|
||||||
String fileContent = file.readString();
|
String fileContent = file.readString();
|
||||||
println("Reading config: ", fileContent);
|
println("Reading config: ", file_path, ", content:", fileContent);
|
||||||
|
|
||||||
DeserializationError error = deserializeJson(jsonDoc, fileContent);
|
DeserializationError error = deserializeJson(jsonDoc, fileContent);
|
||||||
|
|
||||||
@ -62,10 +62,32 @@ bool writeJsonVariantToFile(const char* file_path, JsonVariant& jsonVariant) {
|
|||||||
|
|
||||||
String jsonString;
|
String jsonString;
|
||||||
serializeJson(jsonVariant, jsonString);
|
serializeJson(jsonVariant, jsonString);
|
||||||
println("Writing config: ", jsonString);
|
println("Writing config: ", file_path, ", content:", jsonString);
|
||||||
file.print(jsonString);
|
file.print(jsonString);
|
||||||
|
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void deleteFilesInDir(const char* path) {
|
||||||
|
File dir = LittleFS.open(path);
|
||||||
|
if (!dir.isDirectory()) {
|
||||||
|
Serial.println("Not a directory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
File file = dir.openNextFile();
|
||||||
|
while (file) {
|
||||||
|
String fullPath = String(path) + '/' + String(file.name());
|
||||||
|
if (file.isDirectory()) {
|
||||||
|
deleteFilesInDir(fullPath.c_str());
|
||||||
|
} else {
|
||||||
|
file.close();
|
||||||
|
LittleFS.remove(fullPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
file = dir.openNextFile();
|
||||||
|
}
|
||||||
|
dir.close();
|
||||||
|
}
|
||||||
|
@ -5,3 +5,4 @@
|
|||||||
void initFileSystem();
|
void initFileSystem();
|
||||||
bool readJsonVariantFromFile(const char* filename, DynamicJsonDocument& jsonDoc);
|
bool readJsonVariantFromFile(const char* filename, DynamicJsonDocument& jsonDoc);
|
||||||
bool writeJsonVariantToFile(const char* filename, JsonVariant& jsonObj);
|
bool writeJsonVariantToFile(const char* filename, JsonVariant& jsonObj);
|
||||||
|
void deleteFilesInDir(const char* path);
|
0
src/infra/intercom.cpp
Normal file
0
src/infra/intercom.cpp
Normal file
0
src/infra/intercom.h
Normal file
0
src/infra/intercom.h
Normal file
@ -1,16 +1,23 @@
|
|||||||
#include <Arduino.h>
|
|
||||||
#include <ETH.h>
|
|
||||||
|
|
||||||
#include "config/config.h"
|
#include "config/config.h"
|
||||||
#include "infra/mqtt.h"
|
#include "infra/mqtt.h"
|
||||||
|
#include "infra/eth.h"
|
||||||
|
#include "infra/fs.h"
|
||||||
|
#include "utils/settings.h"
|
||||||
|
|
||||||
AsyncMqttClient mqttClient;
|
AsyncMqttClient mqttClient;
|
||||||
TimerHandle_t mqttReconnectTimer;
|
TimerHandle_t mqttReconnectTimer;
|
||||||
|
AsyncMqttClientDisconnectReason mqttDisconnectReason;
|
||||||
|
|
||||||
void connectToMqtt() {
|
DynamicJsonDocument mqttConf(1024);
|
||||||
Serial.println("Connecting to MQTT...");
|
bool mqttConnected = false;
|
||||||
mqttClient.connect();
|
bool mqttEnabled = true;
|
||||||
}
|
|
||||||
|
// Pointers to hold retained copies of the mqtt client connection strings.
|
||||||
|
// This is required as AsyncMqttClient holds refrences to the supplied connection strings.
|
||||||
|
char* retainedHost;
|
||||||
|
char* retainedClientId;
|
||||||
|
char* retainedUsername;
|
||||||
|
char* retainedPassword;
|
||||||
|
|
||||||
void publishToMQTT(const char* topic, const char* message) {
|
void publishToMQTT(const char* topic, const char* message) {
|
||||||
mqttClient.publish(topic, 2, true, message);
|
mqttClient.publish(topic, 2, true, message);
|
||||||
@ -38,6 +45,8 @@ void onMqttConnect(bool sessionPresent) {
|
|||||||
Serial.print("Session present: ");
|
Serial.print("Session present: ");
|
||||||
Serial.println(sessionPresent);
|
Serial.println(sessionPresent);
|
||||||
|
|
||||||
|
mqttConnected = true;
|
||||||
|
|
||||||
publishToMQTT(MAC_ADDRESS_MQTT_TOPIC, ETH.macAddress().c_str());
|
publishToMQTT(MAC_ADDRESS_MQTT_TOPIC, ETH.macAddress().c_str());
|
||||||
publishToMQTT(IP_ADDRESS_MQTT_TOPIC, ETH.localIP().toString().c_str());
|
publishToMQTT(IP_ADDRESS_MQTT_TOPIC, ETH.localIP().toString().c_str());
|
||||||
publishToMQTT(SERIAL_NUMBER_MQTT_TOPIC, SERIAL_NUMBER);
|
publishToMQTT(SERIAL_NUMBER_MQTT_TOPIC, SERIAL_NUMBER);
|
||||||
@ -49,9 +58,8 @@ void onMqttConnect(bool sessionPresent) {
|
|||||||
|
|
||||||
void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) {
|
void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) {
|
||||||
Serial.println("Disconnected from MQTT.");
|
Serial.println("Disconnected from MQTT.");
|
||||||
if (WiFi.isConnected()) {
|
mqttConnected = false;
|
||||||
xTimerStart(mqttReconnectTimer, 0);
|
mqttDisconnectReason = reason;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void onMqttSubscribe(uint16_t packetId, uint8_t qos) {
|
void onMqttSubscribe(uint16_t packetId, uint8_t qos) {
|
||||||
@ -74,14 +82,157 @@ void onMqttPublish(uint16_t packetId) {
|
|||||||
Serial.println(packetId);
|
Serial.println(packetId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void initMQTT() {
|
AsyncMqttClient& getMqttClient() {
|
||||||
mqttReconnectTimer = xTimerCreate("mqttTimer", pdMS_TO_TICKS(2000), pdFALSE, (void*)0, reinterpret_cast<TimerCallbackFunction_t>(connectToMqtt));
|
return mqttClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
AsyncMqttClientDisconnectReason& getMqttDisconnectReason() {
|
||||||
|
return mqttDisconnectReason;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool getMqttConnected() {
|
||||||
|
return mqttConnected;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool getMqttEnabled() {
|
||||||
|
return mqttEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retains a copy of the cstr provided in the pointer provided using dynamic allocation.
|
||||||
|
*
|
||||||
|
* Frees the pointer before allocation and leaves it as nullptr if cstr == nullptr.
|
||||||
|
*/
|
||||||
|
static char* retainCstr(const char* cstr, char** ptr) {
|
||||||
|
// free up previously retained value if exists
|
||||||
|
free(*ptr);
|
||||||
|
*ptr = nullptr;
|
||||||
|
|
||||||
|
// dynamically allocate and copy cstr (if non null)
|
||||||
|
if (cstr != nullptr) {
|
||||||
|
*ptr = (char*)malloc(strlen(cstr) + 1);
|
||||||
|
strcpy(*ptr, cstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// return reference to pointer for convenience
|
||||||
|
return *ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setMqttServer(String host, uint16_t port) {
|
||||||
|
Serial.print("MQTT server: ");
|
||||||
|
Serial.print(host);
|
||||||
|
Serial.print(":");
|
||||||
|
Serial.println(port);
|
||||||
|
mqttClient.setServer(retainCstr(host.c_str(), &retainedHost), port);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool checkMqttHost(String host, uint16_t port) {
|
||||||
|
if (!checkHost(host.c_str(), port)) {
|
||||||
|
Serial.print("MQTT host is not responding: ");
|
||||||
|
Serial.print(host);
|
||||||
|
Serial.print(":");
|
||||||
|
Serial.println(port);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool configureMqtt(bool enabled, String host, uint16_t port, String username, String password,
|
||||||
|
String clientId, uint16_t keepAlive, bool cleanSession, uint16_t maxTopicLength) {
|
||||||
|
if (!mqttEnabled) {
|
||||||
|
mqttEnabled = enabled;
|
||||||
|
return checkMqttHost(host, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
mqttEnabled = enabled;
|
||||||
|
mqttClient.disconnect();
|
||||||
|
|
||||||
|
if (!checkMqttHost(host, port))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (enabled) {
|
||||||
|
Serial.println(F("Reconnecting to MQTT..."));
|
||||||
|
setMqttServer(host, port);
|
||||||
|
if (username.length() > 0) {
|
||||||
|
mqttClient.setCredentials(
|
||||||
|
retainCstr(username.c_str(), &retainedUsername),
|
||||||
|
retainCstr(password.length() > 0 ? password.c_str() : nullptr, &retainedPassword));
|
||||||
|
} else {
|
||||||
|
mqttClient.setCredentials(retainCstr(nullptr, &retainedUsername), retainCstr(nullptr, &retainedPassword));
|
||||||
|
}
|
||||||
|
mqttClient.setClientId(retainCstr(clientId.c_str(), &retainedClientId));
|
||||||
|
mqttClient.setKeepAlive(keepAlive);
|
||||||
|
mqttClient.setCleanSession(cleanSession);
|
||||||
|
mqttClient.setMaxTopicLength(maxTopicLength);
|
||||||
|
mqttClient.connect();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool configureMqtt(JsonVariant& root) {
|
||||||
|
configureMqtt(
|
||||||
|
root["enabled"].as<bool>(),
|
||||||
|
root["host"].as<String>(),
|
||||||
|
root["port"].as<uint16_t>(),
|
||||||
|
root["username"].as<String>(),
|
||||||
|
root["password"].as<String>(),
|
||||||
|
root["client_id"].as<String>(),
|
||||||
|
root["keep_alive"].as<uint16_t>(),
|
||||||
|
root["clean_session"].as<bool>(),
|
||||||
|
root["max_topic_length"].as<uint16_t>()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void getDefaultMqttConf(JsonVariant& root) {
|
||||||
|
root["enabled"] = FACTORY_MQTT_ENABLED;
|
||||||
|
root["host"] = FACTORY_MQTT_HOST;
|
||||||
|
root["port"] = FACTORY_MQTT_PORT;
|
||||||
|
root["username"] = FACTORY_MQTT_USERNAME;
|
||||||
|
root["password"] = FACTORY_MQTT_PASSWORD;
|
||||||
|
root["client_id"] = formatSetting(FACTORY_MQTT_CLIENT_ID);
|
||||||
|
root["keep_alive"] = FACTORY_MQTT_KEEP_ALIVE;
|
||||||
|
root["clean_session"] = FACTORY_MQTT_CLEAN_SESSION;
|
||||||
|
root["max_topic_length"] = FACTORY_MQTT_MAX_TOPIC_LENGTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool loadMqttConfig() {
|
||||||
|
bool success = readJsonVariantFromFile(MQTT_SETTINGS_PATH, mqttConf);
|
||||||
|
|
||||||
|
if (!success)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reconnectMQTTIfNeeded() {
|
||||||
|
if (!mqttClient.connected()) {
|
||||||
|
if (mqttConf.isNull())
|
||||||
|
loadMqttConfig();
|
||||||
|
|
||||||
|
JsonVariant root = mqttConf.as<JsonVariant>();
|
||||||
|
|
||||||
|
if (!mqttConf.is<JsonVariant>())
|
||||||
|
return;
|
||||||
|
|
||||||
|
bool mqttConfigured = configureMqtt(
|
||||||
|
root["enabled"].as<bool>(),
|
||||||
|
root["host"].as<String>(),
|
||||||
|
root["port"].as<uint16_t>(),
|
||||||
|
root["username"].as<String>(),
|
||||||
|
root["password"].as<String>(),
|
||||||
|
root["client_id"].as<String>(),
|
||||||
|
root["keep_alive"].as<uint16_t>(),
|
||||||
|
root["clean_session"].as<bool>(),
|
||||||
|
root["max_topic_length"].as<uint16_t>()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void initMQTT() {
|
||||||
mqttClient.onConnect(onMqttConnect);
|
mqttClient.onConnect(onMqttConnect);
|
||||||
mqttClient.onDisconnect(onMqttDisconnect);
|
mqttClient.onDisconnect(onMqttDisconnect);
|
||||||
mqttClient.onSubscribe(onMqttSubscribe);
|
mqttClient.onSubscribe(onMqttSubscribe);
|
||||||
mqttClient.onUnsubscribe(onMqttUnsubscribe);
|
mqttClient.onUnsubscribe(onMqttUnsubscribe);
|
||||||
//mqttClient.onMessage(onMqttMessage);
|
//mqttClient.onMessage(onMqttMessage);
|
||||||
//mqttClient.onPublish(onMqttPublish);
|
//mqttClient.onPublish(onMqttPublish);
|
||||||
mqttClient.setServer(MQTT_HOST, MQTT_PORT);
|
|
||||||
}
|
}
|
@ -1,17 +1,37 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
#include <ETH.h>
|
||||||
#include <HTTPClient.h>
|
#include <HTTPClient.h>
|
||||||
#include <AsyncMqttClient.h>
|
#include <AsyncMqttClient.h>
|
||||||
|
|
||||||
void connectToMqtt();
|
|
||||||
void onMqttConnect(bool sessionPresent);
|
void onMqttConnect(bool sessionPresent);
|
||||||
void onMqttDisconnect(AsyncMqttClientDisconnectReason reason);
|
void onMqttDisconnect(AsyncMqttClientDisconnectReason reason);
|
||||||
void onMqttSubscribe(uint16_t packetId, uint8_t qos);
|
void onMqttSubscribe(uint16_t packetId, uint8_t qos);
|
||||||
void onMqttUnsubscribe(uint16_t packetId);
|
void onMqttUnsubscribe(uint16_t packetId);
|
||||||
void onMqttPublish(uint16_t packetId);
|
void onMqttPublish(uint16_t packetId);
|
||||||
void sendDataToMQTT(int flatNumber);
|
|
||||||
void publishToMQTT(const char* topic, const char* message);
|
void publishToMQTT(const char* topic, const char* message);
|
||||||
void publishToMQTT(const char* topic, int message);
|
void publishToMQTT(const char* topic, int message);
|
||||||
void publishToMQTT(const char* topic, float message);
|
void publishToMQTT(const char* topic, float message);
|
||||||
void publishToMQTT(const char* topic, bool message);
|
void publishToMQTT(const char* topic, bool message);
|
||||||
void initMQTT();
|
void initMQTT();
|
||||||
|
|
||||||
|
AsyncMqttClient& getMqttClient();
|
||||||
|
AsyncMqttClientDisconnectReason& getMqttDisconnectReason();
|
||||||
|
bool getMqttConnected();
|
||||||
|
bool getMqttEnabled();
|
||||||
|
bool configureMqtt(
|
||||||
|
bool enabled,
|
||||||
|
String host,
|
||||||
|
uint16_t port,
|
||||||
|
String username,
|
||||||
|
String password,
|
||||||
|
String clientId,
|
||||||
|
uint16_t keepAlive,
|
||||||
|
bool cleanSession,
|
||||||
|
uint16_t maxTopicLength
|
||||||
|
);
|
||||||
|
void getDefaultMqttConf(JsonVariant& root);
|
||||||
|
bool configureMqtt(JsonVariant& root);
|
||||||
|
void reconnectMQTTIfNeeded();
|
0
src/infra/system.cpp
Normal file
0
src/infra/system.cpp
Normal file
0
src/infra/system.h
Normal file
0
src/infra/system.h
Normal file
21
src/main.cpp
21
src/main.cpp
@ -22,10 +22,10 @@
|
|||||||
uint32_t lastMillis;
|
uint32_t lastMillis;
|
||||||
uint64_t lastMicros;
|
uint64_t lastMicros;
|
||||||
|
|
||||||
bool eth_connected = false;
|
|
||||||
|
|
||||||
int data = 0;
|
int data = 0;
|
||||||
|
|
||||||
|
bool flag = false;
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
|
|
||||||
@ -44,6 +44,7 @@ void setup() {
|
|||||||
relayTurnOn();
|
relayTurnOn();
|
||||||
delay(2000);
|
delay(2000);
|
||||||
|
|
||||||
|
//initStateMachine();
|
||||||
initFileSystem();
|
initFileSystem();
|
||||||
initEth();
|
initEth();
|
||||||
initMQTT();
|
initMQTT();
|
||||||
@ -59,11 +60,21 @@ void loop() {
|
|||||||
if (PRINT_RAW_SIGNAL_FLAG)
|
if (PRINT_RAW_SIGNAL_FLAG)
|
||||||
printf("{}", data);
|
printf("{}", data);
|
||||||
|
|
||||||
lastMillis = micros() + DATA_PERIOD;
|
lastMicros = micros() + DATA_PERIOD;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (eth_connected) {
|
if (true) {
|
||||||
if (lastMillis < millis()) {;
|
if (lastMillis < millis()) {
|
||||||
|
if (getMqttEnabled() && !getMqttConnected()) {
|
||||||
|
reconnectMQTTIfNeeded();
|
||||||
|
}
|
||||||
|
/*if (flag) {
|
||||||
|
changeState(RECEIVING_DATA);
|
||||||
|
flag = false;
|
||||||
|
} else {
|
||||||
|
changeState(CONNECTED);
|
||||||
|
flag = true;
|
||||||
|
}*/
|
||||||
lastMillis = millis() + 3000;
|
lastMillis = millis() + 3000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
51
src/utils/settings.cpp
Normal file
51
src/utils/settings.cpp
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
#include "utils/settings.h"
|
||||||
|
|
||||||
|
#ifdef ESP32
|
||||||
|
const String PLATFORM = "esp32";
|
||||||
|
#elif defined(ESP8266)
|
||||||
|
const String PLATFORM = "esp8266";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new string after replacing each instance of the pattern with a value generated by calling the provided
|
||||||
|
* callback.
|
||||||
|
*/
|
||||||
|
String replaceEach(String value, String pattern, String (*generateReplacement)()) {
|
||||||
|
while (true) {
|
||||||
|
int index = value.indexOf(pattern);
|
||||||
|
if (index == -1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
value = value.substring(0, index) + generateReplacement() + value.substring(index + pattern.length());
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a random number, encoded as a hex string.
|
||||||
|
*/
|
||||||
|
String getRandom() {
|
||||||
|
return String(random(2147483647), HEX);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uses the station's MAC address to create a unique id for each device.
|
||||||
|
*/
|
||||||
|
String getUniqueId() {
|
||||||
|
uint8_t mac[6];
|
||||||
|
#ifdef ESP32
|
||||||
|
esp_read_mac(mac, ESP_MAC_WIFI_STA);
|
||||||
|
#elif defined(ESP8266)
|
||||||
|
wifi_get_macaddr(STATION_IF, mac);
|
||||||
|
#endif
|
||||||
|
char macStr[13] = {0};
|
||||||
|
sprintf(macStr, "%02x%02x%02x%02x%02x%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||||
|
return String(macStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
String formatSetting(String value) {
|
||||||
|
value = replaceEach(value, "#{random}", getRandom);
|
||||||
|
value.replace("#{unique_id}", getUniqueId());
|
||||||
|
value.replace("#{platform}", PLATFORM);
|
||||||
|
return value;
|
||||||
|
}
|
5
src/utils/settings.h
Normal file
5
src/utils/settings.h
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
String formatSetting(String value);
|
11
src/utils/utils.cpp
Normal file
11
src/utils/utils.cpp
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#include "utils/utils.h"
|
||||||
|
|
||||||
|
String requestDataToStr(uint8_t *data, size_t len) {
|
||||||
|
String str = "";
|
||||||
|
|
||||||
|
for (size_t i = 0; i < len; i++) {
|
||||||
|
str += (char)data[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
5
src/utils/utils.h
Normal file
5
src/utils/utils.h
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
String requestDataToStr(uint8_t *data, size_t len);
|
Loading…
x
Reference in New Issue
Block a user