Merge pull request #1 from fvanroie/0.1.0-dev

0.1.0 dev
This commit is contained in:
arovak 2020-05-02 01:21:58 +02:00 committed by GitHub
commit 0e7448fb07
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 488 additions and 320 deletions

View File

@ -22,10 +22,10 @@
#define HASP_HAS_FILESYSTEM (ARDUINO_ARCH_ESP32>0 || ARDUINO_ARCH_ESP8266>0)
#define HASP_USE_SPIFFS (HASP_HAS_FILESYSTEM)
#define HASP_USE_EEPROM (HASP_HAS_FILESYSTEM)
#define HASP_USE_EEPROM 1
#define HASP_USE_SDCARD 0
#define HASP_USE_BUTTON 1
#define HASP_USE_GPIO 1
#define HASP_USE_QRCODE 1
#define HASP_USE_PNGDECODE 0
@ -43,7 +43,6 @@
#if HASP_USE_SPIFFS>0
#if defined(ARDUINO_ARCH_ESP32)
#include "SPIFFS.h"
#include "hasp_eeprom.h"
#endif
#include <FS.h> // Include the SPIFFS library
#include "hasp_spiffs.h"

View File

@ -285,19 +285,15 @@ class Logging {
if(_logOutput[i] == NULL || level>_level[i]) continue;
if(_prefix != NULL) {
// _prefix(level, _logOutput[i]);
_prefix(level, _logOutput[i]);
}
va_list args;
va_start(args, msg);
#ifdef STM32_CORE_VERSION_MAJOR
print(_logOutput[i], msg, args);
Serial.println();
#else
print(_logOutput[i], msg, args);
#endif
print(_logOutput[i], msg, args);
if(_suffix != NULL) {
// _suffix(level, _logOutput[i]);
_suffix(level, _logOutput[i]);
}
}

View File

