Add dispatch and calibrate

This commit is contained in:
fvanroie 2020-02-01 19:01:16 +01:00
parent 9eca4d694d
commit 2aa5e59fea
13 changed files with 269 additions and 219 deletions

View File

@ -36,11 +36,11 @@
* DEFINES
*********************/
uint8_t haspStartPage = 0;
uint8_t haspThemeId = 0;
uint16_t haspThemeHue = 200;
String haspPagesPath;
String haspZiFontPath;
uint8_t haspStartPage = 0;
uint8_t haspThemeId = 0;
uint16_t haspThemeHue = 200;
char haspPagesPath[32] = "/pages.jsonl\0";
char haspZiFontPath[32];
/**********************
* TYPEDEFS
@ -256,6 +256,11 @@ void haspSendNewValue(lv_obj_t * obj, const char * txt)
}
}
void haspSendNewValue(lv_obj_t * obj, int16_t val)
{
haspSendNewValue(obj, (int32_t)val);
}
int32_t get_cpicker_value(lv_obj_t * obj)
{
lv_color16_t c16;
@ -263,11 +268,6 @@ int32_t get_cpicker_value(lv_obj_t * obj)
return (int32_t)c16.full;
}
void haspSendNewValue(lv_obj_t * obj, int16_t val)
{
haspSendNewValue(obj, (int32_t)val);
}
void haspSendNewValue(lv_obj_t * obj, lv_color_t color)
{
haspSendNewValue(obj, get_cpicker_value(obj));
@ -457,9 +457,6 @@ bool haspGetObjAttribute(lv_obj_t * obj, String strAttr, std::string & strPayloa
return false;
}
void haspSetAttr(String strTopic, String strPayload)
{}
void haspSetObjAttribute(lv_obj_t * obj, String strAttr, String strPayload)
{
if(!obj) return;
@ -551,37 +548,22 @@ void haspSetObjAttribute(lv_obj_t * obj, String strAttr, String strPayload)
}
}
void haspProcessAttribute(String strTopic, String strPayload)
void haspProcessAttribute(uint8_t pageid, uint8_t objid, String strAttr, String strPayload)
{
if(strTopic.startsWith("p[")) {
String strPageId = strTopic.substring(2, strTopic.indexOf("]"));
String strTemp = strTopic.substring(strTopic.indexOf("]") + 1, strTopic.length());
if(strTemp.startsWith(".b[")) {
String strObjId = strTemp.substring(3, strTemp.indexOf("]"));
String strAttr = strTemp.substring(strTemp.indexOf("]") + 1, strTemp.length());
debugPrintln(strPageId + " && " + strObjId + " && " + strAttr);
int pageid = strPageId.toInt();
int objid = strObjId.toInt();
if(pageid >= 0 && pageid <= 255 && objid > 0 && objid <= 255) {
lv_obj_t * obj = FindObjFromId((uint8_t)pageid, (uint8_t)objid);
if(obj) {
if(strPayload != "")
haspSetObjAttribute(obj, strAttr, strPayload);
else {
/* publish the change */
std::string strValue = "";
if(haspGetObjAttribute(obj, strAttr, strValue)) {
mqttSendNewValue(pageid, objid, String(strValue.c_str()));
} else {
warningPrintln(String(F("HASP: %sUnknown property: ")) + strAttr);
}
} // payload
} // obj
} // valid page
}
}
lv_obj_t * obj = FindObjFromId((uint8_t)pageid, (uint8_t)objid);
if(obj) {
if(strPayload != "")
haspSetObjAttribute(obj, strAttr, strPayload);
else {
/* publish the change */
std::string strValue = "";
if(haspGetObjAttribute(obj, strAttr, strValue)) {
mqttSendNewValue(pageid, objid, String(strValue.c_str()));
} else {
warningPrintln(String(F("HASP: %sUnknown property: ")) + strAttr);
}
} // payload
} // obj
}
////////////////////////////////////////////////////////////////////////////////////////////////////
@ -687,7 +669,6 @@ void haspDisplayAP(const char * ssid, const char * pass)
void haspSetup(JsonObject settings)
{
char buffer[64];
haspPagesPath = F("/pages.jsonl");
haspSetConfig(settings);
@ -706,66 +687,66 @@ void haspSetup(JsonObject settings)
// static lv_font_t *
// my_font = (lv_font_t *)lv_mem_alloc(sizeof(lv_font_t));
my_font = (lv_font_t *)lv_mem_alloc(sizeof(lv_font_t));
my_font[0] = (lv_font_t *)lv_mem_alloc(sizeof(lv_font_t));
lv_zifont_init();
if(lv_zifont_font_init(my_font, haspZiFontPath.c_str(), 24) != 0) {
errorPrintln(String(F("HASP: %sFailed to set the custom font to ")) + haspZiFontPath);
my_font = NULL; // Use default font
if(lv_zifont_font_init(my_font[0], haspZiFontPath, 24) != 0) {
errorPrintln(String(F("HASP: %sFailed to set the custom font to ")) + String(haspZiFontPath));
my_font[0] = NULL; // Use default font
}
lv_theme_t * th;
switch(haspThemeId) {
#if LV_USE_THEME_ALIEN == 1
case 1:
th = lv_theme_alien_init(haspThemeHue, my_font);
th = lv_theme_alien_init(haspThemeHue, my_font[0]);
break;
#endif
#if LV_USE_THEME_NIGHT == 1
case 2:
th = lv_theme_night_init(haspThemeHue, my_font); // heavy
th = lv_theme_night_init(haspThemeHue, my_font[0]); // heavy
break;
#endif
#if LV_USE_THEME_MONO == 1
case 3:
th = lv_theme_mono_init(haspThemeHue, my_font); // lightweight
th = lv_theme_mono_init(haspThemeHue, my_font[0]); // lightweight
break;
#endif
#if LV_USE_THEME_MATERIAL == 1
case 4:
th = lv_theme_material_init(haspThemeHue, my_font);
th = lv_theme_material_init(haspThemeHue, my_font[0]);
break;
#endif
#if LV_USE_THEME_ZEN == 1
case 5:
th = lv_theme_zen_init(haspThemeHue, my_font); // lightweight
th = lv_theme_zen_init(haspThemeHue, my_font[0]); // lightweight
break;
#endif
#if LV_USE_THEME_NEMO == 1
case 6:
th = lv_theme_nemo_init(haspThemeHue, my_font); // heavy
th = lv_theme_nemo_init(haspThemeHue, my_font[0]); // heavy
break;
#endif
#if LV_USE_THEME_TEMPL == 1
case 7:
th = lv_theme_templ_init(haspThemeHue, my_font); // lightweight, not for production...
th = lv_theme_templ_init(haspThemeHue, my_font[0]); // lightweight, not for production...
break;
#endif
#if LV_USE_THEME_HASP == 1
case 8:
th = lv_theme_hasp_init(haspThemeHue, my_font);
th = lv_theme_hasp_init(haspThemeHue, my_font[0]);
break;
#endif
case 0:
#if LV_USE_THEME_DEFAULT == 1
th = lv_theme_default_init(haspThemeHue, my_font);
th = lv_theme_default_init(haspThemeHue, my_font[0]);
#else
th = lv_theme_hasp_init(512, my_font);
th = lv_theme_hasp_init(512, my_font[0]);
#endif
break;
default:
th = lv_theme_hasp_init(512, my_font);
th = lv_theme_hasp_init(512, my_font[0]);
debugPrintln(F("HASP: Unknown theme selected"));
}
@ -799,6 +780,10 @@ void haspSetup(JsonObject settings)
haspLoadPage(haspPagesPath);
haspSetPage(haspStartPage);
// lv_obj_t * img_bin_t = lv_img_create(pages[current_page], NULL); /*Crate an image object*/
// lv_img_set_src(img_bin_t, "F:/dogsmall(1).bin"); /*Set the created file as image (a red rose)*/
// lv_obj_set_pos(img_bin_t, 64, 64); /*Set the positions*/
// // lv_page_set_style(page, LV_PAGE_STYLE_SB, &style_sb); /*Set the scrollbar style*/
// // lv_obj_t *img1 = lv_img_create(pages[2], NULL);
@ -1027,6 +1012,11 @@ static void switch_event_handler(lv_obj_t * obj, lv_event_t event)
if(event == LV_EVENT_VALUE_CHANGED) haspSendNewValue(obj, lv_sw_get_state(obj));
}
static void checkbox_event_handler(lv_obj_t * obj, lv_event_t event)
{
if(event == LV_EVENT_VALUE_CHANGED) haspSendNewValue(obj, lv_cb_is_checked(obj));
}
static void ddlist_event_handler(lv_obj_t * obj, lv_event_t event)
{
if(event == LV_EVENT_VALUE_CHANGED) {
@ -1049,10 +1039,10 @@ static void roller_event_handler(lv_obj_t * obj, lv_event_t event)
///////////////////////////////////////////////////////////////////////////////////////////////////////////
void haspReset()
void haspReset(bool write_config)
{
mqttStop(); // Stop the MQTT Client first
configWriteConfig();
if(write_config) configWriteConfig();
debugStop();
delay(250);
wifiStop();
@ -1159,7 +1149,7 @@ void haspNewObject(const JsonObject & config)
case LV_HASP_CHECKBOX: {
obj = lv_cb_create(parent_obj, NULL);
if(config[F("txt")]) lv_cb_set_text(obj, config[F("txt")].as<String>().c_str());
lv_obj_set_event_cb(obj, switch_event_handler);
lv_obj_set_event_cb(obj, checkbox_event_handler);
break;
}
case LV_HASP_LABEL: {
@ -1360,11 +1350,6 @@ void haspLoadPage(String pages)
bool haspGetConfig(const JsonObject & settings)
{
if(!settings.isNull() && settings[FPSTR(F_CONFIG_STARTPAGE)] == haspStartPage &&
settings[FPSTR(F_CONFIG_THEME)] == haspThemeId && settings[FPSTR(F_CONFIG_HUE)] == haspThemeHue &&
settings[FPSTR(F_CONFIG_ZIFONT)] == haspZiFontPath && settings[FPSTR(F_CONFIG_PAGES)] == haspPagesPath)
return false;
settings[FPSTR(F_CONFIG_STARTPAGE)] = haspStartPage;
settings[FPSTR(F_CONFIG_THEME)] = haspThemeId;
settings[FPSTR(F_CONFIG_HUE)] = haspThemeHue;
@ -1381,55 +1366,30 @@ bool haspGetConfig(const JsonObject & settings)
bool haspSetConfig(const JsonObject & settings)
{
if(!settings.isNull() && settings[FPSTR(F_CONFIG_STARTPAGE)] == haspStartPage &&
settings[FPSTR(F_CONFIG_THEME)] == haspThemeId && settings[FPSTR(F_CONFIG_HUE)] == haspThemeHue &&
settings[FPSTR(F_CONFIG_ZIFONT)] == haspZiFontPath && settings[FPSTR(F_CONFIG_PAGES)] == haspPagesPath)
return false;
bool changed = false;
if(!settings[FPSTR(F_CONFIG_PAGES)].isNull()) {
if(haspPagesPath != settings[FPSTR(F_CONFIG_PAGES)].as<String>().c_str()) {
debugPrintln(F("haspPagesPath changed"));
}
changed |= haspPagesPath != settings[FPSTR(F_CONFIG_PAGES)].as<String>().c_str();
haspPagesPath = settings[FPSTR(F_CONFIG_PAGES)].as<String>().c_str();
changed |= strcmp(haspPagesPath, settings[FPSTR(F_CONFIG_PAGES)]) != 0;
strncpy(haspPagesPath, settings[FPSTR(F_CONFIG_PAGES)], sizeof(haspPagesPath));
}
if(!settings[FPSTR(F_CONFIG_ZIFONT)].isNull()) {
if(haspZiFontPath != settings[FPSTR(F_CONFIG_ZIFONT)].as<String>().c_str()) {
debugPrintln(F("haspZiFontPath changed"));
}
changed |= haspZiFontPath != settings[FPSTR(F_CONFIG_ZIFONT)].as<String>().c_str();
haspZiFontPath = settings[FPSTR(F_CONFIG_ZIFONT)].as<String>().c_str();
changed |= strcmp(haspZiFontPath, settings[FPSTR(F_CONFIG_ZIFONT)]) != 0;
strncpy(haspZiFontPath, settings[FPSTR(F_CONFIG_ZIFONT)], sizeof(haspZiFontPath));
}
if(!settings[FPSTR(F_CONFIG_STARTPAGE)].isNull()) {
if(haspStartPage != settings[FPSTR(F_CONFIG_STARTPAGE)].as<uint8_t>()) {
debugPrintln(F("haspStartPage changed"));
}
changed |= haspStartPage != settings[FPSTR(F_CONFIG_STARTPAGE)].as<uint8_t>();
haspStartPage = settings[FPSTR(F_CONFIG_STARTPAGE)].as<uint8_t>();
}
if(!settings[FPSTR(F_CONFIG_THEME)].isNull()) {
if(haspThemeId != settings[FPSTR(F_CONFIG_THEME)].as<uint8_t>()) {
debugPrintln(F("haspThemeId changed"));
}
changed |= haspThemeId != settings[FPSTR(F_CONFIG_THEME)].as<uint8_t>();
haspThemeId = settings[FPSTR(F_CONFIG_THEME)].as<uint8_t>();
}
if(!settings[FPSTR(F_CONFIG_HUE)].isNull()) {
if(haspThemeHue != settings[FPSTR(F_CONFIG_HUE)].as<uint16_t>()) {
debugPrintln(F("haspStartPage changed"));
}
changed |= haspThemeHue != settings[FPSTR(F_CONFIG_HUE)].as<uint16_t>();
haspThemeHue = settings[FPSTR(F_CONFIG_HUE)].as<uint16_t>();
}

View File

@ -77,11 +77,10 @@ void haspSetNodename(String name);
String haspGetNodename();
float haspGetVersion();
void haspBackground(uint16_t pageid, uint16_t imageid);
void haspReset();
void haspReset(bool write_config);
void haspSetLabelText(String value);
void haspProcessAttribute(String strTopic, String strPayload);
void haspSetAttr(String strTopic, String strPayload);
void haspProcessAttribute(uint8_t pageid, uint8_t objid, String strAttr, String strPayload);
void haspSendCmd(String nextionCmd);
void haspParseJson(String & strPayload);

103
src/hasp_dispatch.cpp Normal file
View File

@ -0,0 +1,103 @@
#include "hasp_dispatch.h"
#include "hasp_mqtt.h"
#include "hasp_http.h"
#include "hasp_mdns.h"
#include "hasp_wifi.h"
#include "hasp_log.h"
#include "hasp_gui.h"
#include "hasp.h"
void dispatchSetup()
{}
void dispatchLoop()
{}
// objectattribute=value
void dispatchAttribute(String & strTopic, String & strPayload)
{
if(strTopic.startsWith("p[")) {
String strPageId = strTopic.substring(2, strTopic.indexOf("]"));
String strTemp = strTopic.substring(strTopic.indexOf("]") + 1, strTopic.length());
if(strTemp.startsWith(".b[")) {
String strObjId = strTemp.substring(3, strTemp.indexOf("]"));
String strAttr = strTemp.substring(strTemp.indexOf("]") + 1, strTemp.length());
// debugPrintln(strPageId + " && " + strObjId + " && " + strAttr);
int pageid = strPageId.toInt();
int objid = strObjId.toInt();
if(pageid >= 0 && pageid <= 255 && objid > 0 && objid <= 255) {
haspProcessAttribute((uint8_t)pageid, (uint8_t)objid, strAttr, strPayload);
} // valid page
}
} else if(strTopic == "page") {
} else if(strTopic == "dim") {
}
}
void dispatchPage(String & strPageid)
{
debugPrintln("PAGE:" + strPageid);
if(strPageid.length() == 0) {
String strPayload = String(haspGetPage());
mqttSendState("page", strPayload.c_str());
} else {
if(strPageid.toInt() <= 250) haspSetPage(strPageid.toInt());
}
}
void dispatchCommand(String cmnd)
{
debugPrintln("CMND: " + cmnd);
if(cmnd == "calibrate") {
guiCalibrate();
return;
}
if(cmnd == "restart") {
haspReset(true);
return;
}
if(cmnd == "" || cmnd == "statusupdate") {
haspReset(true);
return;
}
int pos = cmnd.indexOf("=");
if(pos > 0) {
String strTopic = cmnd.substring(0, pos);
String strPayload = cmnd.substring(pos + 1, cmnd.length());
debugPrintln("CMND: '" + strTopic + "'='" + strPayload + "'");
dispatchAttribute(strTopic, strPayload);
}
}
void dispatchJson(String & strPayload)
{ // Parse an incoming JSON array into individual commands
if(strPayload.endsWith(",]")) {
// Trailing null array elements are an artifact of older Home Assistant automations
// and need to be removed before parsing by ArduinoJSON 6+
strPayload.remove(strPayload.length() - 2, 2);
strPayload.concat("]");
}
DynamicJsonDocument haspCommands(2048 + 1024);
DeserializationError jsonError = deserializeJson(haspCommands, strPayload);
if(jsonError) { // Couldn't parse incoming JSON command
errorPrintln(String(F("JSON: %sFailed to parse incoming JSON command with error: ")) +
String(jsonError.c_str()));
return;
}
for(uint8_t i = 0; i < haspCommands.size(); i++) {
dispatchCommand(haspCommands[i]);
}
}
void dispatchIdle(const __FlashStringHelper * state)
{
mqttSendState(String(F("idle")).c_str(), String(state).c_str());
}

15
src/hasp_dispatch.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef HASP_DISPATCH_H
#define HASP_DISPATCH_H
#include <Arduino.h>
void dispatchSetup(void);
void dispatchLoop(void);
void dispatchAttribute(String & strTopic, String & strPayload);
void dispatchCommand(String cmnd);
void dispatchJson(String & strPayload);
void dispatchPage(String & strPageid);
void dispatchIdle(const __FlashStringHelper * state);
#endif

View File

@ -1,7 +1,8 @@
#include <Ticker.h>
#include "lvgl.h"
#include "lv_conf.h"
#include "lvgl.h"
#include "lv_fs_if.h"
#include "TFT_eSPI.h"
@ -13,6 +14,7 @@
#include "hasp_log.h"
#include "hasp_debug.h"
#include "hasp_config.h"
#include "hasp_dispatch.h"
#include "hasp_gui.h"
#define LVGL_TICK_PERIOD 30 // 30
@ -20,14 +22,15 @@
uint16_t guiSleepTime = 150; // 0.1 second resolution
bool guiSleeping = false;
uint8_t guiTickPeriod = 50;
Ticker tick; /* timer for interrupt handler */
TFT_eSPI tft = TFT_eSPI(); /* TFT instance */
Ticker tick; /* timer for interrupt handler */
TFT_eSPI tft = TFT_eSPI(); /* TFT instance */
uint16_t calData[5] = {0, 0, 0, 0, 0};
bool IRAM_ATTR guiCheckSleep()
{
bool shouldSleep = lv_disp_get_inactive_time(NULL) > guiSleepTime * 100;
if(shouldSleep && !guiSleeping) {
debugPrintln(F("GUI: Going to sleep now..."));
dispatchIdle(F("LONG"));
guiSleeping = true;
}
return shouldSleep;
@ -90,7 +93,7 @@ bool my_touchpad_read(lv_indev_drv_t * indev_driver, lv_indev_data_t * data)
bool shouldSleep = guiCheckSleep();
if(!shouldSleep && guiSleeping) {
debugPrintln(F("GUI: Waking up!"));
dispatchIdle(F("OFF"));
guiSleeping = false;
}
@ -117,10 +120,35 @@ bool my_touchpad_read(lv_indev_drv_t * indev_driver, lv_indev_data_t * data)
return false; /*Return `false` because we are not buffering and no more data to read*/
}
void guiCalibrate()
{
tft.fillScreen(TFT_BLACK);
tft.setCursor(20, 0);
// tft.setTextFont(2);
tft.setTextSize(1);
tft.setTextColor(TFT_WHITE, TFT_BLACK);
tft.println(PSTR("Touch corners as indicated"));
tft.setTextFont(1);
tft.calibrateTouch(calData, TFT_MAGENTA, TFT_BLACK, 15);
for(uint8_t i = 0; i < 5; i++) {
Serial.print(calData[i]);
if(i < 4) Serial.print(", ");
}
tft.setTouch(calData);
lv_obj_invalidate(lv_disp_get_layer_sys(NULL));
}
void guiSetup(TFT_eSPI & screen, JsonObject settings)
{
size_t buffer_size;
tft = screen;
tft.setTouch(calData);
lv_init();
#if defined(ARDUINO_ARCH_ESP32)
@ -209,6 +237,10 @@ void guiSetup(TFT_eSPI & screen, JsonObject settings)
/*Initialize the graphics library's tick*/
tick.attach_ms(guiTickPeriod, lv_tick_handler);
#if LV_USE_FS_IF != 0
lv_fs_if_init();
#endif
// guiLoop();
}

View File

@ -9,6 +9,9 @@
void guiSetup(TFT_eSPI & screen, JsonObject settings);
void guiLoop(void);
void guiStop(void);
void guiCalibrate();
bool guiGetConfig(const JsonObject & settings);
// lv_res_t guiChangeTheme(uint8_t themeid, uint16_t hue, String font, uint8_t fontsize);

View File

@ -251,10 +251,10 @@ void httpHandleReboot()
delay(500);
debugPrintln(PSTR("HTTP: Reboot device"));
haspSetAttr(F("p[0].b[1].txt"), F("\"Rebooting...\""));
// haspProcessAttribute(F("p[0].b[1].txt"), F("\"Rebooting...\""));
delay(500);
haspReset();
haspReset(true);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
@ -1007,7 +1007,7 @@ void httpHandleResetConfig()
if(resetConfirmed) {
delay(250);
// configClearSaved();
haspReset();
haspReset(false); // Do not save the current config
}
}

View File

@ -1,6 +1,7 @@
#ifndef HASP_HTTP_H
#define HASP_HTTP_H
#include <Arduino.h>
#include "ArduinoJson.h"
void httpSetup(const JsonObject & settings);

View File

@ -16,6 +16,7 @@
#include "hasp_config.h"
#include "hasp_mqtt.h"
#include "hasp_wifi.h"
#include "hasp_dispatch.h"
#include "hasp.h"
#ifdef USE_CONFIG_OVERRIDE
@ -71,8 +72,6 @@ std::string mqttPassword = "";
std::string mqttGroupName = "plates";
/*
const String mqttCommandSubscription = mqttCommandTopic + "/#";
const String mqttGroupCommandSubscription = mqttGroupCommandTopic + "/#";
const String mqttLightSubscription = "hasp/" + String(haspGetNodename()) + "/light/#";
const String mqttLightBrightSubscription = "hasp/" + String(haspGetNodename()) + "/brightness/#";
*/
@ -82,87 +81,53 @@ PubSubClient mqttClient(wifiClient);
////////////////////////////////////////////////////////////////////////////////////////////////////
// Send changed values OUT
void mqttSendNewEvent(uint8_t pageid, uint8_t btnid, int32_t val)
void mqttSendState(const char * subtopic, const char * payload)
{
char topic[72];
sprintf_P(topic, PSTR("hasp/%s/state/p[%u].b[%u].event"), haspGetNodename().c_str(), pageid, btnid);
char value[32];
itoa(val, value, 10);
mqttClient.publish(topic, value);
debugPrintln(String(F("MQTT OUT: ")) + String(topic) + " = " + String(value));
// page = 0
// p[0].b[0].attr = abc
// dim = 100
// idle = 0/1
// light = 0/1
// brightness = 100
char topic[128];
sprintf_P(topic, PSTR("%sstate/%s"), mqttNodeTopic.c_str(), subtopic);
mqttClient.publish(topic, payload);
debugPrintln(String(F("MQTT OUT: ")) + String(topic) + " = " + String(payload));
// as json
sprintf_P(topic, PSTR("hasp/%s/state/json"), haspGetNodename().c_str(), pageid, btnid);
sprintf_P(value, PSTR("{\"event\":\"p[%u]].b[%u].event\", \"value\":%u}"), pageid, btnid, val);
char value[256];
sprintf_P(topic, PSTR("%sstate/json"), mqttNodeTopic.c_str());
sprintf_P(value, PSTR("{\"%s\":\"%s\"}"), subtopic, payload);
mqttClient.publish(topic, value);
debugPrintln(String(F("MQTT OUT: ")) + String(topic) + " = " + String(value));
}
void mqttSendNewValue(uint8_t pageid, uint8_t btnid, const char * attribute, String txt)
{
char subtopic[32];
sprintf_P(subtopic, PSTR("p[%u].b[%u].%s"), pageid, btnid, attribute);
mqttSendState(subtopic, txt.c_str());
}
void mqttSendNewValue(uint8_t pageid, uint8_t btnid, int32_t val)
{
char topic[72];
sprintf_P(topic, PSTR("hasp/%s/state/p[%u].b[%u].val"), haspGetNodename().c_str(), pageid, btnid);
char value[32];
char value[16];
itoa(val, value, 10);
mqttClient.publish(topic, value);
debugPrintln(String(F("MQTT OUT: ")) + String(topic) + " = " + String(value));
// as json
sprintf_P(topic, PSTR("hasp/%s/state/json"), haspGetNodename().c_str(), pageid, btnid);
sprintf_P(value, PSTR("{\"event\":\"p[%u]].b[%u].val\", \"value\":%u}"), pageid, btnid, val);
mqttClient.publish(topic, value);
debugPrintln(String(F("MQTT OUT: ")) + String(topic) + " = " + String(value));
mqttSendNewValue(pageid, btnid, "val", value);
}
void mqttSendNewValue(uint8_t pageid, uint8_t btnid, String txt)
{
char topic[72];
sprintf_P(topic, PSTR("hasp/%s/state/p[%u].b[%u].txt"), haspGetNodename().c_str(), pageid, btnid);
mqttClient.publish(topic, txt.c_str());
debugPrintln(String(F("MQTT OUT: ")) + String(topic) + " = " + txt);
// as json
char value[64];
sprintf_P(topic, PSTR("hasp/%s/state/json"), haspGetNodename().c_str(), pageid, btnid);
sprintf_P(value, PSTR("{\"event\":\"p[%u]].b[%u].txt\", \"value\":\"%s\"}"), pageid, btnid, txt.c_str());
mqttClient.publish(topic, value);
debugPrintln(String(F("MQTT OUT: ")) + String(topic) + " = " + String(value));
mqttSendNewValue(pageid, btnid, "txt", txt);
}
void mqttHandlePage(String strPageid)
void mqttSendNewEvent(uint8_t pageid, uint8_t btnid, int32_t val)
{
if(strPageid.length() == 0) {
String strPayload = String(haspGetPage());
String topic = mqttNodeTopic + F("state/page");
char buffer[64];
sprintf_P(buffer, PSTR("MQTT OUT: %s = %s"), topic.c_str(), strPayload.c_str());
debugPrintln(buffer);
mqttClient.publish(topic.c_str(), strPayload.c_str());
} else {
if(strPageid.toInt() <= 250) haspSetPage(strPageid.toInt());
}
}
void mqttHandleJson(String & strPayload)
{ // Parse an incoming JSON array into individual Nextion commands
if(strPayload.endsWith(
",]")) { // Trailing null array elements are an artifact of older Home Assistant automations and need to
// be removed before parsing by ArduinoJSON 6+
strPayload.remove(strPayload.length() - 2, 2);
strPayload.concat("]");
}
DynamicJsonDocument nextionCommands(mqttMaxPacketSize + 1024);
DeserializationError jsonError = deserializeJson(nextionCommands, strPayload);
if(jsonError) { // Couldn't parse incoming JSON command
debugPrintln(String(F("MQTT: [ERROR] Failed to parse incoming JSON command with error: ")) +
String(jsonError.c_str()));
return;
}
for(uint8_t i = 0; i < nextionCommands.size(); i++) {
debugPrintln(nextionCommands[i]);
// nextionSendCmd(nextionCommands[i]);
}
char value[16];
itoa(val, value, 10);
mqttSendNewValue(pageid, btnid, "event", value);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
@ -204,11 +169,7 @@ void mqttCallback(char * topic, byte * payload, unsigned int length)
// debugPrintln(String(F("MQTT Short Topic : '")) + strTopic + "'");
if(strTopic == F("command")) {
if(strPayload == "") { // '[...]/device/command' -m '' = No command requested, respond with mqttStatusUpdate()
// mqttStatusUpdate(); // return status JSON via MQTT
} else { // '[...]/device/command' -m 'dim=50' == nextionSendCmd("dim=50")
// nextionSendCmd(strPayload);
}
dispatchCommand(strPayload);
return;
}
@ -217,7 +178,7 @@ void mqttCallback(char * topic, byte * payload, unsigned int length)
// debugPrintln(String(F("MQTT Shorter Command Topic : '")) + strTopic + "'");
if(strTopic == F("page")) { // '[...]/device/command/page' -m '1' == nextionSendCmd("page 1")
mqttHandlePage(strPayload);
dispatchPage(strPayload);
} else if(strTopic == F("dim")) { // '[...]/device/command/page' -m '1' == nextionSendCmd("page 1")
#if defined(ARDUINO_ARCH_ESP32)
ledcWrite(0, map(strPayload.toInt(), 0, 100, 0, 1023)); // ledChannel and value
@ -227,7 +188,7 @@ void mqttCallback(char * topic, byte * payload, unsigned int length)
} else if(strTopic == F("json")) { // '[...]/device/command/json' -m '["dim=5", "page 1"]' =
// nextionSendCmd("dim=50"), nextionSendCmd("page 1")
mqttHandleJson(strPayload); // Send to nextionParseJson()
dispatchJson(strPayload); // Send to nextionParseJson()
} else if(strTopic == F("statusupdate")) { // '[...]/device/command/statusupdate' == mqttStatusUpdate()
// mqttStatusUpdate(); // return status JSON via MQTT
} else if(strTopic == F("espupdate")) { // '[...]/device/command/espupdate' -m
@ -240,17 +201,18 @@ void mqttCallback(char * topic, byte * payload, unsigned int length)
}
} else if(strTopic == F("reboot")) { // '[...]/device/command/reboot' == reboot microcontroller)
debugPrintln(F("MQTT: Rebooting device"));
haspReset();
haspReset(true);
} else if(strTopic == F("lcdreboot")) { // '[...]/device/command/lcdreboot' == reboot LCD panel)
debugPrintln(F("MQTT: Rebooting LCD"));
haspReset();
haspReset(true);
} else if(strTopic == F("factoryreset")) { // '[...]/device/command/factoryreset' == clear all saved settings)
// configClearSaved();
} else if(strPayload == "") { // '[...]/device/command/p[1].b[4].txt' -m '' == nextionGetAttr("p[1].b[4].txt")
haspProcessAttribute(strTopic, "");
//} else if(strPayload == "") { // '[...]/device/command/p[1].b[4].txt' -m '' ==
// nextionGetAttr("p[1].b[4].txt")
// haspProcessAttribute(strTopic, "");
} else { // '[...]/device/command/p[1].b[4].txt' -m '"Lights On"' ==
// nextionSetAttr("p[1].b[4].txt", "\"Lights On\"")
haspProcessAttribute(strTopic, strPayload);
dispatchAttribute(strTopic, strPayload);
}
return;
}
@ -434,7 +396,7 @@ bool mqttSetConfig(const JsonObject & settings)
if(!settings[FPSTR(F_CONFIG_GROUP)].isNull()) {
if(mqttGroupName != settings[FPSTR(F_CONFIG_GROUP)].as<String>().c_str()) {
debugPrintln(F("mqttGroupName changed"));
debugPrintln(F("mqttGroupName set"));
}
changed |= mqttGroupName != settings[FPSTR(F_CONFIG_GROUP)].as<String>().c_str();
@ -443,7 +405,7 @@ bool mqttSetConfig(const JsonObject & settings)
if(!settings[FPSTR(F_CONFIG_HOST)].isNull()) {
if(mqttServer != settings[FPSTR(F_CONFIG_HOST)].as<String>().c_str()) {
debugPrintln(F("mqttServer changed"));
debugPrintln(F("mqttServer set"));
}
changed |= mqttServer != settings[FPSTR(F_CONFIG_HOST)].as<String>().c_str();
@ -452,7 +414,7 @@ bool mqttSetConfig(const JsonObject & settings)
if(!settings[FPSTR(F_CONFIG_PORT)].isNull()) {
if(mqttPort != settings[FPSTR(F_CONFIG_PORT)].as<uint16_t>()) {
debugPrintln(F("mqttPort changed"));
debugPrintln(F("mqttPort set"));
}
changed |= mqttPort != settings[FPSTR(F_CONFIG_PORT)].as<uint16_t>();
@ -461,7 +423,7 @@ bool mqttSetConfig(const JsonObject & settings)
if(!settings[FPSTR(F_CONFIG_USER)].isNull()) {
if(mqttUser != settings[FPSTR(F_CONFIG_USER)].as<String>().c_str()) {
debugPrintln(F("mqttUser changed"));
debugPrintln(F("mqttUser set"));
}
changed |= mqttUser != settings[FPSTR(F_CONFIG_USER)].as<String>().c_str();
@ -470,7 +432,7 @@ bool mqttSetConfig(const JsonObject & settings)
if(!settings[FPSTR(F_CONFIG_PASS)].isNull()) {
if(mqttPassword != settings[FPSTR(F_CONFIG_PASS)].as<String>().c_str()) {
debugPrintln(F("mqttPassword changed"));
debugPrintln(F("mqttPassword set"));
}
changed |= mqttPassword != settings[FPSTR(F_CONFIG_PASS)].as<String>().c_str();

View File

@ -8,6 +8,7 @@ void mqttLoop(bool wifiIsConnected);
void mqttStop();
void mqttReconnect();
void mqttSendState(const char * subtopic, const char * payload);
void mqttSendNewEvent(uint8_t pageid, uint8_t btnid, int32_t val);
void mqttSendNewValue(uint8_t pageid, uint8_t btnid, int32_t val);
void mqttSendNewValue(uint8_t pageid, uint8_t btnid, String txt);

View File

@ -38,25 +38,6 @@ void tftSetup(TFT_eSPI & tft, JsonObject settings)
// uint16_t calData[5] = {0, 0, 0, 0, 0};
uint8_t calDataOK = 0;
// Calibrate
if(0) {
tft.fillScreen(TFT_BLACK);
tft.setCursor(20, 0);
// tft.setTextFont(2);
tft.setTextSize(1);
tft.setTextColor(TFT_WHITE, TFT_BLACK);
tft.println(PSTR("Touch corners as indicated"));
tft.setTextFont(1);
tft.calibrateTouch(calData, TFT_MAGENTA, TFT_BLACK, 15);
for(uint8_t i = 0; i < 5; i++) {
Serial.print(calData[i]);
if(i < 4) Serial.print(", ");
}
}
tft.setTouch(calData);
}
@ -90,9 +71,6 @@ void tftPinInfo(String pinfunction, int8_t pin)
}
}
void tftCalibrate()
{}
void tftShowConfig(TFT_eSPI & tft)
{
setup_t tftSetup;

View File

@ -7,6 +7,7 @@
void tftSetup(TFT_eSPI & screen, JsonObject settings);
void tftLoop(void);
void tftStop(void);
void tftShowConfig(TFT_eSPI & tft);
#endif

View File

@ -216,16 +216,11 @@ bool wifiGetConfig(const JsonObject & settings)
bool wifiSetConfig(const JsonObject & settings)
{
/* if(!settings.isNull() && settings[FPSTR(F_CONFIG_STARTPAGE)] == haspStartPage &&
settings[FPSTR(F_CONFIG_THEME)] == haspThemeId && settings[FPSTR(F_CONFIG_HUE)] == haspThemeHue &&
settings[FPSTR(F_CONFIG_ZIFONT)] == haspZiFontPath && settings[FPSTR(F_CONFIG_PAGES)] == haspPagesPath)
return false;
*/
bool changed = false;
if(!settings[FPSTR(F_CONFIG_SSID)].isNull()) {
if(wifiSsid != settings[FPSTR(F_CONFIG_SSID)].as<String>().c_str()) {
debugPrintln(F("wifiSsid changed"));
debugPrintln(F("wifiSsid set"));
}
changed |= wifiSsid != settings[FPSTR(F_CONFIG_SSID)].as<String>().c_str();
@ -234,7 +229,7 @@ bool wifiSetConfig(const JsonObject & settings)
if(!settings[FPSTR(F_CONFIG_PASS)].isNull() && settings[FPSTR(F_CONFIG_PASS)].as<String>() != F("********")) {
if(wifiPassword != settings[FPSTR(F_CONFIG_PASS)].as<String>().c_str()) {
debugPrintln(F("wifiPassword changed"));
debugPrintln(F("wifiPassword set"));
}
changed |= wifiPassword != settings[FPSTR(F_CONFIG_PASS)].as<String>().c_str();