You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
234 lines
6.1 KiB
234 lines
6.1 KiB
#include "nx/software/SystemSettings.h" |
|
#include "nx/software/SystemSettingsApi.h" |
|
#include "nx/software/AppSettings.h" |
|
#include "nx/software/AppSettingsApi.h" |
|
|
|
#include "freertos/FreeRTOS.h" |
|
#include "freertos/task.h" |
|
#include "esp_system.h" |
|
|
|
#include "nx/firmware/Storage.h" |
|
#include "nx/firmware/Wifi.h" |
|
#include "nx/firmware/MqTriggerHttpServer.h" |
|
#include "nx/firmware/MqttClient.h" |
|
#include "nx/firmware/SntpClient.h" |
|
#include "nx/firmware/StatusIndicator.h" |
|
#include "nx/firmware/Restarter.h" |
|
|
|
#include "HttpHandlers.h" |
|
|
|
#include "esp_log.h" |
|
|
|
#include <string.h> |
|
|
|
#define TAG "MAIN" |
|
|
|
#define SNTP_RETRIES 8 |
|
#define API_QOS 2 |
|
#define HB_QOS 1 |
|
|
|
static const char* DEVICE_NAME_PREFIX = "mqt-"; |
|
|
|
static void startWifi(void); |
|
static void onWifiConnected(void); |
|
static void onWifiError(void); |
|
static void onAppSettingsUpdate(void); |
|
static void onMqttConnected(); |
|
static void onMqttDisconnected(); |
|
static void onMqttError(); |
|
static void onMqttMessage(const char* msg); |
|
|
|
static void hbTask(void*); |
|
|
|
static SystemSettings* systemSettings = NULL; |
|
static AppSettings* appSettings = NULL; |
|
static WifiSettings wifiSettings; |
|
static MqttSettings mqttSettings; |
|
|
|
static bool wifiStarted = false; |
|
static bool mqttStarted = false; |
|
|
|
static const MqTriggerHttpCallbacks httpCallbacks = { |
|
.getRoot = rootHandler, |
|
.getJs = jsHandler, |
|
.getCss = cssHandler, |
|
.getSysSetForm = sysFormHandler, |
|
.getAppSetForm = appFormHandler, |
|
.getSysSet = nxApiGetSystemSettings, |
|
.postSysSet = nxApiUpdateSystemSettings, |
|
.getAppSet = nxApiGetAppSettings, |
|
.postAppSet = nxApiUpdateAppSettings |
|
// .postCmd = nxApiHandleCmd |
|
}; |
|
|
|
void app_main(void) |
|
{ |
|
nxInitStatusIndicator(); |
|
nxUpdateStatus(STATUS_BOOT); |
|
xTaskCreate(&nxStatusIndicatorTask, "status_task", 2048, NULL, 1, NULL); |
|
|
|
nxInitStorage(); |
|
|
|
// uncomment to force default NVS initialization for development |
|
// uint8_t zero = 0; |
|
// nxStorageWrite("ledinit", &zero, 1); |
|
// nxStorageWrite("sysinit", &zero, 1); |
|
|
|
nxInitSystemSettings(nxStorageWrite, nxStorageRead); |
|
nxInitAppSettings(nxStorageWrite, nxStorageRead, onAppSettingsUpdate); |
|
|
|
systemSettings = nxGetSystemSettings(); |
|
appSettings = nxGetAppSettings(); |
|
|
|
// uncomment to force WiFi settings for development |
|
// strcpy(systemSettings->wifiSsid, "androidAp"); |
|
// strcpy(systemSettings->wifiPassword, "password"); |
|
// systemSettings->useStaticAddr = false; |
|
|
|
nxStartRestarter(systemSettings->rsSchedule, systemSettings->tzEnv); |
|
|
|
nxSetWifiConnectedCallback(onWifiConnected); |
|
nxSetWifiErrorCallback(onWifiError); |
|
startWifi(); |
|
} |
|
|
|
// ----- |
|
|
|
static void startWifi(void) |
|
{ |
|
wifiSettings = (struct WifiSettings){ |
|
.wname = systemSettings->wifiSsid, |
|
.wpass = systemSettings->wifiPassword, |
|
.devicePrefix = DEVICE_NAME_PREFIX, |
|
.usePowerSave = &(systemSettings->wifiPowerSave), |
|
.useStaticAddr = &(systemSettings->useStaticAddr), |
|
.ip4addr = systemSettings->ip4addr, |
|
.ip4gw = systemSettings->ip4gw, |
|
.ip4mask = systemSettings->ip4mask, |
|
.dns = systemSettings->dnsAddr |
|
}; |
|
|
|
ESP_LOGI(TAG, "Initializing WiFi"); |
|
if (!nxInitWifi(&wifiSettings)) { |
|
nxUpdateStatus(STATUS_SYSTEM_ERROR); |
|
} |
|
} |
|
|
|
static void onWifiConnected(void) |
|
{ |
|
nxUpdateStatus(STATUS_OK); |
|
|
|
if (wifiStarted) { |
|
return; |
|
} |
|
|
|
wifiStarted = true; |
|
systemSettings->deviceName = nxGetWifiDeviceName(); |
|
|
|
nxInitSntpClient(SNTP_RETRIES, systemSettings->sntpAddr, systemSettings->tzEnv); |
|
|
|
strcpy(mqttSettings.brokerAddr, appSettings->mqttHost); |
|
strcpy(mqttSettings.apiTopic, appSettings->mqttApiUri); |
|
strcpy(mqttSettings.hbTopic, appSettings->mqttHbUri); |
|
strcpy(mqttSettings.user, appSettings->mqttUser); |
|
|
|
strcpy(mqttSettings.password, appSettings->mqttPassword); |
|
strcpy(mqttSettings.clientId, appSettings->overrideDevName |
|
? appSettings->customDevName |
|
: systemSettings->deviceName); |
|
|
|
mqttSettings.hbIntervalSec = appSettings->mqttHbIntervalSec; |
|
mqttSettings.caCrt = appSettings->mqttUseTls ? appSettings->caCert : NULL; |
|
mqttSettings.messageCb = onMqttMessage; |
|
mqttSettings.connectedCb = onMqttConnected; |
|
mqttSettings.disconnectedCb = onMqttDisconnected; |
|
mqttSettings.errorCb = onMqttError; |
|
|
|
if (!nxStartMqttClient(&mqttSettings)) { |
|
onMqttError(); |
|
} |
|
|
|
nxSetMqTriggerHttpCallbacks(&httpCallbacks); |
|
nxStartMqTriggerHttpServer(); |
|
} |
|
|
|
static void onAppSettingsUpdate(void) |
|
{ |
|
ESP_LOGI(TAG, "App settings updated"); |
|
nxUpdateStatus(STATUS_OK_WORKING); |
|
} |
|
|
|
static void onMqttMessage(const char* msg) |
|
{ |
|
ESP_LOGI(TAG, "MQTT MESSAGE RECEIVED: %s", msg); |
|
nxUpdateStatus(STATUS_OK_WORKING); |
|
} |
|
|
|
static void onWifiError() |
|
{ |
|
ESP_LOGE(TAG, "WiFi ERROR"); |
|
nxUpdateStatus(STATUS_SYSTEM_ERROR); |
|
} |
|
|
|
static void onMqttConnected() |
|
{ |
|
ESP_LOGI(TAG, "MQTT CONNECTED"); |
|
|
|
if (!mqttStarted) { |
|
xTaskCreate(&hbTask, "hb_task", 2048, NULL, 1, NULL); |
|
mqttStarted = true; |
|
} |
|
|
|
// (re)subscribe |
|
if (nxMqttSubscribe(appSettings->mqttApiUri, API_QOS)) { |
|
nxUpdateStatus(STATUS_OK); |
|
} |
|
} |
|
|
|
static void onMqttDisconnected() |
|
{ |
|
ESP_LOGW(TAG, "MQTT DISCONNECTED"); |
|
nxUpdateStatus(STATUS_APP_ERROR); |
|
} |
|
|
|
static void onMqttError() |
|
{ |
|
ESP_LOGE(TAG, "MQTT ERROR"); |
|
nxUpdateStatus(STATUS_APP_ERROR); |
|
} |
|
|
|
static void hbTask(void* param) |
|
{ |
|
// UNUSED(param); |
|
ESP_LOGI(TAG, "Starting MQTT heartbeat task"); |
|
|
|
ESP_LOGI(TAG, "hbIntervalSec: %d", appSettings->mqttHbIntervalSec); |
|
|
|
if (appSettings->mqttHbIntervalSec < 1) { |
|
ESP_LOGI(TAG, "Heartbeat interval < 1 sec, skipping"); |
|
vTaskDelete(NULL); |
|
return; |
|
} |
|
|
|
while (1) { |
|
if (nxMqttIsConnected()) { |
|
ESP_LOGI(TAG, "Sending MQTT heartbeat"); |
|
|
|
char timeStr[DT_FORMAT_LEN]; |
|
nxGetTimeStr(timeStr); |
|
char hbMessage[DT_FORMAT_LEN + strlen(nxGetWifiDeviceName()) + 2]; |
|
strcpy(hbMessage, nxGetWifiDeviceName()); |
|
strcat(hbMessage, " "); |
|
strcat(hbMessage, timeStr); |
|
|
|
if(nxMqttPublish(appSettings->mqttHbUri, HB_QOS, hbMessage, strlen(hbMessage), 1) < 0) { |
|
ESP_LOGE(TAG, "Cannot publish heartbeat message"); |
|
} |
|
} |
|
else { |
|
ESP_LOGW(TAG, "Skipping MQTT heartbeat due to the disconnected client"); |
|
} |
|
|
|
vTaskDelay(appSettings->mqttHbIntervalSec*1000 / portTICK_PERIOD_MS); |
|
} |
|
}
|
|
|