@ -150,7 +150,7 @@ static lv_fs_res_t fs_open(lv_fs_drv_t * drv, void * file_p, const char * path,
Log.verbose(F("LVFS: %d"), __LINE__);
lv_spiffs_file_t * fp = (lv_spiffs_file_t *)file_p; /*Just avoid the confusing casings*/
// Log.verbose(F("LVFS: Copying %s"), f.name());
Log.verbose(F("LVFS: %d"), __LINE__);
Log.verbose(F("LVFS: %d - %x - %d"), __LINE__, fp, sizeof(lv_spiffs_file_t));
if (fp != NULL) (*fp) = file;
// memcpy(fp,&file,sizeof(lv_spiffs_file_t));
Log.verbose(F("LVFS: %d"), __LINE__);

View File

@ -47,11 +47,13 @@ lib_deps =
;TFT_eSPI@^1.4.20 ; Tft SPI drivers
PubSubClient@^2.7.0 ; MQTT client
ArduinoJson@^6.15.1,>6.15.0 ; needs at least 6.15.0
StreamUtils@^1.4.0
Syslog@^2.0.0
AceButton@^1.4.0
;AsyncTCP
;https://github.com/me-no-dev/ESPAsyncWebServer/archive/master.zip
;https://github.com/me-no-dev/ESPAsyncTCP/archive/master.zip
https://github.com/andrethomas/TasmotaSlave.git
lib_ignore =
https://github.com/littlevgl/lvgl.git
@ -67,6 +69,7 @@ build_flags =
-D SPIFFS_TEMPORAL_FD_CACHE ; speedup opening recent files
-D ARDUINOJSON_DECODE_UNICODE=1 ; for utf-8 symbols
-D ARDUINOJSON_ENABLE_PROGMEM=1 ; for PROGMEM arguments
-D STREAMUTILS_ENABLE_EEPROM=1 ; for STM32, it also supports EEPROM
;-D DISABLE_LOGGING
-I include ; include lv_conf.h and hasp_conf.h
${override.build_flags}
@ -88,6 +91,8 @@ esp32_flags=
stm32_flags=
${env.build_flags}
-D IRAM_ATTR= ; No IRAM_ATTR available on STM32
-D STM32
-D STREAMUTILS_USE_EEPROM_UPDATE=1 ; update cell only when changed
; -- By default there are no ${override.build_flags} set
; -- to use it, copy platformio_override.ini from the template
@ -144,7 +149,9 @@ build_flags =
-D TFT_BCKL=-1 ;None, configurable via web UI (e.g. 2 for D4)
-D TOUCH_CS=PC4 ;NC
-D TFT_RST=-1 ;D4
-D STM32
-D HASP_OUTPUT_PIN=PE0 ; User LED D2 on DevEBox board
-D HASP_INPUT_PIN=PD15 ; User Button K1 on DevEBox board
-D STM32_SERIAL1 ; Set this option to use Serial1 as default sersial port, leave out if using Serial2
lib_deps =
${env.lib_deps}

View File

@ -81,8 +81,6 @@ void hasp_send_obj_attribute_int(lv_obj_t * obj, const char * attribute, int32_t
void hasp_send_obj_attribute_color(lv_obj_t * obj, const char * attribute, lv_color_t color);
void hasp_process_attribute(uint8_t pageid, uint8_t objid, const char * attr, const char * payload);
void haspSendCmd(String nextionCmd);
void haspParseJson(String & strPayload);
void haspNewObject(const JsonObject & config, uint8_t & saved_page_id);
void haspReconnect(void);
@ -101,10 +99,10 @@ void IRAM_ATTR toggle_event_handler(lv_obj_t * obj, lv_event_t event);
* MACROS
**********************/
#endif /*LV_USE_DEMO*/
#endif /*HASP_USE_APP*/
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /*DEMO_H*/
#endif /*HASP_H*/

View File

@ -84,13 +84,6 @@ static lv_color_t haspPayloadToColor(const char * payload)
case 7:
if(!strcmp_P(payload, PSTR("magenta"))) return haspLogColor(LV_COLOR_MAGENTA);
/* HEX format #rrggbb or #rrggbbaa */
int r, g, b, a;
if(*payload == '#' && sscanf(payload + 1, "%2x%2x%2x%2x", &r, &g, &b, &a) == 4) {
return haspLogColor(LV_COLOR_MAKE(r, g, b));
} else if(*payload == '#' && sscanf(payload + 1, "%2x%2x%2x", &r, &g, &b) == 3) {
return haspLogColor(LV_COLOR_MAKE(r, g, b));
}
default:
// if(!strcmp_P(payload, PSTR("darkblue"))) return haspLogColor(LV_COLOR_MAKE(0, 51, 102));
// if(!strcmp_P(payload, PSTR("lightblue"))) return haspLogColor(LV_COLOR_MAKE(46, 203,
@ -98,6 +91,14 @@ static lv_color_t haspPayloadToColor(const char * payload)
break;
}
/* HEX format #rrggbb or #rrggbbaa */
int r, g, b, a;
if(*payload == '#' && sscanf(payload + 1, "%2x%2x%2x%2x", &r, &g, &b, &a) == 4) {
return haspLogColor(LV_COLOR_MAKE(r, g, b));
} else if(*payload == '#' && sscanf(payload + 1, "%2x%2x%2x", &r, &g, &b) == 3) {
return haspLogColor(LV_COLOR_MAKE(r, g, b));
}
/* 16-bit RGB565 Color Scheme*/
if(only_digits(payload)) {
uint16_t c = atoi(payload);
@ -582,23 +583,23 @@ static void hasp_process_obj_attribute_val(lv_obj_t * obj, const char * attr, co
lv_dropdown_set_selected(obj, val);
return;
} else if(check_obj_type(objtype, LV_HASP_LMETER)) {
lv_linemeter_set_value(obj, intval);
return;
return update ? lv_linemeter_set_value(obj, intval) : hasp_out_int(obj, attr, lv_linemeter_get_value(obj));
} else if(check_obj_type(objtype, LV_HASP_SLIDER)) {
lv_slider_set_value(obj, intval, LV_ANIM_ON);
return;
return update ? lv_slider_set_value(obj, intval, LV_ANIM_ON)
: hasp_out_int(obj, attr, lv_slider_get_value(obj));
} else if(check_obj_type(objtype, LV_HASP_LED)) {
lv_led_set_bright(obj, (uint8_t)val);
return;
if(update) {
return is_true(payload) ? lv_led_on(obj) : lv_led_off(obj);
} else {
// return hasp_out_int(obj, attr, lv_led_get_state(obj));
}
} else if(check_obj_type(objtype, LV_HASP_GAUGE)) {
lv_gauge_set_value(obj, 0, intval);
return;
return update ? lv_gauge_set_value(obj, 0, intval) : hasp_out_int(obj, attr, lv_gauge_get_value(obj, 0));
} else if(check_obj_type(objtype, LV_HASP_ROLLER)) {
lv_roller_set_selected(obj, val, LV_ANIM_ON);
return;
} else if(check_obj_type(objtype, LV_HASP_BAR)) {
lv_bar_set_value(obj, intval, LV_ANIM_OFF);
return;
return update ? lv_bar_set_value(obj, intval, LV_ANIM_ON) : hasp_out_int(obj, attr, lv_bar_get_value(obj));
} else if(check_obj_type(objtype, LV_HASP_CPICKER)) {
return update ? (void)lv_cpicker_set_color(obj, haspPayloadToColor(payload))
: hasp_out_color(obj, attr, lv_cpicker_get_color(obj));
@ -781,6 +782,16 @@ void hasp_process_obj_attribute(lv_obj_t * obj, const char * attr_p, const char
}
break; // not a options object
case ATTR_BRIGHTNESS:
if(check_obj_type(obj, LV_HASP_LED)) {
if(update) {
lv_led_set_bright(obj, (uint8_t)val);
} else {
hasp_out_int(obj, attr, lv_led_get_bright(obj));
}
return;
}
// default:
// hasp_local_style_attr(obj, attr, payload, update);
}
@ -794,9 +805,10 @@ void hasp_process_obj_attribute(lv_obj_t * obj, const char * attr_p, const char
* **************************/
static inline bool is_true(const char * s)
{
return (!strcmp_P(s, PSTR("true")) || !strcmp_P(s, PSTR("TRUE")) || !strcmp_P(s, PSTR("1")) ||
return (!strcmp_P(s, PSTR("true")) || !strcmp_P(s, PSTR("TRUE")) || !strcmp_P(s, PSTR("True")) ||
!strcmp_P(s, PSTR("on")) || !strcmp_P(s, PSTR("ON")) || !strcmp_P(s, PSTR("On")) ||
!strcmp_P(s, PSTR("yes")) || !strcmp_P(s, PSTR("YES")) || !strcmp_P(s, PSTR("Yes")));
!strcmp_P(s, PSTR("yes")) || !strcmp_P(s, PSTR("YES")) || !strcmp_P(s, PSTR("Yes")) ||
!strcmp_P(s, PSTR("1")));
}
static inline bool only_digits(const char * s)
@ -808,17 +820,17 @@ static inline bool only_digits(const char * s)
return strlen(s) == digits;
}
void hasp_out_int(lv_obj_t * obj, const char * attr, uint32_t val)
void inline hasp_out_int(lv_obj_t * obj, const char * attr, uint32_t val)
{
hasp_send_obj_attribute_int(obj, attr, val);
}
void hasp_out_str(lv_obj_t * obj, const char * attr, const char * data)
void inline hasp_out_str(lv_obj_t * obj, const char * attr, const char * data)
{
hasp_send_obj_attribute_str(obj, attr, data);
}
void hasp_out_color(lv_obj_t * obj, const char * attr, lv_color_t color)
void inline hasp_out_color(lv_obj_t * obj, const char * attr, lv_color_t color)
{
hasp_send_obj_attribute_color(obj, attr, color);
}

View File

@ -212,6 +212,7 @@ _HASP_ATTRIBUTE(SCALE_END_LINE_WIDTH, scale_end_line_width, lv_style_int_t)
#define ATTR_Y 121
#define ATTR_W 119
#define ATTR_H 104
#define ATTR_BRIGHTNESS 10 // LED
#define ATTR_OPTIONS 29886
#define ATTR_ENABLED 28193
#define ATTR_OPACITY 10155

View File

@ -1,75 +0,0 @@
#include "Arduino.h"
#include "ArduinoLog.h"
#include "AceButton.h"
#include "hasp_conf.h"
#include "lv_conf.h"
#include "hasp_mqtt.h" // testing memory consumption
#include "hasp_button.h"
#include "hasp_dispatch.h"
using namespace ace_button;
static AceButton * button[HASP_NUM_INPUTS]; // Connect your button between pin 2 and GND
static void button_event_cb(AceButton * button, uint8_t eventType, uint8_t buttonState)
{
char buffer[8];
switch(eventType) {
case 0: // AceButton::kEventPressed:
memcpy_P(buffer, PSTR("DOWN"), sizeof(buffer));
break;
case 2: // AceButton::kEventClicked:
memcpy_P(buffer, PSTR("SHORT"), sizeof(buffer));
break;
// case AceButton::kEventDoubleClicked:
// memcpy_P(buffer, PSTR("DOUBLE"), sizeof(buffer));
// break;
case 4: // AceButton::kEventLongPressed:
memcpy_P(buffer, PSTR("LONG"), sizeof(buffer));
break;
case 5: // AceButton::kEventRepeatPressed:
return; // Fix needed for switches
memcpy_P(buffer, PSTR("HOLD"), sizeof(buffer));
break;
case 1: // AceButton::kEventReleased:
memcpy_P(buffer, PSTR("UP"), sizeof(buffer));
break;
}
dispatch_button(button->getId(), buffer);
}
void buttonSetup(void)
{
button[0] = new AceButton(HASP_INPUT_PIN, LOW, 0);
button[1] = new AceButton(3, HIGH, 1);
button[2] = new AceButton(4, HIGH, 2);
Log.verbose(F("BTNS: setup(): ready"));
ButtonConfig * buttonConfig = ButtonConfig::getSystemButtonConfig();
buttonConfig->setEventHandler(button_event_cb);
// Features
buttonConfig->setFeature(ButtonConfig::kFeatureClick);
buttonConfig->setFeature(ButtonConfig::kFeatureLongPress);
buttonConfig->setFeature(ButtonConfig::kFeatureRepeatPress);
// buttonConfig->setFeature(ButtonConfig::kFeatureDoubleClick);
// buttonConfig->setFeature(ButtonConfig::kFeatureSuppressClickBeforeDoubleClick);
// Delays
buttonConfig->setClickDelay(LV_INDEV_DEF_LONG_PRESS_TIME);
buttonConfig->setDoubleClickDelay(LV_INDEV_DEF_LONG_PRESS_TIME);
buttonConfig->setLongPressDelay(LV_INDEV_DEF_LONG_PRESS_TIME);
buttonConfig->setRepeatPressDelay(LV_INDEV_DEF_LONG_PRESS_TIME);
buttonConfig->setRepeatPressInterval(LV_INDEV_DEF_LONG_PRESS_REP_TIME);
}
void IRAM_ATTR buttonLoop(void)
{
// Should be called every 4-5ms or faster, for the default debouncing time
// of ~20ms.
for(uint8_t i = 0; i < HASP_NUM_INPUTS; i++) {
if(button[i]) button[i]->check();
}
}

View File

@ -1,10 +0,0 @@
#if HASP_USE_BUTTON
#ifndef HASP_BUTTON_H
#define HASP_BUTTON_H
void buttonSetup(void);
void IRAM_ATTR buttonLoop(void);
#endif
#endif

View File

@ -1,6 +1,7 @@
#include "Arduino.h"
#include "ArduinoJson.h"
#include "ArduinoLog.h"
#include "ArduinoJson.h"
#include "StreamUtils.h"
#include "hasp_config.h"
#include "hasp_debug.h"
@ -13,21 +14,16 @@
#include "hasp_conf.h"
#if HASP_USE_SPIFFS>0
#if HASP_USE_SPIFFS > 0
#include <FS.h> // Include the SPIFFS library
#if defined(ARDUINO_ARCH_ESP32)
#include "SPIFFS.h"
#endif
#endif
#if HASP_USE_EEPROM>0
#if HASP_USE_EEPROM > 0
#include "EEPROM.h"
#endif
#ifndef FPSTR
#define FPSTR(pstr_pointer) (reinterpret_cast<const __FlashStringHelper *>(pstr_pointer))
#endif
void confDebugSet(const char * name)
{
/*char buffer[128];
@ -77,13 +73,17 @@ void configStartDebug(bool setupdebug, String & configFile)
{
if(setupdebug) {
debugStart(); // Debug started, now we can use it; HASP header sent
#if HASP_USE_SPIFFS > 0
Log.notice(F("FILE: [SUCCESS] SPI flash FS mounted"));
#if HASP_USE_SPIFFS>0
spiffsInfo();
spiffsList();
#endif
}
#if HASP_USE_SPIFFS > 0
Log.notice(F("CONF: Loading %s"), configFile.c_str());
#else
Log.notice(F("CONF: reading EEPROM"));
#endif
}
void configGetConfig(JsonDocument & settings, bool setupdebug = false)
@ -91,9 +91,10 @@ void configGetConfig(JsonDocument & settings, bool setupdebug = false)
String configFile((char *)0);
configFile.reserve(128);
configFile = String(FPSTR(HASP_CONFIG_FILE));
DeserializationError error;
#if HASP_USE_SPIFFS>0
File file = SPIFFS.open(configFile, "r");
#if HASP_USE_SPIFFS > 0
File file = SPIFFS.open(configFile, "r");
if(file) {
size_t size = file.size();
@ -102,7 +103,7 @@ void configGetConfig(JsonDocument & settings, bool setupdebug = false)
return;
}
DeserializationError error = deserializeJson(settings, file);
error = deserializeJson(settings, file);
if(!error) {
file.close();
@ -126,17 +127,26 @@ void configGetConfig(JsonDocument & settings, bool setupdebug = false)
return;
}
}
#else
#if HASP_USE_EEPROM > 0
EepromStream eepromStream(0, 1024);
error = deserializeJson(settings, eepromStream);
#endif
#endif
// File does not exist or error reading file
if(setupdebug) {
debugPreSetup(settings[F("debug")]);
}
configStartDebug(setupdebug, configFile);
Log.error(F("CONF: Failed to load %s"), configFile.c_str());
}
#if HASP_USE_SPIFFS > 0
Log.error(F("CONF: Failed to load %s"), configFile.c_str());
#endif
}
/*
void configBackupToEeprom()
{
#if HASP_USE_SPIFFS>0
@ -165,10 +175,9 @@ void configBackupToEeprom()
}
#endif
}
*/
void configWriteConfig()
{
#if HASP_USE_SPIFFS>0
String configFile((char *)0);
configFile.reserve(128);
configFile = String(FPSTR(HASP_CONFIG_FILE));
@ -258,6 +267,7 @@ void configWriteConfig()
// changed |= otaGetConfig(settings[F("ota")].as<JsonObject>());
if(writefile) {
#if HASP_USE_SPIFFS > 0
File file = SPIFFS.open(configFile, "w");
if(file) {
Log.notice(F("CONF: Writing %s"), configFile.c_str());
@ -265,36 +275,70 @@ void configWriteConfig()
file.close();
if(size > 0) {
Log.verbose(F("CONF: [SUCCESS] Saved %s"), configFile.c_str());
configBackupToEeprom();
return;
// configBackupToEeprom();
} else {
Log.error(F("CONF: Failed to write %s"), configFile.c_str());
}
} else {
Log.error(F("CONF: Failed to write %s"), configFile.c_str());
}
#endif
Log.error(F("CONF: Failed to write %s"), configFile.c_str());
// Method 1
// Log.verbose(F("CONF: Writing to EEPROM"));
// EepromStream eepromStream(0, 1024);
// WriteBufferingStream bufferedWifiClient{eepromStream, 512};
// serializeJson(doc, bufferedWifiClient);
// bufferedWifiClient.flush(); // <- OPTIONAL
// eepromStream.flush(); // (for ESP)
#if defined(STM32F4xx)
// Method 2
Log.verbose(F("CONF: Writing to EEPROM"));
char buffer[1024 + 128];
size_t size = serializeJson(doc, buffer, sizeof(buffer));
if(size > 0) {
uint16_t i;
for(i = 0; i < size; i++) eeprom_buffered_write_byte(i, buffer[i]);
eeprom_buffered_write_byte(i, 0);
eeprom_buffer_flush();
Log.verbose(F("CONF: [SUCCESS] Saved EEPROM"));
} else {
Log.error(F("CONF: Failed to save config to EEPROM"));
}
#endif
} else {
Log.notice(F("CONF: Configuration was not changed"));
Log.notice(F("CONF: Configuration did not change"));
}
#endif
}
void configSetup()
{
#if HASP_USE_SPIFFS>0
if(!SPIFFS.begin()) {
#endif
#if HASP_USE_SPIFFS>0
} else {
#endif
DynamicJsonDocument settings(1024 + 128);
Serial.print(__FILE__);
Serial.println(__LINE__);
DynamicJsonDocument settings(1024 + 128);
configGetConfig(settings, true);
for(uint8_t i = 0; i < 2; i++) {
Serial.print(__FILE__);
Serial.println(__LINE__);
Log.error(F("FILE: SPI flash init failed. Unable to mount FS: Using default settings..."));
#if HASP_USE_SPIFFS>0
if(i == 0) {
#if HASP_USE_SPIFFS > 0
EepromStream eepromStream(0, 2048);
DeserializationError error = deserializeJson(settings, eepromStream);
#else
continue;
#endif
} else {
#if HASP_USE_SPIFFS > 0
if(!SPIFFS.begin()) {
Log.error(F("FILE: SPI flash init failed. Unable to mount FS: Using default settings..."));
return;
}
#endif
configGetConfig(settings, true);
}
//#if HASP_USE_SPIFFS > 0
Log.verbose(F("Loading debug settings"));
debugSetConfig(settings[F("debug")]);
Log.verbose(F("Loading GUI settings"));
@ -322,10 +366,11 @@ void configSetup()
Log.verbose(F("Loading HTTP settings"));
httpSetConfig(settings[F("http")]);
#endif
#endif
#endif // Wifi
// }
Log.notice(F("User configuration loaded"));
}
Log.notice(F("User configuration loaded"));
#endif
//#endif
}
void configOutput(const JsonObject & settings)

View File

@ -15,7 +15,7 @@
#endif
#include "hasp_hal.h"
#if HASP_USE_MQTT>0
#if HASP_USE_MQTT > 0
#include "hasp_mqtt.h"
#endif
@ -73,7 +73,7 @@ Syslog * syslog;
// Serial Settings
uint16_t debugSerialBaud = SERIAL_SPEED / 10; // Multiplied by 10
bool debugSerialStarted = false;
bool debugAnsiCodes = true;
bool debugAnsiCodes = true;
//#define TERM_COLOR_Black "\u001b[30m"
#define TERM_COLOR_GRAY "\e[37m"
@ -94,7 +94,8 @@ String debugHaspHeader()
{
String header((char *)0);
header.reserve(256);
header = F(" _____ _____ _____ _____\r\n"
if(debugAnsiCodes) header += TERM_COLOR_YELLOW;
header += F(" _____ _____ _____ _____\r\n"
" | | | _ | __| _ |\r\n"
" | | |__ | __|\r\n"
" |__|__|__|__|_____|__|\r\n"
@ -216,21 +217,23 @@ static void debugPrintTimestamp(int level, Print * _logOutput)
time_t rawtime;
struct tm * timeinfo;
//time(&rawtime);
//timeinfo = localtime(&rawtime);
// time(&rawtime);
// timeinfo = localtime(&rawtime);
// strftime(buffer, sizeof(buffer), "%b %d %H:%M:%S.", timeinfo);
// Serial.println(buffer);
debugSendAnsiCode(F(TERM_COLOR_CYAN), _logOutput);
/* if(timeinfo->tm_year >= 120) {
char buffer[64];
strftime(buffer, sizeof(buffer), "[%b %d %H:%M:%S.", timeinfo); // Literal String
_logOutput->print(buffer);
_logOutput->printf(PSTR("%03lu]"), millis() % 1000);
} else */ {
_logOutput->printf(PSTR("[%20.3f]"), (float)millis() / 1000);
/* if(timeinfo->tm_year >= 120) {
char buffer[64];
strftime(buffer, sizeof(buffer), "[%b %d %H:%M:%S.", timeinfo); // Literal String
_logOutput->print(buffer);
_logOutput->printf(PSTR("%03lu]"), millis() % 1000);
} else */
{
uint32_t msecs = millis();
_logOutput->printf(PSTR("[%16d.%03d]"), msecs/1000, msecs%1000 );
}
}
@ -328,9 +331,9 @@ void debugPreSetup(JsonObject settings)
uint32_t baudrate = settings[FPSTR(F_CONFIG_BAUD)].as<uint32_t>() * 10;
if(baudrate == 0) baudrate = SERIAL_SPEED;
if(baudrate >= 9600u) { /* the baudrates are stored divided by 10 */
if(baudrate >= 9600u) { /* the baudrates are stored divided by 10 */
#ifdef STM32_CORE_VERSION_MAJOR
#if defined(STM32F4xx)
#ifndef STM32_SERIAL1 // Define what Serial port to use for log output
Serial.setRx(PA3); // User Serial2
Serial.setTx(PA2);
@ -338,7 +341,7 @@ void debugPreSetup(JsonObject settings)
#endif
Serial.begin(baudrate); /* prepare for possible serial debug */
delay(10);
Log.registerOutput(0, &Serial, LOG_LEVEL_VERBOSE, true);
Log.registerOutput(0, &Serial, LOG_LEVEL_VERBOSE, true);
debugSerialStarted = true;
Serial.println();
Log.trace(("Serial started at %u baud"), baudrate);

View File

@ -48,10 +48,11 @@ void dispatchOutput(int output, bool state)
int pin = 0;
if(pin >= 0) {
Log.notice(F("PIN OUTPUT STATE %d"),state);
#if defined(ARDUINO_ARCH_ESP32)
ledcWrite(99, state ? 1023 : 0); // ledChannel and value
#elif defined(STM32_CORE_VERSION)
#elif defined(STM32F4xx)
digitalWrite(HASP_OUTPUT_PIN, state);
#else
analogWrite(pin, state ? 1023 : 0);
@ -97,6 +98,7 @@ void dispatchAttribute(String strTopic, const char * payload)
{
if(strTopic.startsWith("p[")) {
dispatchButtonAttribute(strTopic, payload);
} else if(strTopic == F("page")) {
dispatchPage(payload);
@ -192,7 +194,7 @@ void dispatchBacklight(String strPayload)
void dispatchCommand(String cmnd)
{
// dispatchPrintln(F("CMND"), cmnd);
dispatchPrintln(F("CMND"), cmnd);
if(cmnd.startsWith(F("page "))) {
cmnd = cmnd.substring(5, cmnd.length());
@ -303,6 +305,8 @@ void dispatch_button(uint8_t id, const char * event)
{
#if HASP_USE_MQTT > 0
mqtt_send_input(id, event);
#else
Log.notice(F("OUT: input%d = %s"), id, event);
#endif
#if HASP_USE_TASMOTA_SLAVE
slave_send_input(id, event);

View File

@ -1,49 +1,17 @@
#include <Arduino.h>
#include "EEPROM.h"
#include "hasp_debug.h"
void eepromWrite(char addr, std::string & data);
std::string eepromRead(char addr);
void eepromSetup()
{
#if defined(STM32Fxx)
eeprom_buffer_fill();
#endif
// ESP8266 // Don't start at boot, only at write
// EEPROM.begin(1024);
// debugPrintln("EEPROM: Started Eeprom");
}
void eepromLoop()
{}
void eepromUpdate(uint16_t addr, char ch)
{
if(EEPROM.read(addr) != ch) {
EEPROM.write(addr, ch);
}
}
void eepromWrite(uint16_t addr, std::string & data)
{
int count = data.length();
for(int i = 0; i < count; i++) {
eepromUpdate(addr + i, data[i]);
}
eepromUpdate(addr + count, '\0');
// EEPROM.commit();
}
std::string eepromRead(uint16_t addr)
{
char data[1024]; // Max 1024 Bytes
int len = 0;
unsigned char k;
k = EEPROM.read(addr);
while(k != '\0' && len < 1023) // Read until null character
{
k = EEPROM.read(addr + len);
if((uint8_t(k) < 32) || (uint8_t(k) > 127)) break; // check for printable ascii, includes '\0'
data[len] = k;
len++;
}
return std::string(data);
}
{}

View File

@ -1,14 +1,166 @@
#include <Arduino.h>
#include "ArduinoJson.h"
#include "Arduino.h"
#include "ArduinoLog.h"
#include "AceButton.h"
#include "lv_conf.h" // For timing defines
#include "hasp_conf.h"
#include "hasp_gpio.h"
#include "hasp_dispatch.h"
#define HASP_NUM_GPIO_CONFIG 5
uint8_t gpioUsedInputCount = 0;
uint16_t gpioConfig[HASP_NUM_GPIO_CONFIG];
using namespace ace_button;
static AceButton * button[HASP_NUM_INPUTS];
static void gpio_event_cb(AceButton * button, uint8_t eventType, uint8_t buttonState)
{
char buffer[16];
switch(eventType) {
case 0: // AceButton::kEventPressed:
memcpy_P(buffer, PSTR("DOWN"), sizeof(buffer));
break;
case 2: // AceButton::kEventClicked:
memcpy_P(buffer, PSTR("SHORT"), sizeof(buffer));
break;
case AceButton::kEventDoubleClicked:
memcpy_P(buffer, PSTR("DOUBLE"), sizeof(buffer));
break;
case 4: // AceButton::kEventLongPressed:
memcpy_P(buffer, PSTR("LONG"), sizeof(buffer));
break;
case 5: // AceButton::kEventRepeatPressed:
// return; // Fix needed for switches
memcpy_P(buffer, PSTR("HOLD"), sizeof(buffer));
break;
case 1: // AceButton::kEventReleased:
memcpy_P(buffer, PSTR("UP"), sizeof(buffer));
break;
default:
memcpy_P(buffer, PSTR("UNKNOWN"), sizeof(buffer));
}
dispatch_button(button->getId(), buffer);
}
void aceButtonSetup(void)
{
ButtonConfig * buttonConfig = ButtonConfig::getSystemButtonConfig();
buttonConfig->setEventHandler(gpio_event_cb);
// Features
buttonConfig->setFeature(ButtonConfig::kFeatureClick);
buttonConfig->setFeature(ButtonConfig::kFeatureLongPress);
buttonConfig->setFeature(ButtonConfig::kFeatureRepeatPress);
// buttonConfig->setFeature(ButtonConfig::kFeatureDoubleClick);
// buttonConfig->setFeature(ButtonConfig::kFeatureSuppressClickBeforeDoubleClick);
// Delays
buttonConfig->setClickDelay(LV_INDEV_DEF_LONG_PRESS_TIME);
buttonConfig->setDoubleClickDelay(LV_INDEV_DEF_LONG_PRESS_TIME);
buttonConfig->setLongPressDelay(LV_INDEV_DEF_LONG_PRESS_TIME);
buttonConfig->setRepeatPressDelay(LV_INDEV_DEF_LONG_PRESS_TIME);
buttonConfig->setRepeatPressInterval(LV_INDEV_DEF_LONG_PRESS_REP_TIME);
}
void IRAM_ATTR gpioLoop(void)
{
// Should be called every 4-5ms or faster, for the default debouncing time of ~20ms.
for(uint8_t i = 0; i < gpioUsedInputCount; i++) {
if(button[i]) button[i]->check();
}
}
void gpioAddButton(uint8_t pin, uint8_t input_mode, uint8_t default_state, uint8_t channel)
{
uint8_t i;
for(i = 0; i < HASP_NUM_INPUTS; i++) {
if(!button[i]) {
button[i] = new AceButton(pin, default_state, channel);
if(button[i]) {
pinMode(pin, input_mode);
ButtonConfig * buttonConfig = button[i]->getButtonConfig();
buttonConfig->setEventHandler(gpio_event_cb);
buttonConfig->setFeature(ButtonConfig::kFeatureClick);
buttonConfig->setFeature(ButtonConfig::kFeatureDoubleClick);
buttonConfig->setFeature(ButtonConfig::kFeatureLongPress);
buttonConfig->setFeature(ButtonConfig::kFeatureRepeatPress);
buttonConfig->setFeature(ButtonConfig::kFeatureSuppressClickBeforeDoubleClick);
Log.verbose(F("GPIO: Button%d created on pin %d (channel %d) mode %d default %d"), i, pin, channel, input_mode,default_state);
gpioUsedInputCount = i + 1;
return;
}
}
}
Log.error(F("GPIO: Failed to create Button%d pin %d (channel %d). All %d slots available are in use!"), i, pin,
channel, HASP_NUM_INPUTS);
}
void gpioSetup()
{
#if defined(ARDUINO_ARCH_ESP8266)
pinMode(D1, OUTPUT);
pinMode(D2, INPUT_PULLUP);
#endif
#if defined(STM32_CORE_VERSION)
pinMode(HASP_OUTPUT_PIN, OUTPUT);
pinMode(HASP_INPUT_PIN, INPUT_PULLDOWN);
aceButtonSetup();
//gpioConfig[0] = PD15 * 256 + 5 + (INPUT << 3);
for(uint8_t i = 0; i < HASP_NUM_GPIO_CONFIG; i++) {
uint8_t pin = (gpioConfig[i] >> 8) & 0xFF;
uint8_t channel = gpioConfig[i] & 0b111; // 3bit
uint8_t input_mode = (gpioConfig[i] >> 3) & 0b11; // 2bit gpio mode
uint8_t gpiotype = (gpioConfig[i] >> 5) & 0b111; // 3bit
uint8_t default_state = gpioConfig[i] & 0b1; // 1bit: 0=LOW, 1=HIGH
switch(input_mode) {
case 1:
input_mode = OUTPUT;
break;
case 2:
input_mode = INPUT_PULLUP;
break;
case 3:
input_mode = INPUT_PULLDOWN;
break;
default:
input_mode = INPUT;
}
switch(gpiotype) {
case HASP_GPIO_SWITCH:
case HASP_GPIO_BUTTON:
gpioAddButton(pin, input_mode, default_state, channel);
break;
case HASP_GPIO_RELAY:
pinMode(pin, OUTPUT);
break;
// case HASP_GPIO_LED:
case HASP_GPIO_PWM:
case HASP_GPIO_BACKLIGHT:
pinMode(pin, OUTPUT);
#if defined(ARDUINO_ARCH_ESP32)
// configure LED PWM functionalitites
ledcSetup(channel, 20000, 10);
// attach the channel to the GPIO to be controlled
ledcAttachPin(pin, channel);
#endif
break;
}
}
/*
#if defined(ARDUINO_ARCH_ESP8266)
pinMode(D1, OUTPUT);
pinMode(D2, INPUT_PULLUP);
#endif
#if defined(STM32F4xx)
pinMode(HASP_OUTPUT_PIN, OUTPUT);
pinMode(HASP_INPUT_PIN, INPUT);
#endif
*/
}

View File

@ -1,3 +1,25 @@
#ifndef HASP_GPIO_H
#define HASP_GPIO_H
#include "ArduinoJson.h"
void gpioSetup();
#ifdef __cplusplus
extern "C" {
#endif
void gpioSetup(void);
void IRAM_ATTR gpioLoop(void);
enum lv_hasp_gpio_type_t {
HASP_GPIO_SWITCH = 0,
HASP_GPIO_BUTTON = 1,
HASP_GPIO_RELAY = 2,
HASP_GPIO_PWM = 3,
HASP_GPIO_BACKLIGHT = 4,
};
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif

View File

@ -306,14 +306,6 @@ static void IRAM_ATTR lv_tick_handler(void)
lv_tick_inc(guiTickPeriod);
}
#ifdef STM32_CORE_VERSION
void Update_IT_callback(void)
{
Serial.print("?");
lv_tick_inc(guiTickPeriod);
}
#endif
/* Reading input device (simulated encoder here) */
/*bool read_encoder(lv_indev_drv_t * indev, lv_indev_data_t * data)
{
@ -628,6 +620,13 @@ void guiSetup()
{
/* TFT init */
tft.begin();
#ifdef USE_DMA_TO_TFT
// DMA - should work with STM32F2xx/F4xx/F7xx processors
// NOTE: >>>>>> DMA IS FOR SPI DISPLAYS ONLY <<<<<<
tft.initDMA(); // Initialise the DMA engine (tested with STM32F446 and STM32F767)
#endif
tft.setRotation(guiRotation); /* 1/3=Landscape or 0/2=Portrait orientation */
#if TOUCH_DRIVER == 0
tft.setTouch(calData);
@ -673,8 +672,13 @@ void guiSetup()
lv_fs_if_init(); // auxilary file system drivers
#endif
/* Dump TFT Cofiguration */
/* Dump TFT Configuration */
tftSetup(tft);
#ifdef USE_DMA_TO_TFT
Log.verbose(F("TFT: DMA : ENABELD"));
#else
Log.verbose(F("TFT: DMA : DISABELD"));
#endif
/* Load User Settings */
// guiSetConfig(settings);
@ -811,10 +815,10 @@ void guiSetup()
void IRAM_ATTR guiLoop()
{
#ifdef STM32_CORE_VERSION_MAJOR
#if defined(STM32F4xx)
tick.update();
while(Serial.available()) {
while(Serial.available()) {
char ch = Serial.read();
Serial.print(ch);
if (ch == 13 ||ch == 10) {
@ -992,6 +996,7 @@ bool guiSetConfig(const JsonObject & settings)
Log.notice(F("First Touch Calibration enabled"));
oobeSetAutoCalibrate(true);
}
if (status) tft.setTouch(calData);
changed |= status;
}

View File

@ -107,56 +107,7 @@ String halGetResetInfo()
#endif
}
#ifdef __arm__
// should use uinstd.h to define sbrk but Due causes a conflict
extern "C" char* sbrk(int incr);
#else // __ARM__
extern char *__brkval;
#endif // __arm__
int freeMemory() {
char top;
#ifdef __arm__
return &top - reinterpret_cast<char*>(sbrk(0));
#elif defined(CORE_TEENSY) || (ARDUINO > 103 && ARDUINO != 151)
return &top - __brkval;
#else // __arm__
return __brkval ? &top - __brkval : &top - __malloc_heap_start;
#endif // __arm__
}
uint8_t halGetHeapFragmentation()
{
#if defined(ARDUINO_ARCH_ESP32)
return (int8_t)(100.00f - (float)ESP.getMaxAllocHeap() * 100.00f / (float)ESP.getFreeHeap());
#elif defined(ARDUINO_ARCH_ESP8266)
return ESP.getHeapFragmentation();
#else
return 255;
#endif
}
size_t halGetMaxFreeBlock()
{
#if defined(ARDUINO_ARCH_ESP32)
return ESP.getMaxAllocHeap();
#elif defined(ARDUINO_ARCH_ESP8266)
return ESP.getMaxFreeBlockSize();
#else
return freeMemory();
#endif
}
size_t halGetFreeHeap(void)
{
#if defined(ARDUINO_ARCH_ESP32)
return ESP.getFreeHeap();
#elif defined(ARDUINO_ARCH_ESP8266)
return ESP.getFreeHeap();
#else
return 1;
#endif
}
String halGetCoreVersion()
{
@ -193,8 +144,8 @@ String halGetChipModel()
case CHIP_ESP32S2:
model += F("ESP32-S2");
break;
#endif
default:
#endif
default:
model = F("Unknown ESP");
}
model += F(" rev");
@ -202,4 +153,89 @@ String halGetChipModel()
#endif // ESP32
return model;
}
}
/*******************************/
/* Memory Management Functions */
#if defined(STM32F4xx)
#include <malloc.h> // for mallinfo()
#include <unistd.h> // for sbrk()
int freeHighMemory()
{
char top;
#ifdef __arm__
return &top - reinterpret_cast<char *>(sbrk(0));
#elif defined(CORE_TEENSY) || (ARDUINO > 103 && ARDUINO != 151)
return &top - __brkval;
#else // __arm__
return __brkval ? &top - __brkval : &top - __malloc_heap_start;
#endif // __arm__
}
#endif
/*
extern char *fake_heap_end; // current heap start
extern char *fake_heap_start; // current heap end
char* getHeapStart() {
return fake_heap_start;
}
char* getHeapEnd() {
return (char*)sbrk(0);
}
char* getHeapLimit() {
return fake_heap_end;
}
int getMemUsed() { // returns the amount of used memory in bytes
struct mallinfo mi = mallinfo();
return mi.uordblks;
}
int getMemFree() { // returns the amount of free memory in bytes
struct mallinfo mi = mallinfo();
return mi.fordblks + freeHighMemory();
} */
size_t halGetMaxFreeBlock()
{
#if defined(ARDUINO_ARCH_ESP32)
return ESP.getMaxAllocHeap();
#elif defined(ARDUINO_ARCH_ESP8266)
return ESP.getMaxFreeBlockSize();
#else
return freeHighMemory();
#endif
}
size_t halGetFreeHeap(void)
{
#if defined(ARDUINO_ARCH_ESP32)
return ESP.getFreeHeap();
#elif defined(ARDUINO_ARCH_ESP8266)
return ESP.getFreeHeap();
#else
struct mallinfo chuncks = mallinfo();
// fordblks
// This is the total size of memory occupied by free (not in use) chunks.
return chuncks.fordblks + freeHighMemory();
#endif
}
uint8_t halGetHeapFragmentation()
{
#if defined(ARDUINO_ARCH_ESP32)
return (int8_t)(100.00f - (float)ESP.getMaxAllocHeap() * 100.00f / (float)ESP.getFreeHeap());
#elif defined(ARDUINO_ARCH_ESP8266)
return ESP.getHeapFragmentation();
#else
return (int8_t)(100.00f - (float)freeHighMemory() * 100.00f / (float)halGetFreeHeap());
#endif
}

View File

@ -98,6 +98,7 @@ void tftShowConfig(TFT_eSPI & tft)
#if defined(ARDUINO_ARCH_ESP8266)
Log.verbose(F("TFT: SPI overlap : %s"), (tftSetup.overlap == 1) ? PSTR("Yes") : PSTR("No"));
#endif
if(tftSetup.tft_driver != 0xE9D) // For ePaper displays the size is defined in the sketch
{
Log.verbose(F("TFT: Driver : %s"), tftDriverName().c_str()); // tftSetup.tft_driver);

View File

@ -1,12 +1,11 @@
#include "hasp_conf.h" // load first
#include <Arduino.h>
#include "hasp_conf.h"
#include "hasp_debug.h"
#include "hasp_spiffs.h"
#include "hasp_config.h"
#include "hasp_gui.h"
#include "hasp.h"
#include "hasp_conf.h"
#include "hasp_oobe.h"
#include "hasp_gpio.h"
@ -23,7 +22,7 @@ void setup()
/* Init Storage */
#if HASP_USE_EEPROM
// eepromSetup(); // Don't start at boot, only at write
eepromSetup(); // Don't start at boot, only at write
#endif
#if HASP_USE_SPIFFS
@ -44,7 +43,10 @@ void setup()
***************************/
debugSetup();
gpioSetup();
#if HASP_USE_GPIO
guiSetup();
#endif
#if HASP_USE_WIFI
wifiSetup();
@ -76,10 +78,6 @@ void setup()
#endif // WIFI
#if HASP_USE_BUTTON
buttonSetup();
#endif
#if HASP_USE_TASMOTA_SLAVE
slaveSetup();
#endif
@ -90,15 +88,21 @@ void setup()
void loop()
{
/* Storage Loops */
/*
#if HASP_USE_EEPROM
eepromLoop();
#endif
// spiffsLoop();
#if HASP_USE_SDCARD
// sdcardLoop();
// eepromLoop(); // Not used
#endif
// configLoop();
#if HASP_USE_SPIFFS
// spiffsLoop(); // Not used
#endif
#if HASP_USE_SDCARD
// sdcardLoop(); // Not used
#endif
// configLoop(); // Not used
*/
/* Graphics Loops */
// tftLoop();
@ -106,9 +110,9 @@ void loop()
/* Application Loops */
// haspLoop();
#if HASP_USE_BUTTON
buttonLoop();
#endif // BUTTON
#if HASP_USE_GPIO
gpioLoop();
#endif
/* Network Services Loops */
#if HASP_USE_WIFI
@ -139,7 +143,9 @@ void loop()
slaveLoop();
#endif // TASMOTASLAVE
// Every Second Loop
// digitalWrite(HASP_OUTPUT_PIN, digitalRead(HASP_INPUT_PIN)); // sets the LED to the button's value
/* Timer Loop */
if(millis() - mainLastLoopTime >= 1000) {
/* Run Every Second */
#if HASP_USE_OTA
@ -148,27 +154,25 @@ void loop()
debugEverySecond();
/* Run Every 5 Seconds */
if(mainLoopCounter == 0 || mainLoopCounter == 4) {
#if HASP_USE_WIFI
if(mainLoopCounter == 0 || mainLoopCounter == 5) {
isConnected = wifiEvery5Seconds();
#if HASP_USE_HTTP
httpEvery5Seconds();
#endif
#if HASP_USE_WIFI
isConnected = wifiEvery5Seconds();
#if HASP_USE_MQTT
mqttEvery5Seconds(isConnected);
#endif
#endif
}
#endif // Wifi
/* Update counters */
/* Reset loop counter every 10 seconds */
if(mainLoopCounter >= 9) {
mainLoopCounter = 0;
} else {
mainLoopCounter++;
}
mainLastLoopTime += 1000;
mainLoopCounter++;
if(mainLoopCounter >= 10) {
mainLoopCounter = 0;
}
}
delay(3);