Move Settings from DRAM to heap

This commit is contained in:
Theo Arends 2021-06-11 18:14:12 +02:00
parent c8fe3b31ee
commit 5e805e0c4a
156 changed files with 3463 additions and 3454 deletions

View File

@ -15,6 +15,7 @@ All notable changes to this project will be documented in this file.
- Command ``Modules`` layout of JSON message changed to single line
- I2C extended MPU6886 to also support MPU9250 (found in Legacy M5Stack Fire)
- ESP32 increase log buffer from 4k to 6k to support longer messages
- Move Settings from DRAM to heap
## [9.4.0.4]
### Added

View File

@ -101,6 +101,7 @@ The binaries can be downloaded from either https://github.com/arendst/Tasmota/tr
- Command ``Gpio`` layout of JSON message changed to single line
- Command ``Modules`` layout of JSON message changed to single line
- ESP32 increase log buffer from 4k to 6k to support longer messages
- Move Settings from DRAM to heap
### Fixed

View File

@ -1,5 +1,5 @@
/*
settings.h - setting variables for Tasmota
Settings->h - setting variables for Tasmota
Copyright (C) 2021 Theo Arends
@ -435,10 +435,10 @@ typedef union {
};
} DisplayOptions;
const uint32_t settings_text_size = 699; // Settings.text_pool[size] = Settings.display_model (2D2) - Settings.text_pool (017)
const uint32_t settings_text_size = 699; // Settings->text_pool[size] = Settings->display_model (2D2) - Settings->text_pool (017)
const uint8_t MAX_TUYA_FUNCTIONS = 16;
struct {
typedef struct {
uint16_t cfg_holder; // 000 v6 header
uint16_t cfg_size; // 002
unsigned long save_flag; // 004
@ -762,7 +762,7 @@ struct {
uint32_t i2c_drivers[3]; // FEC I2cDriver
uint32_t cfg_timestamp; // FF8
uint32_t cfg_crc32; // FFC
} Settings;
} TSettings;
typedef struct {
uint16_t valid; // 280 (RTC memory offset 100 - sizeof(RTCRBT))

File diff suppressed because it is too large Load Diff

View File

@ -604,9 +604,9 @@ char IndexSeparator(void)
// 20 bytes more costly !?!
const char separators[] = { "-_" };
return separators[Settings.flag3.use_underscore];
return separators[Settings->flag3.use_underscore];
*/
if (Settings.flag3.use_underscore) { // SetOption64 - Enable "_" instead of "-" as sensor index separator
if (Settings->flag3.use_underscore) { // SetOption64 - Enable "_" instead of "-" as sensor index separator
return '_';
} else {
return '-';
@ -727,10 +727,10 @@ float ConvertTemp(float c)
TasmotaGlobal.global_update = TasmotaGlobal.uptime;
TasmotaGlobal.temperature_celsius = c;
if (!isnan(c) && Settings.flag.temperature_conversion) { // SetOption8 - Switch between Celsius or Fahrenheit
if (!isnan(c) && Settings->flag.temperature_conversion) { // SetOption8 - Switch between Celsius or Fahrenheit
result = c * 1.8 + 32; // Fahrenheit
}
result = result + (0.1 * Settings.temp_comp);
result = result + (0.1 * Settings->temp_comp);
return result;
}
@ -738,17 +738,17 @@ float ConvertTempToCelsius(float c)
{
float result = c;
if (!isnan(c) && Settings.flag.temperature_conversion) { // SetOption8 - Switch between Celsius or Fahrenheit
if (!isnan(c) && Settings->flag.temperature_conversion) { // SetOption8 - Switch between Celsius or Fahrenheit
result = (c - 32) / 1.8; // Celsius
}
result = result + (0.1 * Settings.temp_comp);
result = result + (0.1 * Settings->temp_comp);
return result;
}
char TempUnit(void)
{
// SetOption8 - Switch between Celsius or Fahrenheit
return (Settings.flag.temperature_conversion) ? D_UNIT_FAHRENHEIT[0] : D_UNIT_CELSIUS[0];
return (Settings->flag.temperature_conversion) ? D_UNIT_FAHRENHEIT[0] : D_UNIT_CELSIUS[0];
}
float ConvertHumidity(float h)
@ -758,7 +758,7 @@ float ConvertHumidity(float h)
TasmotaGlobal.global_update = TasmotaGlobal.uptime;
TasmotaGlobal.humidity = h;
result = result + (0.1 * Settings.hum_comp);
result = result + (0.1 * Settings->hum_comp);
return result;
}
@ -767,14 +767,14 @@ float CalcTempHumToDew(float t, float h)
{
if (isnan(h) || isnan(t)) { return NAN; }
if (Settings.flag.temperature_conversion) { // SetOption8 - Switch between Celsius or Fahrenheit
if (Settings->flag.temperature_conversion) { // SetOption8 - Switch between Celsius or Fahrenheit
t = (t - 32) / 1.8; // Celsius
}
float gamma = TaylorLog(h / 100) + 17.62 * t / (243.5 + t);
float result = (243.5 * gamma / (17.62 - gamma));
if (Settings.flag.temperature_conversion) { // SetOption8 - Switch between Celsius or Fahrenheit
if (Settings->flag.temperature_conversion) { // SetOption8 - Switch between Celsius or Fahrenheit
result = result * 1.8 + 32; // Fahrenheit
}
return result;
@ -787,7 +787,7 @@ float ConvertPressure(float p)
TasmotaGlobal.global_update = TasmotaGlobal.uptime;
TasmotaGlobal.pressure_hpa = p;
if (!isnan(p) && Settings.flag.pressure_conversion) { // SetOption24 - Switch between hPa or mmHg pressure unit
if (!isnan(p) && Settings->flag.pressure_conversion) { // SetOption24 - Switch between hPa or mmHg pressure unit
result = p * 0.75006375541921; // mmHg
}
return result;
@ -798,24 +798,24 @@ float ConvertPressureForSeaLevel(float pressure)
if (pressure == 0.0f)
return pressure;
return ConvertPressure((pressure / FastPrecisePow(1.0 - ((float)Settings.altitude / 44330.0f), 5.255f)) - 21.6f);
return ConvertPressure((pressure / FastPrecisePow(1.0 - ((float)Settings->altitude / 44330.0f), 5.255f)) - 21.6f);
}
String PressureUnit(void)
{
return (Settings.flag.pressure_conversion) ? String(F(D_UNIT_MILLIMETER_MERCURY)) : String(F(D_UNIT_PRESSURE));
return (Settings->flag.pressure_conversion) ? String(F(D_UNIT_MILLIMETER_MERCURY)) : String(F(D_UNIT_PRESSURE));
}
float ConvertSpeed(float s)
{
// Entry in m/s
return s * kSpeedConversionFactor[Settings.flag2.speed_conversion];
return s * kSpeedConversionFactor[Settings->flag2.speed_conversion];
}
String SpeedUnit(void)
{
char speed[8];
return String(GetTextIndexed(speed, sizeof(speed), Settings.flag2.speed_conversion, kSpeedUnit));
return String(GetTextIndexed(speed, sizeof(speed), Settings->flag2.speed_conversion, kSpeedUnit));
}
void ResetGlobalValues(void)
@ -969,7 +969,7 @@ int GetStateNumber(char *state_text)
}
String GetSerialConfig(void) {
// Settings.serial_config layout
// Settings->serial_config layout
// b000000xx - 5, 6, 7 or 8 data bits
// b00000x00 - 1 or 2 stop bits
// b000xx000 - None, Even or Odd parity
@ -977,9 +977,9 @@ String GetSerialConfig(void) {
const static char kParity[] PROGMEM = "NEOI";
char config[4];
config[0] = '5' + (Settings.serial_config & 0x3);
config[1] = pgm_read_byte(&kParity[(Settings.serial_config >> 3) & 0x3]);
config[2] = '1' + ((Settings.serial_config >> 2) & 0x1);
config[0] = '5' + (Settings->serial_config & 0x3);
config[1] = pgm_read_byte(&kParity[(Settings->serial_config >> 3) & 0x3]);
config[2] = '1' + ((Settings->serial_config >> 2) & 0x1);
config[3] = '\0';
return String(config);
}
@ -990,17 +990,17 @@ uint32_t GetSerialBaudrate(void) {
}
void SetSerialBegin(void) {
TasmotaGlobal.baudrate = Settings.baudrate * 300;
TasmotaGlobal.baudrate = Settings->baudrate * 300;
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_SERIAL "Set to %s %d bit/s"), GetSerialConfig().c_str(), TasmotaGlobal.baudrate);
Serial.flush();
#ifdef ESP8266
Serial.begin(TasmotaGlobal.baudrate, (SerialConfig)pgm_read_byte(kTasmotaSerialConfig + Settings.serial_config));
Serial.begin(TasmotaGlobal.baudrate, (SerialConfig)pgm_read_byte(kTasmotaSerialConfig + Settings->serial_config));
#endif // ESP8266
#ifdef ESP32
delay(10); // Allow time to cleanup queues - if not used hangs ESP32
Serial.end();
delay(10); // Allow time to cleanup queues - if not used hangs ESP32
uint32_t config = pgm_read_dword(kTasmotaSerialConfig + Settings.serial_config);
uint32_t config = pgm_read_dword(kTasmotaSerialConfig + Settings->serial_config);
Serial.begin(TasmotaGlobal.baudrate, config);
#endif // ESP32
}
@ -1009,15 +1009,15 @@ void SetSerialConfig(uint32_t serial_config) {
if (serial_config > TS_SERIAL_8O2) {
serial_config = TS_SERIAL_8N1;
}
if (serial_config != Settings.serial_config) {
Settings.serial_config = serial_config;
if (serial_config != Settings->serial_config) {
Settings->serial_config = serial_config;
SetSerialBegin();
}
}
void SetSerialBaudrate(uint32_t baudrate) {
TasmotaGlobal.baudrate = baudrate;
Settings.baudrate = TasmotaGlobal.baudrate / 300;
Settings->baudrate = TasmotaGlobal.baudrate / 300;
if (GetSerialBaudrate() != TasmotaGlobal.baudrate) {
#if defined(CONFIG_IDF_TARGET_ESP32C3) && !CONFIG_IDF_TARGET_ESP32C3 // crashes on ESP32C3 - TODO
SetSerialBegin();
@ -1026,10 +1026,10 @@ void SetSerialBaudrate(uint32_t baudrate) {
}
void SetSerial(uint32_t baudrate, uint32_t serial_config) {
Settings.flag.mqtt_serial = 0; // CMND_SERIALSEND and CMND_SERIALLOG
Settings.serial_config = serial_config;
Settings->flag.mqtt_serial = 0; // CMND_SERIALSEND and CMND_SERIALLOG
Settings->serial_config = serial_config;
TasmotaGlobal.baudrate = baudrate;
Settings.baudrate = TasmotaGlobal.baudrate / 300;
Settings->baudrate = TasmotaGlobal.baudrate / 300;
SetSeriallog(LOG_LEVEL_NONE);
SetSerialBegin();
}
@ -1039,7 +1039,7 @@ void ClaimSerial(void) {
AddLog(LOG_LEVEL_INFO, PSTR("SNS: Hardware Serial"));
SetSeriallog(LOG_LEVEL_NONE);
TasmotaGlobal.baudrate = GetSerialBaudrate();
Settings.baudrate = TasmotaGlobal.baudrate / 300;
Settings->baudrate = TasmotaGlobal.baudrate / 300;
}
void SerialSendRaw(char *codes)
@ -1111,39 +1111,39 @@ void WebHexCode(uint32_t i, const char* code)
color = w | (w << 4); // 00112233
}
*/
uint32_t j = sizeof(Settings.web_color) / 3; // First area contains j = 18 colors
uint32_t j = sizeof(Settings->web_color) / 3; // First area contains j = 18 colors
/*
if (i < j) {
Settings.web_color[i][0] = (color >> 16) & 0xFF; // Red
Settings.web_color[i][1] = (color >> 8) & 0xFF; // Green
Settings.web_color[i][2] = color & 0xFF; // Blue
Settings->web_color[i][0] = (color >> 16) & 0xFF; // Red
Settings->web_color[i][1] = (color >> 8) & 0xFF; // Green
Settings->web_color[i][2] = color & 0xFF; // Blue
} else {
Settings.web_color2[i-j][0] = (color >> 16) & 0xFF; // Red
Settings.web_color2[i-j][1] = (color >> 8) & 0xFF; // Green
Settings.web_color2[i-j][2] = color & 0xFF; // Blue
Settings->web_color2[i-j][0] = (color >> 16) & 0xFF; // Red
Settings->web_color2[i-j][1] = (color >> 8) & 0xFF; // Green
Settings->web_color2[i-j][2] = color & 0xFF; // Blue
}
*/
if (i >= j) {
// Calculate i to index in Settings.web_color2 - Dirty(!) but saves 128 bytes code
i += ((((uint8_t*)&Settings.web_color2 - (uint8_t*)&Settings.web_color) / 3) - j);
// Calculate i to index in Settings->web_color2 - Dirty(!) but saves 128 bytes code
i += ((((uint8_t*)&Settings->web_color2 - (uint8_t*)&Settings->web_color) / 3) - j);
}
Settings.web_color[i][0] = (color >> 16) & 0xFF; // Red
Settings.web_color[i][1] = (color >> 8) & 0xFF; // Green
Settings.web_color[i][2] = color & 0xFF; // Blue
Settings->web_color[i][0] = (color >> 16) & 0xFF; // Red
Settings->web_color[i][1] = (color >> 8) & 0xFF; // Green
Settings->web_color[i][2] = color & 0xFF; // Blue
}
uint32_t WebColor(uint32_t i)
{
uint32_t j = sizeof(Settings.web_color) / 3; // First area contains j = 18 colors
uint32_t j = sizeof(Settings->web_color) / 3; // First area contains j = 18 colors
/*
uint32_t tcolor = (i<j)? (Settings.web_color[i][0] << 16) | (Settings.web_color[i][1] << 8) | Settings.web_color[i][2] :
(Settings.web_color2[i-j][0] << 16) | (Settings.web_color2[i-j][1] << 8) | Settings.web_color2[i-j][2];
uint32_t tcolor = (i<j)? (Settings->web_color[i][0] << 16) | (Settings->web_color[i][1] << 8) | Settings->web_color[i][2] :
(Settings->web_color2[i-j][0] << 16) | (Settings->web_color2[i-j][1] << 8) | Settings->web_color2[i-j][2];
*/
if (i >= j) {
// Calculate i to index in Settings.web_color2 - Dirty(!) but saves 128 bytes code
i += ((((uint8_t*)&Settings.web_color2 - (uint8_t*)&Settings.web_color) / 3) - j);
// Calculate i to index in Settings->web_color2 - Dirty(!) but saves 128 bytes code
i += ((((uint8_t*)&Settings->web_color2 - (uint8_t*)&Settings->web_color) / 3) - j);
}
uint32_t tcolor = (Settings.web_color[i][0] << 16) | (Settings.web_color[i][1] << 8) | Settings.web_color[i][2];
uint32_t tcolor = (Settings->web_color[i][0] << 16) | (Settings->web_color[i][1] << 8) | Settings->web_color[i][2];
return tcolor;
}
@ -1236,7 +1236,7 @@ int ResponseTime_P(const char* format, ...) // Content send snprintf_P char d
// This uses char strings. Be aware of sending %% if % is needed
#ifdef MQTT_DATA_STRING
char timestr[100];
TasmotaGlobal.mqtt_data = ResponseGetTime(Settings.flag2.time_format, timestr);
TasmotaGlobal.mqtt_data = ResponseGetTime(Settings->flag2.time_format, timestr);
va_list arg;
va_start(arg, format);
@ -1251,7 +1251,7 @@ int ResponseTime_P(const char* format, ...) // Content send snprintf_P char d
va_list args;
va_start(args, format);
ResponseGetTime(Settings.flag2.time_format, TasmotaGlobal.mqtt_data);
ResponseGetTime(Settings->flag2.time_format, TasmotaGlobal.mqtt_data);
int mlen = ResponseLength();
int len = ext_vsnprintf_P(TasmotaGlobal.mqtt_data + mlen, ResponseSize() - mlen, format, args);
@ -1291,16 +1291,16 @@ int ResponseAppendTimeFormat(uint32_t format)
int ResponseAppendTime(void)
{
return ResponseAppendTimeFormat(Settings.flag2.time_format);
return ResponseAppendTimeFormat(Settings->flag2.time_format);
}
int ResponseAppendTHD(float f_temperature, float f_humidity)
{
float dewpoint = CalcTempHumToDew(f_temperature, f_humidity);
return ResponseAppend_P(PSTR("\"" D_JSON_TEMPERATURE "\":%*_f,\"" D_JSON_HUMIDITY "\":%*_f,\"" D_JSON_DEWPOINT "\":%*_f"),
Settings.flag2.temperature_resolution, &f_temperature,
Settings.flag2.humidity_resolution, &f_humidity,
Settings.flag2.temperature_resolution, &dewpoint);
Settings->flag2.temperature_resolution, &f_temperature,
Settings->flag2.humidity_resolution, &f_humidity,
Settings->flag2.temperature_resolution, &dewpoint);
}
int ResponseJsonEnd(void)
@ -1351,15 +1351,15 @@ void TemplateConvert(uint8_t template8[], uint16_t template16[]) {
}
void ConvertGpios(void) {
if (Settings.gpio16_converted != 0xF5A0) {
if (Settings->gpio16_converted != 0xF5A0) {
// Convert 8-bit user template
TemplateConvert((uint8_t*)&Settings.ex_user_template8, (uint16_t*)&Settings.user_template);
TemplateConvert((uint8_t*)&Settings->ex_user_template8, (uint16_t*)&Settings->user_template);
for (uint32_t i = 0; i < sizeof(Settings.ex_my_gp8.io); i++) {
Settings.my_gp.io[i] = GpioConvert(Settings.ex_my_gp8.io[i]);
for (uint32_t i = 0; i < sizeof(Settings->ex_my_gp8.io); i++) {
Settings->my_gp.io[i] = GpioConvert(Settings->ex_my_gp8.io[i]);
}
Settings.my_gp.io[(sizeof(myio) / 2) -1] = Adc0Convert(Settings.ex_my_adc0);
Settings.gpio16_converted = 0xF5A0;
Settings->my_gp.io[(sizeof(myio) / 2) -1] = Adc0Convert(Settings->ex_my_adc0);
Settings->gpio16_converted = 0xF5A0;
}
}
#endif // ESP8266
@ -1408,7 +1408,7 @@ uint8_t ModuleNr(void)
{
// 0 = User module (255)
// 1 up = Template module 0 up
return (USER_MODULE == Settings.module) ? 0 : Settings.module +1;
return (USER_MODULE == Settings->module) ? 0 : Settings->module +1;
}
uint32_t ModuleTemplate(uint32_t module) {
@ -1466,7 +1466,7 @@ String AnyModuleName(uint32_t index)
String ModuleName(void)
{
return AnyModuleName(Settings.module);
return AnyModuleName(Settings->module);
}
#ifdef ESP8266
@ -1513,17 +1513,17 @@ void GetInternalTemplate(void* ptr, uint32_t module, uint32_t option) {
void TemplateGpios(myio *gp)
{
uint16_t *dest = (uint16_t *)gp;
uint16_t src[nitems(Settings.user_template.gp.io)];
uint16_t src[nitems(Settings->user_template.gp.io)];
memset(dest, GPIO_NONE, sizeof(myio));
if (USER_MODULE == Settings.module) {
memcpy(&src, &Settings.user_template.gp, sizeof(mycfgio));
if (USER_MODULE == Settings->module) {
memcpy(&src, &Settings->user_template.gp, sizeof(mycfgio));
} else {
#ifdef ESP8266
GetInternalTemplate(&src, Settings.module, 1);
GetInternalTemplate(&src, Settings->module, 1);
#endif // ESP8266
#ifdef ESP32
memcpy_P(&src, &kModules[ModuleTemplate(Settings.module)].gp, sizeof(mycfgio));
memcpy_P(&src, &kModules[ModuleTemplate(Settings->module)].gp, sizeof(mycfgio));
#endif // ESP32
}
// 11 85 00 85 85 00 00 00 15 38 85 00 00 81
@ -1531,7 +1531,7 @@ void TemplateGpios(myio *gp)
// AddLogBuffer(LOG_LEVEL_DEBUG, (uint8_t *)&src, sizeof(mycfgio));
uint32_t j = 0;
for (uint32_t i = 0; i < nitems(Settings.user_template.gp.io); i++) {
for (uint32_t i = 0; i < nitems(Settings->user_template.gp.io); i++) {
#if defined(ESP32) && CONFIG_IDF_TARGET_ESP32C3
#else
if (6 == i) { j = 9; }
@ -1549,14 +1549,14 @@ gpio_flag ModuleFlag(void)
{
gpio_flag flag;
if (USER_MODULE == Settings.module) {
flag = Settings.user_template.flag;
if (USER_MODULE == Settings->module) {
flag = Settings->user_template.flag;
} else {
#ifdef ESP8266
GetInternalTemplate(&flag, Settings.module, 2);
GetInternalTemplate(&flag, Settings->module, 2);
#endif // ESP8266
#ifdef ESP32
memcpy_P(&flag, &kModules[ModuleTemplate(Settings.module)].flag, sizeof(gpio_flag));
memcpy_P(&flag, &kModules[ModuleTemplate(Settings->module)].flag, sizeof(gpio_flag));
#endif // ESP32
}
@ -1566,7 +1566,7 @@ gpio_flag ModuleFlag(void)
void ModuleDefault(uint32_t module)
{
if (USER_MODULE == module) { module = WEMOS; } // Generic
Settings.user_template_base = module;
Settings->user_template_base = module;
#ifdef ESP32
module = ModuleTemplate(module);
@ -1575,16 +1575,16 @@ void ModuleDefault(uint32_t module)
char name[TOPSZ];
SettingsUpdateText(SET_TEMPLATE_NAME, GetTextIndexed(name, sizeof(name), module, kModuleNames));
#ifdef ESP8266
GetInternalTemplate(&Settings.user_template, module, 3);
GetInternalTemplate(&Settings->user_template, module, 3);
#endif // ESP8266
#ifdef ESP32
memcpy_P(&Settings.user_template, &kModules[module], sizeof(mytmplt));
memcpy_P(&Settings->user_template, &kModules[module], sizeof(mytmplt));
#endif // ESP32
}
void SetModuleType(void)
{
TasmotaGlobal.module_type = (USER_MODULE == Settings.module) ? Settings.user_template_base : Settings.module;
TasmotaGlobal.module_type = (USER_MODULE == Settings->module) ? Settings->user_template_base : Settings->module;
}
bool FlashPin(uint32_t pin)
@ -1610,7 +1610,7 @@ uint32_t ValidPin(uint32_t pin, uint32_t gpio) {
return GPIO_NONE; // Disable flash pins GPIO6, GPIO7, GPIO8 and GPIO11
}
if ((WEMOS == Settings.module) && !Settings.flag3.user_esp8285_enable) { // SetOption51 - Enable ESP8285 user GPIO's
if ((WEMOS == Settings->module) && !Settings->flag3.user_esp8285_enable) { // SetOption51 - Enable ESP8285 user GPIO's
if ((9 == pin) || (10 == pin)) {
return GPIO_NONE; // Disable possible flash GPIO9 and GPIO10
}
@ -1680,22 +1680,22 @@ bool JsonTemplate(char* dataBuf)
if (val) {
template8[nitems(template8) -1] = val.getUInt() & 0x0F;
}
TemplateConvert(template8, Settings.user_template.gp.io);
Settings.user_template.flag.data = 0;
TemplateConvert(template8, Settings->user_template.gp.io);
Settings->user_template.flag.data = 0;
} else {
#endif
for (uint32_t i = 0; i < nitems(Settings.user_template.gp.io); i++) {
for (uint32_t i = 0; i < nitems(Settings->user_template.gp.io); i++) {
JsonParserToken val = arr[i];
if (!val) { break; }
uint16_t gpio = val.getUInt();
if (gpio == (AGPIO(GPIO_NONE) +1)) {
gpio = AGPIO(GPIO_USER);
}
Settings.user_template.gp.io[i] = gpio;
Settings->user_template.gp.io[i] = gpio;
}
val = root[PSTR(D_JSON_FLAG)];
if (val) {
Settings.user_template.flag.data = val.getUInt();
Settings->user_template.flag.data = val.getUInt();
}
}
#ifdef ESP8266
@ -1705,12 +1705,12 @@ bool JsonTemplate(char* dataBuf)
if (val) {
uint32_t base = val.getUInt();
if ((0 == base) || !ValidTemplateModule(base -1)) { base = 18; }
Settings.user_template_base = base -1; // Default WEMOS
Settings->user_template_base = base -1; // Default WEMOS
}
val = root[PSTR(D_JSON_CMND)];
if (val) {
if ((USER_MODULE == Settings.module) || StrCaseStr_P(val.getStr(), PSTR(D_CMND_MODULE " 0"))) { // Only execute if current module = USER_MODULE = this template
if ((USER_MODULE == Settings->module) || StrCaseStr_P(val.getStr(), PSTR(D_CMND_MODULE " 0"))) { // Only execute if current module = USER_MODULE = this template
char* backup_data = XdrvMailbox.data;
XdrvMailbox.data = (char*)val.getStr(); // Backlog commands
ReplaceChar(XdrvMailbox.data, '|', ';'); // Support '|' as command separator for JSON backwards compatibility
@ -1726,7 +1726,7 @@ bool JsonTemplate(char* dataBuf)
}
// AddLog(LOG_LEVEL_DEBUG, PSTR("TPL: Converted"));
// AddLogBufferSize(LOG_LEVEL_DEBUG, (uint8_t*)&Settings.user_template, sizeof(Settings.user_template) / 2, 2);
// AddLogBufferSize(LOG_LEVEL_DEBUG, (uint8_t*)&Settings->user_template, sizeof(Settings->user_template) / 2, 2);
return true;
}
@ -1734,17 +1734,17 @@ bool JsonTemplate(char* dataBuf)
void TemplateJson(void)
{
// AddLog(LOG_LEVEL_DEBUG, PSTR("TPL: Show"));
// AddLogBufferSize(LOG_LEVEL_DEBUG, (uint8_t*)&Settings.user_template, sizeof(Settings.user_template) / 2, 2);
// AddLogBufferSize(LOG_LEVEL_DEBUG, (uint8_t*)&Settings->user_template, sizeof(Settings->user_template) / 2, 2);
Response_P(PSTR("{\"" D_JSON_NAME "\":\"%s\",\"" D_JSON_GPIO "\":["), SettingsText(SET_TEMPLATE_NAME));
for (uint32_t i = 0; i < nitems(Settings.user_template.gp.io); i++) {
uint16_t gpio = Settings.user_template.gp.io[i];
for (uint32_t i = 0; i < nitems(Settings->user_template.gp.io); i++) {
uint16_t gpio = Settings->user_template.gp.io[i];
if (gpio == AGPIO(GPIO_USER)) {
gpio = AGPIO(GPIO_NONE) +1;
}
ResponseAppend_P(PSTR("%s%d"), (i>0)?",":"", gpio);
}
ResponseAppend_P(PSTR("],\"" D_JSON_FLAG "\":%d,\"" D_JSON_BASE "\":%d}"), Settings.user_template.flag, Settings.user_template_base +1);
ResponseAppend_P(PSTR("],\"" D_JSON_FLAG "\":%d,\"" D_JSON_BASE "\":%d}"), Settings->user_template.flag, Settings->user_template_base +1);
}
#if ( defined(USE_SCRIPT) && defined(SUPPORT_MQTT_EVENT) ) || defined (USE_DT_VARS)
@ -2187,14 +2187,14 @@ bool I2cSetDevice(uint32_t addr)
void SetSeriallog(uint32_t loglevel)
{
Settings.seriallog_level = loglevel;
Settings->seriallog_level = loglevel;
TasmotaGlobal.seriallog_level = loglevel;
TasmotaGlobal.seriallog_timer = 0;
}
void SetSyslog(uint32_t loglevel)
{
Settings.syslog_level = loglevel;
Settings->syslog_level = loglevel;
TasmotaGlobal.syslog_level = loglevel;
TasmotaGlobal.syslog_timer = 0;
}
@ -2227,7 +2227,7 @@ void SyslogAsync(bool refresh) {
syslog_host_hash = current_hash;
syslog_host_addr = temp_syslog_host_addr;
}
if (!PortUdp.beginPacket(syslog_host_addr, Settings.syslog_port)) {
if (!PortUdp.beginPacket(syslog_host_addr, Settings->syslog_port)) {
TasmotaGlobal.syslog_level = 0;
TasmotaGlobal.syslog_timer = SYSLOG_TIMER;
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_SYSLOG_HOST_NOT_FOUND ". " D_RETRY_IN " %d " D_UNIT_SECOND), SYSLOG_TIMER);
@ -2352,8 +2352,8 @@ void AddLogData(uint32_t loglevel, const char* log_data, const char* log_data_pa
if (!TasmotaGlobal.log_buffer) { return; } // Leave now if there is no buffer available
uint32_t highest_loglevel = Settings.weblog_level;
if (Settings.mqttlog_level > highest_loglevel) { highest_loglevel = Settings.mqttlog_level; }
uint32_t highest_loglevel = Settings->weblog_level;
if (Settings->mqttlog_level > highest_loglevel) { highest_loglevel = Settings->mqttlog_level; }
if (TasmotaGlobal.syslog_level > highest_loglevel) { highest_loglevel = TasmotaGlobal.syslog_level; }
if (TasmotaGlobal.templog_level > highest_loglevel) { highest_loglevel = TasmotaGlobal.templog_level; }
if (TasmotaGlobal.uptime < 3) { highest_loglevel = LOG_LEVEL_DEBUG_MORE; } // Log all before setup correct log level

View File

@ -143,7 +143,7 @@ void ButtonHandler(void) {
if (TasmotaGlobal.uptime < 4) { return; } // Block GPIO for 4 seconds after poweron to workaround Wemos D1 / Obi RTS circuit
uint8_t hold_time_extent = IMMINENT_RESET_FACTOR; // Extent hold time factor in case of iminnent Reset command
uint16_t loops_per_second = 1000 / Settings.button_debounce; // ButtonDebounce (50)
uint16_t loops_per_second = 1000 / Settings->button_debounce; // ButtonDebounce (50)
char scmnd[20];
for (uint32_t button_index = 0; button_index < MAX_KEYS; button_index++) {
@ -157,7 +157,7 @@ void ButtonHandler(void) {
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON " " D_CODE " %04X"), Button.dual_code);
button = PRESSED;
if (0xF500 == Button.dual_code) { // Button hold
Button.hold_timer[button_index] = (loops_per_second * Settings.param[P_HOLD_TIME] / 10) -1; // SetOption32 (40)
Button.hold_timer[button_index] = (loops_per_second * Settings->param[P_HOLD_TIME] / 10) -1; // SetOption32 (40)
hold_time_extent = 1;
}
Button.dual_code = 0;
@ -225,7 +225,7 @@ void ButtonHandler(void) {
if (!Button.hold_timer[button_index]) { button_pressed = true; } // Do not allow within 1 second
}
if (button_pressed) {
if (!Settings.flag3.mqtt_buttons) { // SetOption73 (0) - Decouple button from relay and send just mqtt topic
if (!Settings->flag3.mqtt_buttons) { // SetOption73 (0) - Decouple button from relay and send just mqtt topic
if (!SendKey(KEY_BUTTON, button_index +1, POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set
ExecuteCommandPower(button_index +1, POWER_TOGGLE, SRC_BUTTON); // Execute Toggle command internally
}
@ -238,8 +238,8 @@ void ButtonHandler(void) {
else {
if ((PRESSED == button) && (NOT_PRESSED == Button.last_state[button_index])) {
if (Settings.flag.button_single) { // SetOption13 (0) - Allow only single button press for immediate action,
if (!Settings.flag3.mqtt_buttons) { // SetOption73 (0) - Decouple button from relay and send just mqtt topic
if (Settings->flag.button_single) { // SetOption13 (0) - Allow only single button press for immediate action,
if (!Settings->flag3.mqtt_buttons) { // SetOption73 (0) - Decouple button from relay and send just mqtt topic
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_IMMEDIATE), button_index +1);
if (!SendKey(KEY_BUTTON, button_index +1, POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set
ExecuteCommandPower(button_index +1, POWER_TOGGLE, SRC_BUTTON); // Execute Toggle command internally
@ -259,29 +259,29 @@ void ButtonHandler(void) {
Button.hold_timer[button_index] = 0;
} else {
Button.hold_timer[button_index]++;
if (Settings.flag.button_single) { // SetOption13 (0) - Allow only single button press for immediate action
if (Button.hold_timer[button_index] == loops_per_second * hold_time_extent * Settings.param[P_HOLD_TIME] / 10) { // SetOption32 (40) - Button held for factor times longer
if (Settings->flag.button_single) { // SetOption13 (0) - Allow only single button press for immediate action
if (Button.hold_timer[button_index] == loops_per_second * hold_time_extent * Settings->param[P_HOLD_TIME] / 10) { // SetOption32 (40) - Button held for factor times longer
snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_SETOPTION "13 0")); // Disable single press only
ExecuteCommand(scmnd, SRC_BUTTON);
}
} else {
if (Button.hold_timer[button_index] == loops_per_second * Settings.param[P_HOLD_TIME] / 10) { // SetOption32 (40) - Button hold
if (Button.hold_timer[button_index] == loops_per_second * Settings->param[P_HOLD_TIME] / 10) { // SetOption32 (40) - Button hold
Button.press_counter[button_index] = 0;
if (Settings.flag3.mqtt_buttons) { // SetOption73 (0) - Decouple button from relay and send just mqtt topic
if (Settings->flag3.mqtt_buttons) { // SetOption73 (0) - Decouple button from relay and send just mqtt topic
MqttButtonTopic(button_index +1, 3, 1);
} else {
SendKey(KEY_BUTTON, button_index +1, POWER_HOLD); // Execute Hold command via MQTT if ButtonTopic is set
}
} else {
if (Settings.flag.button_restrict) { // SetOption1 (0) - Control button multipress
if (Settings.param[P_HOLD_IGNORE] > 0) { // SetOption40 (0) - Do not ignore button hold
if (Button.hold_timer[button_index] > loops_per_second * Settings.param[P_HOLD_IGNORE] / 10) {
if (Settings->flag.button_restrict) { // SetOption1 (0) - Control button multipress
if (Settings->param[P_HOLD_IGNORE] > 0) { // SetOption40 (0) - Do not ignore button hold
if (Button.hold_timer[button_index] > loops_per_second * Settings->param[P_HOLD_IGNORE] / 10) {
Button.hold_timer[button_index] = 0; // Reset button hold counter to stay below hold trigger
Button.press_counter[button_index] = 0; // Discard button press to disable functionality
}
}
} else {
if ((Button.hold_timer[button_index] == loops_per_second * hold_time_extent * Settings.param[P_HOLD_TIME] / 10)) { // SetOption32 (40) - Button held for factor times longer
if ((Button.hold_timer[button_index] == loops_per_second * hold_time_extent * Settings->param[P_HOLD_TIME] / 10)) { // SetOption32 (40) - Button held for factor times longer
Button.press_counter[button_index] = 0;
snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_RESET " 1"));
ExecuteCommand(scmnd, SRC_BUTTON);
@ -291,7 +291,7 @@ void ButtonHandler(void) {
}
}
if (!Settings.flag.button_single) { // SetOption13 (0) - Allow multi-press
if (!Settings->flag.button_single) { // SetOption13 (0) - Allow multi-press
if (Button.window_timer[button_index]) {
Button.window_timer[button_index]--;
} else {
@ -305,9 +305,9 @@ void ButtonHandler(void) {
} else
#endif // ESP8266
{
single_press = (Settings.flag.button_swap +1 == Button.press_counter[button_index]); // SetOption11 (0)
single_press = (Settings->flag.button_swap +1 == Button.press_counter[button_index]); // SetOption11 (0)
if ((1 == Button.present) && (2 == TasmotaGlobal.devices_present)) { // Single Button with two devices only
if (Settings.flag.button_swap) { // SetOption11 (0)
if (Settings->flag.button_swap) { // SetOption11 (0)
Button.press_counter[button_index] = (single_press) ? 1 : 2;
}
}
@ -316,14 +316,14 @@ void ButtonHandler(void) {
#ifdef ROTARY_V1
if (!RotaryButtonPressed(button_index)) {
#endif
if (!Settings.flag3.mqtt_buttons && single_press && SendKey(KEY_BUTTON, button_index + Button.press_counter[button_index], POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set
if (!Settings->flag3.mqtt_buttons && single_press && SendKey(KEY_BUTTON, button_index + Button.press_counter[button_index], POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set
// Success
} else {
if (Button.press_counter[button_index] < 6) { // Single to Penta press
if (WifiState() > WIFI_RESTART) { // Wifimanager active
TasmotaGlobal.restart_flag = 1;
}
if (!Settings.flag3.mqtt_buttons) { // SetOption73 - Detach buttons from relays and enable MQTT action state for multipress
if (!Settings->flag3.mqtt_buttons) { // SetOption73 - Detach buttons from relays and enable MQTT action state for multipress
if (Button.press_counter[button_index] == 1) { // By default first press always send a TOGGLE (2)
ExecuteCommandPower(button_index + Button.press_counter[button_index], POWER_TOGGLE, SRC_BUTTON);
} else {
@ -344,12 +344,12 @@ void ButtonHandler(void) {
}
} else { // 6 press start wificonfig 2
if (!Settings.flag.button_restrict) { // SetOption1 - Control button multipress
if (!Settings->flag.button_restrict) { // SetOption1 - Control button multipress
snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_WIFICONFIG " 2"));
ExecuteCommand(scmnd, SRC_BUTTON);
}
}
if (Settings.flag3.mqtt_buttons) { // SetOption73 (0) - Decouple button from relay and send just mqtt topic
if (Settings->flag3.mqtt_buttons) { // SetOption73 (0) - Decouple button from relay and send just mqtt topic
if (Button.press_counter[button_index] >= 1 && Button.press_counter[button_index] <= 5) {
MqttButtonTopic(button_index +1, Button.press_counter[button_index], 0);
}
@ -377,7 +377,7 @@ void MqttButtonTopic(uint8_t button_id, uint8_t action, uint8_t hold) {
SendKey(KEY_BUTTON, button_id, (hold) ? 3 : action +9);
if (!Settings.flag.hass_discovery) {
if (!Settings->flag.hass_discovery) {
GetTextIndexed(mqttstate, sizeof(mqttstate), action, kMultiPress);
snprintf_P(scommand, sizeof(scommand), PSTR("BUTTON%d"), button_id);
GetTopic_P(stopic, STAT, TasmotaGlobal.mqtt_topic, scommand);
@ -390,7 +390,7 @@ void MqttButtonTopic(uint8_t button_id, uint8_t action, uint8_t hold) {
void MqttButtonTopic(uint32_t button_id, uint32_t action, uint32_t hold) {
SendKey(KEY_BUTTON, button_id, (hold) ? 3 : action +9);
if (!Settings.flag.hass_discovery) { // SetOption19 - Control Home Assistant automatic discovery (See SetOption59)
if (!Settings->flag.hass_discovery) { // SetOption19 - Control Home Assistant automatic discovery (See SetOption59)
char scommand[10];
snprintf_P(scommand, sizeof(scommand), PSTR(D_JSON_BUTTON "%d"), button_id);
char mqttstate[7];
@ -402,7 +402,7 @@ void MqttButtonTopic(uint32_t button_id, uint32_t action, uint32_t hold) {
void ButtonLoop(void) {
if (Button.present) {
if (TimeReached(Button.debounce)) {
SetNextTimeInterval(Button.debounce, Settings.button_debounce); // ButtonDebounce (50)
SetNextTimeInterval(Button.debounce, Settings->button_debounce); // ButtonDebounce (50)
ButtonHandler();
}
}

File diff suppressed because it is too large Load Diff

View File

@ -112,7 +112,7 @@ void DeviceGroupsInit(void)
// If relays in separate device groups is enabled, set the device group count to highest numbered
// relay.
if (Settings.flag4.multiple_device_groups) { // SetOption88 - Enable relays in separate device groups
if (Settings->flag4.multiple_device_groups) { // SetOption88 - Enable relays in separate device groups
for (uint32_t relay_index = 0; relay_index < MAX_RELAYS; relay_index++) {
if (PinUsed(GPIO_REL1, relay_index)) device_group_count = relay_index + 1;
}
@ -156,8 +156,8 @@ void DeviceGroupsInit(void)
}
// If both in and out shared items masks are 0, assume they're unitialized and initialize them.
if (!Settings.device_group_share_in && !Settings.device_group_share_out) {
Settings.device_group_share_in = Settings.device_group_share_out = 0xffffffff;
if (!Settings->device_group_share_in && !Settings->device_group_share_out) {
Settings->device_group_share_in = Settings->device_group_share_out = 0xffffffff;
}
device_groups_initialized = true;
@ -165,7 +165,7 @@ void DeviceGroupsInit(void)
void DeviceGroupsStart()
{
if (Settings.flag4.device_groups_enabled && !device_groups_up && !TasmotaGlobal.restart_flag) {
if (Settings->flag4.device_groups_enabled && !device_groups_up && !TasmotaGlobal.restart_flag) {
// If we haven't successfuly initialized device groups yet, attempt to do it now.
if (!device_groups_initialized) {
@ -391,7 +391,7 @@ void SendReceiveDeviceGroupMessage(struct device_group * device_group, struct de
else
device_group->no_status_share &= ~mask;
if ((!(device_group->no_status_share & mask) || device_group_member == nullptr) && (!mask || (mask & Settings.device_group_share_in))) {
if ((!(device_group->no_status_share & mask) || device_group_member == nullptr) && (!mask || (mask & Settings->device_group_share_in))) {
item_processed = true;
XdrvMailbox.command_code = item;
XdrvMailbox.payload = value;
@ -400,8 +400,8 @@ void SendReceiveDeviceGroupMessage(struct device_group * device_group, struct de
log_remaining--;
switch (item) {
case DGR_ITEM_POWER:
if (Settings.flag4.multiple_device_groups) { // SetOption88 - Enable relays in separate device groups
uint32_t device = Settings.device_group_tie[device_group_index];
if (Settings->flag4.multiple_device_groups) { // SetOption88 - Enable relays in separate device groups
uint32_t device = Settings->device_group_tie[device_group_index];
if (device && device <= TasmotaGlobal.devices_present) {
bool on = (value & 1);
if (on != ((TasmotaGlobal.power >> (device - 1)) & 1)) ExecuteCommandPower(device, (on ? POWER_ON : POWER_OFF), SRC_REMOTE);
@ -497,9 +497,9 @@ bool _SendDeviceGroupMessage(int32_t device, DevGroupMessageType message_type, .
uint8_t device_group_index = -device;
if (device > 0) {
device_group_index = 0;
if (Settings.flag4.multiple_device_groups) { // SetOption88 - Enable relays in separate device groups
if (Settings->flag4.multiple_device_groups) { // SetOption88 - Enable relays in separate device groups
for (; device_group_index < device_group_count; device_group_index++) {
if (Settings.device_group_tie[device_group_index] == device) break;
if (Settings->device_group_tie[device_group_index] == device) break;
}
}
}
@ -536,8 +536,8 @@ bool _SendDeviceGroupMessage(int32_t device, DevGroupMessageType message_type, .
// Call the drivers to build the status update.
power_t power = TasmotaGlobal.power;
if (Settings.flag4.multiple_device_groups) { // SetOption88 - Enable relays in separate device groups
power = (power >> (Settings.device_group_tie[device_group_index] - 1)) & 1;
if (Settings->flag4.multiple_device_groups) { // SetOption88 - Enable relays in separate device groups
power = (power >> (Settings->device_group_tie[device_group_index] - 1)) & 1;
}
SendDeviceGroupMessage(-device_group_index, DGR_MSGTYP_PARTIAL_UPDATE, DGR_ITEM_NO_STATUS_SHARE, device_group->no_status_share, DGR_ITEM_POWER, power);
XdrvMailbox.index = 0;
@ -749,7 +749,7 @@ bool _SendDeviceGroupMessage(int32_t device, DevGroupMessageType message_type, .
else if (!building_status_message)
device_group->no_status_share &= ~mask;
if (message_type != DGR_MSGTYPE_UPDATE_COMMAND) {
shared = (!(mask & device_group->no_status_share) && (device_group_index || (mask & Settings.device_group_share_out)));
shared = (!(mask & device_group->no_status_share) && (device_group_index || (mask & Settings->device_group_share_out)));
}
}
if (shared) {
@ -771,7 +771,7 @@ bool _SendDeviceGroupMessage(int32_t device, DevGroupMessageType message_type, .
*message_ptr++ = value & 0xff;
value >>= 8;
// For the power item, the device count is overlayed onto the highest 8 bits.
if (item == DGR_ITEM_POWER && !value) value = (!Settings.flag4.multiple_device_groups && device_group_index == 0 && first_device_group_is_local ? TasmotaGlobal.devices_present : 1);
if (item == DGR_ITEM_POWER && !value) value = (!Settings->flag4.multiple_device_groups && device_group_index == 0 && first_device_group_is_local ? TasmotaGlobal.devices_present : 1);
*message_ptr++ = value;
}
}
@ -883,7 +883,7 @@ void ProcessDeviceGroupMessage(uint8_t * message, int message_length)
void DeviceGroupStatus(uint8_t device_group_index)
{
if (Settings.flag4.device_groups_enabled && device_group_index < device_group_count) {
if (Settings->flag4.device_groups_enabled && device_group_index < device_group_count) {
char buffer[1024];
int member_count = 0;
struct device_group * device_group = &device_groups[device_group_index];

View File

@ -27,15 +27,15 @@ struct {
#ifdef USE_DISCOVERY
void StartMdns(void) {
// static uint8_t mdns_delayed_start = Settings.param[P_MDNS_DELAYED_START];
// static uint8_t mdns_delayed_start = Settings->param[P_MDNS_DELAYED_START];
if (Settings.flag3.mdns_enabled) { // SetOption55 - Control mDNS service
if (Settings->flag3.mdns_enabled) { // SetOption55 - Control mDNS service
if (!Mdns.begun) {
// if (mdns_delayed_start) {
// AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS D_ATTEMPTING_CONNECTION));
// mdns_delayed_start--;
// } else {
// mdns_delayed_start = Settings.param[P_MDNS_DELAYED_START];
// mdns_delayed_start = Settings->param[P_MDNS_DELAYED_START];
MDNS.end(); // close existing or MDNS.begin will fail
Mdns.begun = (uint8_t)MDNS.begin(TasmotaGlobal.hostname);
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS "%s"), (Mdns.begun) ? PSTR(D_INITIALIZED) : PSTR(D_FAILED));
@ -63,9 +63,9 @@ void MqttDiscoverServer(void)
}
#endif // MDNS_HOSTNAME
SettingsUpdateText(SET_MQTT_HOST, MDNS.hostname(i).c_str());
Settings.mqtt_port = MDNS.port(i);
Settings->mqtt_port = MDNS.port(i);
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS D_MQTT_SERVICE_FOUND " %s," D_PORT " %d"), SettingsText(SET_MQTT_HOST), Settings.mqtt_port);
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS D_MQTT_SERVICE_FOUND " %s," D_PORT " %d"), SettingsText(SET_MQTT_HOST), Settings->mqtt_port);
}
}
#endif // MQTT_HOST_DISCOVERY

View File

@ -91,7 +91,7 @@ bool RotaryButtonPressed(uint32_t button_index) {
bool powered_on = (TasmotaGlobal.power);
#ifdef USE_LIGHT
if (!Settings.flag4.rotary_uses_rules) { // SetOption98 - Use rules instead of light control
if (!Settings->flag4.rotary_uses_rules) { // SetOption98 - Use rules instead of light control
powered_on = LightPower();
}
#endif // USE_LIGHT
@ -131,10 +131,10 @@ void IRAM_ATTR RotaryIsrArg(void *arg) {
}
void RotaryInitMaxSteps(void) {
if (0 == Settings.param[P_ROTARY_MAX_STEP]) {
Settings.param[P_ROTARY_MAX_STEP] = ROTARY_MAX_STEPS; // SetOption43
if (0 == Settings->param[P_ROTARY_MAX_STEP]) {
Settings->param[P_ROTARY_MAX_STEP] = ROTARY_MAX_STEPS; // SetOption43
}
uint8_t max_steps = Settings.param[P_ROTARY_MAX_STEP];
uint8_t max_steps = Settings->param[P_ROTARY_MAX_STEP];
if (!Rotary.model) { max_steps *= 3; }
Rotary.dimmer_increment = 100 / max_steps; // Dimmer 1..100 = 100
Rotary.ct_increment = 350 / max_steps; // Ct 153..500 = 347
@ -186,7 +186,7 @@ void RotaryHandler(void) {
Encoder[index].timeout--;
if (!Encoder[index].timeout) {
#ifdef USE_LIGHT
if (!Settings.flag4.rotary_uses_rules) { // SetOption98 - Use rules instead of light control
if (!Settings->flag4.rotary_uses_rules) { // SetOption98 - Use rules instead of light control
ResponseLightState(0);
MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, PSTR(D_CMND_STATE));
}
@ -203,7 +203,7 @@ void RotaryHandler(void) {
Encoder[index].position = rotary_offset;
interrupts();
if (Settings.save_data && (TasmotaGlobal.save_data_counter < 2)) {
if (Settings->save_data && (TasmotaGlobal.save_data_counter < 2)) {
TasmotaGlobal.save_data_counter = 3; // Postpone flash writes while rotary is turned
}
@ -212,7 +212,7 @@ void RotaryHandler(void) {
// AddLog(LOG_LEVEL_DEBUG, PSTR("ROT: Button1 %d, Position %d"), button_pressed, rotary_position);
#ifdef USE_LIGHT
if (!Settings.flag4.rotary_uses_rules) { // SetOption98 - Use rules instead of light control
if (!Settings->flag4.rotary_uses_rules) { // SetOption98 - Use rules instead of light control
bool second_rotary = (Encoder[1].pinb >= 0);
if (0 == index) { // Rotary1
if (button_pressed) {
@ -225,7 +225,7 @@ void RotaryHandler(void) {
}
} else { // Dimmer RGBCW or RGB only if second rotary
uint32_t dimmer_index = second_rotary ? 1 : 0;
if (!Settings.flag4.rotary_poweron_dimlow || TasmotaGlobal.power) { // SetOption113 - On rotary dial after power off set dimmer low
if (!Settings->flag4.rotary_poweron_dimlow || TasmotaGlobal.power) { // SetOption113 - On rotary dial after power off set dimmer low
LightDimmerOffset(dimmer_index, rotary_position * Rotary.dimmer_increment);
} else {
if (rotary_position > 0) { // Only power on if rotary increase
@ -246,8 +246,8 @@ void RotaryHandler(void) {
if (Encoder[index].abs_position[button_pressed] < 0) {
Encoder[index].abs_position[button_pressed] = 0;
}
if (Encoder[index].abs_position[button_pressed] > Settings.param[P_ROTARY_MAX_STEP]) { // SetOption43 - Rotary steps
Encoder[index].abs_position[button_pressed] = Settings.param[P_ROTARY_MAX_STEP]; // SetOption43 - Rotary steps
if (Encoder[index].abs_position[button_pressed] > Settings->param[P_ROTARY_MAX_STEP]) { // SetOption43 - Rotary steps
Encoder[index].abs_position[button_pressed] = Settings->param[P_ROTARY_MAX_STEP]; // SetOption43 - Rotary steps
}
Response_P(PSTR("{\"Rotary%d\":{\"Pos1\":%d,\"Pos2\":%d}}"), index +1, Encoder[index].abs_position[0], Encoder[index].abs_position[1]);
XdrvRulesProcess(0);

View File

@ -77,7 +77,7 @@ bool MidnightNow(void)
bool IsDst(void)
{
if (Rtc.time_timezone == Settings.toffset[1]) {
if (Rtc.time_timezone == Settings->toffset[1]) {
return true;
}
return false;
@ -199,10 +199,10 @@ String GetDateAndTime(uint8_t time_type)
time = Rtc.restart_time;
break;
case DT_ENERGY:
time = Settings.energy_kWhtotal_time;
time = Settings->energy_kWhtotal_time;
break;
case DT_BOOTCOUNT:
time = Settings.bootcount_reset_time;
time = Settings->bootcount_reset_time;
break;
}
String dt = GetDT(time); // 2017-03-07T11:08:02
@ -214,7 +214,7 @@ String GetDateAndTime(uint8_t time_type)
time_type = DT_LOCAL;
}
if (Settings.flag3.time_append_timezone && (DT_LOCAL == time_type)) { // SetOption52 - Append timezone to JSON time
if (Settings->flag3.time_append_timezone && (DT_LOCAL == time_type)) { // SetOption52 - Append timezone to JSON time
dt += GetTimeZone(); // 2017-03-07T11:08:02-07:00
}
return dt; // 2017-03-07T11:08:02-07:00
@ -392,8 +392,8 @@ void RtcSecond(void)
TIME_T tmpTime;
BreakTime(Rtc.utc_time, tmpTime);
RtcTime.year = tmpTime.year + 1970;
Rtc.daylight_saving_time = RuleToTime(Settings.tflag[1], RtcTime.year);
Rtc.standard_time = RuleToTime(Settings.tflag[0], RtcTime.year);
Rtc.daylight_saving_time = RuleToTime(Settings->tflag[1], RtcTime.year);
Rtc.standard_time = RuleToTime(Settings->tflag[0], RtcTime.year);
AddLog(LOG_LEVEL_DEBUG, PSTR("RTC: " D_UTC_TIME " %s, " D_DST_TIME " %s, " D_STD_TIME " %s"),
GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_DST).c_str(), GetDateAndTime(DT_STD).c_str());
@ -415,13 +415,13 @@ void RtcSecond(void)
Rtc.local_time = Rtc.utc_time;
if (Rtc.local_time > START_VALID_TIME) { // 2016-01-01
int16_t timezone_minutes = Settings.timezone_minutes;
if (Settings.timezone < 0) { timezone_minutes *= -1; }
Rtc.time_timezone = (Settings.timezone * SECS_PER_HOUR) + (timezone_minutes * SECS_PER_MIN);
if (99 == Settings.timezone) {
int32_t dstoffset = Settings.toffset[1] * SECS_PER_MIN;
int32_t stdoffset = Settings.toffset[0] * SECS_PER_MIN;
if (Settings.tflag[1].hemis) {
int16_t timezone_minutes = Settings->timezone_minutes;
if (Settings->timezone < 0) { timezone_minutes *= -1; }
Rtc.time_timezone = (Settings->timezone * SECS_PER_HOUR) + (timezone_minutes * SECS_PER_MIN);
if (99 == Settings->timezone) {
int32_t dstoffset = Settings->toffset[1] * SECS_PER_MIN;
int32_t stdoffset = Settings->toffset[0] * SECS_PER_MIN;
if (Settings->tflag[1].hemis) {
// Southern hemisphere
if ((Rtc.utc_time >= (Rtc.standard_time - dstoffset)) && (Rtc.utc_time < (Rtc.daylight_saving_time - stdoffset))) {
Rtc.time_timezone = stdoffset; // Standard Time
@ -439,11 +439,11 @@ void RtcSecond(void)
}
Rtc.local_time += Rtc.time_timezone;
Rtc.time_timezone /= 60;
if (!Settings.energy_kWhtotal_time) {
Settings.energy_kWhtotal_time = Rtc.local_time;
if (!Settings->energy_kWhtotal_time) {
Settings->energy_kWhtotal_time = Rtc.local_time;
}
if (Settings.bootcount_reset_time < START_VALID_TIME) {
Settings.bootcount_reset_time = Rtc.local_time;
if (Settings->bootcount_reset_time < START_VALID_TIME) {
Settings->bootcount_reset_time = Rtc.local_time;
}
}

View File

@ -78,7 +78,7 @@ uint8_t SwitchLastState(uint32_t index) {
}
bool SwitchState(uint32_t index) {
uint32_t switchmode = Settings.switchmode[index];
uint32_t switchmode = Settings->switchmode[index];
return ((FOLLOW_INV == switchmode) ||
(PUSHBUTTON_INV == switchmode) ||
(PUSHBUTTONHOLD_INV == switchmode) ||
@ -95,21 +95,21 @@ void SwitchProbe(void) {
uint32_t state_filter;
uint32_t first_change = Switch.first_change;
uint32_t debounce_flags = Settings.switch_debounce % 10;
uint32_t debounce_flags = Settings->switch_debounce % 10;
bool force_high = (debounce_flags &1); // 51, 101, 151 etc
bool force_low = (debounce_flags &2); // 52, 102, 152 etc
bool ac_detect = (debounce_flags == 9);
if (ac_detect) {
if (Settings.switch_debounce < 2 * AC_PERIOD * SWITCH_FAST_PROBE_INTERVAL + 9) {
if (Settings->switch_debounce < 2 * AC_PERIOD * SWITCH_FAST_PROBE_INTERVAL + 9) {
state_filter = 2 * AC_PERIOD;
} else if (Settings.switch_debounce > (0x7f - 2 * AC_PERIOD) * SWITCH_FAST_PROBE_INTERVAL) {
} else if (Settings->switch_debounce > (0x7f - 2 * AC_PERIOD) * SWITCH_FAST_PROBE_INTERVAL) {
state_filter = 0x7f;
} else {
state_filter = (Settings.switch_debounce - 9) / SWITCH_FAST_PROBE_INTERVAL;
state_filter = (Settings->switch_debounce - 9) / SWITCH_FAST_PROBE_INTERVAL;
}
} else {
state_filter = Settings.switch_debounce / SWITCH_PROBE_INTERVAL; // 5, 10, 15
state_filter = Settings->switch_debounce / SWITCH_PROBE_INTERVAL; // 5, 10, 15
}
for (uint32_t i = 0; i < MAX_SWITCHES; i++) {
@ -193,7 +193,7 @@ void SwitchProbe(void) {
}
void SwitchInit(void) {
bool ac_detect = (Settings.switch_debounce % 10 == 9);
bool ac_detect = (Settings->switch_debounce % 10 == 9);
Switch.present = 0;
for (uint32_t i = 0; i < MAX_SWITCHES; i++) {
@ -228,18 +228,18 @@ void SwitchInit(void) {
void SwitchHandler(uint32_t mode) {
if (TasmotaGlobal.uptime < 4) { return; } // Block GPIO for 4 seconds after poweron to workaround Wemos D1 / Obi RTS circuit
uint32_t loops_per_second = 1000 / Settings.switch_debounce;
uint32_t loops_per_second = 1000 / Settings->switch_debounce;
for (uint32_t i = 0; i < MAX_SWITCHES; i++) {
if (PinUsed(GPIO_SWT1, i) || (mode)) {
uint32_t button = Switch.virtual_state[i];
uint32_t switchflag = POWER_TOGGLE +1;
uint32_t mqtt_action = POWER_NONE;
uint32_t switchmode = Settings.switchmode[i];
uint32_t switchmode = Settings->switchmode[i];
if (Switch.hold_timer[i] & (((switchmode == PUSHHOLDMULTI) | (switchmode == PUSHHOLDMULTI_INV)) ? SM_TIMER_MASK: SM_NO_TIMER_MASK)) {
Switch.hold_timer[i]--;
if ((Switch.hold_timer[i] & SM_TIMER_MASK) == loops_per_second * Settings.param[P_HOLD_TIME] / 25) {
if ((Switch.hold_timer[i] & SM_TIMER_MASK) == loops_per_second * Settings->param[P_HOLD_TIME] / 25) {
if ((switchmode == PUSHHOLDMULTI) & (NOT_PRESSED == Switch.last_state[i])) {
SendKey(KEY_SWITCH, i +1, POWER_INCREMENT); // Execute command via MQTT
}
@ -260,7 +260,7 @@ void SwitchHandler(uint32_t mode) {
break;
case PUSHHOLDMULTI:
if (NOT_PRESSED == button) {
Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 25;
Switch.hold_timer[i] = loops_per_second * Settings->param[P_HOLD_TIME] / 25;
SendKey(KEY_SWITCH, i +1, POWER_INCREMENT); // Execute command via MQTT
mqtt_action = POWER_INCREMENT;
} else {
@ -271,7 +271,7 @@ void SwitchHandler(uint32_t mode) {
break;
case PUSHHOLDMULTI_INV:
if (PRESSED == button) {
Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 25;
Switch.hold_timer[i] = loops_per_second * Settings->param[P_HOLD_TIME] / 25;
SendKey(KEY_SWITCH, i +1, POWER_INCREMENT); // Execute command via MQTT
mqtt_action = POWER_INCREMENT;
@ -313,7 +313,7 @@ void SwitchHandler(uint32_t mode) {
break;
case PUSHBUTTONHOLD:
if (PRESSED == button) {
Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; // Start timer on button press
Switch.hold_timer[i] = loops_per_second * Settings->param[P_HOLD_TIME] / 10; // Start timer on button press
}
if ((NOT_PRESSED == button) && (Switch.hold_timer[i])) {
Switch.hold_timer[i] = 0; // Button released and hold timer not expired : stop timer...
@ -322,7 +322,7 @@ void SwitchHandler(uint32_t mode) {
break;
case PUSHBUTTONHOLD_INV:
if (NOT_PRESSED == button) {
Switch.hold_timer[i] = loops_per_second * Settings.param[P_HOLD_TIME] / 10; // Start timer on button press...
Switch.hold_timer[i] = loops_per_second * Settings->param[P_HOLD_TIME] / 10; // Start timer on button press...
}
if ((PRESSED == button) && (Switch.hold_timer[i])) {
Switch.hold_timer[i] = 0; // Button released and hold timer not expired : stop timer.
@ -348,7 +348,7 @@ void SwitchHandler(uint32_t mode) {
mqtt_action = POWER_INV;
}
} else {
if ((Switch.hold_timer[i] & SM_TIMER_MASK) > loops_per_second * Settings.param[P_HOLD_TIME] / 25) {
if ((Switch.hold_timer[i] & SM_TIMER_MASK) > loops_per_second * Settings->param[P_HOLD_TIME] / 25) {
if((Switch.hold_timer[i] & ~SM_TIMER_MASK) != SM_SECOND_PRESS) {
Switch.hold_timer[i]= SM_FIRST_PRESS;
switchflag = POWER_TOGGLE; // Toggle with pushbutton
@ -364,7 +364,7 @@ void SwitchHandler(uint32_t mode) {
mqtt_action = POWER_RELEASE;
}
}
Switch.hold_timer[i] = (Switch.hold_timer[i] & ~SM_TIMER_MASK) | loops_per_second * Settings.param[P_HOLD_TIME] / 10;
Switch.hold_timer[i] = (Switch.hold_timer[i] & ~SM_TIMER_MASK) | loops_per_second * Settings->param[P_HOLD_TIME] / 10;
break;
case PUSHHOLDMULTI_INV:
if (PRESSED == button) {
@ -374,7 +374,7 @@ void SwitchHandler(uint32_t mode) {
mqtt_action = POWER_INV;
}
} else {
if ((Switch.hold_timer[i] & SM_TIMER_MASK)> loops_per_second * Settings.param[P_HOLD_TIME] / 25) {
if ((Switch.hold_timer[i] & SM_TIMER_MASK)> loops_per_second * Settings->param[P_HOLD_TIME] / 25) {
if((Switch.hold_timer[i] & ~SM_TIMER_MASK) != SM_SECOND_PRESS) {
Switch.hold_timer[i]= SM_FIRST_PRESS;
switchflag = POWER_TOGGLE; // Toggle with pushbutton
@ -390,7 +390,7 @@ void SwitchHandler(uint32_t mode) {
mqtt_action = POWER_RELEASE;
}
}
Switch.hold_timer[i] = (Switch.hold_timer[i] & ~SM_TIMER_MASK) | loops_per_second * Settings.param[P_HOLD_TIME] / 10;
Switch.hold_timer[i] = (Switch.hold_timer[i] & ~SM_TIMER_MASK) | loops_per_second * Settings->param[P_HOLD_TIME] / 10;
break;
case PUSHON:
if (PRESSED == button) {
@ -410,14 +410,14 @@ void SwitchHandler(uint32_t mode) {
Switch.last_state[i] = button;
}
if (switchflag <= POWER_TOGGLE) {
if (!Settings.flag5.mqtt_switches) { // SetOption114 (0) - Detach Switches from relays and enable MQTT action state for all the SwitchModes
if (!Settings->flag5.mqtt_switches) { // SetOption114 (0) - Detach Switches from relays and enable MQTT action state for all the SwitchModes
if (!SendKey(KEY_SWITCH, i +1, switchflag)) { // Execute command via MQTT
ExecuteCommandPower(i +1, switchflag, SRC_SWITCH); // Execute command internally (if i < TasmotaGlobal.devices_present)
}
} else { mqtt_action = switchflag; }
}
if ((mqtt_action != POWER_NONE) && Settings.flag5.mqtt_switches) { // SetOption114 (0) - Detach Switches from relays and enable MQTT action state for all the SwitchModes
if (!Settings.flag.hass_discovery) { // SetOption19 - Control Home Assistant automatic discovery (See SetOption59)
if ((mqtt_action != POWER_NONE) && Settings->flag5.mqtt_switches) { // SetOption114 (0) - Detach Switches from relays and enable MQTT action state for all the SwitchModes
if (!Settings->flag.hass_discovery) { // SetOption19 - Control Home Assistant automatic discovery (See SetOption59)
char mqtt_state_str[16];
char *mqtt_state = mqtt_state_str;
if (mqtt_action <= 3) {
@ -440,7 +440,7 @@ void SwitchHandler(uint32_t mode) {
void SwitchLoop(void) {
if (Switch.present) {
if (TimeReached(Switch.debounce)) {
SetNextTimeInterval(Switch.debounce, Settings.switch_debounce);
SetNextTimeInterval(Switch.debounce, Settings->switch_debounce);
SwitchHandler(0);
}
}

View File

@ -136,7 +136,7 @@ char* GetGroupTopic_P(char *stopic, const char* subtopic, uint32_t itopic)
{
// SetOption75 0: %prefix%/nothing/%topic% = cmnd/nothing/<grouptopic>/#
// SetOption75 1: cmnd/<grouptopic>
return GetTopic_P(stopic, (Settings.flag3.grouptopic_mode) ? CMND +8 : CMND, SettingsText(itopic), subtopic); // SetOption75 - GroupTopic replaces %topic% (0) or fixed topic cmnd/grouptopic (1)
return GetTopic_P(stopic, (Settings->flag3.grouptopic_mode) ? CMND +8 : CMND, SettingsText(itopic), subtopic); // SetOption75 - GroupTopic replaces %topic% (0) or fixed topic cmnd/grouptopic (1)
}
char* GetFallbackTopic_P(char *stopic, const char* subtopic)
@ -235,23 +235,23 @@ void SetDevicePower(power_t rpower, uint32_t source)
ShowSource(source);
TasmotaGlobal.last_source = source;
if (POWER_ALL_ALWAYS_ON == Settings.poweronstate) { // All on and stay on
if (POWER_ALL_ALWAYS_ON == Settings->poweronstate) { // All on and stay on
TasmotaGlobal.power = (1 << TasmotaGlobal.devices_present) -1;
rpower = TasmotaGlobal.power;
}
if (Settings.flag.interlock) { // Allow only one or no relay set - CMND_INTERLOCK - Enable/disable interlock
if (Settings->flag.interlock) { // Allow only one or no relay set - CMND_INTERLOCK - Enable/disable interlock
for (uint32_t i = 0; i < MAX_INTERLOCKS; i++) {
power_t mask = 1;
uint32_t count = 0;
for (uint32_t j = 0; j < TasmotaGlobal.devices_present; j++) {
if ((Settings.interlock[i] & mask) && (rpower & mask)) {
if ((Settings->interlock[i] & mask) && (rpower & mask)) {
count++;
}
mask <<= 1;
}
if (count > 1) {
mask = ~Settings.interlock[i]; // Turn interlocked group off as there would be multiple relays on
mask = ~Settings->interlock[i]; // Turn interlocked group off as there would be multiple relays on
TasmotaGlobal.power &= mask;
rpower &= mask;
}
@ -314,7 +314,7 @@ void RestorePower(bool publish_power, uint32_t source)
void SetAllPower(uint32_t state, uint32_t source)
{
// state 0 = POWER_OFF = Relay Off
// state 1 = POWER_ON = Relay On (turn off after Settings.pulse_timer * 100 mSec if enabled)
// state 1 = POWER_ON = Relay On (turn off after Settings->pulse_timer * 100 mSec if enabled)
// state 2 = POWER_TOGGLE = Toggle relay
// state 8 = POWER_OFF_NO_STATE = Relay Off and no publishPowerState
// state 9 = POWER_ON_NO_STATE = Relay On and no publishPowerState
@ -349,14 +349,14 @@ void SetPowerOnState(void)
{
#ifdef ESP8266
if (MOTOR == TasmotaGlobal.module_type) {
Settings.poweronstate = POWER_ALL_ON; // Needs always on else in limbo!
Settings->poweronstate = POWER_ALL_ON; // Needs always on else in limbo!
}
#endif // ESP8266
if (POWER_ALL_ALWAYS_ON == Settings.poweronstate) {
if (POWER_ALL_ALWAYS_ON == Settings->poweronstate) {
SetDevicePower(1, SRC_RESTART);
} else {
if ((ResetReason() == REASON_DEFAULT_RST) || (ResetReason() == REASON_EXT_SYS_RST)) {
switch (Settings.poweronstate) {
switch (Settings->poweronstate) {
case POWER_ALL_OFF:
case POWER_ALL_OFF_PULSETIME_ON:
TasmotaGlobal.power = 0;
@ -367,21 +367,21 @@ void SetPowerOnState(void)
SetDevicePower(TasmotaGlobal.power, SRC_RESTART);
break;
case POWER_ALL_SAVED_TOGGLE:
TasmotaGlobal.power = (Settings.power & ((1 << TasmotaGlobal.devices_present) -1)) ^ POWER_MASK;
if (Settings.flag.save_state) { // SetOption0 - Save power state and use after restart
TasmotaGlobal.power = (Settings->power & ((1 << TasmotaGlobal.devices_present) -1)) ^ POWER_MASK;
if (Settings->flag.save_state) { // SetOption0 - Save power state and use after restart
SetDevicePower(TasmotaGlobal.power, SRC_RESTART);
}
break;
case POWER_ALL_SAVED:
TasmotaGlobal.power = Settings.power & ((1 << TasmotaGlobal.devices_present) -1);
if (Settings.flag.save_state) { // SetOption0 - Save power state and use after restart
TasmotaGlobal.power = Settings->power & ((1 << TasmotaGlobal.devices_present) -1);
if (Settings->flag.save_state) { // SetOption0 - Save power state and use after restart
SetDevicePower(TasmotaGlobal.power, SRC_RESTART);
}
break;
}
} else {
TasmotaGlobal.power = Settings.power & ((1 << TasmotaGlobal.devices_present) -1);
if (Settings.flag.save_state) { // SetOption0 - Save power state and use after restart
TasmotaGlobal.power = Settings->power & ((1 << TasmotaGlobal.devices_present) -1);
if (Settings->flag.save_state) { // SetOption0 - Save power state and use after restart
SetDevicePower(TasmotaGlobal.power, SRC_RESTART);
}
}
@ -389,13 +389,13 @@ void SetPowerOnState(void)
// Issue #526 and #909
for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) {
if (!Settings.flag3.no_power_feedback) { // SetOption63 - Don't scan relay power state at restart - #5594 and #5663
if (!Settings->flag3.no_power_feedback) { // SetOption63 - Don't scan relay power state at restart - #5594 and #5663
if ((i < MAX_RELAYS) && PinUsed(GPIO_REL1, i)) {
bitWrite(TasmotaGlobal.power, i, digitalRead(Pin(GPIO_REL1, i)) ^ bitRead(TasmotaGlobal.rel_inverted, i));
}
}
if (bitRead(TasmotaGlobal.power, i) || (POWER_ALL_OFF_PULSETIME_ON == Settings.poweronstate)) {
SetPulseTimer(i % MAX_PULSETIMERS, Settings.pulse_timer[i % MAX_PULSETIMERS]);
if (bitRead(TasmotaGlobal.power, i) || (POWER_ALL_OFF_PULSETIME_ON == Settings->poweronstate)) {
SetPulseTimer(i % MAX_PULSETIMERS, Settings->pulse_timer[i % MAX_PULSETIMERS]);
}
}
TasmotaGlobal.blink_powersave = TasmotaGlobal.power;
@ -424,13 +424,13 @@ void SetLedPowerIdx(uint32_t led, uint32_t state)
TasmotaGlobal.led_power &= (0xFF ^ mask);
}
uint16_t pwm = 0;
if (bitRead(Settings.ledpwm_mask, led)) {
if (bitRead(Settings->ledpwm_mask, led)) {
#ifdef USE_LIGHT
pwm = changeUIntScale(ledGamma10(state ? Settings.ledpwm_on : Settings.ledpwm_off), 0, 1023, 0, Settings.pwm_range); // gamma corrected
pwm = changeUIntScale(ledGamma10(state ? Settings->ledpwm_on : Settings->ledpwm_off), 0, 1023, 0, Settings->pwm_range); // gamma corrected
#else //USE_LIGHT
pwm = changeUIntScale((uint16_t)(state ? Settings.ledpwm_on : Settings.ledpwm_off), 0, 255, 0, Settings.pwm_range); // linear
pwm = changeUIntScale((uint16_t)(state ? Settings->ledpwm_on : Settings->ledpwm_off), 0, 255, 0, Settings->pwm_range); // linear
#endif //USE_LIGHT
analogWrite(Pin(GPIO_LED1, led), bitRead(TasmotaGlobal.led_inverted, led) ? Settings.pwm_range - pwm : pwm);
analogWrite(Pin(GPIO_LED1, led), bitRead(TasmotaGlobal.led_inverted, led) ? Settings->pwm_range - pwm : pwm);
} else {
DigitalWrite(GPIO_LED1, led, bitRead(TasmotaGlobal.led_inverted, led) ? !state : state);
}
@ -518,16 +518,16 @@ bool SendKey(uint32_t key, uint32_t device, uint32_t state)
char *tmp = (key) ? SettingsText(SET_MQTT_SWITCH_TOPIC) : SettingsText(SET_MQTT_BUTTON_TOPIC);
Format(key_topic, tmp, sizeof(key_topic));
if (Settings.flag.mqtt_enabled && MqttIsConnected() && (strlen(key_topic) != 0) && strcmp(key_topic, "0")) { // SetOption3 - Enable MQTT
if (Settings->flag.mqtt_enabled && MqttIsConnected() && (strlen(key_topic) != 0) && strcmp(key_topic, "0")) { // SetOption3 - Enable MQTT
if (!key && (device > TasmotaGlobal.devices_present)) {
device = 1; // Only allow number of buttons up to number of devices
}
GetTopic_P(stopic, CMND, key_topic,
GetPowerDevice(scommand, device, sizeof(scommand), (key + Settings.flag.device_index_enable))); // cmnd/switchtopic/POWERx - SetOption26 - Switch between POWER or POWER1
GetPowerDevice(scommand, device, sizeof(scommand), (key + Settings->flag.device_index_enable))); // cmnd/switchtopic/POWERx - SetOption26 - Switch between POWER or POWER1
if (CLEAR_RETAIN == state) {
ResponseClear();
} else {
if ((Settings.flag3.button_switch_force_local || // SetOption61 - Force local operation when button/switch topic is set
if ((Settings->flag3.button_switch_force_local || // SetOption61 - Force local operation when button/switch topic is set
!strcmp(TasmotaGlobal.mqtt_topic, key_topic) ||
!strcmp(SettingsText(SET_MQTT_GRP_TOPIC), key_topic)) &&
(POWER_TOGGLE == state)) {
@ -538,13 +538,13 @@ bool SendKey(uint32_t key, uint32_t device, uint32_t state)
#ifdef USE_DOMOTICZ
if (!(DomoticzSendKey(key, device, state, ResponseLength()))) {
#endif // USE_DOMOTICZ
MqttPublish(stopic, ((key) ? Settings.flag.mqtt_switch_retain // CMND_SWITCHRETAIN
: Settings.flag.mqtt_button_retain) && // CMND_BUTTONRETAIN
(state != POWER_HOLD || !Settings.flag3.no_hold_retain)); // SetOption62 - Don't use retain flag on HOLD messages
MqttPublish(stopic, ((key) ? Settings->flag.mqtt_switch_retain // CMND_SWITCHRETAIN
: Settings->flag.mqtt_button_retain) && // CMND_BUTTONRETAIN
(state != POWER_HOLD || !Settings->flag3.no_hold_retain)); // SetOption62 - Don't use retain flag on HOLD messages
#ifdef USE_DOMOTICZ
}
#endif // USE_DOMOTICZ
result = !Settings.flag3.button_switch_force_local; // SetOption61 - Force local operation when button/switch topic is set
result = !Settings->flag3.button_switch_force_local; // SetOption61 - Force local operation when button/switch topic is set
} else {
Response_P(PSTR("{\"%s%d\":{\"State\":%d}}"), (key) ? PSTR("Switch") : PSTR("Button"), device, state);
result = XdrvRulesProcess(0);
@ -567,7 +567,7 @@ void ExecuteCommandPower(uint32_t device, uint32_t state, uint32_t source)
{
// device = Relay number 1 and up
// state 0 = POWER_OFF = Relay Off
// state 1 = POWER_ON = Relay On (turn off after Settings.pulse_timer * 100 mSec if enabled)
// state 1 = POWER_ON = Relay On (turn off after Settings->pulse_timer * 100 mSec if enabled)
// state 2 = POWER_TOGGLE = Toggle relay
// state 3 = POWER_BLINK = Blink relay
// state 4 = POWER_BLINK_STOP = Stop blinking relay
@ -581,10 +581,10 @@ void ExecuteCommandPower(uint32_t device, uint32_t state, uint32_t source)
#ifdef USE_SONOFF_IFAN
if (IsModuleIfan()) {
TasmotaGlobal.blink_mask &= 1; // No blinking on the fan relays
Settings.flag.interlock = 0; // No interlock mode as it is already done by the microcontroller - CMND_INTERLOCK - Enable/disable interlock
Settings.pulse_timer[1] = 0; // No pulsetimers on the fan relays
Settings.pulse_timer[2] = 0;
Settings.pulse_timer[3] = 0;
Settings->flag.interlock = 0; // No interlock mode as it is already done by the microcontroller - CMND_INTERLOCK - Enable/disable interlock
Settings->pulse_timer[1] = 0; // No pulsetimers on the fan relays
Settings->pulse_timer[2] = 0;
Settings->pulse_timer[3] = 0;
}
#endif // USE_SONOFF_IFAN
@ -611,17 +611,17 @@ void ExecuteCommandPower(uint32_t device, uint32_t state, uint32_t source)
MqttPublishPowerBlinkState(device);
}
if (Settings.flag.interlock && // CMND_INTERLOCK - Enable/disable interlock
if (Settings->flag.interlock && // CMND_INTERLOCK - Enable/disable interlock
!interlock_mutex &&
((POWER_ON == state) || ((POWER_TOGGLE == state) && !(TasmotaGlobal.power & mask)))
) {
interlock_mutex = true; // Clear all but masked relay in interlock group if new set requested
bool perform_interlock_delay = false;
for (uint32_t i = 0; i < MAX_INTERLOCKS; i++) {
if (Settings.interlock[i] & mask) { // Find interlock group
if (Settings->interlock[i] & mask) { // Find interlock group
for (uint32_t j = 0; j < TasmotaGlobal.devices_present; j++) {
power_t imask = 1 << j;
if ((Settings.interlock[i] & imask) && (TasmotaGlobal.power & imask) && (mask != imask)) {
if ((Settings->interlock[i] & imask) && (TasmotaGlobal.power & imask) && (mask != imask)) {
ExecuteCommandPower(j +1, POWER_OFF, SRC_IGNORE);
perform_interlock_delay = true;
}
@ -651,7 +651,7 @@ void ExecuteCommandPower(uint32_t device, uint32_t state, uint32_t source)
#ifdef USE_DEVICE_GROUPS
if (TasmotaGlobal.power != old_power && SRC_REMOTE != source && SRC_RETRY != source) {
power_t dgr_power = TasmotaGlobal.power;
if (Settings.flag4.multiple_device_groups) { // SetOption88 - Enable relays in separate device groups
if (Settings->flag4.multiple_device_groups) { // SetOption88 - Enable relays in separate device groups
dgr_power = (dgr_power >> (device - 1)) & 1;
}
SendDeviceGroupMessage(device, DGR_MSGTYP_UPDATE, DGR_ITEM_POWER, dgr_power);
@ -664,12 +664,12 @@ void ExecuteCommandPower(uint32_t device, uint32_t state, uint32_t source)
#ifdef USE_KNX
KnxUpdatePowerState(device, TasmotaGlobal.power);
#endif // USE_KNX
if (publish_power && Settings.flag3.hass_tele_on_power) { // SetOption59 - Send tele/%topic%/STATE in addition to stat/%topic%/RESULT
if (publish_power && Settings->flag3.hass_tele_on_power) { // SetOption59 - Send tele/%topic%/STATE in addition to stat/%topic%/RESULT
MqttPublishTeleState();
}
// Restart PulseTime if powered On
SetPulseTimer((device -1) % MAX_PULSETIMERS, (((POWER_ALL_OFF_PULSETIME_ON == Settings.poweronstate) ? ~TasmotaGlobal.power : TasmotaGlobal.power) & mask) ? Settings.pulse_timer[(device -1) % MAX_PULSETIMERS] : 0);
SetPulseTimer((device -1) % MAX_PULSETIMERS, (((POWER_ALL_OFF_PULSETIME_ON == Settings->poweronstate) ? ~TasmotaGlobal.power : TasmotaGlobal.power) & mask) ? Settings->pulse_timer[(device -1) % MAX_PULSETIMERS] : 0);
}
else if (POWER_BLINK == state) {
if (!(TasmotaGlobal.blink_mask & mask)) {
@ -677,7 +677,7 @@ void ExecuteCommandPower(uint32_t device, uint32_t state, uint32_t source)
TasmotaGlobal.blink_power = (TasmotaGlobal.power >> (device -1))&1; // Prep to Toggle
}
TasmotaGlobal.blink_timer = millis() + 100;
TasmotaGlobal.blink_counter = ((!Settings.blinkcount) ? 64000 : (Settings.blinkcount *2)) +1;
TasmotaGlobal.blink_counter = ((!Settings->blinkcount) ? 64000 : (Settings->blinkcount *2)) +1;
TasmotaGlobal.blink_mask |= mask; // Set device mask
MqttPublishPowerBlinkState(device);
return;
@ -716,7 +716,7 @@ void MqttShowPWMState(void)
bool first = true;
for (uint32_t i = 0; i < MAX_PWMS; i++) {
if (PinUsed(GPIO_PWM1, i)) {
ResponseAppend_P(PSTR("%s\"" D_CMND_PWM "%d\":%d"), first ? "" : ",", i+1, Settings.pwm_value[i]);
ResponseAppend_P(PSTR("%s\"" D_CMND_PWM "%d\":%d"), first ? "" : ",", i+1, Settings->pwm_value[i]);
first = false;
}
}
@ -738,7 +738,7 @@ void MqttShowState(void)
#endif // ESP8266
ResponseAppend_P(PSTR(",\"" D_JSON_HEAPSIZE "\":%d,\"SleepMode\":\"%s\",\"Sleep\":%u,\"LoadAvg\":%u,\"MqttCount\":%u"),
ESP_getFreeHeap1024(), GetTextIndexed(stemp1, sizeof(stemp1), Settings.flag3.sleep_normal, kSleepMode), // SetOption60 - Enable normal sleep instead of dynamic sleep
ESP_getFreeHeap1024(), GetTextIndexed(stemp1, sizeof(stemp1), Settings->flag3.sleep_normal, kSleepMode), // SetOption60 - Enable normal sleep instead of dynamic sleep
TasmotaGlobal.sleep, TasmotaGlobal.loop_load_avg, MqttConnectCount());
for (uint32_t i = 1; i <= TasmotaGlobal.devices_present; i++) {
@ -747,7 +747,7 @@ void MqttShowState(void)
if (i == LightDevice()) { ResponseLightState(1); } // call it only once
} else {
#endif
ResponseAppend_P(PSTR(",\"%s\":\"%s\""), GetPowerDevice(stemp1, i, sizeof(stemp1), Settings.flag.device_index_enable), // SetOption26 - Switch between POWER or POWER1
ResponseAppend_P(PSTR(",\"%s\":\"%s\""), GetPowerDevice(stemp1, i, sizeof(stemp1), Settings->flag.device_index_enable), // SetOption26 - Switch between POWER or POWER1
GetStateText(bitRead(TasmotaGlobal.power, i-1)));
#ifdef USE_SONOFF_IFAN
if (IsModuleIfan()) {
@ -768,7 +768,7 @@ void MqttShowState(void)
if (!TasmotaGlobal.global_state.wifi_down) {
int32_t rssi = WiFi.RSSI();
ResponseAppend_P(PSTR(",\"" D_JSON_WIFI "\":{\"" D_JSON_AP "\":%d,\"" D_JSON_SSID "\":\"%s\",\"" D_JSON_BSSID "\":\"%s\",\"" D_JSON_CHANNEL "\":%d,\"" D_JSON_WIFI_MODE "\":\"11%c\",\"" D_JSON_RSSI "\":%d,\"" D_JSON_SIGNAL "\":%d,\"" D_JSON_LINK_COUNT "\":%d,\"" D_JSON_DOWNTIME "\":\"%s\"}"),
Settings.sta_active +1, EscapeJSONString(SettingsText(SET_STASSID1 + Settings.sta_active)).c_str(), WiFi.BSSIDstr().c_str(), WiFi.channel(),
Settings->sta_active +1, EscapeJSONString(SettingsText(SET_STASSID1 + Settings->sta_active)).c_str(), WiFi.BSSIDstr().c_str(), WiFi.channel(),
pgm_read_byte(&kWifiPhyMode[WiFi.getPhyMode() & 0x3]), WifiGetRssiAsQuality(rssi), rssi,
WifiLinkCount(), WifiDowntime().c_str());
}
@ -780,7 +780,7 @@ void MqttPublishTeleState(void)
{
ResponseClear();
MqttShowState();
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_STATE), Settings.flag5.mqtt_state_retain);
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_STATE), Settings->flag5.mqtt_state_retain);
XdrvRulesProcess(1);
}
@ -844,7 +844,7 @@ bool MqttShowSensor(void)
if (ResponseContains_P(PSTR(D_JSON_TEMPERATURE))) {
ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE_UNIT "\":\"%c\""), TempUnit());
}
if (ResponseContains_P(PSTR(D_JSON_SPEED)) && Settings.flag2.speed_conversion) {
if (ResponseContains_P(PSTR(D_JSON_SPEED)) && Settings->flag2.speed_conversion) {
ResponseAppend_P(PSTR(",\"" D_JSON_SPEED_UNIT "\":\"%s\""), SpeedUnit().c_str());
}
ResponseJsonEnd();
@ -863,7 +863,7 @@ void MqttPublishSensor(void) {
void MqttPublishTeleperiodSensor(void) {
ResponseClear();
if (MqttShowSensor()) {
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); // CMND_SENSORRETAIN
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings->flag.mqtt_sensor_retain); // CMND_SENSORRETAIN
XdrvRulesProcess(1);
}
}
@ -886,13 +886,13 @@ void PerformEverySecond(void)
if (BOOT_LOOP_TIME == TasmotaGlobal.uptime) {
RtcRebootReset();
Settings.last_module = Settings.module;
Settings->last_module = Settings->module;
#ifdef USE_DEEPSLEEP
if (!(DeepSleepEnabled() && !Settings.flag3.bootcount_update)) { // SetOption76 - (Deepsleep) Enable incrementing bootcount (1) when deepsleep is enabled
if (!(DeepSleepEnabled() && !Settings->flag3.bootcount_update)) { // SetOption76 - (Deepsleep) Enable incrementing bootcount (1) when deepsleep is enabled
#endif
Settings.bootcount++; // Moved to here to stop flash writes during start-up
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BOOT_COUNT " %d"), Settings.bootcount);
Settings->bootcount++; // Moved to here to stop flash writes during start-up
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BOOT_COUNT " %d"), Settings->bootcount);
#ifdef USE_DEEPSLEEP
}
#endif
@ -918,8 +918,8 @@ void PerformEverySecond(void)
if (TasmotaGlobal.syslog_timer) { // Restore syslog level
TasmotaGlobal.syslog_timer--;
if (!TasmotaGlobal.syslog_timer) {
TasmotaGlobal.syslog_level = Settings.syslog_level;
if (Settings.syslog_level) {
TasmotaGlobal.syslog_level = Settings->syslog_level;
if (Settings->syslog_level) {
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_SYSLOG_LOGGING_REENABLED)); // Might trigger disable again (on purpose)
}
}
@ -930,14 +930,14 @@ void PerformEverySecond(void)
ResetGlobalValues();
if (Settings.tele_period || (3601 == TasmotaGlobal.tele_period)) {
if (Settings->tele_period || (3601 == TasmotaGlobal.tele_period)) {
if (TasmotaGlobal.tele_period >= 9999) {
if (!TasmotaGlobal.global_state.network_down) {
TasmotaGlobal.tele_period = 0; // Allow teleperiod once wifi is connected
}
} else {
TasmotaGlobal.tele_period++;
if (TasmotaGlobal.tele_period >= Settings.tele_period) {
if (TasmotaGlobal.tele_period >= Settings->tele_period) {
TasmotaGlobal.tele_period = 0;
MqttPublishTeleState();
@ -963,8 +963,8 @@ void PerformEverySecond(void)
#ifdef USE_UFILESYS
static bool settings_lkg = false; // Settings saved as Last Known Good
// Copy Settings as Last Known Good if no changes have been saved since 30 minutes
if (!settings_lkg && (UtcTime() > START_VALID_TIME) && (Settings.cfg_timestamp < UtcTime() - (30 * 60))) {
TfsSaveFile(TASM_FILE_SETTINGS_LKG, (const uint8_t*)&Settings, sizeof(Settings));
if (!settings_lkg && (UtcTime() > START_VALID_TIME) && (Settings->cfg_timestamp < UtcTime() - (30 * 60))) {
TfsSaveFile(TASM_FILE_SETTINGS_LKG, (const uint8_t*)Settings, sizeof(TSettings));
settings_lkg = true;
}
#endif
@ -989,7 +989,7 @@ void Every100mSeconds(void)
if (TimeReached(TasmotaGlobal.pulse_timer[i])) { // Timer finished?
TasmotaGlobal.pulse_timer[i] = 0L; // Turn off this timer
for (uint32_t j = 0; j < TasmotaGlobal.devices_present; j = j +MAX_PULSETIMERS) {
ExecuteCommandPower(i + j +1, (POWER_ALL_OFF_PULSETIME_ON == Settings.poweronstate) ? POWER_ON : POWER_OFF, SRC_PULSETIMER);
ExecuteCommandPower(i + j +1, (POWER_ALL_OFF_PULSETIME_ON == Settings->poweronstate) ? POWER_ON : POWER_OFF, SRC_PULSETIMER);
}
}
}
@ -997,7 +997,7 @@ void Every100mSeconds(void)
if (TasmotaGlobal.blink_mask) {
if (TimeReached(TasmotaGlobal.blink_timer)) {
SetNextTimeInterval(TasmotaGlobal.blink_timer, 100 * Settings.blinktime);
SetNextTimeInterval(TasmotaGlobal.blink_timer, 100 * Settings->blinktime);
TasmotaGlobal.blink_counter--;
if (!TasmotaGlobal.blink_counter) {
StopAllPowerBlink();
@ -1039,7 +1039,7 @@ void Every250mSeconds(void)
TasmotaGlobal.global_state.network_down = (TasmotaGlobal.global_state.wifi_down && TasmotaGlobal.global_state.eth_down) ? 1 : 0;
if (!Settings.flag.global_state) { // SetOption31 - Control link led blinking
if (!Settings->flag.global_state) { // SetOption31 - Control link led blinking
if (TasmotaGlobal.global_state.data &0x03) { // Network or MQTT problem
if (TasmotaGlobal.global_state.mqtt_down) { blinkinterval = 7; } // MQTT problem so blink every 2 seconds (slowest)
if (TasmotaGlobal.global_state.network_down) { blinkinterval = 3; } // Network problem so blink every second (slow)
@ -1056,7 +1056,7 @@ void Every250mSeconds(void)
TasmotaGlobal.blinkstate ^= 1; // Blink
}
}
if ((!(Settings.ledstate &0x08)) && ((Settings.ledstate &0x06) || (TasmotaGlobal.blinks > 200) || (TasmotaGlobal.blinkstate))) {
if ((!(Settings->ledstate &0x08)) && ((Settings->ledstate &0x06) || (TasmotaGlobal.blinks > 200) || (TasmotaGlobal.blinkstate))) {
SetLedLink(TasmotaGlobal.blinkstate); // Set led on or off
}
if (!TasmotaGlobal.blinkstate) {
@ -1064,8 +1064,8 @@ void Every250mSeconds(void)
if (200 == TasmotaGlobal.blinks) { TasmotaGlobal.blinks = 0; } // Disable blink
}
}
if (Settings.ledstate &1 && (PinUsed(GPIO_LEDLNK) || !(TasmotaGlobal.blinks || TasmotaGlobal.restart_flag || TasmotaGlobal.ota_state_flag)) ) {
bool tstate = TasmotaGlobal.power & Settings.ledmask;
if (Settings->ledstate &1 && (PinUsed(GPIO_LEDLNK) || !(TasmotaGlobal.blinks || TasmotaGlobal.restart_flag || TasmotaGlobal.ota_state_flag)) ) {
bool tstate = TasmotaGlobal.power & Settings->ledmask;
#ifdef ESP8266
if ((SONOFF_TOUCH == TasmotaGlobal.module_type) || (SONOFF_T11 == TasmotaGlobal.module_type) || (SONOFF_T12 == TasmotaGlobal.module_type) || (SONOFF_T13 == TasmotaGlobal.module_type)) {
tstate = (!TasmotaGlobal.power) ? 1 : 0; // As requested invert signal for Touch devices to find them in the dark
@ -1103,7 +1103,7 @@ void Every250mSeconds(void)
CounterInterruptDisable(true); // Prevent OTA failures on 100Hz counter interrupts
#endif // USE_COUNTER
#ifdef USE_WEBSERVER
if (Settings.webserver) StopWebserver();
if (Settings->webserver) StopWebserver();
#endif // USE_WEBSERVER
#ifdef USE_ARILUX_RF
AriluxRfDisable(); // Prevent restart exception on Arilux Interrupt routine
@ -1203,21 +1203,21 @@ void Every250mSeconds(void)
if (TasmotaGlobal.save_data_counter && CommandsReady()) {
TasmotaGlobal.save_data_counter--;
if (TasmotaGlobal.save_data_counter <= 0) {
if (Settings.flag.save_state) { // SetOption0 - Save power state and use after restart
if (Settings->flag.save_state) { // SetOption0 - Save power state and use after restart
power_t mask = POWER_MASK;
for (uint32_t i = 0; i < TasmotaGlobal.devices_present; i++) {
if ((Settings.pulse_timer[i % MAX_PULSETIMERS] > 0) && (Settings.pulse_timer[i % MAX_PULSETIMERS] < 30)) { // 3 seconds
if ((Settings->pulse_timer[i % MAX_PULSETIMERS] > 0) && (Settings->pulse_timer[i % MAX_PULSETIMERS] < 30)) { // 3 seconds
mask &= ~(1 << i);
}
}
if (!((Settings.power &mask) == (TasmotaGlobal.power &mask))) {
Settings.power = TasmotaGlobal.power;
if (!((Settings->power &mask) == (TasmotaGlobal.power &mask))) {
Settings->power = TasmotaGlobal.power;
}
} else {
Settings.power = 0;
Settings->power = 0;
}
if (!TasmotaGlobal.restart_flag) { SettingsSave(0); }
TasmotaGlobal.save_data_counter = Settings.save_data;
TasmotaGlobal.save_data_counter = Settings->save_data;
}
}
@ -1243,7 +1243,7 @@ void Every250mSeconds(void)
strncpy(storage_mqttpwd, SettingsText(SET_MQTT_PWD), sizeof(storage_mqttpwd));
char storage_mqtttopic[strlen(SettingsText(SET_MQTT_TOPIC)) +1];
strncpy(storage_mqtttopic, SettingsText(SET_MQTT_TOPIC), sizeof(storage_mqtttopic));
uint16_t mqtt_port = Settings.mqtt_port;
uint16_t mqtt_port = Settings->mqtt_port;
// if (216 == TasmotaGlobal.restart_flag) {
// Backup mqtt host, port, client, username and password
@ -1264,7 +1264,7 @@ void Every250mSeconds(void)
SettingsUpdateText(SET_MQTT_USER, storage_mqttuser);
SettingsUpdateText(SET_MQTT_PWD, storage_mqttpwd);
SettingsUpdateText(SET_MQTT_TOPIC, storage_mqtttopic);
Settings.mqtt_port = mqtt_port;
Settings->mqtt_port = mqtt_port;
}
TasmotaGlobal.restart_flag = 3; // Finish backlog then Restart 1
}
@ -1294,7 +1294,7 @@ void Every250mSeconds(void)
}
break;
case 2: // Every x.5 second
if (Settings.flag4.network_wifi) {
if (Settings->flag4.network_wifi) {
WifiCheck(TasmotaGlobal.wifi_state_flag);
TasmotaGlobal.wifi_state_flag = WIFI_RESTART;
} else {
@ -1315,16 +1315,16 @@ void Every250mSeconds(void)
#endif // USE_DISCOVERY
#ifdef USE_WEBSERVER
if (Settings.webserver) {
if (Settings->webserver) {
#ifdef ESP8266
if (!WifiIsInManagerMode()) { StartWebserver(Settings.webserver, WiFi.localIP()); }
if (!WifiIsInManagerMode()) { StartWebserver(Settings->webserver, WiFi.localIP()); }
#endif // ESP8266
#ifdef ESP32
#ifdef USE_ETHERNET
StartWebserver(Settings.webserver, (EthernetLocalIP()) ? EthernetLocalIP() : WiFi.localIP());
StartWebserver(Settings->webserver, (EthernetLocalIP()) ? EthernetLocalIP() : WiFi.localIP());
#else
StartWebserver(Settings.webserver, WiFi.localIP());
StartWebserver(Settings->webserver, WiFi.localIP());
#endif
#endif // ESP32
@ -1337,7 +1337,7 @@ void Every250mSeconds(void)
StopWebserver();
}
#ifdef USE_EMULATION
if (Settings.flag2.emulation) { UdpConnect(); }
if (Settings->flag2.emulation) { UdpConnect(); }
#endif // USE_EMULATION
#endif // USE_WEBSERVER
@ -1346,7 +1346,7 @@ void Every250mSeconds(void)
#endif // USE_DEVICE_GROUPS
#ifdef USE_KNX
if (!knx_started && Settings.flag.knx_enabled) { // CMND_KNX_ENABLED
if (!knx_started && Settings->flag.knx_enabled) { // CMND_KNX_ENABLED
KNXStart();
knx_started = true;
}
@ -1393,12 +1393,12 @@ void ArduinoOTAInit(void)
{
SettingsSave(1); // Free flash for OTA update
#ifdef USE_WEBSERVER
if (Settings.webserver) { StopWebserver(); }
if (Settings->webserver) { StopWebserver(); }
#endif // USE_WEBSERVER
#ifdef USE_ARILUX_RF
AriluxRfDisable(); // Prevent restart exception on Arilux Interrupt routine
#endif // USE_ARILUX_RF
if (Settings.flag.mqtt_enabled) {
if (Settings->flag.mqtt_enabled) {
MqttDisconnect(); // SetOption3 - Enable MQTT
}
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD "Arduino OTA " D_UPLOAD_STARTED));
@ -1497,12 +1497,12 @@ void SerialInput(void)
/*-------------------------------------------------------------------------------------------*/
if (TasmotaGlobal.serial_in_byte > 127 && !Settings.flag.mqtt_serial_raw) { // Discard binary data above 127 if no raw reception allowed - CMND_SERIALSEND3
if (TasmotaGlobal.serial_in_byte > 127 && !Settings->flag.mqtt_serial_raw) { // Discard binary data above 127 if no raw reception allowed - CMND_SERIALSEND3
TasmotaGlobal.serial_in_byte_counter = 0;
Serial.flush();
return;
}
if (!Settings.flag.mqtt_serial) { // SerialSend active - CMND_SERIALSEND and CMND_SERIALLOG
if (!Settings->flag.mqtt_serial) { // SerialSend active - CMND_SERIALSEND and CMND_SERIALLOG
if (isprint(TasmotaGlobal.serial_in_byte)) { // Any char between 32 and 127
if (TasmotaGlobal.serial_in_byte_counter < INPUT_BUFFER_SIZE -1) { // Add char to string if it still fits
TasmotaGlobal.serial_in_buffer[TasmotaGlobal.serial_in_byte_counter++] = TasmotaGlobal.serial_in_byte;
@ -1511,11 +1511,11 @@ void SerialInput(void)
}
}
} else {
if (TasmotaGlobal.serial_in_byte || Settings.flag.mqtt_serial_raw) { // Any char between 1 and 127 or any char (0 - 255) - CMND_SERIALSEND3
if (TasmotaGlobal.serial_in_byte || Settings->flag.mqtt_serial_raw) { // Any char between 1 and 127 or any char (0 - 255) - CMND_SERIALSEND3
bool in_byte_is_delimiter = // Char is delimiter when...
(((Settings.serial_delimiter < 128) && (TasmotaGlobal.serial_in_byte == Settings.serial_delimiter)) || // Any char between 1 and 127 and being delimiter
((Settings.serial_delimiter == 128) && !isprint(TasmotaGlobal.serial_in_byte))) && // Any char not between 32 and 127
!Settings.flag.mqtt_serial_raw; // In raw mode (CMND_SERIALSEND3) there is never a delimiter
(((Settings->serial_delimiter < 128) && (TasmotaGlobal.serial_in_byte == Settings->serial_delimiter)) || // Any char between 1 and 127 and being delimiter
((Settings->serial_delimiter == 128) && !isprint(TasmotaGlobal.serial_in_byte))) && // Any char not between 32 and 127
!Settings->flag.mqtt_serial_raw; // In raw mode (CMND_SERIALSEND3) there is never a delimiter
if ((TasmotaGlobal.serial_in_byte_counter < INPUT_BUFFER_SIZE -1) && // Add char to string if it still fits and ...
!in_byte_is_delimiter) { // Char is not a delimiter
@ -1548,9 +1548,9 @@ void SerialInput(void)
#endif // USE_SONOFF_SC
/*-------------------------------------------------------------------------------------------*/
if (!Settings.flag.mqtt_serial && (TasmotaGlobal.serial_in_byte == '\n')) { // CMND_SERIALSEND and CMND_SERIALLOG
if (!Settings->flag.mqtt_serial && (TasmotaGlobal.serial_in_byte == '\n')) { // CMND_SERIALSEND and CMND_SERIALLOG
TasmotaGlobal.serial_in_buffer[TasmotaGlobal.serial_in_byte_counter] = 0; // Serial data completed
TasmotaGlobal.seriallog_level = (Settings.seriallog_level < LOG_LEVEL_INFO) ? (uint8_t)LOG_LEVEL_INFO : Settings.seriallog_level;
TasmotaGlobal.seriallog_level = (Settings->seriallog_level < LOG_LEVEL_INFO) ? (uint8_t)LOG_LEVEL_INFO : Settings->seriallog_level;
if (serial_buffer_overrun) {
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_COMMAND "Serial buffer overrun"));
} else {
@ -1564,9 +1564,9 @@ void SerialInput(void)
}
}
if (Settings.flag.mqtt_serial && TasmotaGlobal.serial_in_byte_counter && (millis() > (serial_polling_window + SERIAL_POLLING))) { // CMND_SERIALSEND and CMND_SERIALLOG
if (Settings->flag.mqtt_serial && TasmotaGlobal.serial_in_byte_counter && (millis() > (serial_polling_window + SERIAL_POLLING))) { // CMND_SERIALSEND and CMND_SERIALLOG
TasmotaGlobal.serial_in_buffer[TasmotaGlobal.serial_in_byte_counter] = 0; // Serial data completed
bool assume_json = (!Settings.flag.mqtt_serial_raw && (TasmotaGlobal.serial_in_buffer[0] == '{'));
bool assume_json = (!Settings->flag.mqtt_serial_raw && (TasmotaGlobal.serial_in_buffer[0] == '{'));
if (serial_buffer_overrun) {
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_COMMAND "Serial buffer overrun"));
@ -1577,7 +1577,7 @@ void SerialInput(void)
ResponseAppend_P(TasmotaGlobal.serial_in_buffer);
} else {
ResponseAppend_P(PSTR("\""));
if (Settings.flag.mqtt_serial_raw) {
if (Settings->flag.mqtt_serial_raw) {
char hex_char[(TasmotaGlobal.serial_in_byte_counter * 2) + 2];
ResponseAppend_P(ToHex_P((unsigned char*)TasmotaGlobal.serial_in_buffer, TasmotaGlobal.serial_in_byte_counter, hex_char, sizeof(hex_char)));
} else {
@ -1598,8 +1598,8 @@ void ResetPwm(void)
{
for (uint32_t i = 0; i < MAX_PWMS; i++) { // Basic PWM control only
if (PinUsed(GPIO_PWM1, i)) {
analogWrite(Pin(GPIO_PWM1, i), bitRead(TasmotaGlobal.pwm_inverted, i) ? Settings.pwm_range : 0);
// analogWrite(Pin(GPIO_PWM1, i), bitRead(TasmotaGlobal.pwm_inverted, i) ? Settings.pwm_range - Settings.pwm_value[i] : Settings.pwm_value[i]);
analogWrite(Pin(GPIO_PWM1, i), bitRead(TasmotaGlobal.pwm_inverted, i) ? Settings->pwm_range : 0);
// analogWrite(Pin(GPIO_PWM1, i), bitRead(TasmotaGlobal.pwm_inverted, i) ? Settings->pwm_range - Settings->pwm_value[i] : Settings->pwm_value[i]);
}
}
}
@ -1608,7 +1608,7 @@ void ResetPwm(void)
void GpioInit(void)
{
if (!ValidModule(Settings.module)) {
if (!ValidModule(Settings->module)) {
uint32_t module = MODULE;
if (!ValidModule(MODULE)) {
#ifdef ESP8266
@ -1619,8 +1619,8 @@ void GpioInit(void)
#endif // ESP32
}
Settings.module = module;
Settings.last_module = module;
Settings->module = module;
Settings->last_module = module;
}
SetModuleType();
@ -1630,20 +1630,20 @@ void GpioInit(void)
ConvertGpios();
#endif // ESP8266
for (uint32_t i = 0; i < nitems(Settings.user_template.gp.io); i++) {
if ((Settings.user_template.gp.io[i] >= AGPIO(GPIO_SENSOR_END)) && (Settings.user_template.gp.io[i] < AGPIO(GPIO_USER))) {
Settings.user_template.gp.io[i] = AGPIO(GPIO_USER); // Fix not supported sensor ids in template
for (uint32_t i = 0; i < nitems(Settings->user_template.gp.io); i++) {
if ((Settings->user_template.gp.io[i] >= AGPIO(GPIO_SENSOR_END)) && (Settings->user_template.gp.io[i] < AGPIO(GPIO_USER))) {
Settings->user_template.gp.io[i] = AGPIO(GPIO_USER); // Fix not supported sensor ids in template
}
}
myio template_gp;
TemplateGpios(&template_gp);
for (uint32_t i = 0; i < nitems(Settings.my_gp.io); i++) {
if ((Settings.my_gp.io[i] >= AGPIO(GPIO_SENSOR_END)) && (Settings.my_gp.io[i] < AGPIO(GPIO_USER))) {
Settings.my_gp.io[i] = GPIO_NONE; // Fix not supported sensor ids in module
for (uint32_t i = 0; i < nitems(Settings->my_gp.io); i++) {
if ((Settings->my_gp.io[i] >= AGPIO(GPIO_SENSOR_END)) && (Settings->my_gp.io[i] < AGPIO(GPIO_USER))) {
Settings->my_gp.io[i] = GPIO_NONE; // Fix not supported sensor ids in module
}
else if (Settings.my_gp.io[i] > GPIO_NONE) {
TasmotaGlobal.my_module.io[i] = Settings.my_gp.io[i]; // Set User selected Module sensors
else if (Settings->my_gp.io[i] > GPIO_NONE) {
TasmotaGlobal.my_module.io[i] = Settings->my_gp.io[i]; // Set User selected Module sensors
}
if ((template_gp.io[i] > GPIO_NONE) && (template_gp.io[i] < AGPIO(GPIO_USER))) {
TasmotaGlobal.my_module.io[i] = template_gp.io[i]; // Force Template override
@ -1737,8 +1737,8 @@ void GpioInit(void)
// AddLogBufferSize(LOG_LEVEL_DEBUG, (uint8_t*)TasmotaGlobal.gpio_pin, nitems(TasmotaGlobal.gpio_pin), sizeof(TasmotaGlobal.gpio_pin[0]));
analogWriteRange(Settings.pwm_range); // Default is 1023 (Arduino.h)
analogWriteFreq(Settings.pwm_frequency); // Default is 1000 (core_esp8266_wiring_pwm.c)
analogWriteRange(Settings->pwm_range); // Default is 1023 (Arduino.h)
analogWriteFreq(Settings->pwm_frequency); // Default is 1000 (core_esp8266_wiring_pwm.c)
#ifdef ESP8266
if ((2 == Pin(GPIO_TXD)) || (H801 == TasmotaGlobal.module_type)) { Serial.set_tx(2); }
@ -1888,10 +1888,10 @@ void GpioInit(void)
#endif // ESP32
if (TasmotaGlobal.light_type) {
// force PWM GPIOs to low or high mode, see #7165
analogWrite(Pin(GPIO_PWM1, i), bitRead(TasmotaGlobal.pwm_inverted, i) ? Settings.pwm_range : 0);
analogWrite(Pin(GPIO_PWM1, i), bitRead(TasmotaGlobal.pwm_inverted, i) ? Settings->pwm_range : 0);
} else {
TasmotaGlobal.pwm_present = true;
analogWrite(Pin(GPIO_PWM1, i), bitRead(TasmotaGlobal.pwm_inverted, i) ? Settings.pwm_range - Settings.pwm_value[i] : Settings.pwm_value[i]);
analogWrite(Pin(GPIO_PWM1, i), bitRead(TasmotaGlobal.pwm_inverted, i) ? Settings->pwm_range - Settings->pwm_value[i] : Settings->pwm_value[i]);
}
}
}
@ -1933,6 +1933,6 @@ void GpioInit(void)
if (PWM_DIMMER == TasmotaGlobal.module_type && PinUsed(GPIO_REL1)) { TasmotaGlobal.devices_present--; }
#endif // USE_PWM_DIMMER
SetLedPower(Settings.ledstate &8);
SetLedLink(Settings.ledstate &8);
SetLedPower(Settings->ledstate &8);
SetLedLink(Settings->ledstate &8);
}

View File

@ -135,7 +135,7 @@ void PollUdp(void)
// AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("\n%s"), packet_buffer);
// Simple Service Discovery Protocol (SSDP)
if (Settings.flag2.emulation) {
if (Settings->flag2.emulation) {
#if defined(USE_SCRIPT_HUE) || defined(USE_ZIGBEE)
if (strstr_P(packet_buffer, PSTR("M-SEARCH")) != nullptr) {
#else
@ -159,7 +159,7 @@ void PollUdp(void)
bool udp_proccessed = false; // make sure we process the packet only once
#ifdef USE_EMULATION_WEMO
if (!udp_proccessed && (EMUL_WEMO == Settings.flag2.emulation)) {
if (!udp_proccessed && (EMUL_WEMO == Settings->flag2.emulation)) {
if (strstr_P(packet_buffer, URN_BELKIN_DEVICE) != nullptr) { // type1 echo dot 2g, echo 1g's
WemoRespondToMSearch(1);
udp_proccessed = true;
@ -174,7 +174,7 @@ void PollUdp(void)
#endif // USE_EMULATION_WEMO
#ifdef USE_EMULATION_HUE
if (!udp_proccessed && (EMUL_HUE == Settings.flag2.emulation)) {
if (!udp_proccessed && (EMUL_HUE == Settings->flag2.emulation)) {
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("UDP: HUE"));
if ((strstr_P(packet_buffer, PSTR(":device:basic:1")) != nullptr) ||
(strstr_P(packet_buffer, UPNP_ROOTDEVICE) != nullptr) ||

View File

@ -153,7 +153,7 @@ void WiFiSetSleepMode(void)
// Sleep explanation: https://github.com/esp8266/Arduino/blob/3f0c601cfe81439ce17e9bd5d28994a7ed144482/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp#L255
/*
if (TasmotaGlobal.sleep && Settings.flag3.sleep_normal) { // SetOption60 - Enable normal sleep instead of dynamic sleep
if (TasmotaGlobal.sleep && Settings->flag3.sleep_normal) { // SetOption60 - Enable normal sleep instead of dynamic sleep
WiFi.setSleepMode(WIFI_LIGHT_SLEEP); // Allow light sleep during idle times
} else {
WiFi.setSleepMode(WIFI_MODEM_SLEEP); // Disable sleep (Esp8288/Arduino core and sdk default)
@ -164,7 +164,7 @@ void WiFiSetSleepMode(void)
WiFi.setSleepMode(WIFI_NONE_SLEEP); // Disable sleep
}
} else {
if (Settings.flag3.sleep_normal) { // SetOption60 - Enable normal sleep instead of dynamic sleep
if (Settings->flag3.sleep_normal) { // SetOption60 - Enable normal sleep instead of dynamic sleep
WiFi.setSleepMode(WIFI_LIGHT_SLEEP); // Allow light sleep during idle times
} else {
WiFi.setSleepMode(WIFI_MODEM_SLEEP); // Sleep (Esp8288/Arduino core and sdk default)
@ -192,30 +192,30 @@ void WifiBegin(uint8_t flag, uint8_t channel)
switch (flag) {
case 0: // AP1
case 1: // AP2
Settings.sta_active = flag;
Settings->sta_active = flag;
break;
case 2: // Toggle
Settings.sta_active ^= 1;
Settings->sta_active ^= 1;
} // 3: Current AP
if (!strlen(SettingsText(SET_STASSID1 + Settings.sta_active))) {
Settings.sta_active ^= 1; // Skip empty SSID
if (!strlen(SettingsText(SET_STASSID1 + Settings->sta_active))) {
Settings->sta_active ^= 1; // Skip empty SSID
}
if (Settings.ipv4_address[0]) {
WiFi.config(Settings.ipv4_address[0], Settings.ipv4_address[1], Settings.ipv4_address[2], Settings.ipv4_address[3]); // Set static IP
if (Settings->ipv4_address[0]) {
WiFi.config(Settings->ipv4_address[0], Settings->ipv4_address[1], Settings->ipv4_address[2], Settings->ipv4_address[3]); // Set static IP
}
WiFi.hostname(TasmotaGlobal.hostname);
char stemp[40] = { 0 };
if (channel) {
WiFi.begin(SettingsText(SET_STASSID1 + Settings.sta_active), SettingsText(SET_STAPWD1 + Settings.sta_active), channel, Wifi.bssid);
WiFi.begin(SettingsText(SET_STASSID1 + Settings->sta_active), SettingsText(SET_STAPWD1 + Settings->sta_active), channel, Wifi.bssid);
// Add connected BSSID and channel for multi-AP installations
char hex_char[18];
snprintf_P(stemp, sizeof(stemp), PSTR(" Channel %d BSSId %s"), channel, ToHex_P((unsigned char*)Wifi.bssid, 6, hex_char, sizeof(hex_char), ':'));
} else {
WiFi.begin(SettingsText(SET_STASSID1 + Settings.sta_active), SettingsText(SET_STAPWD1 + Settings.sta_active));
WiFi.begin(SettingsText(SET_STASSID1 + Settings->sta_active), SettingsText(SET_STAPWD1 + Settings->sta_active));
}
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CONNECTING_TO_AP "%d %s%s " D_IN_MODE " 11%c " D_AS " %s..."),
Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active), stemp, pgm_read_byte(&kWifiPhyMode[WiFi.getPhyMode() & 0x3]), TasmotaGlobal.hostname);
Settings->sta_active +1, SettingsText(SET_STASSID1 + Settings->sta_active), stemp, pgm_read_byte(&kWifiPhyMode[WiFi.getPhyMode() & 0x3]), TasmotaGlobal.hostname);
#if LWIP_IPV6
for (bool configured = false; !configured;) {
@ -386,19 +386,19 @@ void WifiCheckIp(void)
if (Wifi.status != WL_CONNECTED) {
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CONNECTED));
// AddLog(LOG_LEVEL_INFO, PSTR("Wifi: Set IP addresses"));
Settings.ipv4_address[1] = (uint32_t)WiFi.gatewayIP();
Settings.ipv4_address[2] = (uint32_t)WiFi.subnetMask();
Settings.ipv4_address[3] = (uint32_t)WiFi.dnsIP();
Settings->ipv4_address[1] = (uint32_t)WiFi.gatewayIP();
Settings->ipv4_address[2] = (uint32_t)WiFi.subnetMask();
Settings->ipv4_address[3] = (uint32_t)WiFi.dnsIP();
// Save current AP parameters for quick reconnect
Settings.wifi_channel = WiFi.channel();
Settings->wifi_channel = WiFi.channel();
uint8_t *bssid = WiFi.BSSID();
memcpy((void*) &Settings.wifi_bssid, (void*) bssid, sizeof(Settings.wifi_bssid));
memcpy((void*) &Settings->wifi_bssid, (void*) bssid, sizeof(Settings->wifi_bssid));
}
Wifi.status = WL_CONNECTED;
} else {
WifiSetState(0);
uint8_t wifi_config_tool = Settings.sta_config;
uint8_t wifi_config_tool = Settings->sta_config;
Wifi.status = WiFi.status();
switch (Wifi.status) {
case WL_CONNECTED:
@ -408,8 +408,8 @@ void WifiCheckIp(void)
break;
case WL_NO_SSID_AVAIL:
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CONNECT_FAILED_AP_NOT_REACHED));
Settings.wifi_channel = 0; // Disable stored AP
if (WIFI_WAIT == Settings.sta_config) {
Settings->wifi_channel = 0; // Disable stored AP
if (WIFI_WAIT == Settings->sta_config) {
Wifi.retry = Wifi.retry_init;
} else {
if (Wifi.retry > (Wifi.retry_init / 2)) {
@ -422,7 +422,7 @@ void WifiCheckIp(void)
break;
case WL_CONNECT_FAILED:
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CONNECT_FAILED_WRONG_PASSWORD));
Settings.wifi_channel = 0; // Disable stored AP
Settings->wifi_channel = 0; // Disable stored AP
if (Wifi.retry > (Wifi.retry_init / 2)) {
Wifi.retry = Wifi.retry_init / 2;
}
@ -433,10 +433,10 @@ void WifiCheckIp(void)
default: // WL_IDLE_STATUS and WL_DISCONNECTED
if (!Wifi.retry || ((Wifi.retry_init / 2) == Wifi.retry)) {
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CONNECT_FAILED_AP_TIMEOUT));
Settings.wifi_channel = 0; // Disable stored AP
Settings->wifi_channel = 0; // Disable stored AP
} else {
if (!strlen(SettingsText(SET_STASSID1)) && !strlen(SettingsText(SET_STASSID2))) {
Settings.wifi_channel = 0; // Disable stored AP
Settings->wifi_channel = 0; // Disable stored AP
wifi_config_tool = WIFI_MANAGER; // Skip empty SSIDs and start Wifi config tool
Wifi.retry = 0;
} else {
@ -445,15 +445,15 @@ void WifiCheckIp(void)
}
}
if (Wifi.retry) {
if (Settings.flag3.use_wifi_scan) { // SetOption56 - Scan wifi network at restart for configured AP's
if (Settings->flag3.use_wifi_scan) { // SetOption56 - Scan wifi network at restart for configured AP's
if (Wifi.retry_init == Wifi.retry) {
Wifi.scan_state = 1; // Select scanned SSID
}
} else {
if (Wifi.retry_init == Wifi.retry) {
WifiBegin(3, Settings.wifi_channel); // Select default SSID
WifiBegin(3, Settings->wifi_channel); // Select default SSID
}
if ((Settings.sta_config != WIFI_WAIT) && ((Wifi.retry_init / 2) == Wifi.retry)) {
if ((Settings->sta_config != WIFI_WAIT) && ((Wifi.retry_init / 2) == Wifi.retry)) {
WifiBegin(2, 0); // Select alternate SSID
}
}
@ -487,7 +487,7 @@ void WifiCheck(uint8_t param)
if (strlen(WiFi.psk().c_str())) {
SettingsUpdateText(SET_STAPWD1, WiFi.psk().c_str());
}
Settings.sta_active = 0;
Settings->sta_active = 0;
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_WCFG_2_WIFIMANAGER D_CMND_SSID "1 %s"), SettingsText(SET_STASSID1));
}
}
@ -505,7 +505,7 @@ void WifiCheck(uint8_t param)
}
if ((WL_CONNECTED == WiFi.status()) && WifiCheck_hasIP(WiFi.localIP()) && !Wifi.config_type) {
WifiSetState(1);
if (Settings.flag3.use_wifi_rescan) { // SetOption57 - Scan wifi network every 44 minutes for configured AP's
if (Settings->flag3.use_wifi_rescan) { // SetOption57 - Scan wifi network every 44 minutes for configured AP's
if (!(TasmotaGlobal.uptime % (60 * WIFI_RESCAN_MINUTES))) {
Wifi.scan_state = 2;
}
@ -530,13 +530,13 @@ int WifiState(void)
String WifiGetOutputPower(void)
{
char stemp1[TOPSZ];
dtostrfd((float)(Settings.wifi_output_power) / 10, 1, stemp1);
dtostrfd((float)(Settings->wifi_output_power) / 10, 1, stemp1);
return String(stemp1);
}
void WifiSetOutputPower(void)
{
WiFi.setOutputPower((float)(Settings.wifi_output_power) / 10);
WiFi.setOutputPower((float)(Settings->wifi_output_power) / 10);
}
/*
@ -571,7 +571,7 @@ void WifiEnable(void) {
void WifiConnect(void)
{
if (!Settings.flag4.network_wifi) { return; }
if (!Settings->flag4.network_wifi) { return; }
WifiSetState(0);
WifiSetOutputPower();
@ -581,7 +581,7 @@ void WifiConnect(void)
Wifi.retry = Wifi.retry_init;
Wifi.counter = 1;
memcpy((void*) &Wifi.bssid, (void*) Settings.wifi_bssid, sizeof(Wifi.bssid));
memcpy((void*) &Wifi.bssid, (void*) Settings->wifi_bssid, sizeof(Wifi.bssid));
#ifdef WIFI_RF_PRE_INIT
if (rf_pre_init_flag) {
@ -601,7 +601,7 @@ void WifiShutdown(bool option = false)
delay(100); // Flush anything in the network buffers.
#endif // USE_EMULATION
if (Settings.flag.mqtt_enabled) { // SetOption3 - Enable MQTT
if (Settings->flag.mqtt_enabled) { // SetOption3 - Enable MQTT
MqttDisconnect();
delay(100); // Flush anything in the network buffers.
}
@ -687,7 +687,7 @@ void stationKeepAliveNow(void) {
void wifiKeepAlive(void) {
static uint32_t wifi_timer = millis(); // Wifi keepalive timer
uint32_t wifiTimerSec = Settings.param[P_ARP_GRATUITOUS]; // 8-bits number of seconds, or minutes if > 100
uint32_t wifiTimerSec = Settings->param[P_ARP_GRATUITOUS]; // 8-bits number of seconds, or minutes if > 100
if ((WL_CONNECTED != Wifi.status) || (0 == wifiTimerSec)) { return; } // quick exit if wifi not connected or feature disabled

View File

@ -102,7 +102,7 @@ struct {
GpioOptionABits gpio_optiona; // GPIO Option_A flags
void *log_buffer_mutex; // Control access to log buffer
power_t power; // Current copy of Settings.power
power_t power; // Current copy of Settings->power
power_t rel_inverted; // Relay inverted flag (1 = (0 = On, 1 = Off))
power_t last_power; // Last power set state
power_t blink_power; // Blink power state
@ -154,7 +154,7 @@ struct {
uint8_t state_250mS; // State 250msecond per second flag
uint8_t latching_relay_pulse; // Latching relay pulse timer
uint8_t active_device; // Active device in ExecuteCommandPower
uint8_t sleep; // Current copy of Settings.sleep
uint8_t sleep; // Current copy of Settings->sleep
uint8_t leds_present; // Max number of LED supported
uint8_t led_inverted; // LED inverted flag (1 = (0 = On, 1 = Off))
uint8_t led_power; // LED power state
@ -166,10 +166,10 @@ struct {
uint8_t serial_in_byte; // Received byte
uint8_t devices_present; // Max number of devices supported
uint8_t masterlog_level; // Master log level used to override set log level
uint8_t seriallog_level; // Current copy of Settings.seriallog_level
uint8_t syslog_level; // Current copy of Settings.syslog_level
uint8_t seriallog_level; // Current copy of Settings->seriallog_level
uint8_t syslog_level; // Current copy of Settings->syslog_level
uint8_t templog_level; // Temporary log level to be used by HTTP cm and Telegram
uint8_t module_type; // Current copy of Settings.module or user template type
uint8_t module_type; // Current copy of Settings->module or user template type
uint8_t last_source; // Last command source
uint8_t shutters_present; // Number of actual define shutters
uint8_t discovery_counter; // Delayed discovery counter
@ -195,7 +195,7 @@ struct {
#ifdef ESP8266
#ifdef PIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM48_SECHEAP_SHARED
char* log_buffer; // Log buffer in IRAM
char* log_buffer = nullptr; // Log buffer in IRAM
#else
char log_buffer[LOG_BUFFER_SIZE]; // Log buffer in DRAM
#endif // PIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM48_SECHEAP_SHARED
@ -204,6 +204,8 @@ struct {
#endif // ESP8266
} TasmotaGlobal;
TSettings* Settings = nullptr;
#ifdef SUPPORT_IF_STATEMENT
#include <LinkedList.h>
LinkedList<String> backlog; // Command backlog implemented with LinkedList
@ -260,9 +262,11 @@ void setup(void) {
// Serial.setRxBufferSize(INPUT_BUFFER_SIZE); // Default is 256 chars
TasmotaGlobal.seriallog_level = LOG_LEVEL_INFO; // Allow specific serial messages until config loaded
#ifdef ESP8266
#ifdef PIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM48_SECHEAP_SHARED
ESP.setIramHeap();
Settings = (TSettings*)malloc(sizeof(TSettings)); // Allocate in "new" 16k heap space
TasmotaGlobal.log_buffer = (char*)malloc(LOG_BUFFER_SIZE); // Allocate in "new" 16k heap space
ESP.resetHeap();
if (TasmotaGlobal.log_buffer == nullptr) {
@ -273,6 +277,9 @@ void setup(void) {
}
#endif // PIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM48_SECHEAP_SHARED
#endif // ESP8266
if (Settings == nullptr) {
Settings = (TSettings*)malloc(sizeof(TSettings));
}
AddLog(LOG_LEVEL_INFO, PSTR("HDW: %s"), GetDeviceHardware().c_str());
@ -285,15 +292,15 @@ void setup(void) {
OsWatchInit();
TasmotaGlobal.seriallog_level = Settings.seriallog_level;
TasmotaGlobal.syslog_level = Settings.syslog_level;
TasmotaGlobal.seriallog_level = Settings->seriallog_level;
TasmotaGlobal.syslog_level = Settings->syslog_level;
TasmotaGlobal.module_changed = (Settings.module != Settings.last_module);
TasmotaGlobal.module_changed = (Settings->module != Settings->last_module);
if (TasmotaGlobal.module_changed) {
Settings.baudrate = APP_BAUDRATE / 300;
Settings.serial_config = TS_SERIAL_8N1;
Settings->baudrate = APP_BAUDRATE / 300;
Settings->serial_config = TS_SERIAL_8N1;
}
SetSerialBaudrate(Settings.baudrate * 300); // Reset serial interface if current baudrate is different from requested baudrate
SetSerialBaudrate(Settings->baudrate * 300); // Reset serial interface if current baudrate is different from requested baudrate
if (1 == RtcReboot.fast_reboot_count) { // Allow setting override only when all is well
UpdateQuickPowerCycle(true);
@ -301,54 +308,54 @@ void setup(void) {
if (ResetReason() != REASON_DEEP_SLEEP_AWAKE) {
#ifdef ESP8266
Settings.flag4.network_wifi = 1; // Make sure we're in control
Settings->flag4.network_wifi = 1; // Make sure we're in control
#endif
#ifdef ESP32
if (!Settings.flag4.network_ethernet) {
Settings.flag4.network_wifi = 1; // Make sure we're in control
if (!Settings->flag4.network_ethernet) {
Settings->flag4.network_wifi = 1; // Make sure we're in control
}
#endif
}
TasmotaGlobal.stop_flash_rotate = Settings.flag.stop_flash_rotate; // SetOption12 - Switch between dynamic or fixed slot flash save location
TasmotaGlobal.save_data_counter = Settings.save_data;
TasmotaGlobal.sleep = Settings.sleep;
TasmotaGlobal.stop_flash_rotate = Settings->flag.stop_flash_rotate; // SetOption12 - Switch between dynamic or fixed slot flash save location
TasmotaGlobal.save_data_counter = Settings->save_data;
TasmotaGlobal.sleep = Settings->sleep;
#ifndef USE_EMULATION
Settings.flag2.emulation = 0;
Settings->flag2.emulation = 0;
#else
#ifndef USE_EMULATION_WEMO
if (EMUL_WEMO == Settings.flag2.emulation) { Settings.flag2.emulation = 0; }
if (EMUL_WEMO == Settings->flag2.emulation) { Settings->flag2.emulation = 0; }
#endif
#ifndef USE_EMULATION_HUE
if (EMUL_HUE == Settings.flag2.emulation) { Settings.flag2.emulation = 0; }
if (EMUL_HUE == Settings->flag2.emulation) { Settings->flag2.emulation = 0; }
#endif
#endif // USE_EMULATION
// AddLogBuffer(LOG_LEVEL_DEBUG, (uint8_t*)&TasmotaGlobal, sizeof(TasmotaGlobal));
if (Settings.param[P_BOOT_LOOP_OFFSET]) { // SetOption36
if (Settings->param[P_BOOT_LOOP_OFFSET]) { // SetOption36
// Disable functionality as possible cause of fast restart within BOOT_LOOP_TIME seconds (Exception, WDT or restarts)
if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET]) { // Restart twice
Settings.flag3.user_esp8285_enable = 0; // SetOption51 - Enable ESP8285 user GPIO's - Disable ESP8285 Generic GPIOs interfering with flash SPI
if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET] +1) { // Restart 3 times
if (RtcReboot.fast_reboot_count > Settings->param[P_BOOT_LOOP_OFFSET]) { // Restart twice
Settings->flag3.user_esp8285_enable = 0; // SetOption51 - Enable ESP8285 user GPIO's - Disable ESP8285 Generic GPIOs interfering with flash SPI
if (RtcReboot.fast_reboot_count > Settings->param[P_BOOT_LOOP_OFFSET] +1) { // Restart 3 times
for (uint32_t i = 0; i < MAX_RULE_SETS; i++) {
if (bitRead(Settings.rule_stop, i)) {
bitWrite(Settings.rule_enabled, i, 0); // Disable rules causing boot loop
if (bitRead(Settings->rule_stop, i)) {
bitWrite(Settings->rule_enabled, i, 0); // Disable rules causing boot loop
}
}
}
if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET] +2) { // Restarted 4 times
Settings.rule_enabled = 0; // Disable all rules
if (RtcReboot.fast_reboot_count > Settings->param[P_BOOT_LOOP_OFFSET] +2) { // Restarted 4 times
Settings->rule_enabled = 0; // Disable all rules
TasmotaGlobal.no_autoexec = true;
}
if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET] +3) { // Restarted 5 times
for (uint32_t i = 0; i < nitems(Settings.my_gp.io); i++) {
Settings.my_gp.io[i] = GPIO_NONE; // Reset user defined GPIO disabling sensors
if (RtcReboot.fast_reboot_count > Settings->param[P_BOOT_LOOP_OFFSET] +3) { // Restarted 5 times
for (uint32_t i = 0; i < nitems(Settings->my_gp.io); i++) {
Settings->my_gp.io[i] = GPIO_NONE; // Reset user defined GPIO disabling sensors
}
}
if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET] +4) { // Restarted 6 times
Settings.module = Settings.fallback_module; // Reset module to fallback module
// Settings.last_module = Settings.fallback_module;
if (RtcReboot.fast_reboot_count > Settings->param[P_BOOT_LOOP_OFFSET] +4) { // Restarted 6 times
Settings->module = Settings->fallback_module; // Reset module to fallback module
// Settings->last_module = Settings->fallback_module;
}
AddLog(LOG_LEVEL_INFO, PSTR("FRC: " D_LOG_SOME_SETTINGS_RESET " (%d)"), RtcReboot.fast_reboot_count);
}
@ -402,7 +409,7 @@ void setup(void) {
XdrvCall(FUNC_INIT);
XsnsCall(FUNC_INIT);
#ifdef USE_SCRIPT
if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">BS",3,0);
if (bitRead(Settings->rule_enabled, 0)) Run_Scripter(">BS",3,0);
#endif
TasmotaGlobal.rules_flag.system_init = 1;
@ -524,7 +531,7 @@ void loop(void) {
uint32_t my_activity = millis() - my_sleep;
if (Settings.flag3.sleep_normal) { // SetOption60 - Enable normal sleep instead of dynamic sleep
if (Settings->flag3.sleep_normal) { // SetOption60 - Enable normal sleep instead of dynamic sleep
// yield(); // yield == delay(0), delay contains yield, auto yield in loop
SleepDelay(TasmotaGlobal.sleep); // https://github.com/esp8266/Arduino/issues/2021
} else {

View File

@ -254,7 +254,7 @@ String EthernetMacAddress(void);
#define FS_FILE_APPEND "a"
#define TASM_FILE_SETTINGS "/.settings" // Settings binary blob
#define TASM_FILE_SETTINGS_LKG "/.settings.lkg" // Last Known Good Settings binary blob
#define TASM_FILE_SETTINGS_LKG "/.Settings->lkg" // Last Known Good Settings binary blob
#define TASM_FILE_DRIVER "/.drvset%03d"
#define TASM_FILE_SENSOR "/.snsset%03d"
#define TASM_FILE_TLSKEY "/tlskey" // TLS private key

View File

@ -536,7 +536,7 @@ void WebServer_on(const char * prefix, void (*func)(void), uint8_t method = HTTP
void StartWebserver(int type, IPAddress ipweb)
{
if (!Settings.web_refresh) { Settings.web_refresh = HTTP_REFRESH_TIME; }
if (!Settings->web_refresh) { Settings->web_refresh = HTTP_REFRESH_TIME; }
if (!Web.state) {
if (!Webserver) {
Webserver = new ESP8266WebServer((HTTP_MANAGER == type || HTTP_MANAGER_RESET_ONLY == type) ? 80 : WEB_PORT);
@ -815,9 +815,9 @@ void WSContentSendStyle_P(const char* formatP, ...)
// SetOption53 - Show hostname and IP address in GUI main menu
#if (RESTART_AFTER_INITIAL_WIFI_CONFIG)
if (Settings.flag3.gui_hostname_ip) {
if (Settings->flag3.gui_hostname_ip) {
#else
if ( Settings.flag3.gui_hostname_ip || ( (WiFi.getMode() == WIFI_AP_STA) && (!Web.initial_config) ) ) {
if ( Settings->flag3.gui_hostname_ip || ( (WiFi.getMode() == WIFI_AP_STA) && (!Web.initial_config) ) ) {
#endif
bool lip = (static_cast<uint32_t>(WiFi.localIP()) != 0);
bool sip = (static_cast<uint32_t>(WiFi.softAPIP()) != 0);
@ -868,15 +868,15 @@ void WSContentSpaceButton(uint32_t title_index, bool show=true)
}
void WSContentSend_Temp(const char *types, float f_temperature) {
WSContentSend_PD(HTTP_SNS_F_TEMP, types, Settings.flag2.temperature_resolution, &f_temperature, TempUnit());
WSContentSend_PD(HTTP_SNS_F_TEMP, types, Settings->flag2.temperature_resolution, &f_temperature, TempUnit());
}
void WSContentSend_Voltage(const char *types, float f_voltage) {
WSContentSend_PD(HTTP_SNS_F_VOLTAGE, types, Settings.flag2.voltage_resolution, &f_voltage);
WSContentSend_PD(HTTP_SNS_F_VOLTAGE, types, Settings->flag2.voltage_resolution, &f_voltage);
}
void WSContentSend_CurrentMA(const char *types, float f_current) {
WSContentSend_PD(HTTP_SNS_F_CURRENT_MA, types, Settings.flag2.current_resolution, &f_current);
WSContentSend_PD(HTTP_SNS_F_CURRENT_MA, types, Settings->flag2.current_resolution, &f_current);
}
void WSContentSend_THD(const char *types, float f_temperature, float f_humidity)
@ -884,9 +884,9 @@ void WSContentSend_THD(const char *types, float f_temperature, float f_humidity)
WSContentSend_Temp(types, f_temperature);
char parameter[FLOATSZ];
dtostrfd(f_humidity, Settings.flag2.humidity_resolution, parameter);
dtostrfd(f_humidity, Settings->flag2.humidity_resolution, parameter);
WSContentSend_PD(HTTP_SNS_HUM, types, parameter);
dtostrfd(CalcTempHumToDew(f_temperature, f_humidity), Settings.flag2.temperature_resolution, parameter);
dtostrfd(CalcTempHumToDew(f_temperature, f_humidity), Settings->flag2.temperature_resolution, parameter);
WSContentSend_PD(HTTP_SNS_DEW, types, parameter, TempUnit());
}
@ -1057,9 +1057,9 @@ void HandleRoot(void)
WSContentStart_P(PSTR(D_MAIN_MENU));
#ifdef USE_SCRIPT_WEB_DISPLAY
WSContentSend_P(HTTP_SCRIPT_ROOT, Settings.web_refresh, Settings.web_refresh);
WSContentSend_P(HTTP_SCRIPT_ROOT, Settings->web_refresh, Settings->web_refresh);
#else
WSContentSend_P(HTTP_SCRIPT_ROOT, Settings.web_refresh);
WSContentSend_P(HTTP_SCRIPT_ROOT, Settings->web_refresh);
#endif
WSContentSend_P(HTTP_SCRIPT_ROOT_PART2);
@ -1070,7 +1070,7 @@ void HandleRoot(void)
#ifdef USE_LIGHT
if (TasmotaGlobal.light_type) {
uint8_t light_subtype = TasmotaGlobal.light_type &7;
if (!Settings.flag3.pwm_multi_channels) { // SetOption68 0 - Enable multi-channels PWM instead of Color PWM
if (!Settings->flag3.pwm_multi_channels) { // SetOption68 0 - Enable multi-channels PWM instead of Color PWM
bool split_white = ((LST_RGBW <= light_subtype) && (TasmotaGlobal.devices_present > 1)); // Only on RGBW or RGBCW and SetOption37 128
if ((LST_COLDWARM == light_subtype) || ((LST_RGBCW == light_subtype) && !split_white)) {
@ -1090,7 +1090,7 @@ void HandleRoot(void)
hue,
'h', 0); // h0 - Value id
uint8_t dcolor = changeUIntScale(Settings.light_dimmer, 0, 100, 0, 255);
uint8_t dcolor = changeUIntScale(Settings->light_dimmer, 0, 100, 0, 255);
char scolor[8];
snprintf_P(scolor, sizeof(scolor), PSTR("#%02X%02X%02X"), dcolor, dcolor, dcolor); // Saturation start color from Black to White
uint8_t red, green, blue;
@ -1110,8 +1110,8 @@ void HandleRoot(void)
PSTR("c"), // c - Unique HTML id
PSTR("#000"), PSTR("#fff"), // Black to White
4, // sl4 - Unique range HTML id - Used as source for Saturation begin color
Settings.flag3.slider_dimmer_stay_on, 100, // Range 0/1 to 100% (SetOption77 - Do not power off if slider moved to far left)
Settings.light_dimmer,
Settings->flag3.slider_dimmer_stay_on, 100, // Range 0/1 to 100% (SetOption77 - Do not power off if slider moved to far left)
Settings->light_dimmer,
'd', 0); // d0 - Value id is related to lc("d0", value) and WebGetArg("d0", tmp, sizeof(tmp));
if (split_white) { // SetOption37 128
@ -1122,11 +1122,11 @@ void HandleRoot(void)
PSTR("f"), // f - Unique HTML id
PSTR("#000"), PSTR("#fff"), // Black to White
5, // sl5 - Unique range HTML id - Not used
Settings.flag3.slider_dimmer_stay_on, 100, // Range 0/1 to 100% (SetOption77 - Do not power off if slider moved to far left)
Settings->flag3.slider_dimmer_stay_on, 100, // Range 0/1 to 100% (SetOption77 - Do not power off if slider moved to far left)
LightGetDimmer(2),
'w', 0); // w0 - Value id is related to lc("w0", value) and WebGetArg("w0", tmp, sizeof(tmp));
}
} else { // Settings.flag3.pwm_multi_channels - SetOption68 1 - Enable multi-channels PWM instead of Color PWM
} else { // Settings->flag3.pwm_multi_channels - SetOption68 1 - Enable multi-channels PWM instead of Color PWM
uint32_t pwm_channels = light_subtype > LST_MAX ? LST_MAX : light_subtype;
stemp[0] = 'e'; stemp[1] = '0'; stemp[2] = '\0'; // d0
for (uint32_t i = 0; i < pwm_channels; i++) {
@ -1137,16 +1137,16 @@ void HandleRoot(void)
PSTR("#000"), PSTR("#fff"), // Black to White
i+1, // sl1 to sl5 - Unique range HTML id - Not used
1, 100, // Range 1 to 100%
changeUIntScale(Settings.light_color[i], 0, 255, 0, 100),
changeUIntScale(Settings->light_color[i], 0, 255, 0, 100),
'e', i+1); // e1 to e5 - Value id
}
} // Settings.flag3.pwm_multi_channels
} // Settings->flag3.pwm_multi_channels
}
#endif // USE_LIGHT
#ifdef USE_SHUTTER
if (Settings.flag3.shutter_mode) { // SetOption80 - Enable shutter support
if (Settings->flag3.shutter_mode) { // SetOption80 - Enable shutter support
for (uint32_t i = 0; i < TasmotaGlobal.shutters_present; i++) {
WSContentSend_P(HTTP_MSG_SLIDER_SHUTTER, Settings.shutter_position[i], i+1);
WSContentSend_P(HTTP_MSG_SLIDER_SHUTTER, Settings->shutter_position[i], i+1);
}
}
#endif // USE_SHUTTER
@ -1172,7 +1172,7 @@ void HandleRoot(void)
int32_t ShutterWebButton;
if (ShutterWebButton = IsShutterWebButton(idx)) {
WSContentSend_P(HTTP_DEVICE_CONTROL, 100 / cols, idx,
(set_button) ? SettingsText(SET_BUTTON1 + idx -1) : ((Settings.shutter_options[abs(ShutterWebButton)-1] & 2) /* is locked */ ? "-" : ((Settings.shutter_options[abs(ShutterWebButton)-1] & 8) /* invert web buttons */ ? ((ShutterWebButton>0) ? "&#9660;" : "&#9650;") : ((ShutterWebButton>0) ? "&#9650;" : "&#9660;"))),
(set_button) ? SettingsText(SET_BUTTON1 + idx -1) : ((Settings->shutter_options[abs(ShutterWebButton)-1] & 2) /* is locked */ ? "-" : ((Settings->shutter_options[abs(ShutterWebButton)-1] & 8) /* invert web buttons */ ? ((ShutterWebButton>0) ? "&#9660;" : "&#9650;") : ((ShutterWebButton>0) ? "&#9650;" : "&#9660;"))),
"");
} else {
#endif // USE_SHUTTER
@ -1421,10 +1421,10 @@ bool HandleRootStatusRefresh(void)
int32_t IsShutterWebButton(uint32_t idx) {
/* 0: Not a shutter, 1..4: shutter up idx, -1..-4: shutter down idx */
int32_t ShutterWebButton = 0;
if (Settings.flag3.shutter_mode) { // SetOption80 - Enable shutter support
if (Settings->flag3.shutter_mode) { // SetOption80 - Enable shutter support
for (uint32_t i = 0; i < MAX_SHUTTERS; i++) {
if (Settings.shutter_startrelay[i] && ((Settings.shutter_startrelay[i] == idx) || (Settings.shutter_startrelay[i] == (idx-1)))) {
ShutterWebButton = (Settings.shutter_startrelay[i] == idx) ? (i+1): (-1-i);
if (Settings->shutter_startrelay[i] && ((Settings->shutter_startrelay[i] == idx) || (Settings->shutter_startrelay[i] == (idx-1)))) {
ShutterWebButton = (Settings->shutter_startrelay[i] == idx) ? (i+1): (-1-i);
break;
}
}
@ -1537,12 +1537,12 @@ void HandleTemplateConfiguration(void) {
WebGetArg(PSTR("t"), stemp, sizeof(stemp)); // 0 - 69 Template number
if (strlen(stemp)) {
uint32_t module = atoi(stemp);
uint32_t module_save = Settings.module;
Settings.module = module;
uint32_t module_save = Settings->module;
Settings->module = module;
myio template_gp;
TemplateGpios(&template_gp);
gpio_flag flag = ModuleFlag();
Settings.module = module_save;
Settings->module = module_save;
WSContentBegin(200, CT_PLAIN);
WSContentSend_P(PSTR("%s}1"), AnyModuleName(module).c_str()); // NAME: Generic
@ -1551,7 +1551,7 @@ void HandleTemplateConfiguration(void) {
WSContentSend_P(PSTR("%s%d"), (i>0)?",":"", template_gp.io[i]);
}
}
WSContentSend_P(PSTR("}1%d}1%d"), flag, Settings.user_template_base); // FLAG: 1 BASE: 17
WSContentSend_P(PSTR("}1%d}1%d"), flag, Settings->user_template_base); // FLAG: 1 BASE: 17
WSContentEnd();
return;
}
@ -1631,7 +1631,7 @@ void TemplateSaveSettings(void) {
snprintf_P(command, sizeof(command), PSTR(D_CMND_TEMPLATE " {\"" D_JSON_NAME "\":\"%s\",\"" D_JSON_GPIO "\":["), tmp);
uint32_t j = 0;
for (uint32_t i = 0; i < nitems(Settings.user_template.gp.io); i++) {
for (uint32_t i = 0; i < nitems(Settings->user_template.gp.io); i++) {
if (6 == i) { j = 9; }
if (8 == i) { j = 12; }
snprintf_P(command, sizeof(command), PSTR("%s%s%d"), command, (i>0)?",":"", WebGetGpioArg(j));
@ -1685,7 +1685,7 @@ void HandleModuleConfiguration(void) {
}
WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE_INDEX, midx, AnyModuleName(midx).c_str(), vidx);
}
WSContentSend_P(PSTR("\";sk(%d,99);os=\""), Settings.module);
WSContentSend_P(PSTR("\";sk(%d,99);os=\""), Settings->module);
WSContentSendNiceLists(0);
@ -1698,7 +1698,7 @@ void HandleModuleConfiguration(void) {
#ifdef ESP8266
#ifdef USE_ADC
WSContentSendAdcNiceList(0);
WSContentSend_P(PSTR("\";sk(%d," STR(ADC0_PIN) ");"), Settings.my_gp.io[(sizeof(myio) / 2) -1]);
WSContentSend_P(PSTR("\";sk(%d," STR(ADC0_PIN) ");"), Settings->my_gp.io[(sizeof(myio) / 2) -1]);
#endif // USE_ADC
#endif // ESP8266
@ -1724,17 +1724,17 @@ void ModuleSaveSettings(void) {
char tmp[8]; // WebGetArg numbers only
WebGetArg(PSTR("g99"), tmp, sizeof(tmp)); // Module
uint32_t new_module = (!strlen(tmp)) ? MODULE : atoi(tmp);
Settings.last_module = Settings.module;
Settings.module = new_module;
Settings->last_module = Settings->module;
Settings->module = new_module;
SetModuleType();
myio template_gp;
TemplateGpios(&template_gp);
for (uint32_t i = 0; i < nitems(template_gp.io); i++) {
if (Settings.last_module != new_module) {
Settings.my_gp.io[i] = GPIO_NONE;
if (Settings->last_module != new_module) {
Settings->my_gp.io[i] = GPIO_NONE;
} else {
if (ValidGPIO(i, template_gp.io[i])) {
Settings.my_gp.io[i] = WebGetGpioArg(i); // Gpio
Settings->my_gp.io[i] = WebGetGpioArg(i); // Gpio
}
}
}
@ -1780,10 +1780,10 @@ void HandleWifiConfiguration(void) {
Web.save_data_counter = TasmotaGlobal.save_data_counter;
TasmotaGlobal.save_data_counter = 0; // Stop auto saving data - Updating Settings
Settings.save_data = 0;
Settings->save_data = 0;
if (MAX_WIFI_OPTION == Web.old_wificonfig) { Web.old_wificonfig = Settings.sta_config; }
TasmotaGlobal.wifi_state_flag = Settings.sta_config = WIFI_MANAGER;
if (MAX_WIFI_OPTION == Web.old_wificonfig) { Web.old_wificonfig = Settings->sta_config; }
TasmotaGlobal.wifi_state_flag = Settings->sta_config = WIFI_MANAGER;
TasmotaGlobal.sleep = 0; // Disable sleep
TasmotaGlobal.restart_flag = 0; // No restart
@ -2031,8 +2031,8 @@ void HandleLoggingConfiguration(void) {
char stemp2[32];
uint8_t dlevel[4] = { LOG_LEVEL_INFO, LOG_LEVEL_INFO, LOG_LEVEL_NONE, LOG_LEVEL_NONE };
for (uint32_t idx = 0; idx < 4; idx++) {
if ((2==idx) && !Settings.flag.mqtt_enabled) { continue; } // SetOption3 - Enable MQTT
uint32_t llevel = (0==idx)?Settings.seriallog_level:(1==idx)?Settings.weblog_level:(2==idx)?Settings.mqttlog_level:Settings.syslog_level;
if ((2==idx) && !Settings->flag.mqtt_enabled) { continue; } // SetOption3 - Enable MQTT
uint32_t llevel = (0==idx)?Settings->seriallog_level:(1==idx)?Settings->weblog_level:(2==idx)?Settings->mqttlog_level:Settings->syslog_level;
WSContentSend_P(PSTR("<p><b>%s</b> (%s)<br><select id='l%d'>"),
GetTextIndexed(stemp1, sizeof(stemp1), idx, kLoggingOptions),
GetTextIndexed(stemp2, sizeof(stemp2), dlevel[idx], kLoggingLevels),
@ -2044,7 +2044,7 @@ void HandleLoggingConfiguration(void) {
}
WSContentSend_P(PSTR("</select></p>"));
}
WSContentSend_P(HTTP_FORM_LOG2, SettingsText(SET_SYSLOG_HOST), Settings.syslog_port, Settings.tele_period);
WSContentSend_P(HTTP_FORM_LOG2, SettingsText(SET_SYSLOG_HOST), Settings->syslog_port, Settings->tele_period);
WSContentSend_P(HTTP_FORM_END);
WSContentSpaceButton(BUTTON_CONFIGURATION);
WSContentStop();
@ -2080,11 +2080,11 @@ void HandleOtherConfiguration(void) {
TemplateJson();
#ifdef MQTT_DATA_STRING
WSContentSend_P(HTTP_FORM_OTHER, TasmotaGlobal.mqtt_data.c_str(), (USER_MODULE == Settings.module) ? PSTR(" checked disabled") : "",
WSContentSend_P(HTTP_FORM_OTHER, TasmotaGlobal.mqtt_data.c_str(), (USER_MODULE == Settings->module) ? PSTR(" checked disabled") : "",
#else
WSContentSend_P(HTTP_FORM_OTHER, TasmotaGlobal.mqtt_data, (USER_MODULE == Settings.module) ? PSTR(" checked disabled") : "",
WSContentSend_P(HTTP_FORM_OTHER, TasmotaGlobal.mqtt_data, (USER_MODULE == Settings->module) ? PSTR(" checked disabled") : "",
#endif
(Settings.flag.mqtt_enabled) ? PSTR(" checked") : "", // SetOption3 - Enable MQTT
(Settings->flag.mqtt_enabled) ? PSTR(" checked") : "", // SetOption3 - Enable MQTT
SettingsText(SET_FRIENDLYNAME1), SettingsText(SET_DEVICENAME));
char stemp[32];
@ -2115,7 +2115,7 @@ void HandleOtherConfiguration(void) {
if (i < EMUL_MAX) {
WSContentSend_P(PSTR("<input id='r%d' name='b2' type='radio' value='%d'%s><b>%s</b> %s<br>"), // Different id only used for labels
i, i,
(i == Settings.flag2.emulation) ? PSTR(" checked") : "",
(i == Settings->flag2.emulation) ? PSTR(" checked") : "",
GetTextIndexed(stemp, sizeof(stemp), i, kEmulationOptions),
(i == EMUL_NONE) ? "" : (i == EMUL_WEMO) ? PSTR(D_SINGLE_DEVICE) : PSTR(D_MULTI_DEVICE));
}
@ -2243,12 +2243,12 @@ void HandleInformation(void)
WSContentSend_P(PSTR("}1" D_CORE_AND_SDK_VERSION "}2" ARDUINO_CORE_RELEASE "/%s"), ESP.getSdkVersion());
WSContentSend_P(PSTR("}1" D_UPTIME "}2%s"), GetUptime().c_str());
#ifdef ESP8266
WSContentSend_P(PSTR("}1" D_FLASH_WRITE_COUNT "}2%d at 0x%X"), Settings.save_flag, GetSettingsAddress());
WSContentSend_P(PSTR("}1" D_FLASH_WRITE_COUNT "}2%d at 0x%X"), Settings->save_flag, GetSettingsAddress());
#endif // ESP8266
#ifdef ESP32
WSContentSend_P(PSTR("}1" D_FLASH_WRITE_COUNT "}2%d"), Settings.save_flag);
WSContentSend_P(PSTR("}1" D_FLASH_WRITE_COUNT "}2%d"), Settings->save_flag);
#endif // ESP32
WSContentSend_P(PSTR("}1" D_BOOT_COUNT "}2%d"), Settings.bootcount);
WSContentSend_P(PSTR("}1" D_BOOT_COUNT "}2%d"), Settings->bootcount);
WSContentSend_P(PSTR("}1" D_RESTART_REASON "}2%s"), GetResetReason().c_str());
uint32_t maxfn = (TasmotaGlobal.devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : TasmotaGlobal.devices_present;
#ifdef USE_SONOFF_IFAN
@ -2268,9 +2268,9 @@ void HandleInformation(void)
}
#endif
#endif
if (Settings.flag4.network_wifi) {
if (Settings->flag4.network_wifi) {
int32_t rssi = WiFi.RSSI();
WSContentSend_P(PSTR("}1" D_AP "%d " D_SSID " (" D_RSSI ")}2%s (%d%%, %d dBm) 11%c"), Settings.sta_active +1, HtmlEscape(SettingsText(SET_STASSID1 + Settings.sta_active)).c_str(), WifiGetRssiAsQuality(rssi), rssi, pgm_read_byte(&kWifiPhyMode[WiFi.getPhyMode() & 0x3]) );
WSContentSend_P(PSTR("}1" D_AP "%d " D_SSID " (" D_RSSI ")}2%s (%d%%, %d dBm) 11%c"), Settings->sta_active +1, HtmlEscape(SettingsText(SET_STASSID1 + Settings->sta_active)).c_str(), WifiGetRssiAsQuality(rssi), rssi, pgm_read_byte(&kWifiPhyMode[WiFi.getPhyMode() & 0x3]) );
WSContentSend_P(PSTR("}1" D_HOSTNAME "}2%s%s"), TasmotaGlobal.hostname, (Mdns.begun) ? PSTR(".local") : "");
#if LWIP_IPV6
String ipv6_addr = WifiGetIPv6();
@ -2285,9 +2285,9 @@ void HandleInformation(void)
}
}
if (!TasmotaGlobal.global_state.network_down) {
WSContentSend_P(PSTR("}1" D_GATEWAY "}2%_I"), Settings.ipv4_address[1]);
WSContentSend_P(PSTR("}1" D_SUBNET_MASK "}2%_I"), Settings.ipv4_address[2]);
WSContentSend_P(PSTR("}1" D_DNS_SERVER "}2%_I"), Settings.ipv4_address[3]);
WSContentSend_P(PSTR("}1" D_GATEWAY "}2%_I"), Settings->ipv4_address[1]);
WSContentSend_P(PSTR("}1" D_SUBNET_MASK "}2%_I"), Settings->ipv4_address[2]);
WSContentSend_P(PSTR("}1" D_DNS_SERVER "}2%_I"), Settings->ipv4_address[3]);
}
if ((WiFi.getMode() >= WIFI_AP) && (static_cast<uint32_t>(WiFi.softAPIP()) != 0)) {
WSContentSend_P(PSTR("}1<hr/>}2<hr/>"));
@ -2296,11 +2296,11 @@ void HandleInformation(void)
WSContentSend_P(PSTR("}1" D_GATEWAY "}2%_I"), (uint32_t)WiFi.softAPIP());
}
WSContentSend_P(PSTR("}1}2&nbsp;")); // Empty line
if (Settings.flag.mqtt_enabled) { // SetOption3 - Enable MQTT
if (Settings->flag.mqtt_enabled) { // SetOption3 - Enable MQTT
WSContentSend_P(PSTR("}1" D_MQTT_HOST "}2%s"), SettingsText(SET_MQTT_HOST));
WSContentSend_P(PSTR("}1" D_MQTT_PORT "}2%d"), Settings.mqtt_port);
WSContentSend_P(PSTR("}1" D_MQTT_PORT "}2%d"), Settings->mqtt_port);
#ifdef USE_MQTT_TLS
WSContentSend_P(PSTR("}1" D_MQTT_TLS_ENABLE "}2%s"), Settings.flag4.mqtt_tls ? PSTR(D_ENABLED) : PSTR(D_DISABLED));
WSContentSend_P(PSTR("}1" D_MQTT_TLS_ENABLE "}2%s"), Settings->flag4.mqtt_tls ? PSTR(D_ENABLED) : PSTR(D_DISABLED));
#endif // USE_MQTT_TLS
WSContentSend_P(PSTR("}1" D_MQTT_USER "}2%s"), SettingsText(SET_MQTT_USER));
WSContentSend_P(PSTR("}1" D_MQTT_CLIENT "}2%s"), TasmotaGlobal.mqtt_client);
@ -2314,7 +2314,7 @@ void HandleInformation(void)
}
WSContentSend_P(PSTR("}1" D_MQTT_FULL_TOPIC "}2%s"), GetTopic_P(stopic, CMND, TasmotaGlobal.mqtt_topic, ""));
WSContentSend_P(PSTR("}1" D_MQTT " " D_FALLBACK_TOPIC "}2%s"), GetFallbackTopic_P(stopic, ""));
WSContentSend_P(PSTR("}1" D_MQTT_NO_RETAIN "}2%s"), Settings.flag4.mqtt_no_retain ? PSTR(D_ENABLED) : PSTR(D_DISABLED));
WSContentSend_P(PSTR("}1" D_MQTT_NO_RETAIN "}2%s"), Settings->flag4.mqtt_no_retain ? PSTR(D_ENABLED) : PSTR(D_DISABLED));
} else {
WSContentSend_P(PSTR("}1" D_MQTT "}2" D_DISABLED));
}
@ -2323,11 +2323,11 @@ void HandleInformation(void)
WSContentSend_P(PSTR("}1}2&nbsp;")); // Empty line
#endif // USE_EMULATION or USE_DISCOVERY
#ifdef USE_EMULATION
WSContentSend_P(PSTR("}1" D_EMULATION "}2%s"), GetTextIndexed(stopic, sizeof(stopic), Settings.flag2.emulation, kEmulationOptions));
WSContentSend_P(PSTR("}1" D_EMULATION "}2%s"), GetTextIndexed(stopic, sizeof(stopic), Settings->flag2.emulation, kEmulationOptions));
#endif // USE_EMULATION
#ifdef USE_DISCOVERY
WSContentSend_P(PSTR("}1" D_MDNS_DISCOVERY "}2%s"), (Settings.flag3.mdns_enabled) ? D_ENABLED : D_DISABLED); // SetOption55 - Control mDNS service
if (Settings.flag3.mdns_enabled) { // SetOption55 - Control mDNS service
WSContentSend_P(PSTR("}1" D_MDNS_DISCOVERY "}2%s"), (Settings->flag3.mdns_enabled) ? D_ENABLED : D_DISABLED); // SetOption55 - Control mDNS service
if (Settings->flag3.mdns_enabled) { // SetOption55 - Control mDNS service
#ifdef WEBSERVER_ADVERTISE
WSContentSend_P(PSTR("}1" D_MDNS_ADVERTISE "}2" D_WEB_SERVER));
#else
@ -2492,7 +2492,7 @@ void HandleUploadDone(void) {
}
WSContentSend_P(error);
DEBUG_CORE_LOG(PSTR("UPL: %s"), error);
TasmotaGlobal.stop_flash_rotate = Settings.flag.stop_flash_rotate; // SetOption12 - Switch between dynamic or fixed slot flash save location
TasmotaGlobal.stop_flash_rotate = Settings->flag.stop_flash_rotate; // SetOption12 - Switch between dynamic or fixed slot flash save location
Web.upload_error = 0;
} else {
WSContentSend_P(PSTR("%06x'>" D_SUCCESSFUL "</font></b><br>"), WebColor(COL_TEXT_SUCCESS));
@ -2548,7 +2548,7 @@ void UploadServices(uint32_t start_service) {
#endif // USE_ARILUX_RF
/*
MqttRetryCounter(60);
if (Settings.flag.mqtt_enabled) { // SetOption3 - Enable MQTT
if (Settings->flag.mqtt_enabled) { // SetOption3 - Enable MQTT
MqttDisconnect();
}
*/
@ -2673,7 +2673,7 @@ void HandleUploadLoop(void) {
} // First block received
if (UPL_SETTINGS == Web.upload_file_type) {
if (upload.currentSize > (sizeof(Settings) - (Web.config_block_count * HTTP_UPLOAD_BUFLEN))) {
if (upload.currentSize > (sizeof(TSettings) - (Web.config_block_count * HTTP_UPLOAD_BUFLEN))) {
Web.upload_error = 9; // File too large
return;
}
@ -2883,7 +2883,7 @@ void HandleConsole(void)
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_CONSOLE));
WSContentStart_P(PSTR(D_CONSOLE));
WSContentSend_P(HTTP_SCRIPT_CONSOL, Settings.web_refresh);
WSContentSend_P(HTTP_SCRIPT_CONSOL, Settings->web_refresh);
WSContentSendStyle();
WSContentSend_P(HTTP_FORM_CMND);
WSContentSpaceButton((WebUseManagementSubmenu()) ? BUTTON_MANAGEMENT : BUTTON_MAIN);
@ -2912,7 +2912,7 @@ void HandleConsoleRefresh(void)
bool cflg = (index);
char* line;
size_t len;
while (GetLog(Settings.weblog_level, &index, &line, &len)) {
while (GetLog(Settings->weblog_level, &index, &line, &len)) {
if (cflg) { WSContentSend_P(PSTR("\n")); }
WSContentSend(line, len -1);
cflg = true;
@ -2932,7 +2932,7 @@ void HandleNotFound(void)
#ifdef USE_EMULATION
#ifdef USE_EMULATION_HUE
String path = Webserver->uri();
if ((EMUL_HUE == Settings.flag2.emulation) && (path.startsWith(F("/api")))) {
if ((EMUL_HUE == Settings->flag2.emulation) && (path.startsWith(F("/api")))) {
HandleHueApi(&path);
} else
#endif // USE_EMULATION_HUE
@ -3105,11 +3105,11 @@ void CmndEmulation(void)
if ((EMUL_NONE == XdrvMailbox.payload) || (EMUL_WEMO == XdrvMailbox.payload)) {
#endif
#endif
Settings.flag2.emulation = XdrvMailbox.payload;
Settings->flag2.emulation = XdrvMailbox.payload;
TasmotaGlobal.restart_flag = 2;
}
#endif
ResponseCmndNumber(Settings.flag2.emulation);
ResponseCmndNumber(Settings->flag2.emulation);
}
#endif // USE_EMULATION
@ -3128,11 +3128,11 @@ void CmndSendmail(void)
void CmndWebServer(void)
{
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) {
Settings.webserver = XdrvMailbox.payload;
Settings->webserver = XdrvMailbox.payload;
}
if (Settings.webserver) {
if (Settings->webserver) {
Response_P(PSTR("{\"" D_CMND_WEBSERVER "\":\"" D_JSON_ACTIVE_FOR " %s " D_JSON_ON_DEVICE " %s " D_JSON_WITH_IP_ADDRESS " %_I\"}"),
(2 == Settings.webserver) ? PSTR(D_ADMIN) : PSTR(D_USER), NetworkHostname(), (uint32_t)NetworkAddress());
(2 == Settings->webserver) ? PSTR(D_ADMIN) : PSTR(D_USER), NetworkHostname(), (uint32_t)NetworkAddress());
} else {
ResponseCmndStateText(0);
}
@ -3157,17 +3157,17 @@ void CmndWebPassword(void)
void CmndWeblog(void)
{
if ((XdrvMailbox.payload >= LOG_LEVEL_NONE) && (XdrvMailbox.payload <= LOG_LEVEL_DEBUG_MORE)) {
Settings.weblog_level = XdrvMailbox.payload;
Settings->weblog_level = XdrvMailbox.payload;
}
ResponseCmndNumber(Settings.weblog_level);
ResponseCmndNumber(Settings->weblog_level);
}
void CmndWebRefresh(void)
{
if ((XdrvMailbox.payload > 999) && (XdrvMailbox.payload <= 65000)) {
Settings.web_refresh = XdrvMailbox.payload;
Settings->web_refresh = XdrvMailbox.payload;
}
ResponseCmndNumber(Settings.web_refresh);
ResponseCmndNumber(Settings->web_refresh);
}
void CmndWebSend(void)
@ -3208,7 +3208,7 @@ void CmndWebSensor(void)
{
if (XdrvMailbox.index < MAX_XSNS_DRIVERS) {
if (XdrvMailbox.payload >= 0) {
bitWrite(Settings.sensors[XdrvMailbox.index / 32], XdrvMailbox.index % 32, XdrvMailbox.payload &1);
bitWrite(Settings->sensors[XdrvMailbox.index / 32], XdrvMailbox.index % 32, XdrvMailbox.payload &1);
}
}
Response_P(PSTR("{\"" D_CMND_WEBSENSOR "\":"));
@ -3250,7 +3250,7 @@ bool Xdrv01(uint8_t function)
case FUNC_LOOP:
PollDnsWebserver();
#ifdef USE_EMULATION
if (Settings.flag2.emulation) { PollUdp(); }
if (Settings->flag2.emulation) { PollUdp(); }
#endif // USE_EMULATION
break;
case FUNC_EVERY_SECOND:
@ -3266,10 +3266,10 @@ bool Xdrv01(uint8_t function)
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CMND_SSID "1 %s: " D_CONNECTED " - " D_IP_ADDRESS " %_I"), SettingsText(SET_STASSID1), (uint32_t)WiFi.localIP());
// TasmotaGlobal.blinks = 255; // Signal wifi connection with blinks
if (MAX_WIFI_OPTION != Web.old_wificonfig) {
TasmotaGlobal.wifi_state_flag = Settings.sta_config = Web.old_wificonfig;
TasmotaGlobal.wifi_state_flag = Settings->sta_config = Web.old_wificonfig;
}
TasmotaGlobal.save_data_counter = Web.save_data_counter;
Settings.save_data = Web.save_data_counter;
Settings->save_data = Web.save_data_counter;
SettingsSaveAll();
#if (!RESTART_AFTER_INITIAL_WIFI_CONFIG)
Web.initial_config = false;

View File

@ -60,7 +60,7 @@ uint32_t MqttFileUploadValidate(uint32_t rcv_id) {
// Check buffer size
if (UPL_SETTINGS == FMqtt.file_type) {
if (FMqtt.file_size > sizeof(Settings)) {
if (FMqtt.file_size > sizeof(TSettings)) {
return 2; // Settings supports max 4k size
}
} else { // Check enough flash space for intermediate upload

View File

@ -198,19 +198,19 @@ PubSubClient MqttClient;
void MqttInit(void) {
#ifdef USE_MQTT_AZURE_IOT
Settings.mqtt_port = 8883;
Settings->mqtt_port = 8883;
#endif //USE_MQTT_AZURE_IOT
#ifdef USE_MQTT_TLS
if ((8883 == Settings.mqtt_port) || (8884 == Settings.mqtt_port)) {
if ((8883 == Settings->mqtt_port) || (8884 == Settings->mqtt_port)) {
// Turn on TLS for port 8883 (TLS) and 8884 (TLS, client certificate)
Settings.flag4.mqtt_tls = true;
Settings->flag4.mqtt_tls = true;
}
Mqtt.mqtt_tls = Settings.flag4.mqtt_tls; // this flag should not change even if we change the SetOption (until reboot)
Mqtt.mqtt_tls = Settings->flag4.mqtt_tls; // this flag should not change even if we change the SetOption (until reboot)
// Detect AWS IoT and set default parameters
String host = String(SettingsText(SET_MQTT_HOST));
if (host.indexOf(F(".iot.")) && host.endsWith(F(".amazonaws.com"))) { // look for ".iot." and ".amazonaws.com" in the domain name
Settings.flag4.mqtt_no_retain = true;
Settings->flag4.mqtt_no_retain = true;
}
if (Mqtt.mqtt_tls) {
@ -241,8 +241,8 @@ void MqttInit(void) {
MqttClient.setClient(EspClient);
#endif // USE_MQTT_TLS
MqttClient.setKeepAlive(Settings.mqtt_keepalive);
MqttClient.setSocketTimeout(Settings.mqtt_socket_timeout);
MqttClient.setKeepAlive(Settings->mqtt_keepalive);
MqttClient.setSocketTimeout(Settings->mqtt_socket_timeout);
}
#ifdef USE_MQTT_AZURE_IOT
@ -594,12 +594,12 @@ void MqttUnsubscribe(const char *topic) {
void MqttPublishLoggingAsync(bool refresh) {
static uint32_t index = 1;
if (!Settings.mqttlog_level || !Settings.flag.mqtt_enabled || !Mqtt.connected) { return; } // SetOption3 - Enable MQTT
if (refresh && !NeedLogRefresh(Settings.mqttlog_level, index)) { return; }
if (!Settings->mqttlog_level || !Settings->flag.mqtt_enabled || !Mqtt.connected) { return; } // SetOption3 - Enable MQTT
if (refresh && !NeedLogRefresh(Settings->mqttlog_level, index)) { return; }
char* line;
size_t len;
while (GetLog(Settings.mqttlog_level, &index, &line, &len)) {
while (GetLog(Settings->mqttlog_level, &index, &line, &len)) {
char stopic[TOPSZ];
GetTopic_P(stopic, STAT, TasmotaGlobal.mqtt_topic, PSTR("LOGGING"));
MqttPublishLib(stopic, (const uint8_t*)line, len -1, false);
@ -618,13 +618,13 @@ void MqttPublishPayload(const char* topic, const char* payload, uint32_t binary_
binary_length = strlen(payload);
}
if (Settings.flag4.mqtt_no_retain) { // SetOption104 - Disable all MQTT retained messages, some brokers don't support it: AWS IoT, Losant
if (Settings->flag4.mqtt_no_retain) { // SetOption104 - Disable all MQTT retained messages, some brokers don't support it: AWS IoT, Losant
retained = false; // Some brokers don't support retained, they will disconnect if received
}
// To lower heap usage the payload is not copied to the heap but used directly
String log_data_topic; // 20210420 Moved to heap to solve tight stack resulting in exception 2
if (Settings.flag.mqtt_enabled && MqttPublishLib(topic, (const uint8_t*)payload, binary_length, retained)) { // SetOption3 - Enable MQTT
if (Settings->flag.mqtt_enabled && MqttPublishLib(topic, (const uint8_t*)payload, binary_length, retained)) { // SetOption3 - Enable MQTT
log_data_topic = F(D_LOG_MQTT); // MQT:
log_data_topic += topic; // stat/tasmota/STATUS2
} else {
@ -647,7 +647,7 @@ void MqttPublishPayload(const char* topic, const char* payload, uint32_t binary_
}
AddLogData(LOG_LEVEL_INFO, log_data_topic.c_str(), log_data_payload, log_data_retained); // MQT: stat/tasmota/STATUS2 = {"StatusFWR":{"Version":...
if (Settings.ledstate &0x04) {
if (Settings->ledstate &0x04) {
TasmotaGlobal.blinks++;
}
}
@ -683,7 +683,7 @@ void MqttPublishPayloadPrefixTopic_P(uint32_t prefix, const char* subtopic, cons
prefix 6 = tele using subtopic or RESULT
*/
char romram[64];
snprintf_P(romram, sizeof(romram), ((prefix > 3) && !Settings.flag.mqtt_response) ? S_RSLT_RESULT : subtopic); // SetOption4 - Switch between MQTT RESULT or COMMAND
snprintf_P(romram, sizeof(romram), ((prefix > 3) && !Settings->flag.mqtt_response) ? S_RSLT_RESULT : subtopic); // SetOption4 - Switch between MQTT RESULT or COMMAND
UpperCase(romram, romram);
prefix &= 3;
@ -692,7 +692,7 @@ void MqttPublishPayloadPrefixTopic_P(uint32_t prefix, const char* subtopic, cons
MqttPublishPayload(stopic, payload, binary_length, retained);
#if defined(USE_MQTT_AWS_IOT) || defined(USE_MQTT_AWS_IOT_LIGHT)
if ((prefix > 0) && (Settings.flag4.awsiot_shadow) && (Mqtt.connected)) { // placeholder for SetOptionXX
if ((prefix > 0) && (Settings->flag4.awsiot_shadow) && (Mqtt.connected)) { // placeholder for SetOptionXX
// compute the target topic
char *topic = SettingsText(SET_MQTT_TOPIC);
char topic2[strlen(topic)+1]; // save buffer onto stack
@ -773,7 +773,7 @@ void MqttPublishPrefixTopicRulesProcess_P(uint32_t prefix, const char* subtopic)
void MqttPublishTeleSensor(void) {
// Publish tele/<device>/SENSOR default TasmotaGlobal.mqtt_data string with optional retained
// then process rules
MqttPublishPrefixTopicRulesProcess_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); // CMND_SENSORRETAIN
MqttPublishPrefixTopicRulesProcess_P(TELE, PSTR(D_RSLT_SENSOR), Settings->flag.mqtt_sensor_retain); // CMND_SENSORRETAIN
}
void MqttPublishPowerState(uint32_t device) {
@ -789,21 +789,21 @@ void MqttPublishPowerState(uint32_t device) {
DomoticzUpdateFanState(); // RC Button feedback
#endif // USE_DOMOTICZ
snprintf_P(scommand, sizeof(scommand), PSTR(D_CMND_FANSPEED));
GetTopic_P(stopic, STAT, TasmotaGlobal.mqtt_topic, (Settings.flag.mqtt_response) ? scommand : S_RSLT_RESULT); // SetOption4 - Switch between MQTT RESULT or COMMAND
GetTopic_P(stopic, STAT, TasmotaGlobal.mqtt_topic, (Settings->flag.mqtt_response) ? scommand : S_RSLT_RESULT); // SetOption4 - Switch between MQTT RESULT or COMMAND
Response_P(S_JSON_COMMAND_NVALUE, scommand, GetFanspeed());
MqttPublish(stopic);
}
} else {
#endif // USE_SONOFF_IFAN
GetPowerDevice(scommand, device, sizeof(scommand), Settings.flag.device_index_enable); // SetOption26 - Switch between POWER or POWER1
GetTopic_P(stopic, STAT, TasmotaGlobal.mqtt_topic, (Settings.flag.mqtt_response) ? scommand : S_RSLT_RESULT); // SetOption4 - Switch between MQTT RESULT or COMMAND
GetPowerDevice(scommand, device, sizeof(scommand), Settings->flag.device_index_enable); // SetOption26 - Switch between POWER or POWER1
GetTopic_P(stopic, STAT, TasmotaGlobal.mqtt_topic, (Settings->flag.mqtt_response) ? scommand : S_RSLT_RESULT); // SetOption4 - Switch between MQTT RESULT or COMMAND
Response_P(S_JSON_COMMAND_SVALUE, scommand, GetStateText(bitRead(TasmotaGlobal.power, device -1)));
MqttPublish(stopic);
if (!Settings.flag4.only_json_message) { // SetOption90 - Disable non-json MQTT response
if (!Settings->flag4.only_json_message) { // SetOption90 - Disable non-json MQTT response
GetTopic_P(stopic, STAT, TasmotaGlobal.mqtt_topic, scommand);
Response_P(GetStateText(bitRead(TasmotaGlobal.power, device -1)));
MqttPublish(stopic, Settings.flag.mqtt_power_retain); // CMND_POWERRETAIN
MqttPublish(stopic, Settings->flag.mqtt_power_retain); // CMND_POWERRETAIN
}
#ifdef USE_SONOFF_IFAN
}
@ -826,7 +826,7 @@ void MqttPublishPowerBlinkState(uint32_t device) {
device = 1;
}
Response_P(PSTR("{\"%s\":\"" D_JSON_BLINK " %s\"}"),
GetPowerDevice(scommand, device, sizeof(scommand), Settings.flag.device_index_enable), GetStateText(bitRead(TasmotaGlobal.blink_mask, device -1))); // SetOption26 - Switch between POWER or POWER1
GetPowerDevice(scommand, device, sizeof(scommand), Settings->flag.device_index_enable), GetStateText(bitRead(TasmotaGlobal.blink_mask, device -1))); // SetOption26 - Switch between POWER or POWER1
MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, S_RSLT_POWER);
}
@ -840,14 +840,14 @@ uint16_t MqttConnectCount(void) {
void MqttDisconnected(int state) {
Mqtt.connected = false;
Mqtt.retry_counter = Settings.mqtt_retry * Mqtt.retry_counter_delay;
if ((Settings.mqtt_retry * Mqtt.retry_counter_delay) < 120) {
Mqtt.retry_counter = Settings->mqtt_retry * Mqtt.retry_counter_delay;
if ((Settings->mqtt_retry * Mqtt.retry_counter_delay) < 120) {
Mqtt.retry_counter_delay++;
}
MqttClient.disconnect();
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT D_CONNECT_FAILED_TO " %s:%d, rc %d. " D_RETRY_IN " %d " D_UNIT_SECOND), SettingsText(SET_MQTT_HOST), Settings.mqtt_port, state, Mqtt.retry_counter);
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT D_CONNECT_FAILED_TO " %s:%d, rc %d. " D_RETRY_IN " %d " D_UNIT_SECOND), SettingsText(SET_MQTT_HOST), Settings->mqtt_port, state, Mqtt.retry_counter);
TasmotaGlobal.rules_flag.mqtt_disconnected = 1;
}
@ -865,7 +865,7 @@ void MqttConnected(void) {
Response_P(PSTR(MQTT_LWT_ONLINE));
MqttPublish(stopic, true);
if (!Settings.flag4.only_json_message) { // SetOption90 - Disable non-json MQTT response
if (!Settings->flag4.only_json_message) { // SetOption90 - Disable non-json MQTT response
// Satisfy iobroker (#299)
ResponseClear();
MqttPublishPrefixTopic_P(CMND, S_RSLT_POWER);
@ -894,17 +894,17 @@ void MqttConnected(void) {
char stopic2[TOPSZ];
Response_P(PSTR("{\"Info1\":{\"" D_CMND_MODULE "\":\"%s\",\"" D_JSON_VERSION "\":\"%s%s\",\"" D_JSON_FALLBACKTOPIC "\":\"%s\",\"" D_CMND_GROUPTOPIC "\":\"%s\"}}"),
ModuleName().c_str(), TasmotaGlobal.version, TasmotaGlobal.image_name, GetFallbackTopic_P(stopic, ""), GetGroupTopic_P(stopic2, "", SET_MQTT_GRP_TOPIC));
MqttPublishPrefixTopicRulesProcess_P(TELE, PSTR(D_RSLT_INFO "1"), Settings.flag5.mqtt_info_retain);
MqttPublishPrefixTopicRulesProcess_P(TELE, PSTR(D_RSLT_INFO "1"), Settings->flag5.mqtt_info_retain);
#ifdef USE_WEBSERVER
if (Settings.webserver) {
if (Settings->webserver) {
#if LWIP_IPV6
Response_P(PSTR("{\"Info2\":{\"" D_JSON_WEBSERVER_MODE "\":\"%s\",\"" D_CMND_HOSTNAME "\":\"%s\",\"" D_CMND_IPADDRESS "\":\"%s\",\"IPv6Address\":\"%s\"}}"),
(2 == Settings.webserver) ? PSTR(D_ADMIN) : PSTR(D_USER), NetworkHostname(), NetworkAddress().toString().c_str(), WifiGetIPv6().c_str(), Settings.flag5.mqtt_info_retain);
(2 == Settings->webserver) ? PSTR(D_ADMIN) : PSTR(D_USER), NetworkHostname(), NetworkAddress().toString().c_str(), WifiGetIPv6().c_str(), Settings->flag5.mqtt_info_retain);
#else
Response_P(PSTR("{\"Info2\":{\"" D_JSON_WEBSERVER_MODE "\":\"%s\",\"" D_CMND_HOSTNAME "\":\"%s\",\"" D_CMND_IPADDRESS "\":\"%s\"}}"),
(2 == Settings.webserver) ? PSTR(D_ADMIN) : PSTR(D_USER), NetworkHostname(), NetworkAddress().toString().c_str(), Settings.flag5.mqtt_info_retain);
(2 == Settings->webserver) ? PSTR(D_ADMIN) : PSTR(D_USER), NetworkHostname(), NetworkAddress().toString().c_str(), Settings->flag5.mqtt_info_retain);
#endif // LWIP_IPV6 = 1
MqttPublishPrefixTopicRulesProcess_P(TELE, PSTR(D_RSLT_INFO "2"), Settings.flag5.mqtt_info_retain);
MqttPublishPrefixTopicRulesProcess_P(TELE, PSTR(D_RSLT_INFO "2"), Settings->flag5.mqtt_info_retain);
}
#endif // USE_WEBSERVER
Response_P(PSTR("{\"Info3\":{\"" D_JSON_RESTARTREASON "\":"));
@ -914,12 +914,12 @@ void MqttConnected(void) {
ResponseAppend_P(PSTR("\"%s\""), GetResetReason().c_str());
}
ResponseJsonEndEnd();
MqttPublishPrefixTopicRulesProcess_P(TELE, PSTR(D_RSLT_INFO "3"), Settings.flag5.mqtt_info_retain);
MqttPublishPrefixTopicRulesProcess_P(TELE, PSTR(D_RSLT_INFO "3"), Settings->flag5.mqtt_info_retain);
}
MqttPublishAllPowerState();
if (Settings.tele_period) {
TasmotaGlobal.tele_period = Settings.tele_period -5; // Enable TelePeriod in 5 seconds
if (Settings->tele_period) {
TasmotaGlobal.tele_period = Settings->tele_period -5; // Enable TelePeriod in 5 seconds
}
TasmotaGlobal.rules_flag.system_boot = 1;
XdrvCall(FUNC_MQTT_INIT);
@ -927,7 +927,7 @@ void MqttConnected(void) {
Mqtt.initial_connection_state = 0;
TasmotaGlobal.global_state.mqtt_down = 0;
if (Settings.flag.mqtt_enabled) { // SetOption3 - Enable MQTT
if (Settings->flag.mqtt_enabled) { // SetOption3 - Enable MQTT
TasmotaGlobal.rules_flag.mqtt_connected = 1;
}
}
@ -935,7 +935,7 @@ void MqttConnected(void) {
void MqttReconnect(void) {
char stopic[TOPSZ];
Mqtt.allowed = Settings.flag.mqtt_enabled; // SetOption3 - Enable MQTT
Mqtt.allowed = Settings->flag.mqtt_enabled; // SetOption3 - Enable MQTT
if (Mqtt.allowed) {
#if defined(USE_MQTT_AZURE_DPS_SCOPEID) && defined(USE_MQTT_AZURE_DPS_PRESHAREDKEY)
ProvisionAzureDPS();
@ -945,7 +945,7 @@ void MqttReconnect(void) {
MqttDiscoverServer();
#endif // MQTT_HOST_DISCOVERY
#endif // USE_DISCOVERY
if (!strlen(SettingsText(SET_MQTT_HOST)) || !Settings.mqtt_port) {
if (!strlen(SettingsText(SET_MQTT_HOST)) || !Settings->mqtt_port) {
Mqtt.allowed = false;
}
#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT)
@ -967,13 +967,13 @@ void MqttReconnect(void) {
#endif // USE_EMULATION
Mqtt.connected = false;
Mqtt.retry_counter = Settings.mqtt_retry * Mqtt.retry_counter_delay;
Mqtt.retry_counter = Settings->mqtt_retry * Mqtt.retry_counter_delay;
TasmotaGlobal.global_state.mqtt_down = 1;
#ifdef FIRMWARE_MINIMAL
#ifndef USE_MQTT_TLS
// Don't try to connect if MQTT requires TLS but TLS is not supported
if (Settings.flag4.mqtt_tls) {
if (Settings->flag4.mqtt_tls) {
return;
}
#endif
@ -1022,7 +1022,7 @@ void MqttReconnect(void) {
}
}
#endif
MqttClient.setServer(SettingsText(SET_MQTT_HOST), Settings.mqtt_port);
MqttClient.setServer(SettingsText(SET_MQTT_HOST), Settings->mqtt_port);
uint32_t mqtt_connect_time = millis();
#if defined(USE_MQTT_TLS) && !defined(USE_MQTT_TLS_CA_CERT)
@ -1031,16 +1031,16 @@ void MqttReconnect(void) {
bool learn_fingerprint2;
if (Mqtt.mqtt_tls) {
allow_all_fingerprints = false;
learn_fingerprint1 = is_fingerprint_mono_value(Settings.mqtt_fingerprint[0], 0x00);
learn_fingerprint2 = is_fingerprint_mono_value(Settings.mqtt_fingerprint[1], 0x00);
allow_all_fingerprints |= is_fingerprint_mono_value(Settings.mqtt_fingerprint[0], 0xff);
allow_all_fingerprints |= is_fingerprint_mono_value(Settings.mqtt_fingerprint[1], 0xff);
learn_fingerprint1 = is_fingerprint_mono_value(Settings->mqtt_fingerprint[0], 0x00);
learn_fingerprint2 = is_fingerprint_mono_value(Settings->mqtt_fingerprint[1], 0x00);
allow_all_fingerprints |= is_fingerprint_mono_value(Settings->mqtt_fingerprint[0], 0xff);
allow_all_fingerprints |= is_fingerprint_mono_value(Settings->mqtt_fingerprint[1], 0xff);
allow_all_fingerprints |= learn_fingerprint1;
allow_all_fingerprints |= learn_fingerprint2;
tlsClient->setPubKeyFingerprint(Settings.mqtt_fingerprint[0], Settings.mqtt_fingerprint[1], allow_all_fingerprints);
tlsClient->setPubKeyFingerprint(Settings->mqtt_fingerprint[0], Settings->mqtt_fingerprint[1], allow_all_fingerprints);
}
#endif
bool lwt_retain = Settings.flag4.mqtt_no_retain ? false : true; // no retained last will if "no_retain"
bool lwt_retain = Settings->flag4.mqtt_no_retain ? false : true; // no retained last will if "no_retain"
#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT)
if (Mqtt.mqtt_tls) {
if ((nullptr != AWS_IoT_Private_Key) && (nullptr != AWS_IoT_Client_Certificate)) {
@ -1097,13 +1097,13 @@ void MqttReconnect(void) {
// Otherwise, if the fingerprint slot had the magic trust-on-first-use
// value, we will save the current fingerprint there, but only if the other fingerprint slot
// *didn't* match it.
if (recv_fingerprint[20] & 0x1 || (learn_fingerprint1 && 0 != memcmp(recv_fingerprint, Settings.mqtt_fingerprint[1], 20))) {
memcpy(Settings.mqtt_fingerprint[0], recv_fingerprint, 20);
if (recv_fingerprint[20] & 0x1 || (learn_fingerprint1 && 0 != memcmp(recv_fingerprint, Settings->mqtt_fingerprint[1], 20))) {
memcpy(Settings->mqtt_fingerprint[0], recv_fingerprint, 20);
learned = true;
}
// As above, but for the other slot.
if (recv_fingerprint[20] & 0x2 || (learn_fingerprint2 && 0 != memcmp(recv_fingerprint, Settings.mqtt_fingerprint[0], 20))) {
memcpy(Settings.mqtt_fingerprint[1], recv_fingerprint, 20);
if (recv_fingerprint[20] & 0x2 || (learn_fingerprint2 && 0 != memcmp(recv_fingerprint, Settings->mqtt_fingerprint[0], 20))) {
memcpy(Settings->mqtt_fingerprint[1], recv_fingerprint, 20);
learned = true;
}
@ -1127,7 +1127,7 @@ void MqttReconnect(void) {
}
void MqttCheck(void) {
if (Settings.flag.mqtt_enabled) { // SetOption3 - Enable MQTT
if (Settings->flag.mqtt_enabled) { // SetOption3 - Enable MQTT
if (!MqttIsConnected()) {
TasmotaGlobal.global_state.mqtt_down = 1;
if (!Mqtt.retry_counter) {
@ -1165,17 +1165,17 @@ void CmndMqttFingerprint(void) {
char fingerprint[60];
if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(fingerprint))) {
if (SC_DEFAULT == Shortcut()) {
memcpy_P(Settings.mqtt_fingerprint[XdrvMailbox.index -1], (1 == XdrvMailbox.index) ? default_fingerprint1 : default_fingerprint2, sizeof(default_fingerprint1));
memcpy_P(Settings->mqtt_fingerprint[XdrvMailbox.index -1], (1 == XdrvMailbox.index) ? default_fingerprint1 : default_fingerprint2, sizeof(default_fingerprint1));
} else {
strlcpy(fingerprint, (SC_CLEAR == Shortcut()) ? "" : XdrvMailbox.data, sizeof(fingerprint));
char *p = fingerprint;
for (uint32_t i = 0; i < 20; i++) {
Settings.mqtt_fingerprint[XdrvMailbox.index -1][i] = strtol(p, &p, 16);
Settings->mqtt_fingerprint[XdrvMailbox.index -1][i] = strtol(p, &p, 16);
}
}
TasmotaGlobal.restart_flag = 2;
}
ResponseCmndIdxChar(ToHex_P((unsigned char *)Settings.mqtt_fingerprint[XdrvMailbox.index -1], 20, fingerprint, sizeof(fingerprint), ' '));
ResponseCmndIdxChar(ToHex_P((unsigned char *)Settings->mqtt_fingerprint[XdrvMailbox.index -1], 20, fingerprint, sizeof(fingerprint), ' '));
}
}
#endif
@ -1206,29 +1206,29 @@ void CmndMqttPassword(void) {
void CmndMqttKeepAlive(void) {
if ((XdrvMailbox.payload >= 1) && (XdrvMailbox.payload <= 100)) {
Settings.mqtt_keepalive = XdrvMailbox.payload;
Settings->mqtt_keepalive = XdrvMailbox.payload;
#ifdef USE_MQTT_NEW_PUBSUBCLIENT
MqttClient.setKeepAlive(Settings.mqtt_keepalive);
MqttClient.setKeepAlive(Settings->mqtt_keepalive);
#endif
}
ResponseCmndNumber(Settings.mqtt_keepalive);
ResponseCmndNumber(Settings->mqtt_keepalive);
}
void CmndMqttTimeout(void) {
if ((XdrvMailbox.payload >= 1) && (XdrvMailbox.payload <= 100)) {
Settings.mqtt_socket_timeout = XdrvMailbox.payload;
Settings->mqtt_socket_timeout = XdrvMailbox.payload;
#ifdef USE_MQTT_NEW_PUBSUBCLIENT
MqttClient.setSocketTimeout(Settings.mqtt_socket_timeout);
MqttClient.setSocketTimeout(Settings->mqtt_socket_timeout);
#endif
}
ResponseCmndNumber(Settings.mqtt_socket_timeout);
ResponseCmndNumber(Settings->mqtt_socket_timeout);
}
void CmndMqttlog(void) {
if ((XdrvMailbox.payload >= LOG_LEVEL_NONE) && (XdrvMailbox.payload <= LOG_LEVEL_DEBUG_MORE)) {
Settings.mqttlog_level = XdrvMailbox.payload;
Settings->mqttlog_level = XdrvMailbox.payload;
}
ResponseCmndNumber(Settings.mqttlog_level);
ResponseCmndNumber(Settings->mqttlog_level);
}
void CmndMqttHost(void) {
@ -1241,18 +1241,18 @@ void CmndMqttHost(void) {
void CmndMqttPort(void) {
if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 65536)) {
Settings.mqtt_port = (1 == XdrvMailbox.payload) ? MQTT_PORT : XdrvMailbox.payload;
Settings->mqtt_port = (1 == XdrvMailbox.payload) ? MQTT_PORT : XdrvMailbox.payload;
TasmotaGlobal.restart_flag = 2;
}
ResponseCmndNumber(Settings.mqtt_port);
ResponseCmndNumber(Settings->mqtt_port);
}
void CmndMqttRetry(void) {
if ((XdrvMailbox.payload >= MQTT_RETRY_SECS) && (XdrvMailbox.payload < 32001)) {
Settings.mqtt_retry = XdrvMailbox.payload;
Mqtt.retry_counter = Settings.mqtt_retry;
Settings->mqtt_retry = XdrvMailbox.payload;
Mqtt.retry_counter = Settings->mqtt_retry;
}
ResponseCmndNumber(Settings.mqtt_retry);
ResponseCmndNumber(Settings->mqtt_retry);
}
void CmndStateText(void) {
@ -1286,7 +1286,7 @@ void CmndFullTopic(void) {
char stemp1[TOPSZ];
strlcpy(stemp1, (SC_DEFAULT == Shortcut()) ? MQTT_FULLTOPIC : XdrvMailbox.data, sizeof(stemp1));
if (strcmp(stemp1, SettingsText(SET_MQTT_FULLTOPIC))) {
Response_P((Settings.flag.mqtt_offline) ? S_LWT_OFFLINE : ""); // SetOption10 - Control MQTT LWT message format
Response_P((Settings->flag.mqtt_offline) ? S_LWT_OFFLINE : ""); // SetOption10 - Control MQTT LWT message format
MqttPublishPrefixTopic_P(TELE, S_LWT, true); // Offline or remove previous retained topic
SettingsUpdateText(SET_MQTT_FULLTOPIC, stemp1);
TasmotaGlobal.restart_flag = 2;
@ -1388,7 +1388,7 @@ void CmndTopic(void) {
char stemp1[TOPSZ];
strlcpy(stemp1, (SC_DEFAULT == Shortcut()) ? MQTT_TOPIC : XdrvMailbox.data, sizeof(stemp1));
if (strcmp(stemp1, SettingsText(SET_MQTT_TOPIC))) {
Response_P((Settings.flag.mqtt_offline) ? S_LWT_OFFLINE : ""); // SetOption10 - Control MQTT LWT message format
Response_P((Settings->flag.mqtt_offline) ? S_LWT_OFFLINE : ""); // SetOption10 - Control MQTT LWT message format
MqttPublishPrefixTopic_P(TELE, S_LWT, true); // Offline or remove previous retained topic
SettingsUpdateText(SET_MQTT_TOPIC, stemp1);
TasmotaGlobal.restart_flag = 2;
@ -1432,9 +1432,9 @@ void CmndButtonRetain(void) {
SendKey(KEY_BUTTON, i, CLEAR_RETAIN); // Clear MQTT retain in broker
}
}
Settings.flag.mqtt_button_retain = XdrvMailbox.payload; // CMND_BUTTONRETAIN
Settings->flag.mqtt_button_retain = XdrvMailbox.payload; // CMND_BUTTONRETAIN
}
ResponseCmndStateText(Settings.flag.mqtt_button_retain); // CMND_BUTTONRETAIN
ResponseCmndStateText(Settings->flag.mqtt_button_retain); // CMND_BUTTONRETAIN
}
void CmndSwitchRetain(void) {
@ -1444,9 +1444,9 @@ void CmndSwitchRetain(void) {
SendKey(KEY_SWITCH, i, CLEAR_RETAIN); // Clear MQTT retain in broker
}
}
Settings.flag.mqtt_switch_retain = XdrvMailbox.payload; // CMND_SWITCHRETAIN
Settings->flag.mqtt_switch_retain = XdrvMailbox.payload; // CMND_SWITCHRETAIN
}
ResponseCmndStateText(Settings.flag.mqtt_switch_retain); // CMND_SWITCHRETAIN
ResponseCmndStateText(Settings->flag.mqtt_switch_retain); // CMND_SWITCHRETAIN
}
void CmndPowerRetain(void) {
@ -1455,51 +1455,51 @@ void CmndPowerRetain(void) {
char stemp1[TOPSZ];
char scommand[CMDSZ];
for (uint32_t i = 1; i <= TasmotaGlobal.devices_present; i++) { // Clear MQTT retain in broker
GetTopic_P(stemp1, STAT, TasmotaGlobal.mqtt_topic, GetPowerDevice(scommand, i, sizeof(scommand), Settings.flag.device_index_enable)); // SetOption26 - Switch between POWER or POWER1
GetTopic_P(stemp1, STAT, TasmotaGlobal.mqtt_topic, GetPowerDevice(scommand, i, sizeof(scommand), Settings->flag.device_index_enable)); // SetOption26 - Switch between POWER or POWER1
ResponseClear();
MqttPublish(stemp1, Settings.flag.mqtt_power_retain); // CMND_POWERRETAIN
MqttPublish(stemp1, Settings->flag.mqtt_power_retain); // CMND_POWERRETAIN
}
}
Settings.flag.mqtt_power_retain = XdrvMailbox.payload; // CMND_POWERRETAIN
if (Settings.flag.mqtt_power_retain) {
Settings.flag4.only_json_message = 0; // SetOption90 - Disable non-json MQTT response
Settings->flag.mqtt_power_retain = XdrvMailbox.payload; // CMND_POWERRETAIN
if (Settings->flag.mqtt_power_retain) {
Settings->flag4.only_json_message = 0; // SetOption90 - Disable non-json MQTT response
}
}
ResponseCmndStateText(Settings.flag.mqtt_power_retain); // CMND_POWERRETAIN
ResponseCmndStateText(Settings->flag.mqtt_power_retain); // CMND_POWERRETAIN
}
void CmndSensorRetain(void) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) {
if (!XdrvMailbox.payload) {
ResponseClear();
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); // CMND_SENSORRETAIN
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_ENERGY), Settings.flag.mqtt_sensor_retain); // CMND_SENSORRETAIN
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings->flag.mqtt_sensor_retain); // CMND_SENSORRETAIN
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_ENERGY), Settings->flag.mqtt_sensor_retain); // CMND_SENSORRETAIN
}
Settings.flag.mqtt_sensor_retain = XdrvMailbox.payload; // CMND_SENSORRETAIN
Settings->flag.mqtt_sensor_retain = XdrvMailbox.payload; // CMND_SENSORRETAIN
}
ResponseCmndStateText(Settings.flag.mqtt_sensor_retain); // CMND_SENSORRETAIN
ResponseCmndStateText(Settings->flag.mqtt_sensor_retain); // CMND_SENSORRETAIN
}
void CmndInfoRetain(void) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) {
if (!XdrvMailbox.payload) {
ResponseClear();
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO), Settings.flag5.mqtt_info_retain); // CMND_INFORETAIN
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO), Settings->flag5.mqtt_info_retain); // CMND_INFORETAIN
}
Settings.flag5.mqtt_info_retain = XdrvMailbox.payload; // CMND_INFORETAIN
Settings->flag5.mqtt_info_retain = XdrvMailbox.payload; // CMND_INFORETAIN
}
ResponseCmndStateText(Settings.flag5.mqtt_info_retain); // CMND_INFORETAIN
ResponseCmndStateText(Settings->flag5.mqtt_info_retain); // CMND_INFORETAIN
}
void CmndStateRetain(void) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) {
if (!XdrvMailbox.payload) {
ResponseClear();
MqttPublishPrefixTopic_P(STAT, PSTR(D_RSLT_STATE), Settings.flag5.mqtt_state_retain); // CMND_STATERETAIN
MqttPublishPrefixTopic_P(STAT, PSTR(D_RSLT_STATE), Settings->flag5.mqtt_state_retain); // CMND_STATERETAIN
}
Settings.flag5.mqtt_state_retain = XdrvMailbox.payload; // CMND_STATERETAIN
Settings->flag5.mqtt_state_retain = XdrvMailbox.payload; // CMND_STATERETAIN
}
ResponseCmndStateText(Settings.flag5.mqtt_state_retain); // CMND_STATERETAIN
ResponseCmndStateText(Settings->flag5.mqtt_state_retain); // CMND_STATERETAIN
}
/*********************************************************************************************\
@ -1761,7 +1761,7 @@ void HandleMqttConfiguration(void)
WSContentSendStyle();
WSContentSend_P(HTTP_FORM_MQTT1,
SettingsText(SET_MQTT_HOST),
Settings.mqtt_port,
Settings->mqtt_port,
#ifdef USE_MQTT_TLS
Mqtt.mqtt_tls ? PSTR(" checked") : "", // SetOption102 - Enable MQTT TLS
#endif // USE_MQTT_TLS
@ -1800,7 +1800,7 @@ bool Xdrv02(uint8_t function)
{
bool result = false;
if (Settings.flag.mqtt_enabled) { // SetOption3 - Enable MQTT
if (Settings->flag.mqtt_enabled) { // SetOption3 - Enable MQTT
switch (function) {
case FUNC_EVERY_50_MSECOND: // https://github.com/knolleary/pubsubclient/issues/556
MqttClient.loop();

View File

@ -162,21 +162,21 @@ char* EnergyFormat(char* result, char* input, bool json, bool single = false)
bool EnergyTariff1Active() // Off-Peak hours
{
uint8_t dst = 0;
if (IsDst() && (Settings.tariff[0][1] != Settings.tariff[1][1])) {
if (IsDst() && (Settings->tariff[0][1] != Settings->tariff[1][1])) {
dst = 1;
}
if (Settings.tariff[0][dst] != Settings.tariff[1][dst]) {
if (Settings.flag3.energy_weekend && ((RtcTime.day_of_week == 1) || // CMND_TARIFF
if (Settings->tariff[0][dst] != Settings->tariff[1][dst]) {
if (Settings->flag3.energy_weekend && ((RtcTime.day_of_week == 1) || // CMND_TARIFF
(RtcTime.day_of_week == 7))) {
return true;
}
uint32_t minutes = MinutesPastMidnight();
if (Settings.tariff[0][dst] > Settings.tariff[1][dst]) {
if (Settings->tariff[0][dst] > Settings->tariff[1][dst]) {
// {"Tariff":{"Off-Peak":{"STD":"22:00","DST":"23:00"},"Standard":{"STD":"06:00","DST":"07:00"},"Weekend":"OFF"}}
return ((minutes >= Settings.tariff[0][dst]) || (minutes < Settings.tariff[1][dst]));
return ((minutes >= Settings->tariff[0][dst]) || (minutes < Settings->tariff[1][dst]));
} else {
// {"Tariff":{"Off-Peak":{"STD":"00:29","DST":"01:29"},"Standard":{"STD":"07:29","DST":"08:29"},"Weekend":"OFF"}}
return ((minutes >= Settings.tariff[0][dst]) && (minutes < Settings.tariff[1][dst]));
return ((minutes >= Settings->tariff[0][dst]) && (minutes < Settings->tariff[1][dst]));
}
} else {
return false;
@ -239,11 +239,11 @@ void EnergyUpdateTotal(float value, bool kwh)
}
if ((Energy.total < (value - 0.01)) && // We subtract a little offset to avoid continuous updates
Settings.flag3.hardware_energy_total) { // SetOption72 - Enable hardware energy total counter as reference (#6561)
Settings->flag3.hardware_energy_total) { // SetOption72 - Enable hardware energy total counter as reference (#6561)
RtcSettings.energy_kWhtotal = (unsigned long)((value * multiplier) - Energy.kWhtoday_offset - Energy.kWhtoday);
Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal;
Settings->energy_kWhtotal = RtcSettings.energy_kWhtotal;
Energy.total = (float)(RtcSettings.energy_kWhtotal + Energy.kWhtoday_offset + Energy.kWhtoday) / 100000;
Settings.energy_kWhtotal_time = (!Energy.kWhtoday_offset) ? LocalTime() : Midnight();
Settings->energy_kWhtotal_time = (!Energy.kWhtoday_offset) ? LocalTime() : Midnight();
// AddLog(LOG_LEVEL_DEBUG, PSTR("NRG: Energy Total updated with hardware value"));
}
EnergyUpdateToday();
@ -253,7 +253,7 @@ void EnergyUpdateTotal(float value, bool kwh)
void Energy200ms(void)
{
Energy.power_on = (TasmotaGlobal.power != 0) | Settings.flag.no_power_on_check; // SetOption21 - Show voltage even if powered off
Energy.power_on = (TasmotaGlobal.power != 0) | Settings->flag.no_power_on_check; // SetOption21 - Show voltage even if powered off
Energy.fifth_second++;
if (5 == Energy.fifth_second) {
@ -263,16 +263,16 @@ void Energy200ms(void)
if (RtcTime.valid) {
if (!Energy.kWhtoday_offset_init && (RtcTime.day_of_year == Settings.energy_kWhdoy)) {
Energy.kWhtoday_offset = Settings.energy_kWhtoday;
if (!Energy.kWhtoday_offset_init && (RtcTime.day_of_year == Settings->energy_kWhdoy)) {
Energy.kWhtoday_offset = Settings->energy_kWhtoday;
Energy.kWhtoday_offset_init = true;
}
if (LocalTime() == Midnight()) {
Settings.energy_kWhyesterday = RtcSettings.energy_kWhtoday;
Settings->energy_kWhyesterday = RtcSettings.energy_kWhtoday;
RtcSettings.energy_kWhtotal += RtcSettings.energy_kWhtoday;
Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal;
Settings->energy_kWhtotal = RtcSettings.energy_kWhtotal;
Energy.period -= RtcSettings.energy_kWhtoday; // this becomes a large unsigned, effectively a negative for EnergyShow calculation
Energy.kWhtoday = 0;
@ -287,7 +287,7 @@ void Energy200ms(void)
#endif // USE_ENERGY_POWER_LIMIT
}
#if defined(USE_ENERGY_MARGIN_DETECTION) && defined(USE_ENERGY_POWER_LIMIT)
if ((RtcTime.hour == Settings.energy_max_energy_start) && (3 == Energy.max_energy_state )) {
if ((RtcTime.hour == Settings->energy_max_energy_start) && (3 == Energy.max_energy_state )) {
Energy.max_energy_state = 0;
}
#endif // USE_ENERGY_POWER_LIMIT
@ -300,12 +300,12 @@ void Energy200ms(void)
void EnergySaveState(void)
{
Settings.energy_kWhdoy = (RtcTime.valid) ? RtcTime.day_of_year : 0;
Settings->energy_kWhdoy = (RtcTime.valid) ? RtcTime.day_of_year : 0;
Settings.energy_kWhtoday = RtcSettings.energy_kWhtoday;
Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal;
Settings->energy_kWhtoday = RtcSettings.energy_kWhtoday;
Settings->energy_kWhtotal = RtcSettings.energy_kWhtotal;
Settings.energy_usage = RtcSettings.energy_usage;
Settings->energy_usage = RtcSettings.energy_usage;
}
#ifdef USE_ENERGY_MARGIN_DETECTION
@ -340,20 +340,20 @@ void EnergyMarginCheck(void)
// AddLog(LOG_LEVEL_DEBUG, PSTR("NRG: APower %d, HPower0 %d, HPower1 %d, HPower2 %d"), active_power, Energy.power_history[phase][0], Energy.power_history[phase][1], Energy.power_history[phase][2]);
if (Settings.energy_power_delta[phase]) {
if (Settings->energy_power_delta[phase]) {
power_diff[phase] = active_power - Energy.power_history[phase][0];
uint16_t delta = abs(power_diff[phase]);
bool threshold_met = false;
if (delta > 0) {
if (Settings.energy_power_delta[phase] < 101) { // 1..100 = Percentage
if (Settings->energy_power_delta[phase] < 101) { // 1..100 = Percentage
uint16_t min_power = (Energy.power_history[phase][0] > active_power) ? active_power : Energy.power_history[phase][0];
if (0 == min_power) { min_power++; } // Fix divide by 0 exception (#6741)
delta = (delta * 100) / min_power;
if (delta > Settings.energy_power_delta[phase]) {
if (delta > Settings->energy_power_delta[phase]) {
threshold_met = true;
}
} else { // 101..32000 = Absolute
if (delta > (Settings.energy_power_delta[phase] -100)) {
if (delta > (Settings->energy_power_delta[phase] -100)) {
threshold_met = true;
}
}
@ -381,34 +381,34 @@ void EnergyMarginCheck(void)
uint16_t energy_power_u = (uint16_t)(Energy.active_power[0]);
if (Energy.power_on && (Settings.energy_min_power || Settings.energy_max_power || Settings.energy_min_voltage || Settings.energy_max_voltage || Settings.energy_min_current || Settings.energy_max_current)) {
if (Energy.power_on && (Settings->energy_min_power || Settings->energy_max_power || Settings->energy_min_voltage || Settings->energy_max_voltage || Settings->energy_min_current || Settings->energy_max_current)) {
uint16_t energy_voltage_u = (uint16_t)(Energy.voltage[0]);
uint16_t energy_current_u = (uint16_t)(Energy.current[0] * 1000);
DEBUG_DRIVER_LOG(PSTR("NRG: W %d, U %d, I %d"), energy_power_u, energy_voltage_u, energy_current_u);
bool flag;
if (EnergyMargin(false, Settings.energy_min_power, energy_power_u, flag, Energy.min_power_flag)) {
if (EnergyMargin(false, Settings->energy_min_power, energy_power_u, flag, Energy.min_power_flag)) {
ResponseAppend_P(PSTR("%s\"" D_CMND_POWERLOW "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag));
jsonflg = true;
}
if (EnergyMargin(true, Settings.energy_max_power, energy_power_u, flag, Energy.max_power_flag)) {
if (EnergyMargin(true, Settings->energy_max_power, energy_power_u, flag, Energy.max_power_flag)) {
ResponseAppend_P(PSTR("%s\"" D_CMND_POWERHIGH "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag));
jsonflg = true;
}
if (EnergyMargin(false, Settings.energy_min_voltage, energy_voltage_u, flag, Energy.min_voltage_flag)) {
if (EnergyMargin(false, Settings->energy_min_voltage, energy_voltage_u, flag, Energy.min_voltage_flag)) {
ResponseAppend_P(PSTR("%s\"" D_CMND_VOLTAGELOW "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag));
jsonflg = true;
}
if (EnergyMargin(true, Settings.energy_max_voltage, energy_voltage_u, flag, Energy.max_voltage_flag)) {
if (EnergyMargin(true, Settings->energy_max_voltage, energy_voltage_u, flag, Energy.max_voltage_flag)) {
ResponseAppend_P(PSTR("%s\"" D_CMND_VOLTAGEHIGH "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag));
jsonflg = true;
}
if (EnergyMargin(false, Settings.energy_min_current, energy_current_u, flag, Energy.min_current_flag)) {
if (EnergyMargin(false, Settings->energy_min_current, energy_current_u, flag, Energy.min_current_flag)) {
ResponseAppend_P(PSTR("%s\"" D_CMND_CURRENTLOW "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag));
jsonflg = true;
}
if (EnergyMargin(true, Settings.energy_max_current, energy_current_u, flag, Energy.max_current_flag)) {
if (EnergyMargin(true, Settings->energy_max_current, energy_current_u, flag, Energy.max_current_flag)) {
ResponseAppend_P(PSTR("%s\"" D_CMND_CURRENTHIGH "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag));
jsonflg = true;
}
@ -421,10 +421,10 @@ void EnergyMarginCheck(void)
#ifdef USE_ENERGY_POWER_LIMIT
// Max Power
if (Settings.energy_max_power_limit) {
if (Energy.active_power[0] > Settings.energy_max_power_limit) {
if (Settings->energy_max_power_limit) {
if (Energy.active_power[0] > Settings->energy_max_power_limit) {
if (!Energy.mplh_counter) {
Energy.mplh_counter = Settings.energy_max_power_limit_hold;
Energy.mplh_counter = Settings->energy_max_power_limit_hold;
} else {
Energy.mplh_counter--;
if (!Energy.mplh_counter) {
@ -433,13 +433,13 @@ void EnergyMarginCheck(void)
EnergyMqttShow();
SetAllPower(POWER_ALL_OFF, SRC_MAXPOWER);
if (!Energy.mplr_counter) {
Energy.mplr_counter = Settings.param[P_MAX_POWER_RETRY] +1; // SetOption33 - Max Power Retry count
Energy.mplr_counter = Settings->param[P_MAX_POWER_RETRY] +1; // SetOption33 - Max Power Retry count
}
Energy.mplw_counter = Settings.energy_max_power_limit_window;
Energy.mplw_counter = Settings->energy_max_power_limit_window;
}
}
}
else if (TasmotaGlobal.power && (energy_power_u <= Settings.energy_max_power_limit)) {
else if (TasmotaGlobal.power && (energy_power_u <= Settings->energy_max_power_limit)) {
Energy.mplh_counter = 0;
Energy.mplr_counter = 0;
Energy.mplw_counter = 0;
@ -466,15 +466,15 @@ void EnergyMarginCheck(void)
}
// Max Energy
if (Settings.energy_max_energy) {
if (Settings->energy_max_energy) {
uint16_t energy_daily_u = (uint16_t)(Energy.daily * 1000);
if (!Energy.max_energy_state && (RtcTime.hour == Settings.energy_max_energy_start)) {
if (!Energy.max_energy_state && (RtcTime.hour == Settings->energy_max_energy_start)) {
Energy.max_energy_state = 1;
ResponseTime_P(PSTR(",\"" D_JSON_ENERGYMONITOR "\":\"%s\"}"), GetStateText(1));
MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, PSTR(D_JSON_ENERGYMONITOR));
RestorePower(true, SRC_MAXENERGY);
}
else if ((1 == Energy.max_energy_state ) && (energy_daily_u >= Settings.energy_max_energy)) {
else if ((1 == Energy.max_energy_state ) && (energy_daily_u >= Settings->energy_max_energy)) {
Energy.max_energy_state = 2;
ResponseTime_P(PSTR(",\"" D_JSON_MAXENERGYREACHED "\":%3_f}"), &Energy.daily);
MqttPublishPrefixTopicRulesProcess_P(STAT, S_RSLT_WARNING);
@ -503,7 +503,7 @@ void EnergyEverySecond(void)
{
// Overtemp check
if (Energy.use_overtemp && TasmotaGlobal.global_update) {
if (TasmotaGlobal.power && !isnan(TasmotaGlobal.temperature_celsius) && (TasmotaGlobal.temperature_celsius > (float)Settings.param[P_OVER_TEMP])) { // SetOption42 Device overtemp, turn off relays
if (TasmotaGlobal.power && !isnan(TasmotaGlobal.temperature_celsius) && (TasmotaGlobal.temperature_celsius > (float)Settings->param[P_OVER_TEMP])) { // SetOption42 Device overtemp, turn off relays
AddLog(LOG_LEVEL_DEBUG, PSTR("NRG: Temperature %1_f"), &TasmotaGlobal.temperature_celsius);
@ -569,35 +569,35 @@ void CmndEnergyReset(void) {
Energy.kWhtoday_delta = 0;
Energy.start_energy = 0;
Energy.period = Energy.kWhtoday_offset;
Settings.energy_kWhtoday = Energy.kWhtoday_offset;
Settings->energy_kWhtoday = Energy.kWhtoday_offset;
RtcSettings.energy_kWhtoday = Energy.kWhtoday_offset;
Energy.daily = (float)Energy.kWhtoday_offset / 100000;
if( params > 1) {
Settings.energy_kWhtotal_time = values[1];
Settings->energy_kWhtotal_time = values[1];
}
else {
if (!RtcSettings.energy_kWhtotal && !Energy.kWhtoday_offset) {
Settings.energy_kWhtotal_time = LocalTime();
Settings->energy_kWhtotal_time = LocalTime();
}
}
break;
case 2:
// Reset Energy Yesterday
Settings.energy_kWhyesterday = values[0];
Settings->energy_kWhyesterday = values[0];
if( params > 1) {
Settings.energy_kWhtotal_time = values[1];
Settings->energy_kWhtotal_time = values[1];
}
break;
case 3:
// Reset Energy Total
RtcSettings.energy_kWhtotal = values[0];
Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal;
Settings->energy_kWhtotal = RtcSettings.energy_kWhtotal;
// Energy.total = (float)(RtcSettings.energy_kWhtotal + Energy.kWhtoday_offset + Energy.kWhtoday) / 100000;
if( params > 1) {
Settings.energy_kWhtotal_time = values[1];
Settings->energy_kWhtotal_time = values[1];
}
else {
Settings.energy_kWhtotal_time = (!Energy.kWhtoday_offset) ? LocalTime() : Midnight();
Settings->energy_kWhtotal_time = (!Energy.kWhtoday_offset) ? LocalTime() : Midnight();
}
RtcSettings.energy_usage.last_usage_kWhtotal = (uint32_t)(Energy.total * 1000);
break;
@ -607,8 +607,8 @@ void CmndEnergyReset(void) {
if (params > 1) {
RtcSettings.energy_usage.usage2_kWhtotal = values[1] * 100;
}
Settings.energy_usage.usage1_kWhtotal = RtcSettings.energy_usage.usage1_kWhtotal;
Settings.energy_usage.usage2_kWhtotal = RtcSettings.energy_usage.usage2_kWhtotal;
Settings->energy_usage.usage1_kWhtotal = RtcSettings.energy_usage.usage1_kWhtotal;
Settings->energy_usage.usage2_kWhtotal = RtcSettings.energy_usage.usage2_kWhtotal;
break;
case 5:
// Reset energy_usage.return totals
@ -616,29 +616,29 @@ void CmndEnergyReset(void) {
if (params > 1) {
RtcSettings.energy_usage.return2_kWhtotal = values[1] * 100;
}
Settings.energy_usage.return1_kWhtotal = RtcSettings.energy_usage.return1_kWhtotal;
Settings.energy_usage.return2_kWhtotal = RtcSettings.energy_usage.return2_kWhtotal;
Settings->energy_usage.return1_kWhtotal = RtcSettings.energy_usage.return1_kWhtotal;
Settings->energy_usage.return2_kWhtotal = RtcSettings.energy_usage.return2_kWhtotal;
break;
}
}
}
Energy.total = (float)(RtcSettings.energy_kWhtotal + Energy.kWhtoday_offset + Energy.kWhtoday) / 100000;
float energy_kWhyesterday = (float)Settings.energy_kWhyesterday / 100000;
float usage1_kWhtotal = (float)Settings.energy_usage.usage1_kWhtotal / 100000;
float usage2_kWhtotal = (float)Settings.energy_usage.usage2_kWhtotal / 100000;
float return1_kWhtotal = (float)Settings.energy_usage.return1_kWhtotal / 100000;
float return2_kWhtotal = (float)Settings.energy_usage.return2_kWhtotal / 100000;
float energy_kWhyesterday = (float)Settings->energy_kWhyesterday / 100000;
float usage1_kWhtotal = (float)Settings->energy_usage.usage1_kWhtotal / 100000;
float usage2_kWhtotal = (float)Settings->energy_usage.usage2_kWhtotal / 100000;
float return1_kWhtotal = (float)Settings->energy_usage.return1_kWhtotal / 100000;
float return2_kWhtotal = (float)Settings->energy_usage.return2_kWhtotal / 100000;
Response_P(PSTR("{\"%s\":{\"" D_JSON_TOTAL "\":%*_f,\"" D_JSON_YESTERDAY "\":%*_f,\"" D_JSON_TODAY "\":%*_f,\"" D_JSON_USAGE "\":[%*_f,%*_f],\"" D_JSON_EXPORT "\":[%*_f,%*_f]}}"),
XdrvMailbox.command,
Settings.flag2.energy_resolution, &Energy.total,
Settings.flag2.energy_resolution, &energy_kWhyesterday,
Settings.flag2.energy_resolution, &Energy.daily,
Settings.flag2.energy_resolution, &usage1_kWhtotal,
Settings.flag2.energy_resolution, &usage2_kWhtotal,
Settings.flag2.energy_resolution, &return1_kWhtotal,
Settings.flag2.energy_resolution, &return2_kWhtotal);
Settings->flag2.energy_resolution, &Energy.total,
Settings->flag2.energy_resolution, &energy_kWhyesterday,
Settings->flag2.energy_resolution, &Energy.daily,
Settings->flag2.energy_resolution, &usage1_kWhtotal,
Settings->flag2.energy_resolution, &usage2_kWhtotal,
Settings->flag2.energy_resolution, &return1_kWhtotal,
Settings->flag2.energy_resolution, &return2_kWhtotal);
}
void CmndTariff(void) {
@ -656,42 +656,42 @@ void CmndTariff(void) {
while ((str != nullptr) && (time_type < 2)) {
char *q;
uint32_t value = strtol(str, &q, 10); // 23 or 22
Settings.tariff[tariff][time_type] = value;
Settings->tariff[tariff][time_type] = value;
if (value < 24) { // Below 24 is hours
Settings.tariff[tariff][time_type] *= 60; // Multiply hours by 60 minutes
Settings->tariff[tariff][time_type] *= 60; // Multiply hours by 60 minutes
char *minute = strtok_r(nullptr, ":", &q);
if (minute) {
value = strtol(minute, nullptr, 10); // 15 or 30
if (value > 59) {
value = 59;
}
Settings.tariff[tariff][time_type] += value;
Settings->tariff[tariff][time_type] += value;
}
}
if (Settings.tariff[tariff][time_type] > 1439) {
Settings.tariff[tariff][time_type] = 1439; // Max is 23:59
if (Settings->tariff[tariff][time_type] > 1439) {
Settings->tariff[tariff][time_type] = 1439; // Max is 23:59
}
str = strtok_r(nullptr, ", ", &p);
time_type++;
}
}
else if (XdrvMailbox.index == 9) {
Settings.flag3.energy_weekend = XdrvMailbox.payload & 1; // CMND_TARIFF
Settings->flag3.energy_weekend = XdrvMailbox.payload & 1; // CMND_TARIFF
}
Response_P(PSTR("{\"%s\":{\"Off-Peak\":{\"STD\":\"%s\",\"DST\":\"%s\"},\"Standard\":{\"STD\":\"%s\",\"DST\":\"%s\"},\"Weekend\":\"%s\"}}"),
XdrvMailbox.command,
GetMinuteTime(Settings.tariff[0][0]).c_str(),GetMinuteTime(Settings.tariff[0][1]).c_str(),
GetMinuteTime(Settings.tariff[1][0]).c_str(),GetMinuteTime(Settings.tariff[1][1]).c_str(),
GetStateText(Settings.flag3.energy_weekend)); // CMND_TARIFF
GetMinuteTime(Settings->tariff[0][0]).c_str(),GetMinuteTime(Settings->tariff[0][1]).c_str(),
GetMinuteTime(Settings->tariff[1][0]).c_str(),GetMinuteTime(Settings->tariff[1][1]).c_str(),
GetStateText(Settings->flag3.energy_weekend)); // CMND_TARIFF
}
void CmndPowerCal(void) {
Energy.command_code = CMND_POWERCAL;
if (XnrgCall(FUNC_COMMAND)) { // microseconds
if (XdrvMailbox.payload > 999) {
Settings.energy_power_calibration = XdrvMailbox.payload;
Settings->energy_power_calibration = XdrvMailbox.payload;
}
ResponseCmndNumber(Settings.energy_power_calibration);
ResponseCmndNumber(Settings->energy_power_calibration);
}
}
@ -699,9 +699,9 @@ void CmndVoltageCal(void) {
Energy.command_code = CMND_VOLTAGECAL;
if (XnrgCall(FUNC_COMMAND)) { // microseconds
if (XdrvMailbox.payload > 999) {
Settings.energy_voltage_calibration = XdrvMailbox.payload;
Settings->energy_voltage_calibration = XdrvMailbox.payload;
}
ResponseCmndNumber(Settings.energy_voltage_calibration);
ResponseCmndNumber(Settings->energy_voltage_calibration);
}
}
@ -709,9 +709,9 @@ void CmndCurrentCal(void) {
Energy.command_code = CMND_CURRENTCAL;
if (XnrgCall(FUNC_COMMAND)) { // microseconds
if (XdrvMailbox.payload > 999) {
Settings.energy_current_calibration = XdrvMailbox.payload;
Settings->energy_current_calibration = XdrvMailbox.payload;
}
ResponseCmndNumber(Settings.energy_current_calibration);
ResponseCmndNumber(Settings->energy_current_calibration);
}
}
@ -719,37 +719,37 @@ void CmndFrequencyCal(void) {
Energy.command_code = CMND_FREQUENCYCAL;
if (XnrgCall(FUNC_COMMAND)) { // microseconds
if (XdrvMailbox.payload > 999) {
Settings.energy_frequency_calibration = XdrvMailbox.payload;
Settings->energy_frequency_calibration = XdrvMailbox.payload;
}
ResponseCmndNumber(Settings.energy_frequency_calibration);
ResponseCmndNumber(Settings->energy_frequency_calibration);
}
}
void CmndPowerSet(void) {
Energy.command_code = CMND_POWERSET;
if (XnrgCall(FUNC_COMMAND)) { // Watt
EnergyCommandCalResponse(Settings.energy_power_calibration);
EnergyCommandCalResponse(Settings->energy_power_calibration);
}
}
void CmndVoltageSet(void) {
Energy.command_code = CMND_VOLTAGESET;
if (XnrgCall(FUNC_COMMAND)) { // Volt
EnergyCommandCalResponse(Settings.energy_voltage_calibration);
EnergyCommandCalResponse(Settings->energy_voltage_calibration);
}
}
void CmndCurrentSet(void) {
Energy.command_code = CMND_CURRENTSET;
if (XnrgCall(FUNC_COMMAND)) { // milliAmpere
EnergyCommandCalResponse(Settings.energy_current_calibration);
EnergyCommandCalResponse(Settings->energy_current_calibration);
}
}
void CmndFrequencySet(void) {
Energy.command_code = CMND_FREQUENCYSET;
if (XnrgCall(FUNC_COMMAND)) { // Hz
EnergyCommandCalResponse(Settings.energy_frequency_calibration);
EnergyCommandCalResponse(Settings->energy_frequency_calibration);
}
}
@ -773,110 +773,110 @@ void CmndEnergyConfig(void) {
void CmndPowerDelta(void) {
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= ENERGY_MAX_PHASES)) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 32000)) {
Settings.energy_power_delta[XdrvMailbox.index -1] = XdrvMailbox.payload;
Settings->energy_power_delta[XdrvMailbox.index -1] = XdrvMailbox.payload;
}
ResponseCmndIdxNumber(Settings.energy_power_delta[XdrvMailbox.index -1]);
ResponseCmndIdxNumber(Settings->energy_power_delta[XdrvMailbox.index -1]);
}
}
void CmndPowerLow(void) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) {
Settings.energy_min_power = XdrvMailbox.payload;
Settings->energy_min_power = XdrvMailbox.payload;
}
ResponseCmndNumber(Settings.energy_min_power);
ResponseCmndNumber(Settings->energy_min_power);
}
void CmndPowerHigh(void) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) {
Settings.energy_max_power = XdrvMailbox.payload;
Settings->energy_max_power = XdrvMailbox.payload;
}
ResponseCmndNumber(Settings.energy_max_power);
ResponseCmndNumber(Settings->energy_max_power);
}
void CmndVoltageLow(void) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 501)) {
Settings.energy_min_voltage = XdrvMailbox.payload;
Settings->energy_min_voltage = XdrvMailbox.payload;
}
ResponseCmndNumber(Settings.energy_min_voltage);
ResponseCmndNumber(Settings->energy_min_voltage);
}
void CmndVoltageHigh(void) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 501)) {
Settings.energy_max_voltage = XdrvMailbox.payload;
Settings->energy_max_voltage = XdrvMailbox.payload;
}
ResponseCmndNumber(Settings.energy_max_voltage);
ResponseCmndNumber(Settings->energy_max_voltage);
}
void CmndCurrentLow(void) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 16001)) {
Settings.energy_min_current = XdrvMailbox.payload;
Settings->energy_min_current = XdrvMailbox.payload;
}
ResponseCmndNumber(Settings.energy_min_current);
ResponseCmndNumber(Settings->energy_min_current);
}
void CmndCurrentHigh(void) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 16001)) {
Settings.energy_max_current = XdrvMailbox.payload;
Settings->energy_max_current = XdrvMailbox.payload;
}
ResponseCmndNumber(Settings.energy_max_current);
ResponseCmndNumber(Settings->energy_max_current);
}
#ifdef USE_ENERGY_POWER_LIMIT
void CmndMaxPower(void) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) {
Settings.energy_max_power_limit = XdrvMailbox.payload;
Settings->energy_max_power_limit = XdrvMailbox.payload;
}
ResponseCmndNumber(Settings.energy_max_power_limit);
ResponseCmndNumber(Settings->energy_max_power_limit);
}
void CmndMaxPowerHold(void) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) {
Settings.energy_max_power_limit_hold = (1 == XdrvMailbox.payload) ? MAX_POWER_HOLD : XdrvMailbox.payload;
Settings->energy_max_power_limit_hold = (1 == XdrvMailbox.payload) ? MAX_POWER_HOLD : XdrvMailbox.payload;
}
ResponseCmndNumber(Settings.energy_max_power_limit_hold);
ResponseCmndNumber(Settings->energy_max_power_limit_hold);
}
void CmndMaxPowerWindow(void) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) {
Settings.energy_max_power_limit_window = (1 == XdrvMailbox.payload) ? MAX_POWER_WINDOW : XdrvMailbox.payload;
Settings->energy_max_power_limit_window = (1 == XdrvMailbox.payload) ? MAX_POWER_WINDOW : XdrvMailbox.payload;
}
ResponseCmndNumber(Settings.energy_max_power_limit_window);
ResponseCmndNumber(Settings->energy_max_power_limit_window);
}
void CmndSafePower(void) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) {
Settings.energy_max_power_safe_limit = XdrvMailbox.payload;
Settings->energy_max_power_safe_limit = XdrvMailbox.payload;
}
ResponseCmndNumber(Settings.energy_max_power_safe_limit);
ResponseCmndNumber(Settings->energy_max_power_safe_limit);
}
void CmndSafePowerHold(void) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) {
Settings.energy_max_power_safe_limit_hold = (1 == XdrvMailbox.payload) ? SAFE_POWER_HOLD : XdrvMailbox.payload;
Settings->energy_max_power_safe_limit_hold = (1 == XdrvMailbox.payload) ? SAFE_POWER_HOLD : XdrvMailbox.payload;
}
ResponseCmndNumber(Settings.energy_max_power_safe_limit_hold);
ResponseCmndNumber(Settings->energy_max_power_safe_limit_hold);
}
void CmndSafePowerWindow(void) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 1440)) {
Settings.energy_max_power_safe_limit_window = (1 == XdrvMailbox.payload) ? SAFE_POWER_WINDOW : XdrvMailbox.payload;
Settings->energy_max_power_safe_limit_window = (1 == XdrvMailbox.payload) ? SAFE_POWER_WINDOW : XdrvMailbox.payload;
}
ResponseCmndNumber(Settings.energy_max_power_safe_limit_window);
ResponseCmndNumber(Settings->energy_max_power_safe_limit_window);
}
void CmndMaxEnergy(void) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) {
Settings.energy_max_energy = XdrvMailbox.payload;
Settings->energy_max_energy = XdrvMailbox.payload;
Energy.max_energy_state = 3;
}
ResponseCmndNumber(Settings.energy_max_energy);
ResponseCmndNumber(Settings->energy_max_energy);
}
void CmndMaxEnergyStart(void) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 24)) {
Settings.energy_max_energy_start = XdrvMailbox.payload;
Settings->energy_max_energy_start = XdrvMailbox.payload;
}
ResponseCmndNumber(Settings.energy_max_energy_start);
ResponseCmndNumber(Settings->energy_max_energy_start);
}
#endif // USE_ENERGY_POWER_LIMIT
#endif // USE_ENERGY_MARGIN_DETECTION
@ -994,8 +994,8 @@ void EnergyShow(bool json)
}
}
dtostrfd(apparent_power, Settings.flag2.wattage_resolution, apparent_power_chr[i]);
dtostrfd(reactive_power, Settings.flag2.wattage_resolution, reactive_power_chr[i]);
dtostrfd(apparent_power, Settings->flag2.wattage_resolution, apparent_power_chr[i]);
dtostrfd(reactive_power, Settings->flag2.wattage_resolution, reactive_power_chr[i]);
dtostrfd(power_factor, 2, power_factor_chr[i]);
}
}
@ -1004,7 +1004,7 @@ void EnergyShow(bool json)
if (isnan(Energy.frequency[i])) {
frequency = 0;
}
dtostrfd(frequency, Settings.flag2.frequency_resolution, frequency_chr[i]);
dtostrfd(frequency, Settings->flag2.frequency_resolution, frequency_chr[i]);
}
}
@ -1016,31 +1016,31 @@ void EnergyShow(bool json)
#endif // SDM630_IMPORT || SDM72_IMPEXP
char export_active_chr[Energy.phase_count][FLOATSZ];
for (uint32_t i = 0; i < Energy.phase_count; i++) {
dtostrfd(Energy.voltage[i], Settings.flag2.voltage_resolution, voltage_chr[i]);
dtostrfd(Energy.current[i], Settings.flag2.current_resolution, current_chr[i]);
dtostrfd(Energy.active_power[i], Settings.flag2.wattage_resolution, active_power_chr[i]);
dtostrfd(Energy.voltage[i], Settings->flag2.voltage_resolution, voltage_chr[i]);
dtostrfd(Energy.current[i], Settings->flag2.current_resolution, current_chr[i]);
dtostrfd(Energy.active_power[i], Settings->flag2.wattage_resolution, active_power_chr[i]);
#if defined(SDM630_IMPORT) || defined(SDM72_IMPEXP)
dtostrfd(Energy.import_active[i], Settings.flag2.energy_resolution, import_active_chr[i]);
dtostrfd(Energy.import_active[i], Settings->flag2.energy_resolution, import_active_chr[i]);
#endif // SDM630_IMPORT || SDM72_IMPEXP
dtostrfd(Energy.export_active[i], Settings.flag2.energy_resolution, export_active_chr[i]);
dtostrfd(Energy.export_active[i], Settings->flag2.energy_resolution, export_active_chr[i]);
}
char energy_total_chr[FLOATSZ];
dtostrfd(Energy.total, Settings.flag2.energy_resolution, energy_total_chr);
dtostrfd(Energy.total, Settings->flag2.energy_resolution, energy_total_chr);
char energy_daily_chr[FLOATSZ];
dtostrfd(Energy.daily, Settings.flag2.energy_resolution, energy_daily_chr);
dtostrfd(Energy.daily, Settings->flag2.energy_resolution, energy_daily_chr);
char energy_yesterday_chr[FLOATSZ];
dtostrfd((float)Settings.energy_kWhyesterday / 100000, Settings.flag2.energy_resolution, energy_yesterday_chr);
dtostrfd((float)Settings->energy_kWhyesterday / 100000, Settings->flag2.energy_resolution, energy_yesterday_chr);
bool energy_tariff = false;
char energy_usage_chr[2][FLOATSZ];
char energy_return_chr[2][FLOATSZ];
if (Settings.tariff[0][0] != Settings.tariff[1][0]) {
dtostrfd((float)RtcSettings.energy_usage.usage1_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_usage_chr[0]); // Tariff1
dtostrfd((float)RtcSettings.energy_usage.usage2_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_usage_chr[1]); // Tariff2
dtostrfd((float)RtcSettings.energy_usage.return1_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_return_chr[0]); // Tariff1
dtostrfd((float)RtcSettings.energy_usage.return2_kWhtotal / 100000, Settings.flag2.energy_resolution, energy_return_chr[1]); // Tariff2
if (Settings->tariff[0][0] != Settings->tariff[1][0]) {
dtostrfd((float)RtcSettings.energy_usage.usage1_kWhtotal / 100000, Settings->flag2.energy_resolution, energy_usage_chr[0]); // Tariff1
dtostrfd((float)RtcSettings.energy_usage.usage2_kWhtotal / 100000, Settings->flag2.energy_resolution, energy_usage_chr[1]); // Tariff2
dtostrfd((float)RtcSettings.energy_usage.return1_kWhtotal / 100000, Settings->flag2.energy_resolution, energy_return_chr[0]); // Tariff1
dtostrfd((float)RtcSettings.energy_usage.return2_kWhtotal / 100000, Settings->flag2.energy_resolution, energy_return_chr[1]); // Tariff2
energy_tariff = true;
}
@ -1088,7 +1088,7 @@ void EnergyShow(bool json)
float energy = (float)(RtcSettings.energy_kWhtoday - Energy.period) / 100;
Energy.period = RtcSettings.energy_kWhtoday;
char energy_period_chr[FLOATSZ];
dtostrfd(energy, Settings.flag2.wattage_resolution, energy_period_chr);
dtostrfd(energy, Settings->flag2.wattage_resolution, energy_period_chr);
ResponseAppend_P(PSTR(",\"" D_JSON_PERIOD "\":%s"), energy_period_chr);
}
ResponseAppend_P(PSTR(",\"" D_JSON_POWERUSAGE "\":%s"),
@ -1149,7 +1149,7 @@ void EnergyShow(bool json)
}
KnxSensor(KNX_ENERGY_DAILY, Energy.daily);
KnxSensor(KNX_ENERGY_TOTAL, Energy.total);
KnxSensor(KNX_ENERGY_YESTERDAY, (float)Settings.energy_kWhyesterday / 100000);
KnxSensor(KNX_ENERGY_YESTERDAY, (float)Settings->energy_kWhyesterday / 100000);
}
#endif // USE_KNX
#ifdef USE_WEBSERVER

View File

@ -738,31 +738,31 @@ public:
void loadSettings() {
#ifdef DEBUG_LIGHT
AddLog(LOG_LEVEL_DEBUG_MORE, "LightControllerClass::loadSettings Settings.light_color (%d %d %d %d %d - %d)",
Settings.light_color[0], Settings.light_color[1], Settings.light_color[2],
Settings.light_color[3], Settings.light_color[4], Settings.light_dimmer);
AddLog(LOG_LEVEL_DEBUG_MORE, "LightControllerClass::loadSettings Settings->light_color (%d %d %d %d %d - %d)",
Settings->light_color[0], Settings->light_color[1], Settings->light_color[2],
Settings->light_color[3], Settings->light_color[4], Settings->light_dimmer);
AddLog(LOG_LEVEL_DEBUG_MORE, "LightControllerClass::loadSettings light_type/sub (%d %d)",
TasmotaGlobal.light_type, Light.subtype);
#endif
if (_pwm_multi_channels) {
_state->setChannelsRaw(Settings.light_color);
_state->setChannelsRaw(Settings->light_color);
} else {
// first try setting CW, if zero, it select RGB mode
_state->setCW(Settings.light_color[3], Settings.light_color[4], true);
_state->setRGB(Settings.light_color[0], Settings.light_color[1], Settings.light_color[2]);
_state->setCW(Settings->light_color[3], Settings->light_color[4], true);
_state->setRGB(Settings->light_color[0], Settings->light_color[1], Settings->light_color[2]);
// only if non-multi channel
// We apply dimmer in priority to RGB
uint8_t bri = _state->DimmerToBri(Settings.light_dimmer);
uint8_t bri = _state->DimmerToBri(Settings->light_dimmer);
// The default values are #FFFFFFFFFF, in this case we avoid setting all channels
// at the same time, see #6534 and #8120
if ((DEFAULT_LIGHT_COMPONENT == Settings.light_color[0]) &&
(DEFAULT_LIGHT_COMPONENT == Settings.light_color[1]) &&
(DEFAULT_LIGHT_COMPONENT == Settings.light_color[2]) &&
(DEFAULT_LIGHT_COMPONENT == Settings.light_color[3]) &&
(DEFAULT_LIGHT_COMPONENT == Settings.light_color[4]) &&
(DEFAULT_LIGHT_DIMMER == Settings.light_dimmer) ) {
if ((DEFAULT_LIGHT_COMPONENT == Settings->light_color[0]) &&
(DEFAULT_LIGHT_COMPONENT == Settings->light_color[1]) &&
(DEFAULT_LIGHT_COMPONENT == Settings->light_color[2]) &&
(DEFAULT_LIGHT_COMPONENT == Settings->light_color[3]) &&
(DEFAULT_LIGHT_COMPONENT == Settings->light_color[4]) &&
(DEFAULT_LIGHT_DIMMER == Settings->light_dimmer) ) {
if ((LST_COLDWARM == Light.subtype) || (LST_RGBCW == Light.subtype)) {
_state->setCW(255, 0); // avoid having both white channels at 100%, zero second channel (#see 8120)
}
@ -771,7 +771,7 @@ public:
_state->setColorMode(LCM_RGB);
}
if (Settings.light_color[0] + Settings.light_color[1] + Settings.light_color[2] > 0) {
if (Settings->light_color[0] + Settings->light_color[1] + Settings->light_color[2] > 0) {
_state->setBriRGB(bri);
} else {
_state->setBriCT(bri);
@ -892,33 +892,33 @@ public:
calcLevels();
}
// save the current light state to Settings.
// save the current light state to Settings->
void saveSettings() {
if (Light.pwm_multi_channels) {
// simply save each channel
_state->getChannelsRaw(Settings.light_color);
Settings.light_dimmer = 100; // arbitrary value, unused in this mode
_state->getChannelsRaw(Settings->light_color);
Settings->light_dimmer = 100; // arbitrary value, unused in this mode
} else {
uint8_t cm = _state->getColorMode();
memset(&Settings.light_color[0], 0, sizeof(Settings.light_color)); // clear all channels
memset(&Settings->light_color[0], 0, sizeof(Settings->light_color)); // clear all channels
if (LCM_RGB & cm) { // can be either LCM_RGB or LCM_BOTH
_state->getRGB(&Settings.light_color[0], &Settings.light_color[1], &Settings.light_color[2]);
Settings.light_dimmer = _state->BriToDimmer(_state->getBriRGB());
_state->getRGB(&Settings->light_color[0], &Settings->light_color[1], &Settings->light_color[2]);
Settings->light_dimmer = _state->BriToDimmer(_state->getBriRGB());
// anyways we always store RGB with BrightnessRGB
if (LCM_BOTH == cm) {
// then store at actual brightness CW/WW if dual mode
_state->getActualRGBCW(nullptr, nullptr, nullptr, &Settings.light_color[3], &Settings.light_color[4]);
_state->getActualRGBCW(nullptr, nullptr, nullptr, &Settings->light_color[3], &Settings->light_color[4]);
}
} else if (LCM_CT == cm) { // cm can only be LCM_CT
_state->getCW(&Settings.light_color[3], &Settings.light_color[4]);
Settings.light_dimmer = _state->BriToDimmer(_state->getBriCT());
_state->getCW(&Settings->light_color[3], &Settings->light_color[4]);
Settings->light_dimmer = _state->BriToDimmer(_state->getBriCT());
}
}
#ifdef DEBUG_LIGHT
AddLog(LOG_LEVEL_DEBUG_MORE, "LightControllerClass::saveSettings Settings.light_color (%d %d %d %d %d - %d)",
Settings.light_color[0], Settings.light_color[1], Settings.light_color[2],
Settings.light_color[3], Settings.light_color[4], Settings.light_dimmer);
AddLog(LOG_LEVEL_DEBUG_MORE, "LightControllerClass::saveSettings Settings->light_color (%d %d %d %d %d - %d)",
Settings->light_color[0], Settings->light_color[1], Settings->light_color[2],
Settings->light_color[3], Settings->light_color[4], Settings->light_dimmer);
#endif
}
@ -968,7 +968,7 @@ void checkVirtualCT(void) {
// Init default values for virtual CT, depending on the number of channels
void initCTRange(uint32_t channels) {
if (channels == 4) {
if (Settings.flag4.virtual_ct_cw) { // Hardware White is Cold White
if (Settings->flag4.virtual_ct_cw) { // Hardware White is Cold White
memcpy_P(Light.vct_color[0], CT_PIVOTS_CWW, sizeof(Light.vct_color[0])); // Cold white
memcpy_P(Light.vct_color[1], CT_PIVOTS_RGB, sizeof(Light.vct_color[1])); // Warm white
} else { // Hardware White is Warm White
@ -1002,7 +1002,7 @@ void setCTRange(uint16_t ct_min, uint16_t ct_max) {
}
void setAlexaCTRange(void) { // depending on SetOption82, full or limited CT range
if (Settings.flag4.alexa_ct_range) {
if (Settings->flag4.alexa_ct_range) {
setCTRange(CT_MIN_ALEXA, CT_MAX_ALEXA);
} else {
setCTRange(CT_MIN, CT_MAX);
@ -1020,7 +1020,7 @@ bool LightModuleInit(void)
{
TasmotaGlobal.light_type = LT_BASIC; // Use basic PWM control if SetOption15 = 0
if (Settings.flag.pwm_control) { // SetOption15 - Switch between commands PWM or COLOR/DIMMER/CT/CHANNEL
if (Settings->flag.pwm_control) { // SetOption15 - Switch between commands PWM or COLOR/DIMMER/CT/CHANNEL
for (uint32_t i = 0; i < MAX_PWMS; i++) {
if (PinUsed(GPIO_PWM1, i)) { TasmotaGlobal.light_type++; } // Use Dimmer/Color control for all PWM as SetOption15 = 1
}
@ -1053,7 +1053,7 @@ bool LightModuleInit(void)
#ifdef USE_PWM_DIMMER
#ifdef USE_DEVICE_GROUPS
else if (PWM_DIMMER == TasmotaGlobal.module_type) {
TasmotaGlobal.light_type = Settings.pwm_dimmer_cfg.pwm_count + 1;
TasmotaGlobal.light_type = Settings->pwm_dimmer_cfg.pwm_count + 1;
}
#endif // USE_DEVICE_GROUPS
#endif // USE_PWM_DIMMER
@ -1064,16 +1064,16 @@ bool LightModuleInit(void)
// post-process for lights
uint32_t pwm_channels = (TasmotaGlobal.light_type & 7) > LST_MAX ? LST_MAX : (TasmotaGlobal.light_type & 7);
if (Settings.flag3.pwm_multi_channels) { // SetOption68 - Enable multi-channels PWM instead of Color PWM
if (Settings->flag3.pwm_multi_channels) { // SetOption68 - Enable multi-channels PWM instead of Color PWM
if (0 == pwm_channels) { pwm_channels = 1; }
TasmotaGlobal.devices_present += pwm_channels - 1; // add the pwm channels controls at the end
} else if ((Settings.param[P_RGB_REMAP] & 128) && (LST_RGBW <= pwm_channels)) { // SetOption37
} else if ((Settings->param[P_RGB_REMAP] & 128) && (LST_RGBW <= pwm_channels)) { // SetOption37
// if RGBW or RGBCW, and SetOption37 >= 128, we manage RGB and W separately, hence adding a device
TasmotaGlobal.devices_present++;
} else {
#ifdef USE_LIGHT_VIRTUAL_CT
initCTRange(pwm_channels);
if ((Settings.flag4.virtual_ct) && (LST_RGB <= pwm_channels)) {
if ((Settings->flag4.virtual_ct) && (LST_RGB <= pwm_channels)) {
Light.virtual_ct = true; // enabled
TasmotaGlobal.light_type += 5 - pwm_channels; // pretend it is a 5 channels bulb
}
@ -1088,43 +1088,43 @@ bool LightModuleInit(void)
void LightCalcPWMRange(void) {
uint16_t pwm_min, pwm_max;
pwm_min = change8to10(LightStateClass::DimmerToBri(Settings.dimmer_hw_min)); // default 0
pwm_max = change8to10(LightStateClass::DimmerToBri(Settings.dimmer_hw_max)); // default 100
if (Settings.light_correction) {
pwm_min = change8to10(LightStateClass::DimmerToBri(Settings->dimmer_hw_min)); // default 0
pwm_max = change8to10(LightStateClass::DimmerToBri(Settings->dimmer_hw_max)); // default 100
if (Settings->light_correction) {
pwm_min = ledGamma10_10(pwm_min); // apply gamma correction
pwm_max = ledGamma10_10(pwm_max); // 0..1023
}
pwm_min = pwm_min > 0 ? changeUIntScale(pwm_min, 1, 1023, 1, Settings.pwm_range) : 0; // adapt range but keep zero and non-zero values
pwm_max = changeUIntScale(pwm_max, 1, 1023, 1, Settings.pwm_range); // pwm_max cannot be zero
pwm_min = pwm_min > 0 ? changeUIntScale(pwm_min, 1, 1023, 1, Settings->pwm_range) : 0; // adapt range but keep zero and non-zero values
pwm_max = changeUIntScale(pwm_max, 1, 1023, 1, Settings->pwm_range); // pwm_max cannot be zero
Light.pwm_min = pwm_min;
Light.pwm_max = pwm_max;
//AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("LightCalcPWMRange %d %d - %d %d"), Settings.dimmer_hw_min, Settings.dimmer_hw_max, Light.pwm_min, Light.pwm_max);
//AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("LightCalcPWMRange %d %d - %d %d"), Settings->dimmer_hw_min, Settings->dimmer_hw_max, Light.pwm_min, Light.pwm_max);
}
void LightSetScheme(uint32_t scheme) {
if (!scheme && Settings.light_scheme) {
if (!scheme && Settings->light_scheme) {
Light.update = true;
}
Settings.light_scheme = scheme;
Settings->light_scheme = scheme;
}
void LightInit(void)
{
// move white blend mode from deprecated `RGBWWTable` to `SetOption105`
if (0 == Settings.rgbwwTable[4]) {
Settings.flag4.white_blend_mode = true;
Settings.rgbwwTable[4] = 255; // set RGBWWTable value to its default
if (0 == Settings->rgbwwTable[4]) {
Settings->flag4.white_blend_mode = true;
Settings->rgbwwTable[4] = 255; // set RGBWWTable value to its default
}
Light.device = TasmotaGlobal.devices_present;
Light.subtype = (TasmotaGlobal.light_type & 7) > LST_MAX ? LST_MAX : (TasmotaGlobal.light_type & 7); // Always 0 - LST_MAX (5)
Light.pwm_multi_channels = Settings.flag3.pwm_multi_channels; // SetOption68 - Enable multi-channels PWM instead of Color PWM
Light.pwm_multi_channels = Settings->flag3.pwm_multi_channels; // SetOption68 - Enable multi-channels PWM instead of Color PWM
if (LST_RGBW <= Light.subtype) {
// only change if RGBW or RGBCW
// do not allow independant RGB and WC colors
bool ct_rgb_linked = !(Settings.param[P_RGB_REMAP] & 128); // SetOption37
bool ct_rgb_linked = !(Settings->param[P_RGB_REMAP] & 128); // SetOption37
light_controller.setCTRGBLinked(ct_rgb_linked);
}
@ -1148,11 +1148,11 @@ void LightInit(void)
light_controller.calcLevels(); // calculate the initial values (#8058)
if (LST_SINGLE == Light.subtype) {
Settings.light_color[0] = 255; // One channel only supports Dimmer but needs max color
Settings->light_color[0] = 255; // One channel only supports Dimmer but needs max color
}
if (TasmotaGlobal.light_type < LT_PWM6) { // PWM
for (uint32_t i = 0; i < TasmotaGlobal.light_type; i++) {
Settings.pwm_value[i] = 0; // Disable direct PWM control
Settings->pwm_value[i] = 0; // Disable direct PWM control
if (PinUsed(GPIO_PWM1, i)) {
#ifdef ESP8266
pinMode(Pin(GPIO_PWM1, i), OUTPUT);
@ -1174,16 +1174,16 @@ void LightInit(void)
if (Light.subtype < LST_RGB) {
max_scheme = LS_POWER;
}
if ((LS_WAKEUP == Settings.light_scheme) || (Settings.light_scheme > max_scheme)) {
if ((LS_WAKEUP == Settings->light_scheme) || (Settings->light_scheme > max_scheme)) {
LightSetScheme(LS_POWER);
}
Light.power = 0;
Light.update = true;
Light.wakeup_active = 0;
if (0 == Settings.light_wakeup) {
Settings.light_wakeup = 60; // Fix divide by zero exception 0 in Animate
if (0 == Settings->light_wakeup) {
Settings->light_wakeup = 60; // Fix divide by zero exception 0 in Animate
}
if (Settings.flag4.fade_at_startup) {
if (Settings->flag4.fade_at_startup) {
Light.fade_initialized = true; // consider fade intialized starting from black
}
@ -1192,7 +1192,7 @@ void LightInit(void)
void LightUpdateColorMapping(void)
{
uint8_t param = Settings.param[P_RGB_REMAP] & 127; // SetOption37
uint8_t param = Settings->param[P_RGB_REMAP] & 127; // SetOption37
if (param > 119){ param = 0; }
uint8_t tmp[] = {0,1,2,3,4};
@ -1215,7 +1215,7 @@ void LightUpdateColorMapping(void)
Light.color_remap[4] = tmp[1-param];
Light.update = true;
//AddLog(LOG_LEVEL_DEBUG, PSTR("%d colors: %d %d %d %d %d") ,Settings.param[P_RGB_REMAP], Light.color_remap[0],Light.color_remap[1],Light.color_remap[2],Light.color_remap[3],Light.color_remap[4]);
//AddLog(LOG_LEVEL_DEBUG, PSTR("%d colors: %d %d %d %d %d") ,Settings->param[P_RGB_REMAP], Light.color_remap[0],Light.color_remap[1],Light.color_remap[2],Light.color_remap[3],Light.color_remap[4]);
}
uint8_t LightGetDimmer(uint8_t dimmer) {
@ -1352,7 +1352,7 @@ void LightSetSignal(uint16_t lo, uint16_t hi, uint16_t value)
/* lo - below lo is green
hi - above hi is red
*/
if (Settings.flag.light_signal) { // SetOption18 - Pair light signal with CO2 sensor
if (Settings->flag.light_signal) { // SetOption18 - Pair light signal with CO2 sensor
uint16_t signal = changeUIntScale(value, lo, hi, 0, 255); // 0..255
// AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "Light signal %d"), signal);
light_controller.changeRGB(signal, 255 - signal, 0, true); // keep bri
@ -1366,12 +1366,12 @@ void LightSetSignal(uint16_t lo, uint16_t hi, uint16_t value)
// convert channels to string, use Option 17 to foce decimal, unless force_hex
char* LightGetColor(char* scolor, boolean force_hex = false)
{
if ((0 == Settings.light_scheme) || (!Light.pwm_multi_channels)) {
if ((0 == Settings->light_scheme) || (!Light.pwm_multi_channels)) {
light_controller.calcLevels(); // recalculate levels only if Scheme 0, otherwise we mess up levels
}
scolor[0] = '\0';
for (uint32_t i = 0; i < Light.subtype; i++) {
if (!force_hex && Settings.flag.decimal_text) { // SetOption17 - Switch between decimal or hexadecimal output
if (!force_hex && Settings->flag.decimal_text) { // SetOption17 - Switch between decimal or hexadecimal output
snprintf_P(scolor, LIGHT_COLOR_SIZE, PSTR("%s%s%d"), scolor, (i > 0) ? "," : "", Light.current_color[i]);
} else {
snprintf_P(scolor, LIGHT_COLOR_SIZE, PSTR("%s%02X"), scolor, Light.current_color[i]);
@ -1406,7 +1406,7 @@ void ResponseLightState(uint8_t append)
Light.device, GetStateText(Light.power & 1), light_state.getDimmer(1),
Light.device + 1, GetStateText(Light.power & 2 ? 1 : 0), light_state.getDimmer(2));
} else {
GetPowerDevice(scommand, Light.device, sizeof(scommand), Settings.flag.device_index_enable); // SetOption26 - Switch between POWER or POWER1
GetPowerDevice(scommand, Light.device, sizeof(scommand), Settings->flag.device_index_enable); // SetOption26 - Switch between POWER or POWER1
ResponseAppend_P(PSTR("\"%s\":\"%s\",\"" D_CMND_DIMMER "\":%d"), scommand, GetStateText(Light.power & 1),
light_state.getDimmer());
}
@ -1445,13 +1445,13 @@ void ResponseLightState(uint8_t append)
if (append) {
if (Light.subtype >= LST_RGB) {
ResponseAppend_P(PSTR(",\"" D_CMND_SCHEME "\":%d"), Settings.light_scheme);
ResponseAppend_P(PSTR(",\"" D_CMND_SCHEME "\":%d"), Settings->light_scheme);
}
if (Light.max_scheme > LS_MAX) {
ResponseAppend_P(PSTR(",\"" D_CMND_WIDTH "\":%d"), Settings.light_width);
ResponseAppend_P(PSTR(",\"" D_CMND_WIDTH "\":%d"), Settings->light_width);
}
ResponseAppend_P(PSTR(",\"" D_CMND_FADE "\":\"%s\",\"" D_CMND_SPEED "\":%d,\"" D_CMND_LEDTABLE "\":\"%s\""),
GetStateText(Settings.light_fade), Settings.light_speed, GetStateText(Settings.light_correction));
GetStateText(Settings->light_fade), Settings->light_speed, GetStateText(Settings->light_correction));
}
} else { // Light.pwm_multi_channels
for (uint32_t i = 0; i < Light.subtype; i++) {
@ -1479,7 +1479,7 @@ void LightPreparePower(power_t channels = 0xFFFFFFFF) { // 1 = only RGB, 2 =
if (bitRead(channels, i)) {
// if channel is non-null, channel is supposed to be on, but it is off, do Power On
if ((Light.current_color[i]) && (!bitRead(Light.power, i))) {
if (!Settings.flag.not_power_linked) { // SetOption20 - Control power in relation to Dimmer/Color/Ct changes
if (!Settings->flag.not_power_linked) { // SetOption20 - Control power in relation to Dimmer/Color/Ct changes
ExecuteCommandPower(Light.device + i, POWER_ON_NO_STATE, SRC_LIGHT);
}
} else {
@ -1496,7 +1496,7 @@ void LightPreparePower(power_t channels = 0xFFFFFFFF) { // 1 = only RGB, 2 =
} else {
if (light_controller.isCTRGBLinked()) { // linked, standard
if (light_state.getBri() && !(Light.power)) {
if (!Settings.flag.not_power_linked) { // SetOption20 - Control power in relation to Dimmer/Color/Ct changes
if (!Settings->flag.not_power_linked) { // SetOption20 - Control power in relation to Dimmer/Color/Ct changes
ExecuteCommandPower(Light.device, POWER_ON_NO_STATE, SRC_LIGHT);
}
} else if (!light_state.getBri() && Light.power) {
@ -1506,7 +1506,7 @@ void LightPreparePower(power_t channels = 0xFFFFFFFF) { // 1 = only RGB, 2 =
// RGB
if (channels & 1) {
if (light_state.getBriRGB() && !(Light.power & 1)) {
if (!Settings.flag.not_power_linked) { // SetOption20 - Control power in relation to Dimmer/Color/Ct changes
if (!Settings->flag.not_power_linked) { // SetOption20 - Control power in relation to Dimmer/Color/Ct changes
ExecuteCommandPower(Light.device, POWER_ON_NO_STATE, SRC_LIGHT);
}
} else if (!light_state.getBriRGB() && (Light.power & 1)) {
@ -1516,7 +1516,7 @@ void LightPreparePower(power_t channels = 0xFFFFFFFF) { // 1 = only RGB, 2 =
// White CT
if (channels & 2) {
if (light_state.getBriCT() && !(Light.power & 2)) {
if (!Settings.flag.not_power_linked) { // SetOption20 - Control power in relation to Dimmer/Color/Ct changes
if (!Settings->flag.not_power_linked) { // SetOption20 - Control power in relation to Dimmer/Color/Ct changes
ExecuteCommandPower(Light.device + 1, POWER_ON_NO_STATE, SRC_LIGHT);
}
} else if (!light_state.getBriCT() && (Light.power & 2)) {
@ -1529,7 +1529,7 @@ void LightPreparePower(power_t channels = 0xFFFFFFFF) { // 1 = only RGB, 2 =
#endif // USE_DOMOTICZ
}
if (Settings.flag3.hass_tele_on_power) { // SetOption59 - Send tele/%topic%/STATE in addition to stat/%topic%/RESULT
if (Settings->flag3.hass_tele_on_power) { // SetOption59 - Send tele/%topic%/STATE in addition to stat/%topic%/RESULT
MqttPublishTeleState();
}
@ -1558,9 +1558,9 @@ void LightSetPaletteEntry(void)
void LightCycleColor(int8_t direction)
{
// if (Light.strip_timer_counter % (Settings.light_speed * 2)) { return; } // Speed 1: 24sec, 2: 48sec, 3: 72sec, etc
if (Settings.light_speed > 3) {
if (Light.strip_timer_counter % (Settings.light_speed - 2)) { return; } // Speed 4: 24sec, 5: 36sec, 6: 48sec, etc
// if (Light.strip_timer_counter % (Settings->light_speed * 2)) { return; } // Speed 1: 24sec, 2: 48sec, 3: 72sec, etc
if (Settings->light_speed > 3) {
if (Light.strip_timer_counter % (Settings->light_speed - 2)) { return; } // Speed 4: 24sec, 5: 36sec, 6: 48sec, etc
}
#ifdef USE_LIGHT_PALETTE
@ -1597,8 +1597,8 @@ void LightCycleColor(int8_t direction)
direction = (Light.random &0x01) ? 1 : -1;
}
// if (Settings.light_speed < 3) { direction <<= (3 - Settings.light_speed); } // Speed 1: 12/4=3sec, 2: 12/2=6sec, 3: 12sec
if (Settings.light_speed < 3) { direction *= (4 - Settings.light_speed); } // Speed 1: 12/3=4sec, 2: 12/2=6sec, 3: 12sec
// if (Settings->light_speed < 3) { direction <<= (3 - Settings->light_speed); } // Speed 1: 12/4=3sec, 2: 12/2=6sec, 3: 12sec
if (Settings->light_speed < 3) { direction *= (4 - Settings->light_speed); } // Speed 1: 12/3=4sec, 2: 12/2=6sec, 3: 12sec
Light.wheel += direction;
uint16_t hue = changeUIntScale(Light.wheel, 0, 255, 0, 359); // Scale to hue to keep amount of steps low (max 255 instead of 359)
@ -1648,12 +1648,12 @@ void LightSetPower(void)
bool LightGetFadeSetting(void) {
if (Light.fade_once_enabled) return Light.fade_once_value;
return Settings.light_fade;
return Settings->light_fade;
}
uint8_t LightGetSpeedSetting(void) {
if (Light.speed_once_enabled) return Light.speed_once_value;
return Settings.light_speed;
return Settings->light_speed;
}
// On entry Light.new_color[5] contains the color to be displayed
@ -1669,22 +1669,22 @@ void LightAnimate(void)
// set sleep parameter: either settings,
// or set a maximum of PWM_MAX_SLEEP if light is on or Fade is running
if (Light.power || Light.fade_running) {
if (Settings.sleep > PWM_MAX_SLEEP) {
if (Settings->sleep > PWM_MAX_SLEEP) {
TasmotaGlobal.sleep = PWM_MAX_SLEEP; // set a maximum value (in milliseconds) to sleep to ensure that animations are smooth
} else {
TasmotaGlobal.sleep = Settings.sleep; // or keep the current sleep if it's low enough
TasmotaGlobal.sleep = Settings->sleep; // or keep the current sleep if it's low enough
}
} else {
TasmotaGlobal.sleep = Settings.sleep;
TasmotaGlobal.sleep = Settings->sleep;
}
if (!Light.power) { // All channels powered off
Light.strip_timer_counter = 0;
if (Settings.light_scheme >= LS_MAX) {
if (Settings->light_scheme >= LS_MAX) {
power_off = true;
}
} else {
switch (Settings.light_scheme) {
switch (Settings->light_scheme) {
case LS_POWER:
light_controller.calcLevels(Light.new_color);
break;
@ -1698,9 +1698,9 @@ void LightAnimate(void)
Light.wakeup_start_time = millis();
}
// which step are we in a range 0..1023
uint32_t step_10 = ((millis() - Light.wakeup_start_time) * 1023) / (Settings.light_wakeup * 1000);
uint32_t step_10 = ((millis() - Light.wakeup_start_time) * 1023) / (Settings->light_wakeup * 1000);
if (step_10 > 1023) { step_10 = 1023; } // sanity check
uint8_t wakeup_bri = changeUIntScale(step_10, 0, 1023, 0, LightStateClass::DimmerToBri(Settings.light_dimmer));
uint8_t wakeup_bri = changeUIntScale(step_10, 0, 1023, 0, LightStateClass::DimmerToBri(Settings->light_dimmer));
if (wakeup_bri != light_state.getBri()) {
light_state.setBri(wakeup_bri);
@ -1723,17 +1723,17 @@ void LightAnimate(void)
case LS_CYCLEUP:
case LS_CYCLEDN:
case LS_RANDOM:
if (LS_CYCLEUP == Settings.light_scheme) {
if (LS_CYCLEUP == Settings->light_scheme) {
LightCycleColor(1);
} else if (LS_CYCLEDN == Settings.light_scheme) {
} else if (LS_CYCLEDN == Settings->light_scheme) {
LightCycleColor(-1);
} else {
LightCycleColor(0);
}
if (Light.pwm_multi_channels) { // See #8058
Light.new_color[0] = changeUIntScale(Light.new_color[0], 0, 255, 0, Settings.light_color[0]);
Light.new_color[1] = changeUIntScale(Light.new_color[1], 0, 255, 0, Settings.light_color[1]);
Light.new_color[2] = changeUIntScale(Light.new_color[2], 0, 255, 0, Settings.light_color[2]);
Light.new_color[0] = changeUIntScale(Light.new_color[0], 0, 255, 0, Settings->light_color[0]);
Light.new_color[1] = changeUIntScale(Light.new_color[1], 0, 255, 0, Settings->light_color[1]);
Light.new_color[2] = changeUIntScale(Light.new_color[2], 0, 255, 0, Settings->light_color[2]);
}
break;
default:
@ -1741,15 +1741,15 @@ void LightAnimate(void)
}
#ifdef USE_DEVICE_GROUPS
if (Settings.light_scheme != Light.last_scheme) {
Light.last_scheme = Settings.light_scheme;
SendDeviceGroupMessage(Light.device, DGR_MSGTYP_UPDATE, DGR_ITEM_LIGHT_SCHEME, Settings.light_scheme);
if (Settings->light_scheme != Light.last_scheme) {
Light.last_scheme = Settings->light_scheme;
SendDeviceGroupMessage(Light.device, DGR_MSGTYP_UPDATE, DGR_ITEM_LIGHT_SCHEME, Settings->light_scheme);
Light.devgrp_no_channels_out = false;
}
#endif // USE_DEVICE_GROUPS
}
if ((Settings.light_scheme < LS_MAX) || power_off) { // exclude WS281X Neopixel schemes
if ((Settings->light_scheme < LS_MAX) || power_off) { // exclude WS281X Neopixel schemes
// Apply power modifiers to Light.new_color
LightApplyPower(Light.new_color, Light.power);
@ -1787,16 +1787,16 @@ void LightAnimate(void)
// AddLog(LOG_LEVEL_INFO, PSTR(">>> calcGammaBulbs Out %03X,%03X,%03X,%03X,%03X"), cur_col_10[0], cur_col_10[1], cur_col_10[2], cur_col_10[3], cur_col_10[4]);
}
// Apply RGBWWTable only if not Settings.flag4.white_blend_mode
// Apply RGBWWTable only if not Settings->flag4.white_blend_mode
for (uint32_t i = 0; i < (rgbwwtable_applied_white ? 3 : Light.subtype); i++) {
uint32_t adjust = change8to10(Settings.rgbwwTable[i]);
uint32_t adjust = change8to10(Settings->rgbwwTable[i]);
cur_col_10[i] = changeUIntScale(cur_col_10[i], 0, 1023, 0, adjust);
}
// final adjusments for PMW ranges, post-gamma correction
for (uint32_t i = 0; i < LST_MAX; i++) {
// scale from 0..1023 to 0..pwm_range, but keep any non-zero value to at least 1
cur_col_10[i] = (cur_col_10[i] > 0) ? changeUIntScale(cur_col_10[i], 1, 1023, 1, Settings.pwm_range) : 0;
cur_col_10[i] = (cur_col_10[i] > 0) ? changeUIntScale(cur_col_10[i], 1, 1023, 1, Settings->pwm_range) : 0;
}
// apply port remapping on both 8 bits and 10 bits versions
@ -1847,10 +1847,10 @@ void LightAnimate(void)
}
bool isChannelGammaCorrected(uint32_t channel) {
if (!Settings.light_correction) { return false; } // Gamma correction not activated
if (!Settings->light_correction) { return false; } // Gamma correction not activated
if (channel >= Light.subtype) { return false; } // Out of range
#ifdef ESP8266
if ((PHILIPS == TasmotaGlobal.module_type) || (Settings.flag4.pwm_ct_mode)) {
if ((PHILIPS == TasmotaGlobal.module_type) || (Settings->flag4.pwm_ct_mode)) {
if ((LST_COLDWARM == Light.subtype) && (1 == channel)) { return false; } // PMW reserved for CT
if ((LST_RGBCW == Light.subtype) && (4 == channel)) { return false; } // PMW reserved for CT
}
@ -1861,7 +1861,7 @@ bool isChannelGammaCorrected(uint32_t channel) {
// is the channel a regular PWM or ColorTemp control
bool isChannelCT(uint32_t channel) {
#ifdef ESP8266
if ((PHILIPS == TasmotaGlobal.module_type) || (Settings.flag4.pwm_ct_mode)) {
if ((PHILIPS == TasmotaGlobal.module_type) || (Settings->flag4.pwm_ct_mode)) {
if ((LST_COLDWARM == Light.subtype) && (1 == channel)) { return true; } // PMW reserved for CT
if ((LST_RGBCW == Light.subtype) && (4 == channel)) { return true; } // PMW reserved for CT
}
@ -1916,14 +1916,14 @@ bool LightApplyFade(void) { // did the value chanegd and needs to be applied
}
if (distance > 0) {
// compute the duration of the animation
// Note: Settings.light_speed is the number of half-seconds for a 100% fade,
// Note: Settings->light_speed is the number of half-seconds for a 100% fade,
// i.e. light_speed=1 means 1024 steps in 500ms
Light.fade_duration = LightGetSpeedSetting() * 500;
Light.speed_once_enabled = false; // The once off speed value has been read, reset it
if (!Settings.flag5.fade_fixed_duration) {
if (!Settings->flag5.fade_fixed_duration) {
Light.fade_duration = (distance * Light.fade_duration) / 1023; // time is proportional to distance, except with SO117
}
if (Settings.save_data) {
if (Settings->save_data) {
// Also postpone the save_data for the duration of the Fade (in seconds)
uint32_t delay_seconds = 1 + (Light.fade_duration + 999) / 1000; // add one more second
// AddLog(LOG_LEVEL_INFO, PSTR("delay_seconds %d, save_data_counter %d"), delay_seconds, TasmotaGlobal.save_data_counter);
@ -2005,10 +2005,10 @@ void LightSetOutputs(const uint16_t *cur_col_10) {
//AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "Cur_Col%d 10 bits %d"), i, cur_col_10[i]);
uint16_t cur_col = cur_col_10[i + Light.pwm_offset];
if (!isChannelCT(i)) { // if CT don't use pwm_min and pwm_max
cur_col = cur_col > 0 ? changeUIntScale(cur_col, 0, Settings.pwm_range, Light.pwm_min, Light.pwm_max) : 0; // shrink to the range of pwm_min..pwm_max
cur_col = cur_col > 0 ? changeUIntScale(cur_col, 0, Settings->pwm_range, Light.pwm_min, Light.pwm_max) : 0; // shrink to the range of pwm_min..pwm_max
}
if (!Settings.flag4.zerocross_dimmer) {
analogWrite(Pin(GPIO_PWM1, i), bitRead(TasmotaGlobal.pwm_inverted, i) ? Settings.pwm_range - cur_col : cur_col);
if (!Settings->flag4.zerocross_dimmer) {
analogWrite(Pin(GPIO_PWM1, i), bitRead(TasmotaGlobal.pwm_inverted, i) ? Settings->pwm_range - cur_col : cur_col);
}
#ifdef USE_PWM_DIMMER
// Animate brightness LEDs to follow PWM dimmer brightness
@ -2047,7 +2047,7 @@ void LightSetOutputs(const uint16_t *cur_col_10) {
// Just apply basic Gamma to each channel
void calcGammaMultiChannels(uint16_t cur_col_10[5]) {
// Apply gamma correction for 8 and 10 bits resolutions, if needed
if (Settings.light_correction) {
if (Settings->light_correction) {
for (uint32_t i = 0; i < LST_MAX; i++) {
cur_col_10[i] = ledGamma10_10(cur_col_10[i]);
}
@ -2072,7 +2072,7 @@ void calcGammaBulbCW(uint16_t cw10[2], uint16_t *white_bri10_out, bool *white_fr
bool white_free_cw = (white_bri10 > 1031); // take a margin of 8 above 1023 to account for rounding errors
white_bri10 = (white_bri10 > 1023) ? 1023 : white_bri10; // max 1023
if (Settings.light_correction) {
if (Settings->light_correction) {
if (white_free_cw) {
cw10[0] = ledGamma10_10(cw10[0]);
cw10[1] = ledGamma10_10(cw10[1]);
@ -2103,7 +2103,7 @@ void calcGammaBulbCW(uint16_t cw10[2], uint16_t *white_bri10_out, bool *white_fr
//
void calcGammaBulb5Channels(uint16_t col10[LST_MAX], uint16_t *white_bri10_out, bool *white_free_cw) {
for (uint32_t i = 0; i < 3; i++) {
if (Settings.light_correction) {
if (Settings->light_correction) {
col10[i] = ledGamma10_10(col10[i]);
}
}
@ -2142,7 +2142,7 @@ bool calcGammaBulbs(uint16_t cur_col_10[5]) {
#ifdef ESP8266
if ((LST_COLDWARM == Light.subtype) || (LST_RGBCW == Light.subtype)) {
if ((PHILIPS == TasmotaGlobal.module_type) || (Settings.flag4.pwm_ct_mode)) { // channel 1 is the color tone, mapped to cold channel (0..255)
if ((PHILIPS == TasmotaGlobal.module_type) || (Settings->flag4.pwm_ct_mode)) { // channel 1 is the color tone, mapped to cold channel (0..255)
pwm_ct = true;
// Xiaomi Philips bulbs follow a different scheme:
// channel 0=intensity, channel1=temperature
@ -2155,14 +2155,14 @@ bool calcGammaBulbs(uint16_t cur_col_10[5]) {
// Now see if we need to mix RGB and White
// Valid only for LST_RGBW, LST_RGBCW, SetOption105 1, and white is zero (see doc)
if ((LST_RGBW <= Light.subtype) && (Settings.flag4.white_blend_mode) && (0 == cur_col_10[3]+cur_col_10[4])) {
if ((LST_RGBW <= Light.subtype) && (Settings->flag4.white_blend_mode) && (0 == cur_col_10[3]+cur_col_10[4])) {
uint32_t min_rgb_10 = min3(cur_col_10[0], cur_col_10[1], cur_col_10[2]);
cur_col_10[0] -= min_rgb_10;
cur_col_10[1] -= min_rgb_10;
cur_col_10[2] -= min_rgb_10;
// Add to white level
uint32_t adjust_w_10 = change8to10(Settings.rgbwwTable[3]); // take the correction factor, bought back to 10 bits
uint32_t adjust_w_10 = change8to10(Settings->rgbwwTable[3]); // take the correction factor, bought back to 10 bits
white_bri10 += changeUIntScale(min_rgb_10, 0, 1023, 0, adjust_w_10); // set white power down corrected with rgbwwTable[3]
white_bri10 = (white_bri10 > 1023) ? 1023 : white_bri10; // max 1023
rgbwwtable_applied_white = true;
@ -2251,7 +2251,7 @@ void LightHandleDevGroupItem(void)
static bool send_state = false;
static bool restore_power = false;
if (Settings.flag4.multiple_device_groups ? Settings.device_group_tie[*XdrvMailbox.topic] != Light.device : !(XdrvMailbox.index & DGR_FLAG_LOCAL)) return;
if (Settings->flag4.multiple_device_groups ? Settings->device_group_tie[*XdrvMailbox.topic] != Light.device : !(XdrvMailbox.index & DGR_FLAG_LOCAL)) return;
bool more_to_come;
uint32_t value = XdrvMailbox.payload;
switch (XdrvMailbox.command_code) {
@ -2270,7 +2270,7 @@ void LightHandleDevGroupItem(void)
TasmotaGlobal.skip_light_fade = false;
if (send_state && !more_to_come) {
light_controller.saveSettings();
if (Settings.flag3.hass_tele_on_power) { // SetOption59 - Send tele/%topic%/STATE in addition to stat/%topic%/RESULT
if (Settings->flag3.hass_tele_on_power) { // SetOption59 - Send tele/%topic%/STATE in addition to stat/%topic%/RESULT
MqttPublishTeleState();
}
send_state = false;
@ -2279,13 +2279,13 @@ void LightHandleDevGroupItem(void)
case DGR_ITEM_LIGHT_BRI:
if (light_state.getBri() != value) {
light_state.setBri(value);
Settings.light_dimmer = light_state.BriToDimmer(value);
Settings->light_dimmer = light_state.BriToDimmer(value);
send_state = true;
}
break;
case DGR_ITEM_LIGHT_SCHEME:
if (Settings.light_scheme != value) {
Light.last_scheme = Settings.light_scheme = value;
if (Settings->light_scheme != value) {
Light.last_scheme = Settings->light_scheme = value;
Light.devgrp_no_channels_out = (value != 0);
send_state = true;
}
@ -2339,10 +2339,10 @@ void LightHandleDevGroupItem(void)
if (value > MAX_FIXED_COLOR) value += 200 - MAX_FIXED_COLOR;
}
Light.fixed_color_index = value;
bool save_decimal_text = Settings.flag.decimal_text;
bool save_decimal_text = Settings->flag.decimal_text;
char str[16];
LightColorEntry(str, sprintf_P(str, PSTR("%u"), value));
Settings.flag.decimal_text = save_decimal_text;
Settings->flag.decimal_text = save_decimal_text;
uint32_t old_bri = light_state.getBri();
light_controller.changeChannels(Light.entry_color);
light_controller.changeBri(old_bri);
@ -2355,20 +2355,20 @@ void LightHandleDevGroupItem(void)
}
break;
case DGR_ITEM_LIGHT_FADE:
if (Settings.light_fade != value) {
Settings.light_fade = value;
if (Settings->light_fade != value) {
Settings->light_fade = value;
send_state = true;
}
break;
case DGR_ITEM_LIGHT_SPEED:
if (Settings.light_speed != value && value > 0 && value <= 40) {
Settings.light_speed = value;
if (Settings->light_speed != value && value > 0 && value <= 40) {
Settings->light_speed = value;
send_state = true;
}
break;
case DGR_ITEM_STATUS:
SendDeviceGroupMessage(Light.device, DGR_MSGTYP_PARTIAL_UPDATE, DGR_ITEM_LIGHT_FADE, Settings.light_fade,
DGR_ITEM_LIGHT_SPEED, Settings.light_speed, DGR_ITEM_LIGHT_SCHEME, Settings.light_scheme);
SendDeviceGroupMessage(Light.device, DGR_MSGTYP_PARTIAL_UPDATE, DGR_ITEM_LIGHT_FADE, Settings->light_fade,
DGR_ITEM_LIGHT_SPEED, Settings->light_speed, DGR_ITEM_LIGHT_SCHEME, Settings->light_scheme);
LightSendDeviceGroupStatus();
break;
}
@ -2473,7 +2473,7 @@ bool LightColorEntry(char *buffer, uint32_t buffer_length)
// Too much magic so removed since 9.0.0.3
// if (entry_type) {
// Settings.flag.decimal_text = entry_type -1; // SetOption17 - Switch between decimal or hexadecimal output
// Settings->flag.decimal_text = entry_type -1; // SetOption17 - Switch between decimal or hexadecimal output
// }
return (entry_type);
@ -2510,7 +2510,7 @@ void CmndSupportColor(void)
coldim = true;
} else { // Color3, 4, 5 and 6
for (uint32_t i = 0; i < LST_RGB; i++) {
Settings.ws_color[XdrvMailbox.index -3][i] = Light.entry_color[i];
Settings->ws_color[XdrvMailbox.index -3][i] = Light.entry_color[i];
}
}
}
@ -2522,10 +2522,10 @@ void CmndSupportColor(void)
if (XdrvMailbox.index >= 3) {
scolor[0] = '\0';
for (uint32_t i = 0; i < LST_RGB; i++) {
if (Settings.flag.decimal_text) { // SetOption17 - Switch between decimal or hexadecimal output
snprintf_P(scolor, sizeof(scolor), PSTR("%s%s%d"), scolor, (i > 0) ? "," : "", Settings.ws_color[XdrvMailbox.index -3][i]);
if (Settings->flag.decimal_text) { // SetOption17 - Switch between decimal or hexadecimal output
snprintf_P(scolor, sizeof(scolor), PSTR("%s%s%d"), scolor, (i > 0) ? "," : "", Settings->ws_color[XdrvMailbox.index -3][i]);
} else {
snprintf_P(scolor, sizeof(scolor), PSTR("%s%02X"), scolor, Settings.ws_color[XdrvMailbox.index -3][i]);
snprintf_P(scolor, sizeof(scolor), PSTR("%s%02X"), scolor, Settings->ws_color[XdrvMailbox.index -3][i]);
}
}
ResponseCmndIdxChar(scolor);
@ -2660,11 +2660,11 @@ void CmndScheme(void)
uint32_t max_scheme = Light.max_scheme;
if (1 == XdrvMailbox.data_len) {
if (('+' == XdrvMailbox.data[0]) && (Settings.light_scheme < max_scheme)) {
XdrvMailbox.payload = Settings.light_scheme + ((0 == Settings.light_scheme) ? 2 : 1); // Skip wakeup
if (('+' == XdrvMailbox.data[0]) && (Settings->light_scheme < max_scheme)) {
XdrvMailbox.payload = Settings->light_scheme + ((0 == Settings->light_scheme) ? 2 : 1); // Skip wakeup
}
else if (('-' == XdrvMailbox.data[0]) && (Settings.light_scheme > 0)) {
XdrvMailbox.payload = Settings.light_scheme - ((2 == Settings.light_scheme) ? 2 : 1); // Skip wakeup
else if (('-' == XdrvMailbox.data[0]) && (Settings->light_scheme > 0)) {
XdrvMailbox.payload = Settings->light_scheme - ((2 == Settings->light_scheme) ? 2 : 1); // Skip wakeup
}
}
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= max_scheme)) {
@ -2676,17 +2676,17 @@ void CmndScheme(void)
#endif // USE_LIGHT_PALETTE
}
LightSetScheme(XdrvMailbox.payload);
if (LS_WAKEUP == Settings.light_scheme) {
if (LS_WAKEUP == Settings->light_scheme) {
Light.wakeup_active = 3;
}
LightPowerOn();
Light.strip_timer_counter = 0;
// Publish state message for Hass
if (Settings.flag3.hass_tele_on_power) { // SetOption59 - Send tele/%topic%/STATE in addition to stat/%topic%/RESULT
if (Settings->flag3.hass_tele_on_power) { // SetOption59 - Send tele/%topic%/STATE in addition to stat/%topic%/RESULT
MqttPublishTeleState();
}
}
ResponseCmndNumber(Settings.light_scheme);
ResponseCmndNumber(Settings->light_scheme);
}
}
@ -2731,7 +2731,7 @@ void CmndColorTemperature(void)
void LightDimmerOffset(uint32_t index, int32_t offset) {
int32_t dimmer = light_state.getDimmer(index) + offset;
if (dimmer < 1) { dimmer = Settings.flag3.slider_dimmer_stay_on; } // SetOption77 - Do not power off if slider moved to far left
if (dimmer < 1) { dimmer = Settings->flag3.slider_dimmer_stay_on; } // SetOption77 - Do not power off if slider moved to far left
if (dimmer > 100) { dimmer = 100; }
XdrvMailbox.index = index;
@ -2765,9 +2765,9 @@ void CmndDimmer(void)
// Handle +/-/!/</> special commands
if (1 == XdrvMailbox.data_len) {
if ('+' == XdrvMailbox.data[0]) {
XdrvMailbox.payload = (dimmer > (100 - Settings.dimmer_step - 1)) ? 100 : dimmer + Settings.dimmer_step;
XdrvMailbox.payload = (dimmer > (100 - Settings->dimmer_step - 1)) ? 100 : dimmer + Settings->dimmer_step;
} else if ('-' == XdrvMailbox.data[0]) {
XdrvMailbox.payload = (dimmer < (Settings.dimmer_step + 1)) ? 1 : dimmer - Settings.dimmer_step;
XdrvMailbox.payload = (dimmer < (Settings->dimmer_step + 1)) ? 1 : dimmer - Settings->dimmer_step;
} else if ('!' == XdrvMailbox.data[0] && Light.fade_running) {
XdrvMailbox.payload = LightGetCurFadeBri();
} else if ('<' == XdrvMailbox.data[0] ) {
@ -2802,9 +2802,9 @@ void CmndDimmer(void)
}
#if defined(USE_PWM_DIMMER) && defined(USE_DEVICE_GROUPS)
uint8_t bri = light_state.getBri();
if (bri != Settings.bri_power_on) {
Settings.bri_power_on = bri;
SendDeviceGroupMessage(Light.device, DGR_MSGTYP_PARTIAL_UPDATE, DGR_ITEM_BRI_POWER_ON, Settings.bri_power_on);
if (bri != Settings->bri_power_on) {
Settings->bri_power_on = bri;
SendDeviceGroupMessage(Light.device, DGR_MSGTYP_PARTIAL_UPDATE, DGR_ITEM_BRI_POWER_ON, Settings->bri_power_on);
}
#endif // USE_PWM_DIMMER && USE_DEVICE_GROUPS
Light.update = true;
@ -2821,20 +2821,20 @@ void CmndDimmerRange(void)
// DimmerRange 0,100 - Set dimmer hardware range from 0 to 100 and restart
if (XdrvMailbox.data_len > 0) {
uint32_t parm[2];
parm[0] = Settings.dimmer_hw_min;
parm[1] = Settings.dimmer_hw_max;
parm[0] = Settings->dimmer_hw_min;
parm[1] = Settings->dimmer_hw_max;
ParseParameters(2, parm);
if (parm[0] < parm[1]) {
Settings.dimmer_hw_min = parm[0];
Settings.dimmer_hw_max = parm[1];
Settings->dimmer_hw_min = parm[0];
Settings->dimmer_hw_max = parm[1];
} else {
Settings.dimmer_hw_min = parm[1];
Settings.dimmer_hw_max = parm[0];
Settings->dimmer_hw_min = parm[1];
Settings->dimmer_hw_max = parm[0];
}
LightCalcPWMRange();
Light.update = true;
}
Response_P(PSTR("{\"" D_CMND_DIMMER_RANGE "\":{\"Min\":%d,\"Max\":%d}}"), Settings.dimmer_hw_min, Settings.dimmer_hw_max);
Response_P(PSTR("{\"" D_CMND_DIMMER_RANGE "\":{\"Min\":%d,\"Max\":%d}}"), Settings->dimmer_hw_min, Settings->dimmer_hw_max);
}
void CmndDimmerStep(void)
@ -2843,14 +2843,14 @@ void CmndDimmerStep(void)
// DimmerStep 1..50 - Set dimmer step
if (XdrvMailbox.data_len > 0) {
if (XdrvMailbox.payload < 1) {
Settings.dimmer_step = 1;
Settings->dimmer_step = 1;
} else if (XdrvMailbox.payload > 50) {
Settings.dimmer_step = 50;
Settings->dimmer_step = 50;
} else {
Settings.dimmer_step = XdrvMailbox.payload;
Settings->dimmer_step = XdrvMailbox.payload;
}
}
ResponseCmndNumber(Settings.dimmer_step);
ResponseCmndNumber(Settings->dimmer_step);
}
void CmndLedTable(void)
@ -2863,16 +2863,16 @@ void CmndLedTable(void)
switch (XdrvMailbox.payload) {
case 0: // Off
case 1: // On
Settings.light_correction = XdrvMailbox.payload;
Settings->light_correction = XdrvMailbox.payload;
break;
case 2: // Toggle
Settings.light_correction ^= 1;
Settings->light_correction ^= 1;
break;
}
LightCalcPWMRange();
Light.update = true;
}
ResponseCmndStateText(Settings.light_correction);
ResponseCmndStateText(Settings->light_correction);
}
void CmndRgbwwTable(void)
@ -2883,14 +2883,14 @@ void CmndRgbwwTable(void)
uint32_t parm[LST_RGBCW -1];
uint32_t parmcount = ParseParameters(LST_RGBCW, parm);
for (uint32_t i = 0; i < parmcount; i++) {
Settings.rgbwwTable[i] = parm[i];
Settings->rgbwwTable[i] = parm[i];
}
Light.update = true;
}
char scolor[LIGHT_COLOR_SIZE];
scolor[0] = '\0';
for (uint32_t i = 0; i < LST_RGBCW; i++) {
snprintf_P(scolor, sizeof(scolor), PSTR("%s%s%d"), scolor, (i > 0) ? "," : "", Settings.rgbwwTable[i]);
snprintf_P(scolor, sizeof(scolor), PSTR("%s%s%d"), scolor, (i > 0) ? "," : "", Settings->rgbwwTable[i]);
}
ResponseCmndChar(scolor);
}
@ -2907,18 +2907,18 @@ void CmndFade(void)
switch (XdrvMailbox.payload) {
case 0: // Off
case 1: // On
Settings.light_fade = XdrvMailbox.payload;
Settings->light_fade = XdrvMailbox.payload;
break;
case 2: // Toggle
Settings.light_fade ^= 1;
Settings->light_fade ^= 1;
break;
}
#ifdef USE_DEVICE_GROUPS
if (XdrvMailbox.payload >= 0 && XdrvMailbox.payload <= 2) SendDeviceGroupMessage(Light.device, DGR_MSGTYP_UPDATE, DGR_ITEM_LIGHT_FADE, Settings.light_fade);
if (XdrvMailbox.payload >= 0 && XdrvMailbox.payload <= 2) SendDeviceGroupMessage(Light.device, DGR_MSGTYP_UPDATE, DGR_ITEM_LIGHT_FADE, Settings->light_fade);
#endif // USE_DEVICE_GROUPS
if (!Settings.light_fade) { Light.fade_running = false; }
if (!Settings->light_fade) { Light.fade_running = false; }
}
ResponseCmndStateText(Settings.light_fade);
ResponseCmndStateText(Settings->light_fade);
}
void CmndSpeed(void)
@ -2939,20 +2939,20 @@ void CmndSpeed(void)
// Speed + - Increment Speed
// Speed - - Decrement Speed
if (1 == XdrvMailbox.data_len) {
if (('+' == XdrvMailbox.data[0]) && (Settings.light_speed > 1)) {
XdrvMailbox.payload = Settings.light_speed - 1;
if (('+' == XdrvMailbox.data[0]) && (Settings->light_speed > 1)) {
XdrvMailbox.payload = Settings->light_speed - 1;
}
else if (('-' == XdrvMailbox.data[0]) && (Settings.light_speed < 40)) {
XdrvMailbox.payload = Settings.light_speed + 1;
else if (('-' == XdrvMailbox.data[0]) && (Settings->light_speed < 40)) {
XdrvMailbox.payload = Settings->light_speed + 1;
}
}
if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 40)) {
Settings.light_speed = XdrvMailbox.payload;
Settings->light_speed = XdrvMailbox.payload;
#ifdef USE_DEVICE_GROUPS
SendDeviceGroupMessage(Light.device, DGR_MSGTYP_UPDATE, DGR_ITEM_LIGHT_SPEED, Settings.light_speed);
SendDeviceGroupMessage(Light.device, DGR_MSGTYP_UPDATE, DGR_ITEM_LIGHT_SPEED, Settings->light_speed);
#endif // USE_DEVICE_GROUPS
}
ResponseCmndNumber(Settings.light_speed);
ResponseCmndNumber(Settings->light_speed);
}
}
@ -2961,10 +2961,10 @@ void CmndWakeupDuration(void)
// WakeUpDuration - Show current Wake Up duration in seconds
// WakeUpDuration 60 - Set Wake Up duration to 60 seconds
if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 3001)) {
Settings.light_wakeup = XdrvMailbox.payload;
Settings->light_wakeup = XdrvMailbox.payload;
Light.wakeup_active = 0;
}
ResponseCmndNumber(Settings.light_wakeup);
ResponseCmndNumber(Settings->light_wakeup);
}
void CmndCTRange(void)
@ -2994,7 +2994,7 @@ void CmndCTRange(void)
#ifdef USE_LIGHT_VIRTUAL_CT
void CmndVirtualCT(void)
{
if (!Settings.flag4.virtual_ct) {
if (!Settings->flag4.virtual_ct) {
ResponseCmndChar_P(PSTR("You need to enable `SetOption106 1`"));
return;
}
@ -3086,7 +3086,7 @@ void CmndPalette(void)
if (Light.palette_count) {
palette_entry = Light.palette;
for (int entry = 0; entry < Light.palette_count; entry++) {
if (Settings.flag.decimal_text) { // SetOption17 - Switch between decimal or hexadecimal output
if (Settings->flag.decimal_text) { // SetOption17 - Switch between decimal or hexadecimal output
*p++ = '"';
for (uint32_t i = 0; i < Light.subtype; i++) {
p += sprintf_P(p, PSTR("%d,"), *palette_entry++);
@ -3140,7 +3140,7 @@ void CmndUndocA(void)
char scolor[LIGHT_COLOR_SIZE];
LightGetColor(scolor, true); // force hex whatever Option 17
scolor[6] = '\0'; // RGB only
Response_P(PSTR("%s,%d,%d,%d,%d,%d"), scolor, Settings.light_fade, Settings.light_correction, Settings.light_scheme, Settings.light_speed, Settings.light_width);
Response_P(PSTR("%s,%d,%d,%d,%d,%d"), scolor, Settings->light_fade, Settings->light_correction, Settings->light_scheme, Settings->light_speed, Settings->light_width);
MqttPublishPrefixTopicRulesProcess_P(STAT, XdrvMailbox.topic);
ResponseClear();
}

View File

@ -190,8 +190,8 @@ unsigned long ir_lasttime = 0;
void IrReceiveUpdateThreshold(void)
{
if (irrecv != nullptr) {
if (Settings.param[P_IR_UNKNOW_THRESHOLD] < 6) { Settings.param[P_IR_UNKNOW_THRESHOLD] = 6; }
irrecv->setUnknownThreshold(Settings.param[P_IR_UNKNOW_THRESHOLD]);
if (Settings->param[P_IR_UNKNOW_THRESHOLD] < 6) { Settings->param[P_IR_UNKNOW_THRESHOLD] = 6; }
irrecv->setUnknownThreshold(Settings->param[P_IR_UNKNOW_THRESHOLD]);
}
}
@ -199,7 +199,7 @@ void IrReceiveInit(void)
{
// an IR led is at GPIO_IRRECV
irrecv = new IRrecv(Pin(GPIO_IRRECV), IR_RCV_BUFFER_SIZE, IR_RCV_TIMEOUT, IR_RCV_SAVE_BUFFER);
irrecv->setUnknownThreshold(Settings.param[P_IR_UNKNOW_THRESHOLD]);
irrecv->setUnknownThreshold(Settings->param[P_IR_UNKNOW_THRESHOLD]);
irrecv->enableIRIn(); // Start the receiver
// AddLog(LOG_LEVEL_DEBUG, PSTR("IrReceive initialized"));
@ -240,7 +240,7 @@ void IrReceiveCheck(void)
ir_lasttime = now;
char svalue[64];
if (Settings.flag.ir_receive_decimal) { // SetOption29 - IR receive data format
if (Settings->flag.ir_receive_decimal) { // SetOption29 - IR receive data format
ulltoa(results.value, svalue, 10);
} else {
snprintf_P(svalue, sizeof(svalue), PSTR("\"0x%s\""), hvalue);
@ -257,7 +257,7 @@ void IrReceiveCheck(void)
bool prev_number = false; // was the previous value a number, meaning we may need a comma prefix
bool ir_high = true; // alternate high/low
// Add raw data in a compact format
if (Settings.flag3.receive_raw) { // SetOption58 - Add IR Raw data to JSON message
if (Settings->flag3.receive_raw) { // SetOption58 - Add IR Raw data to JSON message
ResponseAppend_P(PSTR(",\"" D_JSON_IR_RAWDATA "\":\""));
size_t rawlen = results.rawlen;
uint32_t i;

View File

@ -188,8 +188,8 @@ unsigned long ir_lasttime = 0;
void IrReceiveUpdateThreshold(void)
{
if (irrecv != nullptr) {
if (Settings.param[P_IR_UNKNOW_THRESHOLD] < 6) { Settings.param[P_IR_UNKNOW_THRESHOLD] = 6; }
irrecv->setUnknownThreshold(Settings.param[P_IR_UNKNOW_THRESHOLD]);
if (Settings->param[P_IR_UNKNOW_THRESHOLD] < 6) { Settings->param[P_IR_UNKNOW_THRESHOLD] = 6; }
irrecv->setUnknownThreshold(Settings->param[P_IR_UNKNOW_THRESHOLD]);
}
}
@ -197,7 +197,7 @@ void IrReceiveInit(void)
{
// an IR led is at GPIO_IRRECV
irrecv = new IRrecv(Pin(GPIO_IRRECV), IR_FULL_BUFFER_SIZE, IR__FULL_RCV_TIMEOUT, IR_FULL_RCV_SAVE_BUFFER);
irrecv->setUnknownThreshold(Settings.param[P_IR_UNKNOW_THRESHOLD]);
irrecv->setUnknownThreshold(Settings->param[P_IR_UNKNOW_THRESHOLD]);
irrecv->enableIRIn(); // Start the receiver
}
@ -247,7 +247,7 @@ void sendIRJsonState(const struct decode_results &results) {
resultToHexidecimal(&results).c_str());
} else {
ResponseAppend_P(PSTR(",\"%s\":"), UNKNOWN != results.decode_type ? PSTR(D_JSON_IR_DATA) : PSTR(D_JSON_IR_HASH));
if (Settings.flag.ir_receive_decimal) { // SetOption29 - IR receive data format
if (Settings->flag.ir_receive_decimal) { // SetOption29 - IR receive data format
ResponseAppend_P(PSTR("%u"), (uint32_t) results.value);
} else {
if (UNKNOWN != results.decode_type) {
@ -286,7 +286,7 @@ void IrReceiveCheck(void)
bool prev_number = false; // was the previous value a number, meaning we may need a comma prefix
bool ir_high = true; // alternate high/low
// Add raw data in a compact format
if (Settings.flag3.receive_raw) { // SetOption58 - Add IR Raw data to JSON message
if (Settings->flag3.receive_raw) { // SetOption58 - Add IR Raw data to JSON message
ResponseAppend_P(PSTR(",\"" D_JSON_IR_RAWDATA "\":\""));
size_t rawlen = results.rawlen;
uint32_t i;

View File

@ -205,7 +205,7 @@ void SonoffBridgeReceived(void)
high_time = TasmotaGlobal.serial_in_buffer[5] << 8 | TasmotaGlobal.serial_in_buffer[6]; // High time in uSec
if (low_time && high_time) {
for (uint32_t i = 0; i < 9; i++) {
Settings.rf_code[SnfBridge.learn_key][i] = TasmotaGlobal.serial_in_buffer[i +1];
Settings->rf_code[SnfBridge.learn_key][i] = TasmotaGlobal.serial_in_buffer[i +1];
}
Response_P(S_JSON_COMMAND_INDEX_SVALUE, D_CMND_RFKEY, SnfBridge.learn_key, D_JSON_LEARNED);
MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, PSTR(D_CMND_RFKEY));
@ -228,15 +228,15 @@ void SonoffBridgeReceived(void)
SnfBridge.last_time = now;
strncpy_P(rfkey, PSTR("\"" D_JSON_NONE "\""), sizeof(rfkey));
for (uint32_t i = 1; i <= 16; i++) {
if (Settings.rf_code[i][0]) {
uint32_t send_id = Settings.rf_code[i][6] << 16 | Settings.rf_code[i][7] << 8 | Settings.rf_code[i][8];
if (Settings->rf_code[i][0]) {
uint32_t send_id = Settings->rf_code[i][6] << 16 | Settings->rf_code[i][7] << 8 | Settings->rf_code[i][8];
if (send_id == received_id) {
snprintf_P(rfkey, sizeof(rfkey), PSTR("%d"), i);
break;
}
}
}
if (Settings.flag.rf_receive_decimal) { // SetOption28 - RF receive data format
if (Settings->flag.rf_receive_decimal) { // SetOption28 - RF receive data format
snprintf_P(stemp, sizeof(stemp), PSTR("%u"), received_id);
} else {
snprintf_P(stemp, sizeof(stemp), PSTR("\"%06X\""), received_id);
@ -323,7 +323,7 @@ void SonoffBridgeSendCode(uint32_t code)
Serial.write(0xAA); // Start of Text
Serial.write(0xA5); // Send following code
for (uint32_t i = 0; i < 6; i++) {
Serial.write(Settings.rf_code[0][i]);
Serial.write(Settings->rf_code[0][i]);
}
Serial.write((code >> 16) & 0xff);
Serial.write((code >> 8) & 0xff);
@ -340,18 +340,18 @@ void SonoffBridgeSend(uint8_t idx, uint8_t key)
Serial.write(0xAA); // Start of Text
Serial.write(0xA5); // Send following code
for (uint32_t i = 0; i < 8; i++) {
Serial.write(Settings.rf_code[idx][i]);
Serial.write(Settings->rf_code[idx][i]);
}
if (0 == idx) {
code = (0x10 << (key >> 2)) | (1 << (key & 3)); // 11,12,14,18,21,22,24,28,41,42,44,48,81,82,84,88
} else {
code = Settings.rf_code[idx][8];
code = Settings->rf_code[idx][8];
}
Serial.write(code);
Serial.write(0x55); // End of Text
Serial.flush();
#ifdef USE_DOMOTICZ
// uint32_t rid = Settings.rf_code[idx][6] << 16 | Settings.rf_code[idx][7] << 8 | code;
// uint32_t rid = Settings->rf_code[idx][6] << 16 | Settings->rf_code[idx][7] << 8 | code;
// DomoticzSensor(DZ_COUNT, rid); // Send rid as Domoticz Counter value
#endif // USE_DOMOTICZ
}
@ -398,8 +398,8 @@ void CmndRfBridge(void) // RfSync, RfLow, RfHigh, RfHost and RfCode
uint8_t msb = code >> 8;
uint8_t lsb = code & 0xFF;
if ((code > 0) && (code < 0x7FFF) && (msb != 0x55) && (lsb != 0x55)) { // Check for End of Text codes
Settings.rf_code[0][set_index] = msb;
Settings.rf_code[0][set_index +1] = lsb;
Settings->rf_code[0][set_index] = msb;
Settings->rf_code[0][set_index +1] = lsb;
}
}
}
@ -407,7 +407,7 @@ void CmndRfBridge(void) // RfSync, RfLow, RfHigh, RfHost and RfCode
if (CMND_RFCODE == XdrvMailbox.command_code) {
code = SnfBridge.last_send_code;
} else {
code = Settings.rf_code[0][set_index] << 8 | Settings.rf_code[0][set_index +1];
code = Settings->rf_code[0][set_index] << 8 | Settings->rf_code[0][set_index +1];
}
if (10 == radix) {
snprintf_P(stemp, sizeof(stemp), PSTR("%d"), code);
@ -428,34 +428,34 @@ void CmndRfKey(void)
ResponseCmndIdxChar(PSTR(D_JSON_START_LEARNING));
}
else if (3 == XdrvMailbox.payload) { // Unlearn RF data
Settings.rf_code[XdrvMailbox.index][0] = 0; // Reset sync_time MSB
Settings->rf_code[XdrvMailbox.index][0] = 0; // Reset sync_time MSB
ResponseCmndIdxChar(PSTR(D_JSON_SET_TO_DEFAULT));
}
else if (4 == XdrvMailbox.payload) { // Save RF data provided by RFSync, RfLow, RfHigh and last RfCode
for (uint32_t i = 0; i < 6; i++) {
Settings.rf_code[XdrvMailbox.index][i] = Settings.rf_code[0][i];
Settings->rf_code[XdrvMailbox.index][i] = Settings->rf_code[0][i];
}
Settings.rf_code[XdrvMailbox.index][6] = (SnfBridge.last_send_code >> 16) & 0xff;
Settings.rf_code[XdrvMailbox.index][7] = (SnfBridge.last_send_code >> 8) & 0xff;
Settings.rf_code[XdrvMailbox.index][8] = SnfBridge.last_send_code & 0xff;
Settings->rf_code[XdrvMailbox.index][6] = (SnfBridge.last_send_code >> 16) & 0xff;
Settings->rf_code[XdrvMailbox.index][7] = (SnfBridge.last_send_code >> 8) & 0xff;
Settings->rf_code[XdrvMailbox.index][8] = SnfBridge.last_send_code & 0xff;
ResponseCmndIdxChar(PSTR(D_JSON_SAVED));
} else if (5 == XdrvMailbox.payload) { // Show default or learned RF data
uint8_t key = XdrvMailbox.index;
uint8_t index = (0 == Settings.rf_code[key][0]) ? 0 : key; // Use default if sync_time MSB = 0
uint16_t sync_time = (Settings.rf_code[index][0] << 8) | Settings.rf_code[index][1];
uint16_t low_time = (Settings.rf_code[index][2] << 8) | Settings.rf_code[index][3];
uint16_t high_time = (Settings.rf_code[index][4] << 8) | Settings.rf_code[index][5];
uint32_t code = (Settings.rf_code[index][6] << 16) | (Settings.rf_code[index][7] << 8);
uint8_t index = (0 == Settings->rf_code[key][0]) ? 0 : key; // Use default if sync_time MSB = 0
uint16_t sync_time = (Settings->rf_code[index][0] << 8) | Settings->rf_code[index][1];
uint16_t low_time = (Settings->rf_code[index][2] << 8) | Settings->rf_code[index][3];
uint16_t high_time = (Settings->rf_code[index][4] << 8) | Settings->rf_code[index][5];
uint32_t code = (Settings->rf_code[index][6] << 16) | (Settings->rf_code[index][7] << 8);
if (0 == index) {
key--;
code |= (uint8_t)((0x10 << (key >> 2)) | (1 << (key & 3)));
} else {
code |= Settings.rf_code[index][8];
code |= Settings->rf_code[index][8];
}
Response_P(PSTR("{\"%s%d\":{\"" D_JSON_SYNC "\":%d,\"" D_JSON_LOW "\":%d,\"" D_JSON_HIGH "\":%d,\"" D_JSON_DATA "\":\"%06X\"}}"),
XdrvMailbox.command, XdrvMailbox.index, sync_time, low_time, high_time, code);
} else {
if ((1 == XdrvMailbox.payload) || (0 == Settings.rf_code[XdrvMailbox.index][0])) { // Test sync_time MSB
if ((1 == XdrvMailbox.payload) || (0 == Settings->rf_code[XdrvMailbox.index][0])) { // Test sync_time MSB
SonoffBridgeSend(0, XdrvMailbox.index); // Send default RF data
ResponseCmndIdxChar(PSTR(D_JSON_DEFAULT_SENT));
} else {

View File

@ -39,7 +39,7 @@ void (* const DomoticzCommand[])(void) PROGMEM = {
const char DOMOTICZ_MESSAGE[] PROGMEM = "{\"idx\":%d,\"nvalue\":%d,\"svalue\":\"%s\",\"Battery\":%d,\"RSSI\":%d}";
#if MAX_DOMOTICZ_SNS_IDX < DZ_MAX_SENSORS
#error "Domoticz: Too many sensors or change settings.h layout"
#error "Domoticz: Too many sensors or change Settings->h layout"
#endif
const char kDomoticzSensors[] PROGMEM =
@ -89,12 +89,12 @@ int DomoticzRssiQuality(void) {
#ifdef USE_SONOFF_IFAN
void MqttPublishDomoticzFanState(void) {
if (Settings.flag.mqtt_enabled && Settings.domoticz_relay_idx[1]) { // SetOption3 - Enable MQTT
if (Settings->flag.mqtt_enabled && Settings->domoticz_relay_idx[1]) { // SetOption3 - Enable MQTT
char svalue[8]; // Fanspeed value
int fan_speed = GetFanspeed();
snprintf_P(svalue, sizeof(svalue), PSTR("%d"), fan_speed * 10);
Response_P(DOMOTICZ_MESSAGE, (int)Settings.domoticz_relay_idx[1], (0 == fan_speed) ? 0 : 2, svalue, DomoticzBatteryQuality(), DomoticzRssiQuality());
Response_P(DOMOTICZ_MESSAGE, (int)Settings->domoticz_relay_idx[1], (0 == fan_speed) ? 0 : 2, svalue, DomoticzBatteryQuality(), DomoticzRssiQuality());
MqttPublish(domoticz_in_topic);
domoticz_fan_debounce = millis();
@ -110,10 +110,10 @@ void DomoticzUpdateFanState(void) {
#endif // USE_SONOFF_IFAN
void MqttPublishDomoticzPowerState(uint8_t device) {
if (Settings.flag.mqtt_enabled) { // SetOption3 - Enable MQTT
if (Settings->flag.mqtt_enabled) { // SetOption3 - Enable MQTT
if (device < 1) { device = 1; }
if ((device > TasmotaGlobal.devices_present) || (device > MAX_DOMOTICZ_IDX)) { return; }
if (Settings.domoticz_relay_idx[device -1]) {
if (Settings->domoticz_relay_idx[device -1]) {
#ifdef USE_SHUTTER
if (domoticz_is_shutter) {
// Shutter is updated by sensor update - power state should not be sent
@ -126,8 +126,8 @@ void MqttPublishDomoticzPowerState(uint8_t device) {
#endif // USE_SONOFF_IFAN
char svalue[8]; // Dimmer value
snprintf_P(svalue, sizeof(svalue), PSTR("%d"), Settings.light_dimmer);
Response_P(DOMOTICZ_MESSAGE, (int)Settings.domoticz_relay_idx[device -1], (TasmotaGlobal.power & (1 << (device -1))) ? 1 : 0, (TasmotaGlobal.light_type) ? svalue : "", DomoticzBatteryQuality(), DomoticzRssiQuality());
snprintf_P(svalue, sizeof(svalue), PSTR("%d"), Settings->light_dimmer);
Response_P(DOMOTICZ_MESSAGE, (int)Settings->domoticz_relay_idx[device -1], (TasmotaGlobal.power & (1 << (device -1))) ? 1 : 0, (TasmotaGlobal.light_type) ? svalue : "", DomoticzBatteryQuality(), DomoticzRssiQuality());
MqttPublish(domoticz_in_topic);
#ifdef USE_SONOFF_IFAN
}
@ -147,10 +147,10 @@ void DomoticzUpdatePowerState(uint8_t device) {
}
void DomoticzMqttUpdate(void) {
if (domoticz_subscribe && (Settings.domoticz_update_timer || domoticz_update_timer)) {
if (domoticz_subscribe && (Settings->domoticz_update_timer || domoticz_update_timer)) {
domoticz_update_timer--;
if (domoticz_update_timer <= 0) {
domoticz_update_timer = Settings.domoticz_update_timer;
domoticz_update_timer = Settings->domoticz_update_timer;
for (uint32_t i = 1; i <= TasmotaGlobal.devices_present; i++) {
#ifdef USE_SHUTTER
if (domoticz_is_shutter)
@ -177,7 +177,7 @@ void DomoticzMqttUpdate(void) {
void DomoticzMqttSubscribe(void) {
uint8_t maxdev = (TasmotaGlobal.devices_present > MAX_DOMOTICZ_IDX) ? MAX_DOMOTICZ_IDX : TasmotaGlobal.devices_present;
for (uint32_t i = 0; i < maxdev; i++) {
if (Settings.domoticz_relay_idx[i]) {
if (Settings->domoticz_relay_idx[i]) {
domoticz_subscribe = true;
}
}
@ -225,7 +225,7 @@ bool DomoticzMqttData(void) {
if ((idx > 0) && (nvalue >= 0) && (nvalue <= 15)) {
uint8_t maxdev = (TasmotaGlobal.devices_present > MAX_DOMOTICZ_IDX) ? MAX_DOMOTICZ_IDX : TasmotaGlobal.devices_present;
for (uint32_t i = 0; i < maxdev; i++) {
if (idx == Settings.domoticz_relay_idx[i]) {
if (idx == Settings->domoticz_relay_idx[i]) {
bool iscolordimmer = strcmp_P(domoticz.getStr(PSTR("dtype")), PSTR("Color Switch")) == 0;
bool isShutter = strcmp_P(domoticz.getStr(PSTR("dtype")), PSTR("Light/Switch")) == 0 & strncmp_P(domoticz.getStr(PSTR("switchType")),PSTR("Blinds"), 6) == 0;
@ -293,7 +293,7 @@ bool DomoticzMqttData(void) {
} else {
return true; // Invalid data
}
if (TasmotaGlobal.light_type && (Settings.light_dimmer == nvalue) && ((TasmotaGlobal.power >> i) &1)) {
if (TasmotaGlobal.light_type && (Settings->light_dimmer == nvalue) && ((TasmotaGlobal.power >> i) &1)) {
return true; // State already set
}
snprintf_P(XdrvMailbox.topic, XdrvMailbox.index, PSTR("/" D_CMND_DIMMER));
@ -334,8 +334,8 @@ bool DomoticzSendKey(uint8_t key, uint8_t device, uint8_t state, uint8_t svalflg
bool result = false;
if (device <= MAX_DOMOTICZ_IDX) {
if ((Settings.domoticz_key_idx[device -1] || Settings.domoticz_switch_idx[device -1]) && (svalflg)) {
DomoticzSendSwitch(0, (key) ? Settings.domoticz_switch_idx[device -1] : Settings.domoticz_key_idx[device -1], state);
if ((Settings->domoticz_key_idx[device -1] || Settings->domoticz_switch_idx[device -1]) && (svalflg)) {
DomoticzSendSwitch(0, (key) ? Settings->domoticz_switch_idx[device -1] : Settings->domoticz_key_idx[device -1], state);
result = true;
}
}
@ -379,8 +379,8 @@ void DomoticzSendData(uint32_t sensor_idx, uint32_t idx, char *data) {
}
void DomoticzSensor(uint8_t idx, char *data) {
if (Settings.domoticz_sensor_idx[idx]) {
DomoticzSendData(idx, Settings.domoticz_sensor_idx[idx], data);
if (Settings->domoticz_sensor_idx[idx]) {
DomoticzSendData(idx, Settings->domoticz_sensor_idx[idx], data);
}
}
@ -398,16 +398,16 @@ void DomoticzFloatSensor(uint8_t idx, float value) {
uint32_t resolution = 1;
/*
switch (idx) {
case DZ_TEMP: resolution = Settings.flag2.temperature_resolution; break;
case DZ_POWER_ENERGY: resolution = Settings.flag2.wattage_resolution; break;
case DZ_VOLTAGE: resolution = Settings.flag2.voltage_resolution; break;
case DZ_CURRENT: resolution = Settings.flag2.current_resolution; break;
case DZ_TEMP: resolution = Settings->flag2.temperature_resolution; break;
case DZ_POWER_ENERGY: resolution = Settings->flag2.wattage_resolution; break;
case DZ_VOLTAGE: resolution = Settings->flag2.voltage_resolution; break;
case DZ_CURRENT: resolution = Settings->flag2.current_resolution; break;
}
*/
if (DZ_TEMP == idx) { resolution = Settings.flag2.temperature_resolution; }
else if (DZ_POWER_ENERGY == idx) { resolution = Settings.flag2.wattage_resolution; }
else if (DZ_VOLTAGE == idx) { resolution = Settings.flag2.voltage_resolution; }
else if (DZ_CURRENT == idx) { resolution = Settings.flag2.current_resolution; }
if (DZ_TEMP == idx) { resolution = Settings->flag2.temperature_resolution; }
else if (DZ_POWER_ENERGY == idx) { resolution = Settings->flag2.wattage_resolution; }
else if (DZ_VOLTAGE == idx) { resolution = Settings->flag2.voltage_resolution; }
else if (DZ_CURRENT == idx) { resolution = Settings->flag2.current_resolution; }
char data[FLOATSZ];
dtostrfd(value, resolution, data);
DomoticzSensor(idx, data);
@ -416,14 +416,14 @@ void DomoticzFloatSensor(uint8_t idx, float value) {
//void DomoticzTempHumPressureSensor(float temp, float hum, float baro = -1);
void DomoticzTempHumPressureSensor(float temp, float hum, float baro) {
char temperature[FLOATSZ];
dtostrfd(temp, Settings.flag2.temperature_resolution, temperature);
dtostrfd(temp, Settings->flag2.temperature_resolution, temperature);
char humidity[FLOATSZ];
dtostrfd(hum, Settings.flag2.humidity_resolution, humidity);
dtostrfd(hum, Settings->flag2.humidity_resolution, humidity);
char data[32];
if (baro > -1) {
char pressure[FLOATSZ];
dtostrfd(baro, Settings.flag2.pressure_resolution, pressure);
dtostrfd(baro, Settings->flag2.pressure_resolution, pressure);
snprintf_P(data, sizeof(data), PSTR("%s;%s;%d;%s;5"), temperature, humidity, DomoticzHumidityState(hum), pressure);
DomoticzSensor(DZ_TEMP_HUM_BARO, data);
@ -463,45 +463,45 @@ void DomoticzSensorP1SmartMeter(char *usage1, char *usage2, char *return1, char
void CmndDomoticzIdx(void) {
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_DOMOTICZ_IDX)) {
if (XdrvMailbox.payload >= 0) {
Settings.domoticz_relay_idx[XdrvMailbox.index -1] = XdrvMailbox.payload;
Settings->domoticz_relay_idx[XdrvMailbox.index -1] = XdrvMailbox.payload;
TasmotaGlobal.restart_flag = 2;
}
ResponseCmndIdxNumber(Settings.domoticz_relay_idx[XdrvMailbox.index -1]);
ResponseCmndIdxNumber(Settings->domoticz_relay_idx[XdrvMailbox.index -1]);
}
}
void CmndDomoticzKeyIdx(void) {
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_DOMOTICZ_IDX)) {
if (XdrvMailbox.payload >= 0) {
Settings.domoticz_key_idx[XdrvMailbox.index -1] = XdrvMailbox.payload;
Settings->domoticz_key_idx[XdrvMailbox.index -1] = XdrvMailbox.payload;
}
ResponseCmndIdxNumber(Settings.domoticz_key_idx[XdrvMailbox.index -1]);
ResponseCmndIdxNumber(Settings->domoticz_key_idx[XdrvMailbox.index -1]);
}
}
void CmndDomoticzSwitchIdx(void) {
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_DOMOTICZ_IDX)) {
if (XdrvMailbox.payload >= 0) {
Settings.domoticz_switch_idx[XdrvMailbox.index -1] = XdrvMailbox.payload;
Settings->domoticz_switch_idx[XdrvMailbox.index -1] = XdrvMailbox.payload;
}
ResponseCmndIdxNumber(Settings.domoticz_switch_idx[XdrvMailbox.index -1]);
ResponseCmndIdxNumber(Settings->domoticz_switch_idx[XdrvMailbox.index -1]);
}
}
void CmndDomoticzSensorIdx(void) {
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= DZ_MAX_SENSORS)) {
if (XdrvMailbox.payload >= 0) {
Settings.domoticz_sensor_idx[XdrvMailbox.index -1] = XdrvMailbox.payload;
Settings->domoticz_sensor_idx[XdrvMailbox.index -1] = XdrvMailbox.payload;
}
ResponseCmndIdxNumber(Settings.domoticz_sensor_idx[XdrvMailbox.index -1]);
ResponseCmndIdxNumber(Settings->domoticz_sensor_idx[XdrvMailbox.index -1]);
}
}
void CmndDomoticzUpdateTimer(void) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) {
Settings.domoticz_update_timer = XdrvMailbox.payload;
Settings->domoticz_update_timer = XdrvMailbox.payload;
}
ResponseCmndNumber(Settings.domoticz_update_timer);
ResponseCmndNumber(Settings->domoticz_update_timer);
}
void CmndDomoticzSend(void) {
@ -576,12 +576,12 @@ void HandleDomoticzConfiguration(void) {
for (uint32_t i = 0; i < MAX_DOMOTICZ_IDX; i++) {
if (i < TasmotaGlobal.devices_present) {
WSContentSend_P(HTTP_FORM_DOMOTICZ_RELAY,
i +1, i, Settings.domoticz_relay_idx[i],
i +1, i, Settings.domoticz_key_idx[i]);
i +1, i, Settings->domoticz_relay_idx[i],
i +1, i, Settings->domoticz_key_idx[i]);
}
if (PinUsed(GPIO_SWT1, i)) {
WSContentSend_P(HTTP_FORM_DOMOTICZ_SWITCH,
i +1, i, Settings.domoticz_switch_idx[i]);
i +1, i, Settings->domoticz_switch_idx[i]);
}
#ifdef USE_SONOFF_IFAN
if (IsModuleIfan() && (1 == i)) { break; }
@ -589,9 +589,9 @@ void HandleDomoticzConfiguration(void) {
}
for (uint32_t i = 0; i < DZ_MAX_SENSORS; i++) {
WSContentSend_P(HTTP_FORM_DOMOTICZ_SENSOR,
i +1, GetTextIndexed(stemp, sizeof(stemp), i, kDomoticzSensors), i, Settings.domoticz_sensor_idx[i]);
i +1, GetTextIndexed(stemp, sizeof(stemp), i, kDomoticzSensors), i, Settings->domoticz_sensor_idx[i]);
}
WSContentSend_P(HTTP_FORM_DOMOTICZ_TIMER, Settings.domoticz_update_timer);
WSContentSend_P(HTTP_FORM_DOMOTICZ_TIMER, Settings->domoticz_update_timer);
WSContentSend_P(PSTR("</table>"));
WSContentSend_P(HTTP_FORM_END);
WSContentSpaceButton(BUTTON_CONFIGURATION);
@ -630,7 +630,7 @@ void DomoticzSaveSettings(void) {
bool Xdrv07(uint8_t function) {
bool result = false;
if (Settings.flag.mqtt_enabled) { // SetOption3 - Enable MQTT
if (Settings->flag.mqtt_enabled) { // SetOption3 - Enable MQTT
switch (function) {
case FUNC_EVERY_SECOND:
DomoticzMqttUpdate();
@ -649,7 +649,7 @@ bool Xdrv07(uint8_t function) {
case FUNC_MQTT_SUBSCRIBE:
DomoticzMqttSubscribe();
#ifdef USE_SHUTTER
if (Settings.domoticz_sensor_idx[DZ_SHUTTER]) { domoticz_is_shutter = true; }
if (Settings->domoticz_sensor_idx[DZ_SHUTTER]) { domoticz_is_shutter = true; }
#endif // USE_SHUTTER
break;
case FUNC_MQTT_INIT:

View File

@ -56,8 +56,8 @@ void SerialBridgeInput(void)
}
if (serial_in_byte || serial_bridge_raw) { // Any char between 1 and 127 or any char (0 - 255)
bool in_byte_is_delimiter = // Char is delimiter when...
(((Settings.serial_delimiter < 128) && (serial_in_byte == Settings.serial_delimiter)) || // Any char between 1 and 127 and being delimiter
((Settings.serial_delimiter == 128) && !isprint(serial_in_byte))) && // Any char not between 32 and 127
(((Settings->serial_delimiter < 128) && (serial_in_byte == Settings->serial_delimiter)) || // Any char between 1 and 127 and being delimiter
((Settings->serial_delimiter == 128) && !isprint(serial_in_byte))) && // Any char not between 32 and 127
!serial_bridge_raw; // In raw mode (CMND_SERIALSEND3) there is never a delimiter
if ((serial_bridge_in_byte_counter < SERIAL_BRIDGE_BUFFER_SIZE -1) && // Add char to string if it still fits and ...
@ -106,7 +106,7 @@ void SerialBridgeInit(void)
serial_bridge_active = false;
if (PinUsed(GPIO_SBR_RX) && PinUsed(GPIO_SBR_TX)) {
SerialBridgeSerial = new TasmotaSerial(Pin(GPIO_SBR_RX), Pin(GPIO_SBR_TX), HARDWARE_FALLBACK);
if (SerialBridgeSerial->begin(Settings.sbaudrate * 300)) { // Baud rate is stored div 300 so it fits into 16 bits
if (SerialBridgeSerial->begin(Settings->sbaudrate * 300)) { // Baud rate is stored div 300 so it fits into 16 bits
if (SerialBridgeSerial->hardwareSerial()) {
ClaimSerial();
serial_bridge_buffer = TasmotaGlobal.serial_in_buffer; // Use idle serial buffer to save RAM
@ -172,10 +172,10 @@ void CmndSBaudrate(void)
{
if (XdrvMailbox.payload >= 300) {
XdrvMailbox.payload /= 300; // Make it a valid baudrate
Settings.sbaudrate = XdrvMailbox.payload;
SerialBridgeSerial->begin(Settings.sbaudrate * 300); // Reinitialize serial port with new baud rate
Settings->sbaudrate = XdrvMailbox.payload;
SerialBridgeSerial->begin(Settings->sbaudrate * 300); // Reinitialize serial port with new baud rate
}
ResponseCmndNumber(Settings.sbaudrate * 300);
ResponseCmndNumber(Settings->sbaudrate * 300);
}
/*********************************************************************************************\

View File

@ -132,9 +132,9 @@ void DuskTillDawn(uint8_t *hour_up,uint8_t *minute_up, uint8_t *hour_down, uint8
const float h = SUNRISE_DAWN_ANGLE * RAD;
const float sin_h = sinf(h); // let GCC pre-compute the sin() at compile time
float B = Settings.latitude / (1000000.0f / RAD); // geographische Breite
//float B = (((float)Settings.latitude)/1000000) * RAD; // geographische Breite
float GeographischeLaenge = ((float)Settings.longitude)/1000000;
float B = Settings->latitude / (1000000.0f / RAD); // geographische Breite
//float B = (((float)Settings->latitude)/1000000) * RAD; // geographische Breite
float GeographischeLaenge = ((float)Settings->longitude)/1000000;
// double Zeitzone = 0; //Weltzeit
// double Zeitzone = 1; //Winterzeit
// double Zeitzone = 2.0; //Sommerzeit
@ -175,7 +175,7 @@ void ApplyTimerOffsets(Timer *duskdawn)
if (hour[mode]==255) {
// Permanent day/night sets the unreachable limit values
if ((Settings.latitude > 0) != (RtcTime.month>=4 && RtcTime.month<=9)) {
if ((Settings->latitude > 0) != (RtcTime.month>=4 && RtcTime.month<=9)) {
duskdawn->time=2046; // permanent night
} else {
duskdawn->time=2047; // permanent day
@ -240,8 +240,8 @@ uint16_t SunMinutes(uint32_t dawn)
void TimerSetRandomWindow(uint32_t index)
{
timer_window[index] = 0;
if (Settings.timer[index].window) {
timer_window[index] = (random(0, (Settings.timer[index].window << 1) +1)) - Settings.timer[index].window; // -15 .. 15
if (Settings->timer[index].window) {
timer_window[index] = (random(0, (Settings->timer[index].window << 1) +1)) - Settings->timer[index].window; // -15 .. 15
}
}
@ -254,14 +254,14 @@ void TimerEverySecond(void)
{
if (RtcTime.valid) {
if (!RtcTime.hour && !RtcTime.minute && !RtcTime.second) { TimerSetRandomWindows(); } // Midnight
if (Settings.flag3.timers_enable && // CMND_TIMERS
if (Settings->flag3.timers_enable && // CMND_TIMERS
(TasmotaGlobal.uptime > 60) && (RtcTime.minute != timer_last_minute)) { // Execute from one minute after restart every minute only once
timer_last_minute = RtcTime.minute;
int32_t time = (RtcTime.hour *60) + RtcTime.minute;
uint8_t days = 1 << (RtcTime.day_of_week -1);
for (uint32_t i = 0; i < MAX_TIMERS; i++) {
Timer xtimer = Settings.timer[i];
Timer xtimer = Settings->timer[i];
if (xtimer.arm) {
#ifdef USE_SUNRISE
if ((1 == xtimer.mode) || (2 == xtimer.mode)) { // Sunrise or Sunset
@ -282,7 +282,7 @@ void TimerEverySecond(void)
if (time == set_time) {
if (xtimer.days & days) {
Settings.timer[i].arm = xtimer.repeat;
Settings->timer[i].arm = xtimer.repeat;
#if defined(USE_RULES) || defined(USE_SCRIPT)
if (POWER_BLINK == xtimer.power) { // Blink becomes Rule disregarding device and allowing use of Backlog commands
Response_P(PSTR("{\"Clock\":{\"Timer\":%d}}"), i +1);
@ -300,7 +300,7 @@ void TimerEverySecond(void)
void PrepShowTimer(uint32_t index)
{
Timer xtimer = Settings.timer[index -1];
Timer xtimer = Settings->timer[index -1];
char days[8] = { 0 };
for (uint32_t i = 0; i < 7; i++) {
@ -342,9 +342,9 @@ void CmndTimer(void)
if (XdrvMailbox.data_len) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= MAX_TIMERS)) {
if (XdrvMailbox.payload == 0) {
Settings.timer[index -1].data = 0; // Clear timer
Settings->timer[index -1].data = 0; // Clear timer
} else {
Settings.timer[index -1].data = Settings.timer[XdrvMailbox.payload -1].data; // Copy timer
Settings->timer[index -1].data = Settings->timer[XdrvMailbox.payload -1].data; // Copy timer
}
} else {
//#ifndef USE_RULES
@ -361,12 +361,12 @@ void CmndTimer(void)
index--;
JsonParserToken val = root[PSTR(D_JSON_TIMER_ARM)];
if (val) {
Settings.timer[index].arm = (val.getInt() != 0);
Settings->timer[index].arm = (val.getInt() != 0);
}
#ifdef USE_SUNRISE
val = root[PSTR(D_JSON_TIMER_MODE)];
if (val) {
Settings.timer[index].mode = val.getUInt() & 0x03;
Settings->timer[index].mode = val.getUInt() & 0x03;
}
#endif
val = root[PSTR(D_JSON_TIMER_TIME)];
@ -395,40 +395,40 @@ void CmndTimer(void)
itime += value;
}
}
Settings.timer[index].time = itime;
Settings->timer[index].time = itime;
}
val = root[PSTR(D_JSON_TIMER_WINDOW)];
if (val) {
Settings.timer[index].window = val.getUInt() & 0x0F;
Settings->timer[index].window = val.getUInt() & 0x0F;
TimerSetRandomWindow(index);
}
val = root[PSTR(D_JSON_TIMER_DAYS)];
if (val) {
// SMTWTFS = 1234567 = 0011001 = 00TW00S = --TW--S
Settings.timer[index].days = 0;
Settings->timer[index].days = 0;
const char *tday = val.getStr();
uint8_t i = 0;
char ch = *tday++;
while ((ch != '\0') && (i < 7)) {
if (ch == '-') { ch = '0'; }
uint8_t mask = 1 << i++;
Settings.timer[index].days |= (ch == '0') ? 0 : mask;
Settings->timer[index].days |= (ch == '0') ? 0 : mask;
ch = *tday++;
}
}
val = root[PSTR(D_JSON_TIMER_REPEAT)];
if (val) {
Settings.timer[index].repeat = (val.getUInt() != 0);
Settings->timer[index].repeat = (val.getUInt() != 0);
}
val = root[PSTR(D_JSON_TIMER_OUTPUT)];
if (val) {
uint8_t device = (val.getUInt() -1) & 0x0F;
Settings.timer[index].device = (device < TasmotaGlobal.devices_present) ? device : 0;
Settings->timer[index].device = (device < TasmotaGlobal.devices_present) ? device : 0;
}
val = root[PSTR(D_JSON_TIMER_ACTION)];
if (val) {
uint8_t action = val.getUInt() & 0x03;
Settings.timer[index].power = (TasmotaGlobal.devices_present) ? action : 3; // If no devices than only allow rules
Settings->timer[index].power = (TasmotaGlobal.devices_present) ? action : 3; // If no devices than only allow rules
}
index++;
@ -454,21 +454,21 @@ void CmndTimers(void)
{
if (XdrvMailbox.data_len) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) {
Settings.flag3.timers_enable = XdrvMailbox.payload; // CMND_TIMERS
Settings->flag3.timers_enable = XdrvMailbox.payload; // CMND_TIMERS
}
if (XdrvMailbox.payload == 2) {
Settings.flag3.timers_enable = !Settings.flag3.timers_enable; // CMND_TIMERS
Settings->flag3.timers_enable = !Settings->flag3.timers_enable; // CMND_TIMERS
}
}
#ifdef MQTT_DATA_STRING
Response_P(PSTR("{\"" D_CMND_TIMERS "\":\"%s\""), GetStateText(Settings.flag3.timers_enable));
Response_P(PSTR("{\"" D_CMND_TIMERS "\":\"%s\""), GetStateText(Settings->flag3.timers_enable));
for (uint32_t i = 0; i < MAX_TIMERS; i++) {
ResponseAppend_P(PSTR(","));
PrepShowTimer(i +1);
}
ResponseJsonEnd();
#else
ResponseCmndStateText(Settings.flag3.timers_enable); // CMND_TIMERS
ResponseCmndStateText(Settings->flag3.timers_enable); // CMND_TIMERS
MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, XdrvMailbox.command);
uint32_t jsflg = 0;
@ -495,17 +495,17 @@ void CmndTimers(void)
void CmndLongitude(void)
{
if (XdrvMailbox.data_len) {
Settings.longitude = (int)(CharToFloat(XdrvMailbox.data) *1000000);
Settings->longitude = (int)(CharToFloat(XdrvMailbox.data) *1000000);
}
ResponseCmndFloat((float)(Settings.longitude) /1000000, 6);
ResponseCmndFloat((float)(Settings->longitude) /1000000, 6);
}
void CmndLatitude(void)
{
if (XdrvMailbox.data_len) {
Settings.latitude = (int)(CharToFloat(XdrvMailbox.data) *1000000);
Settings->latitude = (int)(CharToFloat(XdrvMailbox.data) *1000000);
}
ResponseCmndFloat((float)(Settings.latitude) /1000000, 6);
ResponseCmndFloat((float)(Settings->latitude) /1000000, 6);
}
#endif // USE_SUNRISE
@ -865,9 +865,9 @@ void HandleTimerConfiguration(void)
WSContentSend_P(HTTP_TIMER_SCRIPT5, MAX_TIMERS, TasmotaGlobal.devices_present);
WSContentSend_P(HTTP_TIMER_SCRIPT6, TasmotaGlobal.devices_present);
WSContentSendStyle_P(HTTP_TIMER_STYLE, WebColor(COL_FORM));
WSContentSend_P(HTTP_FORM_TIMER1, (Settings.flag3.timers_enable) ? PSTR(" checked") : ""); // CMND_TIMERS
WSContentSend_P(HTTP_FORM_TIMER1, (Settings->flag3.timers_enable) ? PSTR(" checked") : ""); // CMND_TIMERS
for (uint32_t i = 0; i < MAX_TIMERS; i++) {
WSContentSend_P(PSTR("%s%u"), (i > 0) ? "," : "", Settings.timer[i].data);
WSContentSend_P(PSTR("%s%u"), (i > 0) ? "," : "", Settings->timer[i].data);
}
WSContentSend_P(HTTP_FORM_TIMER2);
#ifdef USE_SUNRISE
@ -889,7 +889,7 @@ void TimerSaveSettings(void)
{
Timer timer;
Settings.flag3.timers_enable = Webserver->hasArg(F("e0")); // CMND_TIMERS
Settings->flag3.timers_enable = Webserver->hasArg(F("e0")); // CMND_TIMERS
char tmp[MAX_TIMERS *12]; // Need space for MAX_TIMERS x 10 digit numbers separated by a comma
WebGetArg(PSTR("t0"), tmp, sizeof(tmp));
char *p = tmp;
@ -897,8 +897,8 @@ void TimerSaveSettings(void)
timer.data = strtol(p, &p, 10);
p++; // Skip comma
if (timer.time < 1440) {
bool flag = (timer.window != Settings.timer[i].window);
Settings.timer[i].data = timer.data;
bool flag = (timer.window != Settings->timer[i].window);
Settings->timer[i].data = timer.data;
if (flag) TimerSetRandomWindow(i);
}
}

View File

@ -228,7 +228,7 @@ String k_rules[MAX_RULE_SETS] = { String(), String(), String() }; // Strings a
// Returns whether the rule is uncompressed, which means the first byte is not NULL
inline bool IsRuleUncompressed(uint32_t idx) {
#ifdef USE_UNISHOX_COMPRESSION
return Settings.rules[idx][0] ? true : false; // first byte not NULL, the rule is not empty and not compressed
return Settings->rules[idx][0] ? true : false; // first byte not NULL, the rule is not empty and not compressed
#else
return true;
#endif
@ -237,9 +237,9 @@ inline bool IsRuleUncompressed(uint32_t idx) {
// Returns whether the rule is empty, which requires two consecutive NULL
inline bool IsRuleEmpty(uint32_t idx) {
#ifdef USE_UNISHOX_COMPRESSION
return (Settings.rules[idx][0] == 0) && (Settings.rules[idx][1] == 0) ? true : false;
return (Settings->rules[idx][0] == 0) && (Settings->rules[idx][1] == 0) ? true : false;
#else
return (Settings.rules[idx][0] == 0) ? true : false;
return (Settings->rules[idx][0] == 0) ? true : false;
#endif
}
@ -247,22 +247,22 @@ inline bool IsRuleEmpty(uint32_t idx) {
size_t GetRuleLen(uint32_t idx) {
// no need to use #ifdef USE_UNISHOX_COMPRESSION, the compiler will optimize since first test is always true
if (IsRuleUncompressed(idx)) {
return strlen(Settings.rules[idx]);
return strlen(Settings->rules[idx]);
} else { // either empty or compressed
return Settings.rules[idx][1] * 8; // cheap calculation, but not byte accurate (may overshoot by 7)
return Settings->rules[idx][1] * 8; // cheap calculation, but not byte accurate (may overshoot by 7)
}
}
// Returns the actual Flash storage for the Rule, including trailing NULL
size_t GetRuleLenStorage(uint32_t idx) {
#ifdef USE_UNISHOX_COMPRESSION
if (Settings.rules[idx][0] || !Settings.rules[idx][1]) { // if first byte is non-NULL it is uncompressed, if second byte is NULL, then it's either uncompressed or empty
return 1 + strlen(Settings.rules[idx]); // uncompressed or empty
if (Settings->rules[idx][0] || !Settings->rules[idx][1]) { // if first byte is non-NULL it is uncompressed, if second byte is NULL, then it's either uncompressed or empty
return 1 + strlen(Settings->rules[idx]); // uncompressed or empty
} else {
return 2 + strlen(&Settings.rules[idx][1]); // skip first byte and get len of the compressed rule
return 2 + strlen(&Settings->rules[idx][1]); // skip first byte and get len of the compressed rule
}
#else
return 1 + strlen(Settings.rules[idx]);
return 1 + strlen(Settings->rules[idx]);
#endif
}
@ -282,17 +282,17 @@ void GetRule_decompress(String &rule, const char *rule_head) {
// Returns: String() object containing a copy of the rule (rule processing is destructive and will change the String)
String GetRule(uint32_t idx) {
if (IsRuleUncompressed(idx)) {
return String(Settings.rules[idx]);
return String(Settings->rules[idx]);
} else {
#ifdef USE_UNISHOX_COMPRESSION // we still do #ifdef to make sure we don't link unnecessary code
String rule("");
if (Settings.rules[idx][1] == 0) { return rule; } // the rule is empty
if (Settings->rules[idx][1] == 0) { return rule; } // the rule is empty
// If the cache is empty, we need to decompress from Settings
if (0 == k_rules[idx].length() ) {
GetRule_decompress(rule, &Settings.rules[idx][1]);
if (!Settings.flag4.compress_rules_cpu) {
GetRule_decompress(rule, &Settings->rules[idx][1]);
if (!Settings->flag4.compress_rules_cpu) {
k_rules[idx] = rule; // keep a copy for next time
}
} else {
@ -315,7 +315,7 @@ int32_t SetRule_compress(uint32_t idx, const char *in, size_t in_len, char *out,
if (len_compressed >= 0) { // negative means compression failed because of buffer too small, we leave the rule untouched
// check if we need to store in cache
k_rules[idx] = (const char*) nullptr; // Assign the String to nullptr, clears previous string and disallocate internal buffers of String object
if ((!Settings.flag4.compress_rules_cpu) && out) { // if out == nullptr, don't store cache
if ((!Settings->flag4.compress_rules_cpu) && out) { // if out == nullptr, don't store cache
// keep copy in cache
k_rules[idx] = in;
}
@ -338,7 +338,7 @@ int32_t SetRule(uint32_t idx, const char *content, bool append = false) {
}
if (append) {
if (IsRuleUncompressed(idx) || IsRuleEmpty(idx)) { // if already uncompressed (so below 512) and append mode, check if it still fits uncompressed
offset = strlen(Settings.rules[idx]);
offset = strlen(Settings->rules[idx]);
if (len_in + offset >= MAX_RULE_SIZE) {
needsCompress = true;
}
@ -348,10 +348,10 @@ int32_t SetRule(uint32_t idx, const char *content, bool append = false) {
}
if (!needsCompress) { // the rule fits uncompressed, so just copy it
// strlcpy(Settings.rules[idx] + offset, content, sizeof(Settings.rules[idx]));
strlcpy(Settings.rules[idx] + offset, content, sizeof(Settings.rules[idx]) - offset);
if (0 == Settings.rules[idx][0]) {
Settings.rules[idx][1] = 0;
// strlcpy(Settings->rules[idx] + offset, content, sizeof(Settings->rules[idx]));
strlcpy(Settings->rules[idx] + offset, content, sizeof(Settings->rules[idx]) - offset);
if (0 == Settings->rules[idx][0]) {
Settings->rules[idx][1] = 0;
}
#ifdef USE_UNISHOX_COMPRESSION
@ -359,8 +359,8 @@ int32_t SetRule(uint32_t idx, const char *content, bool append = false) {
// do a dry-run compression to display how much it would be compressed
int32_t len_compressed, len_uncompressed;
len_uncompressed = strlen(Settings.rules[idx]);
len_compressed = compressor.unishox_compress(Settings.rules[idx], len_uncompressed, nullptr /* dry-run */, MAX_RULE_SIZE + 8);
len_uncompressed = strlen(Settings->rules[idx]);
len_compressed = compressor.unishox_compress(Settings->rules[idx], len_uncompressed, nullptr /* dry-run */, MAX_RULE_SIZE + 8);
AddLog(LOG_LEVEL_INFO, PSTR("RUL: Stored uncompressed, would compress from %d to %d (-%d%%)"), len_uncompressed, len_compressed, 100 - changeUIntScale(len_compressed, 0, len_uncompressed, 0, 100));
}
@ -386,12 +386,12 @@ int32_t SetRule(uint32_t idx, const char *content, bool append = false) {
if ((len_compressed >= 0) && (len_compressed < MAX_RULE_SIZE - 2)) {
// size is ok, copy to Settings
Settings.rules[idx][0] = 0; // clear first byte to mark as compressed
Settings.rules[idx][1] = (len_in + 7) / 8; // store original length in first bytes (4 bytes chuks)
memcpy(&Settings.rules[idx][2], buf_out, len_compressed);
Settings.rules[idx][len_compressed + 2] = 0; // add NULL termination
Settings->rules[idx][0] = 0; // clear first byte to mark as compressed
Settings->rules[idx][1] = (len_in + 7) / 8; // store original length in first bytes (4 bytes chuks)
memcpy(&Settings->rules[idx][2], buf_out, len_compressed);
Settings->rules[idx][len_compressed + 2] = 0; // add NULL termination
AddLog(LOG_LEVEL_INFO, PSTR("RUL: Compressed from %d to %d (-%d%%)"), len_in, len_compressed, 100 - changeUIntScale(len_compressed, 0, len_in, 0, 100));
// AddLog(LOG_LEVEL_INFO, PSTR("RUL: First bytes: %02X%02X%02X%02X"), Settings.rules[idx][0], Settings.rules[idx][1], Settings.rules[idx][2], Settings.rules[idx][3]);
// AddLog(LOG_LEVEL_INFO, PSTR("RUL: First bytes: %02X%02X%02X%02X"), Settings->rules[idx][0], Settings->rules[idx][1], Settings->rules[idx][2], Settings->rules[idx][3]);
// AddLog(LOG_LEVEL_INFO, PSTR("RUL: GetRuleLenStorage = %d"), GetRuleLenStorage(idx));
} else {
len_compressed = -1; // failed
@ -610,7 +610,7 @@ bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule, bool stop_all
//AddLog(LOG_LEVEL_DEBUG, PSTR("RUL-RM4: Match 1 %d, Triggers %08X, TriggerCount %d"), match, Rules.triggers[rule_set], Rules.trigger_count[rule_set]);
if (bitRead(Settings.rule_once, rule_set)) {
if (bitRead(Settings->rule_once, rule_set)) {
if (match) { // Only allow match state changes
if (!bitRead(Rules.triggers[rule_set], Rules.trigger_count[rule_set])) {
bitSet(Rules.triggers[rule_set], Rules.trigger_count[rule_set]);
@ -694,7 +694,7 @@ bool RuleSetProcess(uint8_t rule_set, String &event_saved)
delay(0); // Prohibit possible loop software watchdog
//AddLog(LOG_LEVEL_DEBUG, PSTR("RUL-RP1: Event = %s, Rule = %s"), event_saved.c_str(), Settings.rules[rule_set]);
//AddLog(LOG_LEVEL_DEBUG, PSTR("RUL-RP1: Event = %s, Rule = %s"), event_saved.c_str(), Settings->rules[rule_set]);
String rules = GetRule(rule_set);
@ -825,7 +825,7 @@ bool RulesProcessEvent(const char *json_event)
//AddLog(LOG_LEVEL_DEBUG, PSTR("RUL: Event |%s|"), event_saved.c_str());
for (uint32_t i = 0; i < MAX_RULE_SETS; i++) {
if (GetRuleLen(i) && bitRead(Settings.rule_enabled, i)) {
if (GetRuleLen(i) && bitRead(Settings->rule_enabled, i)) {
if (RuleSetProcess(i, event_saved)) { serviced = true; }
}
}
@ -842,15 +842,15 @@ bool RulesProcess(void) {
void RulesInit(void)
{
// indicates scripter not enabled
bitWrite(Settings.rule_once, 7, 0);
bitWrite(Settings->rule_once, 7, 0);
// and indicates scripter do not use compress
bitWrite(Settings.rule_once, 6, 0);
bitWrite(Settings->rule_once, 6, 0);
TasmotaGlobal.rules_flag.data = 0;
for (uint32_t i = 0; i < MAX_RULE_SETS; i++) {
if (0 == GetRuleLen(i)) {
bitWrite(Settings.rule_enabled, i, 0);
bitWrite(Settings.rule_once, i, 0);
bitWrite(Settings->rule_enabled, i, 0);
bitWrite(Settings->rule_once, i, 0);
}
}
Rules.teleperiod = false;
@ -858,7 +858,7 @@ void RulesInit(void)
void RulesEvery50ms(void)
{
if (Settings.rule_enabled && !Rules.busy) { // Any rule enabled
if (Settings->rule_enabled && !Rules.busy) { // Any rule enabled
char json_event[120];
if (-1 == Rules.new_power) { Rules.new_power = TasmotaGlobal.power; }
@ -892,15 +892,15 @@ void RulesEvery50ms(void)
}
Rules.old_power = Rules.new_power;
}
else if (Rules.old_dimm != Settings.light_dimmer) {
else if (Rules.old_dimm != Settings->light_dimmer) {
if (Rules.old_dimm != -1) {
snprintf_P(json_event, sizeof(json_event), PSTR("{\"Dimmer\":{\"State\":%d}}"), Settings.light_dimmer);
snprintf_P(json_event, sizeof(json_event), PSTR("{\"Dimmer\":{\"State\":%d}}"), Settings->light_dimmer);
} else {
// Boot time DIMMER VALUE
snprintf_P(json_event, sizeof(json_event), PSTR("{\"Dimmer\":{\"Boot\":%d}}"), Settings.light_dimmer);
snprintf_P(json_event, sizeof(json_event), PSTR("{\"Dimmer\":{\"Boot\":%d}}"), Settings->light_dimmer);
}
RulesProcessEvent(json_event);
Rules.old_dimm = Settings.light_dimmer;
Rules.old_dimm = Settings->light_dimmer;
}
else if (Rules.event_data[0]) {
char *event;
@ -977,7 +977,7 @@ void RulesEvery50ms(void)
void RulesEvery100ms(void) {
static uint8_t xsns_index = 0;
if (Settings.rule_enabled && !Rules.busy && (TasmotaGlobal.uptime > 4)) { // Any rule enabled and allow 4 seconds start-up time for sensors (#3811)
if (Settings->rule_enabled && !Rules.busy && (TasmotaGlobal.uptime > 4)) { // Any rule enabled and allow 4 seconds start-up time for sensors (#3811)
ResponseClear();
int tele_period_save = TasmotaGlobal.tele_period;
TasmotaGlobal.tele_period = 2; // Do not allow HA updates during next function call
@ -998,7 +998,7 @@ void RulesEvery100ms(void) {
void RulesEverySecond(void)
{
char json_event[120];
if (Settings.rule_enabled && !Rules.busy) { // Any rule enabled
if (Settings->rule_enabled && !Rules.busy) { // Any rule enabled
if (RtcTime.valid) {
if ((TasmotaGlobal.uptime > 60) && (RtcTime.minute != Rules.last_minute)) { // Execute from one minute after restart every minute only once
Rules.last_minute = RtcTime.minute;
@ -1011,7 +1011,7 @@ void RulesEverySecond(void)
if (Rules.timer[i] != 0L) { // Timer active?
if (TimeReached(Rules.timer[i])) { // Timer finished?
Rules.timer[i] = 0L; // Turn off this timer
if (Settings.rule_enabled && !Rules.busy) { // Any rule enabled
if (Settings->rule_enabled && !Rules.busy) { // Any rule enabled
snprintf_P(json_event, sizeof(json_event), PSTR("{\"Rules\":{\"Timer\":%d}}"), i +1);
RulesProcessEvent(json_event);
}
@ -1022,7 +1022,7 @@ void RulesEverySecond(void)
void RulesSaveBeforeRestart(void)
{
if (Settings.rule_enabled && !Rules.busy) { // Any rule enabled
if (Settings->rule_enabled && !Rules.busy) { // Any rule enabled
char json_event[32];
strncpy_P(json_event, PSTR("{\"System\":{\"Save\":1}}"), sizeof(json_event));
@ -2078,30 +2078,30 @@ void CmndRule(void)
}
uint8_t index = XdrvMailbox.index;
if ((index > 0) && (index <= MAX_RULE_SETS)) {
// if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.rules[index -1]))) { // TODO postpone size calculation
// if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings->rules[index -1]))) { // TODO postpone size calculation
if (XdrvMailbox.data_len > 0) { // TODO postpone size calculation
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 10)) {
switch (XdrvMailbox.payload) {
case 0: // Off
case 1: // On
bitWrite(Settings.rule_enabled, index -1, XdrvMailbox.payload);
bitWrite(Settings->rule_enabled, index -1, XdrvMailbox.payload);
break;
case 2: // Toggle
bitWrite(Settings.rule_enabled, index -1, bitRead(Settings.rule_enabled, index -1) ^1);
bitWrite(Settings->rule_enabled, index -1, bitRead(Settings->rule_enabled, index -1) ^1);
break;
case 4: // Off
case 5: // On
bitWrite(Settings.rule_once, index -1, XdrvMailbox.payload &1);
bitWrite(Settings->rule_once, index -1, XdrvMailbox.payload &1);
break;
case 6: // Toggle
bitWrite(Settings.rule_once, index -1, bitRead(Settings.rule_once, index -1) ^1);
bitWrite(Settings->rule_once, index -1, bitRead(Settings->rule_once, index -1) ^1);
break;
case 8: // Off
case 9: // On
bitWrite(Settings.rule_stop, index -1, XdrvMailbox.payload &1);
bitWrite(Settings->rule_stop, index -1, XdrvMailbox.payload &1);
break;
case 10: // Toggle
bitWrite(Settings.rule_stop, index -1, bitRead(Settings.rule_stop, index -1) ^1);
bitWrite(Settings->rule_stop, index -1, bitRead(Settings->rule_stop, index -1) ^1);
break;
}
} else {
@ -2143,8 +2143,8 @@ void CmndRule(void)
rule += F("...");
}
Response_P(PSTR("{\"%s%d\":{\"State\":\"%s\",\"Once\":\"%s\",\"StopOnError\":\"%s\",\"Length\":%d,\"Free\":%d,\"Rules\":\"%s\"}}"),
XdrvMailbox.command, index, GetStateText(bitRead(Settings.rule_enabled, index -1)), GetStateText(bitRead(Settings.rule_once, index -1)),
GetStateText(bitRead(Settings.rule_stop, index -1)),
XdrvMailbox.command, index, GetStateText(bitRead(Settings->rule_enabled, index -1)), GetStateText(bitRead(Settings->rule_once, index -1)),
GetStateText(bitRead(Settings->rule_stop, index -1)),
rule_len, MAX_RULE_SIZE - GetRuleLenStorage(index - 1),
EscapeJSONString(rule.c_str()).c_str());
}
@ -2202,7 +2202,7 @@ void CmndVariable(void)
if (XdrvMailbox.data_len > 0) {
#ifdef USE_EXPRESSION
if (XdrvMailbox.data[0] == '=') { // Spaces already been skipped in data
dtostrfd(evaluateExpression(XdrvMailbox.data + 1, XdrvMailbox.data_len - 1), Settings.flag2.calc_resolution, rules_vars[XdrvMailbox.index -1]);
dtostrfd(evaluateExpression(XdrvMailbox.data + 1, XdrvMailbox.data_len - 1), Settings->flag2.calc_resolution, rules_vars[XdrvMailbox.index -1]);
} else {
strlcpy(rules_vars[XdrvMailbox.index -1], ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data, sizeof(rules_vars[XdrvMailbox.index -1]));
}
@ -2226,7 +2226,7 @@ void CmndMemory(void)
#ifdef USE_EXPRESSION
if (XdrvMailbox.data[0] == '=') { // Spaces already been skipped in data
char rules_mem[FLOATSZ];
dtostrfd(evaluateExpression(XdrvMailbox.data + 1, XdrvMailbox.data_len - 1), Settings.flag2.calc_resolution, rules_mem);
dtostrfd(evaluateExpression(XdrvMailbox.data + 1, XdrvMailbox.data_len - 1), Settings->flag2.calc_resolution, rules_mem);
SettingsUpdateText(SET_MEM1 + XdrvMailbox.index -1, rules_mem);
} else {
SettingsUpdateText(SET_MEM1 + XdrvMailbox.index -1, ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data);
@ -2244,9 +2244,9 @@ void CmndMemory(void)
void CmndCalcResolution(void)
{
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 7)) {
Settings.flag2.calc_resolution = XdrvMailbox.payload;
Settings->flag2.calc_resolution = XdrvMailbox.payload;
}
ResponseCmndNumber(Settings.flag2.calc_resolution);
ResponseCmndNumber(Settings->flag2.calc_resolution);
}
void CmndAddition(void)
@ -2254,7 +2254,7 @@ void CmndAddition(void)
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_RULE_VARS)) {
if (XdrvMailbox.data_len > 0) {
float tempvar = CharToFloat(rules_vars[XdrvMailbox.index -1]) + CharToFloat(XdrvMailbox.data);
dtostrfd(tempvar, Settings.flag2.calc_resolution, rules_vars[XdrvMailbox.index -1]);
dtostrfd(tempvar, Settings->flag2.calc_resolution, rules_vars[XdrvMailbox.index -1]);
bitSet(Rules.vars_event, XdrvMailbox.index -1);
}
ResponseCmndIdxChar(rules_vars[XdrvMailbox.index -1]);
@ -2266,7 +2266,7 @@ void CmndSubtract(void)
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_RULE_VARS)) {
if (XdrvMailbox.data_len > 0) {
float tempvar = CharToFloat(rules_vars[XdrvMailbox.index -1]) - CharToFloat(XdrvMailbox.data);
dtostrfd(tempvar, Settings.flag2.calc_resolution, rules_vars[XdrvMailbox.index -1]);
dtostrfd(tempvar, Settings->flag2.calc_resolution, rules_vars[XdrvMailbox.index -1]);
bitSet(Rules.vars_event, XdrvMailbox.index -1);
}
ResponseCmndIdxChar(rules_vars[XdrvMailbox.index -1]);
@ -2278,7 +2278,7 @@ void CmndMultiply(void)
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_RULE_VARS)) {
if (XdrvMailbox.data_len > 0) {
float tempvar = CharToFloat(rules_vars[XdrvMailbox.index -1]) * CharToFloat(XdrvMailbox.data);
dtostrfd(tempvar, Settings.flag2.calc_resolution, rules_vars[XdrvMailbox.index -1]);
dtostrfd(tempvar, Settings->flag2.calc_resolution, rules_vars[XdrvMailbox.index -1]);
bitSet(Rules.vars_event, XdrvMailbox.index -1);
}
ResponseCmndIdxChar(rules_vars[XdrvMailbox.index -1]);
@ -2298,7 +2298,7 @@ void CmndScale(void)
float toLow = CharToFloat(ArgV(argument, 4));
float toHigh = CharToFloat(ArgV(argument, 5));
float value = map_double(valueIN, fromLow, fromHigh, toLow, toHigh);
dtostrfd(value, Settings.flag2.calc_resolution, rules_vars[XdrvMailbox.index -1]);
dtostrfd(value, Settings->flag2.calc_resolution, rules_vars[XdrvMailbox.index -1]);
bitSet(Rules.vars_event, XdrvMailbox.index -1);
} else {
ResponseCmndIdxError();

View File

@ -61,7 +61,7 @@ keywords if then else endif, or, and are better readable for beginners (others m
#endif
#define SCRIPT_EOL '\n'
#define SCRIPT_FLOAT_PRECISION 2
#define PMEM_SIZE sizeof(Settings.script_pram)
#define PMEM_SIZE sizeof(Settings->script_pram)
#define SCRIPT_MAXPERM (PMEM_SIZE)-4/sizeof(float)
#define MAX_SCRIPT_SIZE MAX_RULE_SIZE*MAX_RULE_SETS
@ -471,7 +471,7 @@ uint8_t UfsReject(char *name);
void ScriptEverySecond(void) {
if (bitRead(Settings.rule_enabled, 0)) {
if (bitRead(Settings->rule_enabled, 0)) {
struct T_INDEX *vtp = glob_script_mem.type;
float delta = (millis() - glob_script_mem.script_lastmillis) / 1000.0;
glob_script_mem.script_lastmillis = millis();
@ -1078,7 +1078,7 @@ void ws2812_set_array(float *array ,uint32_t len, uint32_t offset) {
Ws2812ForceSuspend();
for (uint32_t cnt = 0; cnt<len; cnt++) {
uint32_t index = cnt + offset;
if (index>Settings.light_pixels) break;
if (index>Settings->light_pixels) break;
uint32_t col = array[cnt];
Ws2812SetColor(index + 1, col>>16, col>>8, col, 0);
}
@ -1952,7 +1952,7 @@ chknext:
fvar = Energy.daily;
break;
case 12:
fvar = (float)Settings.energy_kWhyesterday/100000.0;
fvar = (float)Settings->energy_kWhyesterday/100000.0;
break;
default:
@ -3070,7 +3070,7 @@ chknext:
GetNumericArgument(vname + 4, OPER_EQU, &fvar, gv);
uint8_t index = fvar;
if (index<=TasmotaGlobal.shutters_present) {
fvar = Settings.shutter_position[index - 1];
fvar = Settings->shutter_position[index - 1];
} else {
fvar = -1;
}
@ -3160,7 +3160,7 @@ chknext:
goto exit;
}
if (!strncmp(vname, "tper", 4)) {
fvar = Settings.tele_period;
fvar = Settings->tele_period;
tind->index = SCRIPT_TELEPERIOD;
goto exit_settable;
}
@ -4663,16 +4663,16 @@ int16_t Run_script_sub(const char *type, int8_t tlen, struct GVARS *gv) {
// allow recursive call
} else {
tasm_cmd_activ = 1;
svmqtt = Settings.flag.mqtt_enabled; // SetOption3 - Enable MQTT
swll = Settings.weblog_level;
Settings.flag.mqtt_enabled = 0; // SetOption3 - Enable MQTT
Settings.weblog_level = 0;
svmqtt = Settings->flag.mqtt_enabled; // SetOption3 - Enable MQTT
swll = Settings->weblog_level;
Settings->flag.mqtt_enabled = 0; // SetOption3 - Enable MQTT
Settings->weblog_level = 0;
}
ExecuteCommand((char*)tmp, SRC_RULE);
tasm_cmd_activ = 0;
if (sflag==1) {
Settings.flag.mqtt_enabled = svmqtt; // SetOption3 - Enable MQTT
Settings.weblog_level = swll;
Settings->flag.mqtt_enabled = svmqtt; // SetOption3 - Enable MQTT
Settings->weblog_level = swll;
}
}
if (cmdmem) free(cmdmem);
@ -4813,7 +4813,7 @@ int16_t Run_script_sub(const char *type, int8_t tlen, struct GVARS *gv) {
case SCRIPT_TELEPERIOD:
if (*dfvar<10) *dfvar = 10;
if (*dfvar>300) *dfvar = 300;
Settings.tele_period = *dfvar;
Settings->tele_period = *dfvar;
break;
case SCRIPT_EVENT_HANDLED:
glob_script_mem.event_handeled = *dfvar;
@ -4981,7 +4981,7 @@ int16_t Run_script_sub(const char *type, int8_t tlen, struct GVARS *gv) {
void ScripterEvery100ms(void) {
static uint8_t xsns_index = 0;
if (bitRead(Settings.rule_enabled, 0) && (TasmotaGlobal.uptime > 4)) {
if (bitRead(Settings->rule_enabled, 0) && (TasmotaGlobal.uptime > 4)) {
ResponseClear();
uint16_t script_tele_period_save = TasmotaGlobal.tele_period;
TasmotaGlobal.tele_period = 2;
@ -4997,7 +4997,7 @@ void ScripterEvery100ms(void) {
#endif
}
}
if (bitRead(Settings.rule_enabled, 0)) {
if (bitRead(Settings->rule_enabled, 0)) {
if (glob_script_mem.fast_script == 99) Run_Scripter(">F", 2, 0);
}
}
@ -5191,8 +5191,8 @@ void script_upload_start(void) {
}
uplsize = 0;
sc_state = bitRead(Settings.rule_enabled, 0);
bitWrite(Settings.rule_enabled, 0, 0);
sc_state = bitRead(Settings->rule_enabled, 0);
bitWrite(Settings->rule_enabled, 0, 0);
} else if(upload.status == UPLOAD_FILE_WRITE) {
//AddLog(LOG_LEVEL_INFO, PSTR("HTP: upload write"));
@ -5219,7 +5219,7 @@ void script_upload_start(void) {
AddLog(LOG_LEVEL_INFO, PSTR("HTP: upload error"));
} else {
*script_ex_ptr = 0;
bitWrite(Settings.rule_enabled, 0, sc_state);
bitWrite(Settings->rule_enabled, 0, sc_state);
SaveScript();
SaveScriptEnd();
//AddLog(LOG_LEVEL_INFO, PSTR("HTP: upload success"));
@ -5333,10 +5333,10 @@ void HandleScriptConfiguration(void) {
#ifdef xSCRIPT_STRIP_COMMENTS
uint16_t ssize = glob_script_mem.script_size;
if (bitRead(Settings.rule_enabled, 1)) ssize *= 2;
WSContentSend_P(HTTP_FORM_SCRIPT1,1,1,bitRead(Settings.rule_enabled,0) ? PSTR(" checked") : "",ssize);
if (bitRead(Settings->rule_enabled, 1)) ssize *= 2;
WSContentSend_P(HTTP_FORM_SCRIPT1,1,1,bitRead(Settings->rule_enabled,0) ? PSTR(" checked") : "",ssize);
#else
WSContentSend_P(HTTP_FORM_SCRIPT1,1,1,bitRead(Settings.rule_enabled,0) ? PSTR(" checked") : "",glob_script_mem.script_size);
WSContentSend_P(HTTP_FORM_SCRIPT1,1,1,bitRead(Settings->rule_enabled,0) ? PSTR(" checked") : "",glob_script_mem.script_size);
#endif // xSCRIPT_STRIP_COMMENTS
// script is to large for WSContentSend_P
@ -5370,7 +5370,7 @@ void SaveScript(void) {
file.close();
} else {
// fallback to compressed mode
script_compress(Settings.rules[0],MAX_SCRIPT_SIZE-1);
script_compress(Settings->rules[0],MAX_SCRIPT_SIZE-1);
}
#else // USE_UFILESYS
@ -5390,7 +5390,7 @@ void SaveScript(void) {
}
#else
// default mode is compression
script_compress(Settings.rules[0],MAX_SCRIPT_SIZE-1);
script_compress(Settings->rules[0],MAX_SCRIPT_SIZE-1);
#endif // EEP_SCRIPT_SIZE
@ -5400,9 +5400,9 @@ void SaveScript(void) {
void ScriptSaveSettings(void) {
if (Webserver->hasArg("c1")) {
bitWrite(Settings.rule_enabled, 0, 1);
bitWrite(Settings->rule_enabled, 0, 1);
} else {
bitWrite(Settings.rule_enabled, 0, 0);
bitWrite(Settings->rule_enabled, 0, 0);
}
String str = Webserver->arg("t1");
@ -5416,7 +5416,7 @@ void ScriptSaveSettings(void) {
if (glob_script_mem.script_ram[0]!='>' && glob_script_mem.script_ram[1]!='D') {
AddLog(LOG_LEVEL_INFO, PSTR("script error: must start with >D"));
bitWrite(Settings.rule_enabled, 0, 0);
bitWrite(Settings->rule_enabled, 0, 0);
}
SaveScript();
@ -5454,7 +5454,7 @@ void SaveScriptEnd(void) {
glob_script_mem.script_mem_size = 0;
}
if (bitRead(Settings.rule_enabled, 0)) {
if (bitRead(Settings->rule_enabled, 0)) {
int16_t res = Init_Scripter();
if (res) {
@ -5684,7 +5684,7 @@ void Script_HueStatus(String *response, uint16_t hue_devs) {
}
void Script_Check_Hue(String *response) {
if (!bitRead(Settings.rule_enabled, 0)) return;
if (!bitRead(Settings->rule_enabled, 0)) return;
uint8_t hue_script_found = Run_Scripter(">H", -2, 0);
if (hue_script_found!=99) return;
@ -5955,7 +5955,7 @@ void Script_Handle_Hue(String *path) {
#ifdef USE_SCRIPT_SUB_COMMAND
bool Script_SubCmd(void) {
if (!bitRead(Settings.rule_enabled, 0)) return false;
if (!bitRead(Settings->rule_enabled, 0)) return false;
if (tasm_cmd_activ) return false;
//AddLog(LOG_LEVEL_INFO,PSTR(">> %s, %s, %d, %d "),XdrvMailbox.topic, XdrvMailbox.data, XdrvMailbox.payload, XdrvMailbox.index);
@ -6038,14 +6038,14 @@ bool ScriptCommand(void) {
switch (XdrvMailbox.payload) {
case 0: // Off
case 1: // On
bitWrite(Settings.rule_enabled, index -1, XdrvMailbox.payload);
bitWrite(Settings->rule_enabled, index -1, XdrvMailbox.payload);
break;
#ifdef xSCRIPT_STRIP_COMMENTS
case 2:
bitWrite(Settings.rule_enabled, 1, 0);
bitWrite(Settings->rule_enabled, 1, 0);
break;
case 3:
bitWrite(Settings.rule_enabled, 1, 1);
bitWrite(Settings->rule_enabled, 1, 1);
break;
#endif //xSCRIPT_STRIP_COMMENTS
}
@ -6053,7 +6053,7 @@ bool ScriptCommand(void) {
if ('>' == XdrvMailbox.data[0]) {
// execute script
Response_P(PSTR("{\"%s\":\"%s\"}"), command, XdrvMailbox.data);
if (bitRead(Settings.rule_enabled, 0)) {
if (bitRead(Settings->rule_enabled, 0)) {
for (uint8_t count = 0; count<XdrvMailbox.data_len; count++) {
if (XdrvMailbox.data[count]==';') XdrvMailbox.data[count] = '\n';
}
@ -6079,7 +6079,7 @@ bool ScriptCommand(void) {
}
return serviced;
}
Response_P(PSTR("{\"%s\":\"%s\",\"Free\":%d}"), command, GetStateText(bitRead(Settings.rule_enabled, 0)), glob_script_mem.script_size - strlen(glob_script_mem.script_ram));
Response_P(PSTR("{\"%s\":\"%s\",\"Free\":%d}"), command, GetStateText(bitRead(Settings->rule_enabled, 0)), glob_script_mem.script_size - strlen(glob_script_mem.script_ram));
#ifdef SUPPORT_MQTT_EVENT
} else if (CMND_SUBSCRIBE == command_code) { //MQTT Subscribe command. Subscribe <Event>, <Topic> [, <Key>]
String result = ScriptSubscribe(XdrvMailbox.data, XdrvMailbox.data_len);
@ -6516,36 +6516,36 @@ char buff[512];
if (renderer && renderer->framebuffer) {
uint8_t *bp = renderer->framebuffer;
uint8_t *lbuf = (uint8_t*)special_malloc(Settings.display_width * 3 + 2);
uint8_t *lbuf = (uint8_t*)special_malloc(Settings->display_width * 3 + 2);
if (!lbuf) return;
int8_t bpp = renderer->disp_bpp;
uint8_t *lbp;
uint8_t fileHeader[fileHeaderSize];
createBitmapFileHeader(Settings.display_height , Settings.display_width , fileHeader);
createBitmapFileHeader(Settings->display_height , Settings->display_width , fileHeader);
Webserver->client().write((uint8_t *)fileHeader, fileHeaderSize);
uint8_t infoHeader[infoHeaderSize];
createBitmapInfoHeader(Settings.display_height, Settings.display_width, infoHeader );
createBitmapInfoHeader(Settings->display_height, Settings->display_width, infoHeader );
Webserver->client().write((uint8_t *)infoHeader, infoHeaderSize);
if (bpp == -1) {
for (uint32_t lins = Settings.display_height - 1; lins >= 0 ; lins--) {
for (uint32_t lins = Settings->display_height - 1; lins >= 0 ; lins--) {
lbp = lbuf;
for (uint32_t cols = 0; cols < Settings.display_width; cols ++) {
for (uint32_t cols = 0; cols < Settings->display_width; cols ++) {
uint8_t pixel = 0;
if (bp[cols + (lins / 8) * Settings.display_width] & (1 << (lins & 7))) {
if (bp[cols + (lins / 8) * Settings->display_width] & (1 << (lins & 7))) {
pixel = 0xff;
}
*lbp++ = pixel;
*lbp++ = pixel;
*lbp++ = pixel;
}
Webserver->client().write((const char*)lbuf, Settings.display_width * 3);
Webserver->client().write((const char*)lbuf, Settings->display_width * 3);
}
} else {
for (uint32_t lins = 0; lins<Settings.display_height; lins++) {
lbp = lbuf + (Settings.display_width * 3);
for (uint32_t lins = 0; lins<Settings->display_height; lins++) {
lbp = lbuf + (Settings->display_width * 3);
if (bpp == 4) {
for (uint32_t cols = 0; cols < Settings.display_width; cols += 2) {
for (uint32_t cols = 0; cols < Settings->display_width; cols += 2) {
uint8_t pixel;
for (uint32_t cnt = 0; cnt <= 1; cnt++) {
if (cnt & 1) {
@ -6561,7 +6561,7 @@ char buff[512];
bp++;
}
} else {
for (uint32_t cols = 0; cols < Settings.display_width; cols += 8) {
for (uint32_t cols = 0; cols < Settings->display_width; cols += 8) {
uint8_t bits = 0x80;
while (bits) {
if (!((*bp) & bits)) {
@ -6579,7 +6579,7 @@ char buff[512];
}
}
}
Webserver->client().write((const char*)lbuf, Settings.display_width * 3);
Webserver->client().write((const char*)lbuf, Settings->display_width * 3);
}
if (lbuf) free(lbuf);
Webserver->client().stop();
@ -6641,7 +6641,7 @@ const char HTTP_SCRIPT_FULLPAGE1[] PROGMEM =
"if (rfsh) {"
"x.open('GET','./sfd?m=1'+a,true);" // ?m related to Webserver->hasArg("m")
"x.send();"
"lt=setTimeout(la,%d);" // Settings.web_refresh
"lt=setTimeout(la,%d);" // Settings->web_refresh
"}"
"}";
@ -7580,7 +7580,7 @@ void ScriptJsonAppend(void) {
bool RulesProcessEvent(const char *json_event) {
if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">E", 2, json_event);
if (bitRead(Settings->rule_enabled, 0)) Run_Scripter(">E", 2, json_event);
return true;
}
@ -7609,7 +7609,7 @@ void script_task1(void *arg) {
//if (time<esp32_tasks[1].task_timer) {delay(time); }
//if (time<=esp32_tasks[0].task_timer) {vTaskDelay( pdMS_TO_TICKS( time ) ); }
delay(esp32_tasks[0].task_timer);
if (bitRead(Settings.rule_enabled, 0)) {
if (bitRead(Settings->rule_enabled, 0)) {
Run_Scripter(">t1", 3, 0);
}
}
@ -7625,7 +7625,7 @@ void script_task2(void *arg) {
//if (time<esp32_tasks[1].task_timer) {delay(time); }
//if (time<=esp32_tasks[1].task_timer) {vTaskDelay( pdMS_TO_TICKS( time ) ); }
delay(esp32_tasks[1].task_timer);
if (bitRead(Settings.rule_enabled, 0)) {
if (bitRead(Settings->rule_enabled, 0)) {
Run_Scripter(">t2", 3, 0);
}
}
@ -8258,12 +8258,12 @@ bool Xdrv10(uint8_t function)
//case FUNC_PRE_INIT:
case FUNC_INIT:
// set defaults to rules memory
//bitWrite(Settings.rule_enabled,0,0);
glob_script_mem.script_ram = Settings.rules[0];
//bitWrite(Settings->rule_enabled,0,0);
glob_script_mem.script_ram = Settings->rules[0];
glob_script_mem.script_size = MAX_SCRIPT_SIZE;
glob_script_mem.FLAGS.fsys = false;
glob_script_mem.FLAGS.eeprom = false;
glob_script_mem.script_pram = (uint8_t*)Settings.script_pram[0];
glob_script_mem.script_pram = (uint8_t*)Settings->script_pram[0];
glob_script_mem.script_pram_size = PMEM_SIZE;
#ifdef USE_UFILESYS
@ -8283,11 +8283,11 @@ bool Xdrv10(uint8_t function)
}
script[UFSYS_SIZE - 1] = 0;
// use rules storage for permanent vars
glob_script_mem.script_pram = (uint8_t*)Settings.rules[0];
glob_script_mem.script_pram = (uint8_t*)Settings->rules[0];
glob_script_mem.script_pram_size = MAX_SCRIPT_SIZE;
glob_script_mem.FLAGS.fsys = true;
// indicates scripter use no compression
bitWrite(Settings.rule_once, 6, 0);
bitWrite(Settings->rule_once, 6, 0);
} else {
AddLog(LOG_LEVEL_INFO,PSTR("UFILESYSTEM fail, using compression!"));
int32_t len_decompressed;
@ -8295,10 +8295,10 @@ bool Xdrv10(uint8_t function)
if (!sprt) { break; }
glob_script_mem.script_ram = sprt;
glob_script_mem.script_size = UNISHOXRSIZE;
len_decompressed = SCRIPT_DECOMPRESS(Settings.rules[0], strlen(Settings.rules[0]), glob_script_mem.script_ram, glob_script_mem.script_size);
len_decompressed = SCRIPT_DECOMPRESS(Settings->rules[0], strlen(Settings->rules[0]), glob_script_mem.script_ram, glob_script_mem.script_size);
if (len_decompressed>0) glob_script_mem.script_ram[len_decompressed] = 0;
// indicates scripter use compression
bitWrite(Settings.rule_once, 6, 1);
bitWrite(Settings->rule_once, 6, 1);
}
#else // USE_UFILESYS
@ -8341,7 +8341,7 @@ bool Xdrv10(uint8_t function)
}
// use rules storage for permanent vars
glob_script_mem.script_pram = (uint8_t*)Settings.rules[0];
glob_script_mem.script_pram = (uint8_t*)Settings->rules[0];
glob_script_mem.script_pram_size = MAX_SCRIPT_SIZE;
glob_script_mem.FLAGS.eeprom = true;
@ -8354,10 +8354,10 @@ bool Xdrv10(uint8_t function)
if (!sprt) { break; }
glob_script_mem.script_ram = sprt;
glob_script_mem.script_size = UNISHOXRSIZE;
len_decompressed = SCRIPT_DECOMPRESS(Settings.rules[0], strlen(Settings.rules[0]), glob_script_mem.script_ram, glob_script_mem.script_size);
len_decompressed = SCRIPT_DECOMPRESS(Settings->rules[0], strlen(Settings->rules[0]), glob_script_mem.script_ram, glob_script_mem.script_size);
if (len_decompressed>0) glob_script_mem.script_ram[len_decompressed] = 0;
// indicates scripter use compression
bitWrite(Settings.rule_once, 6, 1);
bitWrite(Settings->rule_once, 6, 1);
#endif
@ -8365,7 +8365,7 @@ bool Xdrv10(uint8_t function)
// indicates scripter enabled (use rules[][] as single array)
bitWrite(Settings.rule_once, 7, 1);
bitWrite(Settings->rule_once, 7, 1);
#ifdef USE_BUTTON_EVENT
for (uint32_t cnt = 0; cnt < MAX_KEYS; cnt++) {
@ -8378,7 +8378,7 @@ bool Xdrv10(uint8_t function)
// clr all
memset(glob_script_mem.script_ram, 0 ,glob_script_mem.script_size);
strcpy_P(glob_script_mem.script_ram, PSTR(">D\nscript error must start with >D"));
bitWrite(Settings.rule_enabled, 0, 0);
bitWrite(Settings->rule_enabled, 0, 0);
}
// assure permanent memory is 4 byte aligned
@ -8389,11 +8389,11 @@ bool Xdrv10(uint8_t function)
glob_script_mem.script_pram_size -= 4;
}
if (bitRead(Settings.rule_enabled, 0)) Init_Scripter();
if (bitRead(Settings->rule_enabled, 0)) Init_Scripter();
// break;
//case FUNC_INIT:
if (bitRead(Settings.rule_enabled, 0)) {
if (bitRead(Settings->rule_enabled, 0)) {
Run_Scripter(">B\n", 3, 0);
glob_script_mem.fast_script = Run_Scripter(">F", -2, 0);
#if defined(USE_SCRIPT_HUE) && defined(USE_WEBSERVER) && defined(USE_EMULATION) && defined(USE_EMULATION_HUE) && defined(USE_LIGHT)
@ -8413,16 +8413,16 @@ bool Xdrv10(uint8_t function)
break;
case FUNC_SET_POWER:
#ifdef SCRIPT_POWER_SECTION
if (bitRead(Settings.rule_enabled, 0)) Run_Scripter(">P", 2, 0);
if (bitRead(Settings->rule_enabled, 0)) Run_Scripter(">P", 2, 0);
#else
if (bitRead(Settings.rule_enabled, 0)) {
if (bitRead(Settings->rule_enabled, 0)) {
Run_Scripter(">E", 2, 0);
result = glob_script_mem.event_handeled;
}
#endif //SCRIPT_POWER_SECTION
break;
case FUNC_RULES_PROCESS:
if (bitRead(Settings.rule_enabled, 0)) {
if (bitRead(Settings->rule_enabled, 0)) {
#ifdef MQTT_DATA_STRING
#ifdef USE_SCRIPT_STATUS
if (!strncmp_P(TasmotaGlobal.mqtt_data.c_str(), PSTR("{\"Status"), 8)) {
@ -8448,7 +8448,7 @@ bool Xdrv10(uint8_t function)
}
break;
case FUNC_TELEPERIOD_RULES_PROCESS:
if (bitRead(Settings.rule_enabled, 0)) {
if (bitRead(Settings->rule_enabled, 0)) {
#ifdef MQTT_DATA_STRING
if (TasmotaGlobal.mqtt_data.length()) {
Run_Scripter(">T", 2, TasmotaGlobal.mqtt_data.c_str());
@ -8470,7 +8470,7 @@ bool Xdrv10(uint8_t function)
break;
#ifdef USE_SCRIPT_WEB_DISPLAY
case FUNC_WEB_ADD_MAIN_BUTTON:
if (bitRead(Settings.rule_enabled, 0)) {
if (bitRead(Settings->rule_enabled, 0)) {
ScriptWebShow('$');
#ifdef SCRIPT_FULL_WEBPAGE
uint8_t web_script = Run_Scripter(">w", -2, 0);
@ -8497,7 +8497,7 @@ bool Xdrv10(uint8_t function)
break;
case FUNC_SAVE_BEFORE_RESTART:
if (bitRead(Settings.rule_enabled, 0)) {
if (bitRead(Settings->rule_enabled, 0)) {
Run_Scripter(">R", 2, 0);
Scripter_save_pvars();
}
@ -8507,14 +8507,14 @@ bool Xdrv10(uint8_t function)
break;
#ifdef SUPPORT_MQTT_EVENT
case FUNC_MQTT_DATA:
if (bitRead(Settings.rule_enabled, 0)) {
if (bitRead(Settings->rule_enabled, 0)) {
result = ScriptMqttData();
}
break;
#endif //SUPPORT_MQTT_EVENT
#ifdef USE_SCRIPT_WEB_DISPLAY
case FUNC_WEB_SENSOR:
if (bitRead(Settings.rule_enabled, 0)) {
if (bitRead(Settings->rule_enabled, 0)) {
ScriptWebShow(0);
}
break;
@ -8522,7 +8522,7 @@ bool Xdrv10(uint8_t function)
#ifdef USE_SCRIPT_JSON_EXPORT
case FUNC_JSON_APPEND:
if (bitRead(Settings.rule_enabled, 0)) {
if (bitRead(Settings->rule_enabled, 0)) {
ScriptJsonAppend();
}
break;
@ -8530,7 +8530,7 @@ bool Xdrv10(uint8_t function)
#ifdef USE_BUTTON_EVENT
case FUNC_BUTTON_PRESSED:
if (bitRead(Settings.rule_enabled, 0)) {
if (bitRead(Settings->rule_enabled, 0)) {
if ((glob_script_mem.script_button[XdrvMailbox.index]&1)!=(XdrvMailbox.payload&1)) {
glob_script_mem.script_button[XdrvMailbox.index] = XdrvMailbox.payload;
Run_Scripter(">b", 2, 0);

View File

@ -34,17 +34,17 @@ Constants in tasmota.h
#define MAX_CALLBACKS 10
Both to MAX_KNX_CB
Variables in settings.h
Variables in Settings->h
-----------------------
bool Settings.flag.knx_enabled Enable/Disable KNX Protocol
uint16_t Settings.knx_physsical_addr Physical KNX address of this device
uint8_t Settings.knx_GA_registered Number of group address to read
uint8_t Settings.knx_CB_registered Number of group address to write
uint16_t Settings.knx_GA_addr[MAX_KNX_GA] Group address to read
uint16_t Settings.knx_CB_addr[MAX_KNX_CB] Group address to write
uint8_t Settings.knx_GA_param[MAX_KNX_GA] Type of Input (relay changed, button pressed, sensor read)
uint8_t Settings.knx_CB_param[MAX_KNX_CB] Type of Output (set relay, toggle relay, reply sensor value)
bool Settings->flag.knx_enabled Enable/Disable KNX Protocol
uint16_t Settings->knx_physsical_addr Physical KNX address of this device
uint8_t Settings->knx_GA_registered Number of group address to read
uint8_t Settings->knx_CB_registered Number of group address to write
uint16_t Settings->knx_GA_addr[MAX_KNX_GA] Group address to read
uint16_t Settings->knx_CB_addr[MAX_KNX_CB] Group address to write
uint8_t Settings->knx_GA_param[MAX_KNX_GA] Type of Input (relay changed, button pressed, sensor read)
uint8_t Settings->knx_CB_param[MAX_KNX_CB] Type of Output (set relay, toggle relay, reply sensor value)
\*********************************************************************************************/
@ -210,11 +210,11 @@ void (* const KnxCommand[])(void) PROGMEM = {
uint8_t KNX_GA_Search( uint8_t param, uint8_t start = 0 )
{
for (uint32_t i = start; i < Settings.knx_GA_registered; ++i)
for (uint32_t i = start; i < Settings->knx_GA_registered; ++i)
{
if ( Settings.knx_GA_param[i] == param )
if ( Settings->knx_GA_param[i] == param )
{
if ( Settings.knx_GA_addr[i] != 0 ) // Relay has group address set? GA=0/0/0 can not be used as KNX address, so it is used here as a: not set value
if ( Settings->knx_GA_addr[i] != 0 ) // Relay has group address set? GA=0/0/0 can not be used as KNX address, so it is used here as a: not set value
{
if ( i >= start ) { return i; }
}
@ -226,11 +226,11 @@ uint8_t KNX_GA_Search( uint8_t param, uint8_t start = 0 )
uint8_t KNX_CB_Search( uint8_t param, uint8_t start = 0 )
{
for (uint32_t i = start; i < Settings.knx_CB_registered; ++i)
for (uint32_t i = start; i < Settings->knx_CB_registered; ++i)
{
if ( Settings.knx_CB_param[i] == param )
if ( Settings->knx_CB_param[i] == param )
{
if ( Settings.knx_CB_addr[i] != 0 )
if ( Settings->knx_CB_addr[i] != 0 )
{
if ( i >= start ) { return i; }
}
@ -243,20 +243,20 @@ uint8_t KNX_CB_Search( uint8_t param, uint8_t start = 0 )
void KNX_ADD_GA( uint8_t GAop, uint8_t GA_FNUM, uint8_t GA_AREA, uint8_t GA_FDEF )
{
// Check if all GA were assigned. If yes-> return
if ( Settings.knx_GA_registered >= MAX_KNX_GA ) { return; }
if ( Settings->knx_GA_registered >= MAX_KNX_GA ) { return; }
if ( GA_FNUM == 0 && GA_AREA == 0 && GA_FDEF == 0 ) { return; }
// Assign a GA to that address
Settings.knx_GA_param[Settings.knx_GA_registered] = GAop;
Settings->knx_GA_param[Settings->knx_GA_registered] = GAop;
KNX_addr.ga.area = GA_FNUM;
KNX_addr.ga.line = GA_AREA;
KNX_addr.ga.member = GA_FDEF;
Settings.knx_GA_addr[Settings.knx_GA_registered] = KNX_addr.value;
Settings->knx_GA_addr[Settings->knx_GA_registered] = KNX_addr.value;
Settings.knx_GA_registered++;
Settings->knx_GA_registered++;
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_ADD " GA #%d: %s " D_TO " %d/%d/%d"),
Settings.knx_GA_registered,
Settings->knx_GA_registered,
device_param_ga[GAop-1],
GA_FNUM, GA_AREA, GA_FDEF );
}
@ -270,18 +270,18 @@ void KNX_DEL_GA( uint8_t GAnum )
uint8_t len = 0;
// Delete GA
Settings.knx_GA_param[GAnum-1] = 0;
Settings->knx_GA_param[GAnum-1] = 0;
if (GAnum == 1)
{
// start of array, so delete first entry
src_offset = 1;
// Settings.knx_GA_registered will be 1 in case of only one entry
// Settings.knx_GA_registered will be 2 in case of two entries, etc..
// Settings->knx_GA_registered will be 1 in case of only one entry
// Settings->knx_GA_registered will be 2 in case of two entries, etc..
// so only copy anything, if there is it at least more then one element
len = (Settings.knx_GA_registered - 1);
len = (Settings->knx_GA_registered - 1);
}
else if (GAnum == Settings.knx_GA_registered)
else if (GAnum == Settings->knx_GA_registered)
{
// last element, don't do anything, simply decrement counter
}
@ -293,16 +293,16 @@ void KNX_DEL_GA( uint8_t GAnum )
// skip all prev elements
dest_offset = GAnum -1 ; // GAnum -1 is equal to how many element are in front of it
src_offset = dest_offset + 1; // start after the current element
len = (Settings.knx_GA_registered - GAnum);
len = (Settings->knx_GA_registered - GAnum);
}
if (len > 0)
{
memmove(Settings.knx_GA_param + dest_offset, Settings.knx_GA_param + src_offset, len * sizeof(uint8_t));
memmove(Settings.knx_GA_addr + dest_offset, Settings.knx_GA_addr + src_offset, len * sizeof(uint16_t));
memmove(Settings->knx_GA_param + dest_offset, Settings->knx_GA_param + src_offset, len * sizeof(uint8_t));
memmove(Settings->knx_GA_addr + dest_offset, Settings->knx_GA_addr + src_offset, len * sizeof(uint16_t));
}
Settings.knx_GA_registered--;
Settings->knx_GA_registered--;
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_DELETE " GA #%d"),
GAnum );
@ -312,7 +312,7 @@ void KNX_DEL_GA( uint8_t GAnum )
void KNX_ADD_CB( uint8_t CBop, uint8_t CB_FNUM, uint8_t CB_AREA, uint8_t CB_FDEF )
{
// Check if all callbacks were assigned. If yes-> return
if ( Settings.knx_CB_registered >= MAX_KNX_CB ) { return; }
if ( Settings->knx_CB_registered >= MAX_KNX_CB ) { return; }
if ( CB_FNUM == 0 && CB_AREA == 0 && CB_FDEF == 0 ) { return; }
// Check if a CB for CBop was registered on the ESP-KNX-IP Library
@ -326,18 +326,18 @@ void KNX_ADD_CB( uint8_t CBop, uint8_t CB_FNUM, uint8_t CB_AREA, uint8_t CB_FDEF
// Is going to be used device_param[j].type that stores the type number (1: relay 1, etc)
}
// Assign a callback to CB address
Settings.knx_CB_param[Settings.knx_CB_registered] = CBop;
Settings->knx_CB_param[Settings->knx_CB_registered] = CBop;
KNX_addr.ga.area = CB_FNUM;
KNX_addr.ga.line = CB_AREA;
KNX_addr.ga.member = CB_FDEF;
Settings.knx_CB_addr[Settings.knx_CB_registered] = KNX_addr.value;
Settings->knx_CB_addr[Settings->knx_CB_registered] = KNX_addr.value;
knx.callback_assign( device_param[CBop-1].CB_id, KNX_addr );
Settings.knx_CB_registered++;
Settings->knx_CB_registered++;
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_ADD " CB #%d: %d/%d/%d " D_TO " %s"),
Settings.knx_CB_registered,
Settings->knx_CB_registered,
CB_FNUM, CB_AREA, CB_FDEF,
device_param_cb[CBop-1] );
}
@ -345,25 +345,25 @@ void KNX_ADD_CB( uint8_t CBop, uint8_t CB_FNUM, uint8_t CB_AREA, uint8_t CB_FDEF
void KNX_DEL_CB( uint8_t CBnum )
{
uint8_t oldparam = Settings.knx_CB_param[CBnum-1];
uint8_t oldparam = Settings->knx_CB_param[CBnum-1];
uint8_t dest_offset = 0;
uint8_t src_offset = 0;
uint8_t len = 0;
// Delete assigment
knx.callback_unassign(CBnum-1);
Settings.knx_CB_param[CBnum-1] = 0;
Settings->knx_CB_param[CBnum-1] = 0;
if (CBnum == 1)
{
// start of array, so delete first entry
src_offset = 1;
// Settings.knx_CB_registered will be 1 in case of only one entry
// Settings.knx_CB_registered will be 2 in case of two entries, etc..
// Settings->knx_CB_registered will be 1 in case of only one entry
// Settings->knx_CB_registered will be 2 in case of two entries, etc..
// so only copy anything, if there is it at least more then one element
len = (Settings.knx_CB_registered - 1);
len = (Settings->knx_CB_registered - 1);
}
else if (CBnum == Settings.knx_CB_registered)
else if (CBnum == Settings->knx_CB_registered)
{
// last element, don't do anything, simply decrement counter
}
@ -375,16 +375,16 @@ void KNX_DEL_CB( uint8_t CBnum )
// skip all prev elements
dest_offset = CBnum -1 ; // GAnum -1 is equal to how many element are in front of it
src_offset = dest_offset + 1; // start after the current element
len = (Settings.knx_CB_registered - CBnum);
len = (Settings->knx_CB_registered - CBnum);
}
if (len > 0)
{
memmove(Settings.knx_CB_param + dest_offset, Settings.knx_CB_param + src_offset, len * sizeof(uint8_t));
memmove(Settings.knx_CB_addr + dest_offset, Settings.knx_CB_addr + src_offset, len * sizeof(uint16_t));
memmove(Settings->knx_CB_param + dest_offset, Settings->knx_CB_param + src_offset, len * sizeof(uint8_t));
memmove(Settings->knx_CB_addr + dest_offset, Settings->knx_CB_addr + src_offset, len * sizeof(uint16_t));
}
Settings.knx_CB_registered--;
Settings->knx_CB_registered--;
// Check if there is no other assigment to that callback. If there is not. delete that callback register
if ( KNX_CB_Search( oldparam ) == KNX_Empty ) {
@ -421,21 +421,21 @@ bool KNX_CONFIG_NOT_MATCH(void)
}
// Check for invalid or erroneous configuration (tasmota flashed without clearing the memory)
for (uint32_t i = 0; i < Settings.knx_GA_registered; ++i)
for (uint32_t i = 0; i < Settings->knx_GA_registered; ++i)
{
if ( Settings.knx_GA_param[i] != 0 ) // the GA[i] have a parameter defined?
if ( Settings->knx_GA_param[i] != 0 ) // the GA[i] have a parameter defined?
{
if ( Settings.knx_GA_addr[i] == 0 ) // the GA[i] with parameter have the 0/0/0 as address?
if ( Settings->knx_GA_addr[i] == 0 ) // the GA[i] with parameter have the 0/0/0 as address?
{
return true; // So, it is invalid. Reset KNX configuration
}
}
}
for (uint32_t i = 0; i < Settings.knx_CB_registered; ++i)
for (uint32_t i = 0; i < Settings->knx_CB_registered; ++i)
{
if ( Settings.knx_CB_param[i] != 0 ) // the CB[i] have a parameter defined?
if ( Settings->knx_CB_param[i] != 0 ) // the CB[i] have a parameter defined?
{
if ( Settings.knx_CB_addr[i] == 0 ) // the CB[i] with parameter have the 0/0/0 as address?
if ( Settings->knx_CB_addr[i] == 0 ) // the CB[i] with parameter have the 0/0/0 as address?
{
return true; // So, it is invalid. Reset KNX configuration
}
@ -456,11 +456,11 @@ void KNXStart(void)
void KNX_INIT(void)
{
// Check for incompatible config
if (Settings.knx_GA_registered > MAX_KNX_GA) { Settings.knx_GA_registered = MAX_KNX_GA; }
if (Settings.knx_CB_registered > MAX_KNX_CB) { Settings.knx_CB_registered = MAX_KNX_CB; }
if (Settings->knx_GA_registered > MAX_KNX_GA) { Settings->knx_GA_registered = MAX_KNX_GA; }
if (Settings->knx_CB_registered > MAX_KNX_CB) { Settings->knx_CB_registered = MAX_KNX_CB; }
// Set Physical KNX Address of the device
KNX_physs_addr.value = Settings.knx_physsical_addr;
KNX_physs_addr.value = Settings->knx_physsical_addr;
knx.physical_address_set( KNX_physs_addr );
// Read Configuration
@ -520,8 +520,8 @@ void KNX_INIT(void)
// Delete from KNX settings all configuration is not anymore related to this device
if (KNX_CONFIG_NOT_MATCH()) {
Settings.knx_GA_registered = 0;
Settings.knx_CB_registered = 0;
Settings->knx_GA_registered = 0;
Settings->knx_CB_registered = 0;
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_DELETE " " D_KNX_PARAMETERS));
}
@ -529,16 +529,16 @@ void KNX_INIT(void)
// Search on the settings if there is a group address set for receive KNX messages for the type: device_param[j].type
// If there is, register the group address on the KNX_IP Library to Receive data for Executing Callbacks
uint8_t j;
for (uint32_t i = 0; i < Settings.knx_CB_registered; ++i)
for (uint32_t i = 0; i < Settings->knx_CB_registered; ++i)
{
j = Settings.knx_CB_param[i];
j = Settings->knx_CB_param[i];
if ( j > 0 )
{
device_param[j-1].CB_id = knx.callback_register("", KNX_CB_Action, &device_param[j-1]); // KNX IP Library requires a parameter
// to identify which action was requested on the KNX network
// to be performed on this device (set relay, etc.)
// Is going to be used device_param[j].type that stores the type number (1: relay 1, etc)
KNX_addr.value = Settings.knx_CB_addr[i];
KNX_addr.value = Settings->knx_CB_addr[i];
knx.callback_assign( device_param[j-1].CB_id, KNX_addr );
}
}
@ -548,7 +548,7 @@ void KNX_INIT(void)
void KNX_CB_Action(message_t const &msg, void *arg)
{
device_parameters_t *chan = (device_parameters_t *)arg;
if (!(Settings.flag.knx_enabled)) { return; }
if (!(Settings->flag.knx_enabled)) { return; }
char tempchar[33];
@ -581,7 +581,7 @@ void KNX_CB_Action(message_t const &msg, void *arg)
{
if (!toggle_inhibit) {
ExecuteCommandPower((chan->type) -8, POWER_TOGGLE, SRC_KNX);
if (Settings.flag.knx_enable_enhancement) {
if (Settings->flag.knx_enable_enhancement) {
toggle_inhibit = TOGGLE_INHIBIT_TIME;
}
}
@ -599,7 +599,7 @@ void KNX_CB_Action(message_t const &msg, void *arg)
snprintf_P(command, sizeof(command), PSTR("event KNXRX_VAL%d=%s"), ((chan->type) - KNX_SLOT1 + 1 ), tempchar);
}
ExecuteCommand(command, SRC_KNX);
if (Settings.flag.knx_enable_enhancement) {
if (Settings->flag.knx_enable_enhancement) {
toggle_inhibit = TOGGLE_INHIBIT_TIME;
}
}
@ -611,7 +611,7 @@ void KNX_CB_Action(message_t const &msg, void *arg)
// Value received
snprintf_P(command, sizeof(command), PSTR("event KNX_SCENE=%s"), tempchar);
ExecuteCommand(command, SRC_KNX);
if (Settings.flag.knx_enable_enhancement) {
if (Settings->flag.knx_enable_enhancement) {
toggle_inhibit = TOGGLE_INHIBIT_TIME;
}
}
@ -623,7 +623,7 @@ void KNX_CB_Action(message_t const &msg, void *arg)
if (chan->type < 9) // reply Relays status
{
knx.answer_1bit(msg.received_on, chan->last_state);
if (Settings.flag.knx_enable_enhancement) {
if (Settings->flag.knx_enable_enhancement) {
knx.answer_1bit(msg.received_on, chan->last_state);
knx.answer_1bit(msg.received_on, chan->last_state);
}
@ -631,7 +631,7 @@ void KNX_CB_Action(message_t const &msg, void *arg)
else if (chan->type == KNX_TEMPERATURE) // Reply Temperature
{
knx.answer_4byte_float(msg.received_on, last_temp);
if (Settings.flag.knx_enable_enhancement) {
if (Settings->flag.knx_enable_enhancement) {
knx.answer_4byte_float(msg.received_on, last_temp);
knx.answer_4byte_float(msg.received_on, last_temp);
}
@ -639,7 +639,7 @@ void KNX_CB_Action(message_t const &msg, void *arg)
else if (chan->type == KNX_HUMIDITY) // Reply Humidity
{
knx.answer_4byte_float(msg.received_on, last_hum);
if (Settings.flag.knx_enable_enhancement) {
if (Settings->flag.knx_enable_enhancement) {
knx.answer_4byte_float(msg.received_on, last_hum);
knx.answer_4byte_float(msg.received_on, last_hum);
}
@ -647,7 +647,7 @@ void KNX_CB_Action(message_t const &msg, void *arg)
else if (chan->type == KNX_ENERGY_VOLTAGE) // Reply KNX_ENERGY_VOLTAGE
{
knx.answer_4byte_float(msg.received_on, Energy.voltage[0]);
if (Settings.flag.knx_enable_enhancement) {
if (Settings->flag.knx_enable_enhancement) {
knx.answer_4byte_float(msg.received_on, Energy.voltage[0]);
knx.answer_4byte_float(msg.received_on, Energy.voltage[0]);
}
@ -655,7 +655,7 @@ void KNX_CB_Action(message_t const &msg, void *arg)
else if (chan->type == KNX_ENERGY_CURRENT) // Reply KNX_ENERGY_CURRENT
{
knx.answer_4byte_float(msg.received_on, Energy.current[0]);
if (Settings.flag.knx_enable_enhancement) {
if (Settings->flag.knx_enable_enhancement) {
knx.answer_4byte_float(msg.received_on, Energy.current[0]);
knx.answer_4byte_float(msg.received_on, Energy.current[0]);
}
@ -663,7 +663,7 @@ void KNX_CB_Action(message_t const &msg, void *arg)
else if (chan->type == KNX_ENERGY_POWER) // Reply KNX_ENERGY_POWER
{
knx.answer_4byte_float(msg.received_on, Energy.active_power[0]);
if (Settings.flag.knx_enable_enhancement) {
if (Settings->flag.knx_enable_enhancement) {
knx.answer_4byte_float(msg.received_on, Energy.active_power[0]);
knx.answer_4byte_float(msg.received_on, Energy.active_power[0]);
}
@ -671,16 +671,16 @@ void KNX_CB_Action(message_t const &msg, void *arg)
else if (chan->type == KNX_ENERGY_POWERFACTOR) // Reply KNX_ENERGY_POWERFACTOR
{
knx.answer_4byte_float(msg.received_on, Energy.power_factor[0]);
if (Settings.flag.knx_enable_enhancement) {
if (Settings->flag.knx_enable_enhancement) {
knx.answer_4byte_float(msg.received_on, Energy.power_factor[0]);
knx.answer_4byte_float(msg.received_on, Energy.power_factor[0]);
}
}
else if (chan->type == KNX_ENERGY_YESTERDAY) // Reply KNX_ENERGY_YESTERDAY
{
float energy_kWhyesterday = (float)Settings.energy_kWhyesterday / 100000;
float energy_kWhyesterday = (float)Settings->energy_kWhyesterday / 100000;
knx.answer_4byte_float(msg.received_on, energy_kWhyesterday);
if (Settings.flag.knx_enable_enhancement) {
if (Settings->flag.knx_enable_enhancement) {
knx.answer_4byte_float(msg.received_on, energy_kWhyesterday);
knx.answer_4byte_float(msg.received_on, energy_kWhyesterday);
}
@ -688,7 +688,7 @@ void KNX_CB_Action(message_t const &msg, void *arg)
else if (chan->type == KNX_ENERGY_DAILY) // Reply KNX_ENERGY_DAILY
{
knx.answer_4byte_float(msg.received_on, Energy.daily);
if (Settings.flag.knx_enable_enhancement) {
if (Settings->flag.knx_enable_enhancement) {
knx.answer_4byte_float(msg.received_on, Energy.daily);
knx.answer_4byte_float(msg.received_on, Energy.daily);
}
@ -696,7 +696,7 @@ void KNX_CB_Action(message_t const &msg, void *arg)
else if (chan->type == KNX_ENERGY_TOTAL) // Reply KNX_ENERGY_TOTAL
{
knx.answer_4byte_float(msg.received_on, Energy.total);
if (Settings.flag.knx_enable_enhancement) {
if (Settings->flag.knx_enable_enhancement) {
knx.answer_4byte_float(msg.received_on, Energy.total);
knx.answer_4byte_float(msg.received_on, Energy.total);
}
@ -708,7 +708,7 @@ void KNX_CB_Action(message_t const &msg, void *arg)
char command[25];
snprintf_P(command, sizeof(command), PSTR("event KNXRX_REQ%d"), ((chan->type) - KNX_SLOT1 + 1 ) );
ExecuteCommand(command, SRC_KNX);
if (Settings.flag.knx_enable_enhancement) {
if (Settings->flag.knx_enable_enhancement) {
toggle_inhibit = TOGGLE_INHIBIT_TIME;
}
}
@ -721,16 +721,16 @@ void KNX_CB_Action(message_t const &msg, void *arg)
void KnxUpdatePowerState(uint8_t device, power_t state)
{
if (!(Settings.flag.knx_enabled)) { return; }
if (!(Settings->flag.knx_enabled)) { return; }
device_param[device -1].last_state = bitRead(state, device -1); // power state (on/off)
// Search all the registered GA that has that output (variable: device) as parameter
uint8_t i = KNX_GA_Search(device);
while ( i != KNX_Empty ) {
KNX_addr.value = Settings.knx_GA_addr[i];
KNX_addr.value = Settings->knx_GA_addr[i];
knx.write_1bit(KNX_addr, device_param[device -1].last_state);
if (Settings.flag.knx_enable_enhancement) {
if (Settings->flag.knx_enable_enhancement) {
knx.write_1bit(KNX_addr, device_param[device -1].last_state);
knx.write_1bit(KNX_addr, device_param[device -1].last_state);
}
@ -746,7 +746,7 @@ void KnxUpdatePowerState(uint8_t device, power_t state)
void KnxSendButtonPower(void)
{
if (!(Settings.flag.knx_enabled)) { return; }
if (!(Settings->flag.knx_enabled)) { return; }
uint32_t key = (XdrvMailbox.payload >> 16) & 0xFF;
uint32_t device = XdrvMailbox.payload & 0xFF;
@ -762,9 +762,9 @@ void KnxSendButtonPower(void)
// Search all the registered GA that has that output (variable: device) as parameter
uint8_t i = KNX_GA_Search(device + 8);
while ( i != KNX_Empty ) {
KNX_addr.value = Settings.knx_GA_addr[i];
KNX_addr.value = Settings->knx_GA_addr[i];
knx.write_1bit(KNX_addr, !(state == 0));
if (Settings.flag.knx_enable_enhancement) {
if (Settings->flag.knx_enable_enhancement) {
knx.write_1bit(KNX_addr, !(state == 0));
knx.write_1bit(KNX_addr, !(state == 0));
}
@ -789,13 +789,13 @@ void KnxSensor(uint8_t sensor_type, float value)
last_hum = value;
}
if (!(Settings.flag.knx_enabled)) { return; }
if (!(Settings->flag.knx_enabled)) { return; }
uint8_t i = KNX_GA_Search(sensor_type);
while ( i != KNX_Empty ) {
KNX_addr.value = Settings.knx_GA_addr[i];
KNX_addr.value = Settings->knx_GA_addr[i];
knx.write_4byte_float(KNX_addr, value);
if (Settings.flag.knx_enable_enhancement) {
if (Settings->flag.knx_enable_enhancement) {
knx.write_4byte_float(KNX_addr, value);
knx.write_4byte_float(KNX_addr, value);
}
@ -957,11 +957,11 @@ void HandleKNXConfiguration(void)
"}"
"}"));
WSContentSendStyle();
KNX_physs_addr.value = Settings.knx_physsical_addr;
KNX_physs_addr.value = Settings->knx_physsical_addr;
WSContentSend_P(HTTP_FORM_KNX, KNX_physs_addr.pa.area, KNX_physs_addr.pa.line, KNX_physs_addr.pa.member);
if ( Settings.flag.knx_enabled ) { WSContentSend_P(PSTR(" checked")); }
if ( Settings->flag.knx_enabled ) { WSContentSend_P(PSTR(" checked")); }
WSContentSend_P(HTTP_FORM_KNX1);
if ( Settings.flag.knx_enable_enhancement ) { WSContentSend_P(PSTR(" checked")); }
if ( Settings->flag.knx_enable_enhancement ) { WSContentSend_P(PSTR(" checked")); }
WSContentSend_P(HTTP_FORM_KNX2);
for (uint32_t i = 0; i < KNX_MAX_device_param ; i++)
@ -973,13 +973,13 @@ void HandleKNXConfiguration(void)
}
WSContentSend_P(PSTR("</select> -> "));
WSContentSend_P(HTTP_FORM_KNX_GA, "GA_FNUM", "GA_AREA", "GA_FDEF");
WSContentSend_P(HTTP_FORM_KNX_ADD_BTN, "GAwarning", (Settings.knx_GA_registered < MAX_KNX_GA) ? "" : "disabled", 1);
for (uint32_t i = 0; i < Settings.knx_GA_registered ; ++i)
WSContentSend_P(HTTP_FORM_KNX_ADD_BTN, "GAwarning", (Settings->knx_GA_registered < MAX_KNX_GA) ? "" : "disabled", 1);
for (uint32_t i = 0; i < Settings->knx_GA_registered ; ++i)
{
if ( Settings.knx_GA_param[i] )
if ( Settings->knx_GA_param[i] )
{
KNX_addr.value = Settings.knx_GA_addr[i];
WSContentSend_P(HTTP_FORM_KNX_ADD_TABLE_ROW, device_param_ga[Settings.knx_GA_param[i]-1], KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member, i +1);
KNX_addr.value = Settings->knx_GA_addr[i];
WSContentSend_P(HTTP_FORM_KNX_ADD_TABLE_ROW, device_param_ga[Settings->knx_GA_param[i]-1], KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member, i +1);
}
}
@ -999,14 +999,14 @@ void HandleKNXConfiguration(void)
}
}
WSContentSend_P(PSTR("</select> "));
WSContentSend_P(HTTP_FORM_KNX_ADD_BTN, "CBwarning", (Settings.knx_CB_registered < MAX_KNX_CB) ? "" : "disabled", 2);
WSContentSend_P(HTTP_FORM_KNX_ADD_BTN, "CBwarning", (Settings->knx_CB_registered < MAX_KNX_CB) ? "" : "disabled", 2);
for (uint32_t i = 0; i < Settings.knx_CB_registered ; ++i)
for (uint32_t i = 0; i < Settings->knx_CB_registered ; ++i)
{
if ( Settings.knx_CB_param[i] )
if ( Settings->knx_CB_param[i] )
{
KNX_addr.value = Settings.knx_CB_addr[i];
WSContentSend_P(HTTP_FORM_KNX_ADD_TABLE_ROW2, KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member, device_param_cb[Settings.knx_CB_param[i]-1], i +1);
KNX_addr.value = Settings->knx_CB_addr[i];
WSContentSend_P(HTTP_FORM_KNX_ADD_TABLE_ROW2, KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member, device_param_cb[Settings->knx_CB_param[i]-1], i +1);
}
}
WSContentSend_P(PSTR("</table></center></fieldset>"));
@ -1023,10 +1023,10 @@ void KNX_Save_Settings(void)
String stmp;
address_t KNX_addr;
Settings.flag.knx_enabled = Webserver->hasArg("b1");
Settings.flag.knx_enable_enhancement = Webserver->hasArg("b2");
Settings->flag.knx_enabled = Webserver->hasArg("b1");
Settings->flag.knx_enable_enhancement = Webserver->hasArg("b2");
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_ENABLED ": %d, " D_KNX_ENHANCEMENT ": %d"),
Settings.flag.knx_enabled, Settings.flag.knx_enable_enhancement );
Settings->flag.knx_enabled, Settings->flag.knx_enable_enhancement );
stmp = Webserver->arg("area");
KNX_addr.pa.area = stmp.toInt();
@ -1034,31 +1034,31 @@ void KNX_Save_Settings(void)
KNX_addr.pa.line = stmp.toInt();
stmp = Webserver->arg("member");
KNX_addr.pa.member = stmp.toInt();
Settings.knx_physsical_addr = KNX_addr.value;
Settings->knx_physsical_addr = KNX_addr.value;
knx.physical_address_set( KNX_addr ); // Set Physical KNX Address of the device
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX D_KNX_PHYSICAL_ADDRESS ": %d.%d.%d "),
KNX_addr.pa.area, KNX_addr.pa.line, KNX_addr.pa.member );
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX "GA: %d"),
Settings.knx_GA_registered );
for (uint32_t i = 0; i < Settings.knx_GA_registered ; ++i)
Settings->knx_GA_registered );
for (uint32_t i = 0; i < Settings->knx_GA_registered ; ++i)
{
KNX_addr.value = Settings.knx_GA_addr[i];
KNX_addr.value = Settings->knx_GA_addr[i];
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX "GA #%d: %s " D_TO " %d/%d/%d"),
i+1, device_param_ga[Settings.knx_GA_param[i]-1],
i+1, device_param_ga[Settings->knx_GA_param[i]-1],
KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member );
}
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX "CB: %d"),
Settings.knx_CB_registered );
for (uint32_t i = 0; i < Settings.knx_CB_registered ; ++i)
Settings->knx_CB_registered );
for (uint32_t i = 0; i < Settings->knx_CB_registered ; ++i)
{
KNX_addr.value = Settings.knx_CB_addr[i];
KNX_addr.value = Settings->knx_CB_addr[i];
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_KNX "CB #%d: %d/%d/%d " D_TO " %s"),
i+1,
KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member,
device_param_cb[Settings.knx_CB_param[i]-1] );
device_param_cb[Settings->knx_CB_param[i]-1] );
}
}
@ -1071,15 +1071,15 @@ void KNX_Save_Settings(void)
void CmndKnxTxCmnd(void)
{
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_KNXTX_CMNDS) && (XdrvMailbox.data_len > 0) && Settings.flag.knx_enabled) {
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_KNXTX_CMNDS) && (XdrvMailbox.data_len > 0) && Settings->flag.knx_enabled) {
// XdrvMailbox.index <- KNX SLOT to use
// XdrvMailbox.payload <- data to send
// Search all the registered GA that has that output (variable: KNX SLOTx) as parameter
uint8_t i = KNX_GA_Search(XdrvMailbox.index + KNX_SLOT1 -1);
while ( i != KNX_Empty ) {
KNX_addr.value = Settings.knx_GA_addr[i];
KNX_addr.value = Settings->knx_GA_addr[i];
knx.write_1bit(KNX_addr, !(XdrvMailbox.payload == 0));
if (Settings.flag.knx_enable_enhancement) {
if (Settings->flag.knx_enable_enhancement) {
knx.write_1bit(KNX_addr, !(XdrvMailbox.payload == 0));
knx.write_1bit(KNX_addr, !(XdrvMailbox.payload == 0));
}
@ -1096,19 +1096,19 @@ void CmndKnxTxCmnd(void)
void CmndKnxTxVal(void)
{
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_KNXTX_CMNDS) && (XdrvMailbox.data_len > 0) && Settings.flag.knx_enabled) {
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_KNXTX_CMNDS) && (XdrvMailbox.data_len > 0) && Settings->flag.knx_enabled) {
// XdrvMailbox.index <- KNX SLOT to use
// XdrvMailbox.payload <- data to send
// Search all the registered GA that has that output (variable: KNX SLOTx) as parameter
uint8_t i = KNX_GA_Search(XdrvMailbox.index + KNX_SLOT1 -1);
while ( i != KNX_Empty ) {
KNX_addr.value = Settings.knx_GA_addr[i];
KNX_addr.value = Settings->knx_GA_addr[i];
float tempvar = CharToFloat(XdrvMailbox.data);
dtostrfd(tempvar,2,XdrvMailbox.data);
knx.write_4byte_float(KNX_addr, tempvar);
if (Settings.flag.knx_enable_enhancement) {
if (Settings->flag.knx_enable_enhancement) {
knx.write_4byte_float(KNX_addr, tempvar);
knx.write_4byte_float(KNX_addr, tempvar);
}
@ -1125,17 +1125,17 @@ void CmndKnxTxVal(void)
void CmndKnxTxScene(void)
{
if ( (XdrvMailbox.data_len > 0) && Settings.flag.knx_enabled ) {
if ( (XdrvMailbox.data_len > 0) && Settings->flag.knx_enabled ) {
// XdrvMailbox.payload <- scene number to send
uint8_t i = KNX_GA_Search(KNX_SCENE);
if ( i != KNX_Empty ) {
KNX_addr.value = Settings.knx_GA_addr[i];
KNX_addr.value = Settings->knx_GA_addr[i];
uint8_t tempvar = TextToInt(XdrvMailbox.data);
dtostrfd(tempvar,0,XdrvMailbox.data);
knx.write_1byte_uint(KNX_addr, tempvar);
if (Settings.flag.knx_enable_enhancement) {
if (Settings->flag.knx_enable_enhancement) {
knx.write_1byte_uint(KNX_addr, tempvar);
knx.write_1byte_uint(KNX_addr, tempvar);
}
@ -1151,17 +1151,17 @@ void CmndKnxTxScene(void)
void CmndKnxEnabled(void)
{
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) {
Settings.flag.knx_enabled = XdrvMailbox.payload;
Settings->flag.knx_enabled = XdrvMailbox.payload;
}
ResponseCmndChar (GetStateText(Settings.flag.knx_enabled) );
ResponseCmndChar (GetStateText(Settings->flag.knx_enabled) );
}
void CmndKnxEnhanced(void)
{
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) {
Settings.flag.knx_enable_enhancement = XdrvMailbox.payload;
Settings->flag.knx_enable_enhancement = XdrvMailbox.payload;
}
ResponseCmndChar (GetStateText(Settings.flag.knx_enable_enhancement) );
ResponseCmndChar (GetStateText(Settings->flag.knx_enable_enhancement) );
}
void CmndKnxPa(void)
@ -1183,10 +1183,10 @@ void CmndKnxPa(void)
KNX_addr.pa.area = pa_area;
KNX_addr.pa.line = pa_line;
KNX_addr.pa.member = pa_member;
Settings.knx_physsical_addr = KNX_addr.value;
Settings->knx_physsical_addr = KNX_addr.value;
}
}
KNX_addr.value = Settings.knx_physsical_addr;
KNX_addr.value = Settings->knx_physsical_addr;
Response_P (PSTR("{\"%s\":\"%d.%d.%d\"}"),
XdrvMailbox.command, KNX_addr.pa.area, KNX_addr.pa.line, KNX_addr.pa.member );
}
@ -1215,29 +1215,29 @@ void CmndKnxGa(void)
KNX_addr.ga.line = ga_line;
KNX_addr.ga.member = ga_member;
if ( XdrvMailbox.index > Settings.knx_GA_registered ) {
Settings.knx_GA_registered ++;
XdrvMailbox.index = Settings.knx_GA_registered;
if ( XdrvMailbox.index > Settings->knx_GA_registered ) {
Settings->knx_GA_registered ++;
XdrvMailbox.index = Settings->knx_GA_registered;
}
Settings.knx_GA_addr[XdrvMailbox.index -1] = KNX_addr.value;
Settings.knx_GA_param[XdrvMailbox.index -1] = ga_option;
Settings->knx_GA_addr[XdrvMailbox.index -1] = KNX_addr.value;
Settings->knx_GA_param[XdrvMailbox.index -1] = ga_option;
} else {
if ( (XdrvMailbox.payload <= Settings.knx_GA_registered) && (XdrvMailbox.payload > 0) ) {
if ( (XdrvMailbox.payload <= Settings->knx_GA_registered) && (XdrvMailbox.payload > 0) ) {
XdrvMailbox.index = XdrvMailbox.payload;
} else {
ResponseCmndIdxError();
return;
}
}
if ( XdrvMailbox.index <= Settings.knx_GA_registered ) {
KNX_addr.value = Settings.knx_GA_addr[XdrvMailbox.index -1];
if ( XdrvMailbox.index <= Settings->knx_GA_registered ) {
KNX_addr.value = Settings->knx_GA_addr[XdrvMailbox.index -1];
Response_P (PSTR("{\"%s%d\":\"%s, %d/%d/%d\"}"),
XdrvMailbox.command, XdrvMailbox.index, device_param_ga[Settings.knx_GA_param[XdrvMailbox.index-1]-1],
XdrvMailbox.command, XdrvMailbox.index, device_param_ga[Settings->knx_GA_param[XdrvMailbox.index-1]-1],
KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member );
}
} else {
ResponseCmndIdxNumber (Settings.knx_GA_registered );
ResponseCmndIdxNumber (Settings->knx_GA_registered );
}
}
}
@ -1266,29 +1266,29 @@ void CmndKnxCb(void)
KNX_addr.ga.line = cb_line;
KNX_addr.ga.member = cb_member;
if ( XdrvMailbox.index > Settings.knx_CB_registered ) {
Settings.knx_CB_registered ++;
XdrvMailbox.index = Settings.knx_CB_registered;
if ( XdrvMailbox.index > Settings->knx_CB_registered ) {
Settings->knx_CB_registered ++;
XdrvMailbox.index = Settings->knx_CB_registered;
}
Settings.knx_CB_addr[XdrvMailbox.index -1] = KNX_addr.value;
Settings.knx_CB_param[XdrvMailbox.index -1] = cb_option;
Settings->knx_CB_addr[XdrvMailbox.index -1] = KNX_addr.value;
Settings->knx_CB_param[XdrvMailbox.index -1] = cb_option;
} else {
if ( (XdrvMailbox.payload <= Settings.knx_CB_registered) && (XdrvMailbox.payload > 0) ) {
if ( (XdrvMailbox.payload <= Settings->knx_CB_registered) && (XdrvMailbox.payload > 0) ) {
XdrvMailbox.index = XdrvMailbox.payload;
} else {
ResponseCmndIdxError();
return;
}
}
if ( XdrvMailbox.index <= Settings.knx_CB_registered ) {
KNX_addr.value = Settings.knx_CB_addr[XdrvMailbox.index -1];
if ( XdrvMailbox.index <= Settings->knx_CB_registered ) {
KNX_addr.value = Settings->knx_CB_addr[XdrvMailbox.index -1];
Response_P (PSTR("{\"%s%d\":\"%s, %d/%d/%d\"}"),
XdrvMailbox.command, XdrvMailbox.index, device_param_cb[Settings.knx_CB_param[XdrvMailbox.index-1]-1],
XdrvMailbox.command, XdrvMailbox.index, device_param_cb[Settings->knx_CB_param[XdrvMailbox.index-1]-1],
KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member );
}
} else {
ResponseCmndIdxNumber (Settings.knx_CB_registered );
ResponseCmndIdxNumber (Settings->knx_CB_registered );
}
}
}

View File

@ -88,7 +88,7 @@ void TasDiscoverMessage(void) {
}
}
if ((Light.device > 0) && Settings.flag3.pwm_multi_channels) { // How many relays are light devices?
if ((Light.device > 0) && Settings->flag3.pwm_multi_channels) { // How many relays are light devices?
lightidx = TasmotaGlobal.devices_present - Light.subtype;
}
@ -98,13 +98,13 @@ void TasDiscoverMessage(void) {
if (i < TasmotaGlobal.devices_present) {
#ifdef USE_SHUTTER
if (Settings.flag3.shutter_mode) {
if (Settings->flag3.shutter_mode) {
for (uint32_t k = 0; k < MAX_SHUTTERS; k++) {
if (0 == Settings.shutter_startrelay[k]) {
if (0 == Settings->shutter_startrelay[k]) {
break;
} else {
if (Settings.shutter_startrelay[k] > 0 && Settings.shutter_startrelay[k] <= MAX_SHUTTER_RELAYS) {
Shutter[Settings.shutter_startrelay[k]-1] = Shutter[Settings.shutter_startrelay[k]] = 1;
if (Settings->shutter_startrelay[k] > 0 && Settings->shutter_startrelay[k] <= MAX_SHUTTER_RELAYS) {
Shutter[Settings->shutter_startrelay[k]-1] = Shutter[Settings->shutter_startrelay[k]] = 1;
}
}
}
@ -131,7 +131,7 @@ void TasDiscoverMessage(void) {
// Enable Discovery for Switches only if SetOption114 is enabled
for (uint32_t i = 0; i < MAX_SWITCHES; i++) {
ResponseAppend_P(PSTR("%s%d"), (i > 0 ? "," : ""), (PinUsed(GPIO_SWT1, i) && Settings.flag5.mqtt_switches) ? Settings.switchmode[i] : -1);
ResponseAppend_P(PSTR("%s%d"), (i > 0 ? "," : ""), (PinUsed(GPIO_SWT1, i) && Settings->flag5.mqtt_switches) ? Settings->switchmode[i] : -1);
}
ResponseAppend_P(PSTR("]," // Switch modes (end)
@ -141,7 +141,7 @@ void TasDiscoverMessage(void) {
for (uint32_t i = 0; i < MAX_SWITCHES; i++) {
char sname[TOPSZ];
snprintf_P(sname, sizeof(sname), PSTR("\"%s\""), GetSwitchText(i).c_str());
ResponseAppend_P(PSTR("%s%s"), (i > 0 ? "," : ""), (PinUsed(GPIO_SWT1, i) && Settings.flag5.mqtt_switches) ? sname : PSTR("null"));
ResponseAppend_P(PSTR("%s%s"), (i > 0 ? "," : ""), (PinUsed(GPIO_SWT1, i) && Settings->flag5.mqtt_switches) ? sname : PSTR("null"));
}
ResponseAppend_P(PSTR("]," // Switch names (end)
@ -153,7 +153,7 @@ void TasDiscoverMessage(void) {
#ifdef ESP8266
SerialButton = ((0 == i) && (SONOFF_DUAL == TasmotaGlobal.module_type ));
#endif // ESP8266
ResponseAppend_P(PSTR("%s%d"), (i > 0 ? "," : ""), (SerialButton ? 1 : (PinUsed(GPIO_KEY1, i)) && Settings.flag3.mqtt_buttons));
ResponseAppend_P(PSTR("%s%d"), (i > 0 ? "," : ""), (SerialButton ? 1 : (PinUsed(GPIO_KEY1, i)) && Settings->flag3.mqtt_buttons));
}
ResponseAppend_P(PSTR("]," // Button flag (end)
@ -171,23 +171,23 @@ void TasDiscoverMessage(void) {
"\"lk\":%d," // Light CTRGB linked
"\"lt_st\":%d," // Light SubType
"\"sho\":["), // Shutter Options (start)
Settings.flag.mqtt_response,
Settings.flag.button_swap,
Settings.flag.button_single,
Settings.flag.decimal_text,
Settings.flag.not_power_linked,
Settings.flag.hass_light,
Settings.flag3.pwm_multi_channels,
Settings.flag3.mqtt_buttons,
Settings.flag4.alexa_ct_range,
Settings.flag5.mqtt_switches,
Settings.flag5.fade_fixed_duration,
Settings->flag.mqtt_response,
Settings->flag.button_swap,
Settings->flag.button_single,
Settings->flag.decimal_text,
Settings->flag.not_power_linked,
Settings->flag.hass_light,
Settings->flag3.pwm_multi_channels,
Settings->flag3.mqtt_buttons,
Settings->flag4.alexa_ct_range,
Settings->flag5.mqtt_switches,
Settings->flag5.fade_fixed_duration,
light_controller.isCTRGBLinked(),
Light.subtype);
for (uint32_t i = 0; i < MAX_SHUTTERS; i++) {
#ifdef USE_SHUTTER
ResponseAppend_P(PSTR("%s%d"), (i > 0 ? "," : ""), Settings.shutter_options[i]);
ResponseAppend_P(PSTR("%s%d"), (i > 0 ? "," : ""), Settings->shutter_options[i]);
#else
ResponseAppend_P(PSTR("%s0"), (i > 0 ? "," : ""));
#endif // USE_SHUTTER
@ -201,14 +201,14 @@ void TasDiscovery(void) {
TasmotaGlobal.masterlog_level = LOG_LEVEL_DEBUG_MORE; // Hide topic on clean and remove use weblog 4 to show it
ResponseClear(); // Clear retained message
if (!Settings.flag.hass_discovery) { // SetOption19 - Clear retained message
if (!Settings->flag.hass_discovery) { // SetOption19 - Clear retained message
TasDiscoverMessage(); // Build discovery message
}
char stopic[TOPSZ];
snprintf_P(stopic, sizeof(stopic), PSTR("tasmota/discovery/%s/config"), NetworkUniqueId().c_str());
MqttPublish(stopic, true);
if (!Settings.flag.hass_discovery) { // SetOption19 - Clear retained message
if (!Settings->flag.hass_discovery) { // SetOption19 - Clear retained message
Response_P(PSTR("{\"sn\":"));
MqttShowSensor();
ResponseAppend_P(PSTR(",\"ver\":1}"));
@ -225,7 +225,7 @@ void TasRediscover(void) {
void TasDiscoverInit(void) {
if (ResetReason() != REASON_DEEP_SLEEP_AWAKE) {
Settings.flag.hass_discovery = 0; // SetOption19 - Enable Tasmota discovery and Disable legacy Hass discovery
Settings->flag.hass_discovery = 0; // SetOption19 - Enable Tasmota discovery and Disable legacy Hass discovery
TasmotaGlobal.discovery_counter = 10; // Delayed discovery
}
}
@ -255,10 +255,10 @@ void (* const TasDiscoverCommand[])(void) PROGMEM = {
void CmndTasDiscover(void) {
if (XdrvMailbox.payload >= 0) {
Settings.flag.hass_discovery = !(XdrvMailbox.payload & 1);
Settings->flag.hass_discovery = !(XdrvMailbox.payload & 1);
TasRediscover();
}
ResponseCmndChar(GetStateText(!Settings.flag.hass_discovery));
ResponseCmndChar(GetStateText(!Settings->flag.hass_discovery));
}
/*********************************************************************************************\
@ -268,7 +268,7 @@ void CmndTasDiscover(void) {
bool Xdrv12(uint8_t function) {
bool result = false;
if (Settings.flag.mqtt_enabled) { // SetOption3 - Enable MQTT
if (Settings->flag.mqtt_enabled) { // SetOption3 - Enable MQTT
switch (function) {
case FUNC_EVERY_SECOND:
if (TasmotaGlobal.discovery_counter) {

View File

@ -232,7 +232,7 @@ void HassDiscoveryRelays(struct HASS &Hass)
}
}
if (Light.device > 0 && Settings.flag3.pwm_multi_channels) { // How many relays are light devices?
if (Light.device > 0 && Settings->flag3.pwm_multi_channels) { // How many relays are light devices?
lightidx = TasmotaGlobal.devices_present - Light.subtype;
}
@ -241,13 +241,13 @@ void HassDiscoveryRelays(struct HASS &Hass)
if (i < TasmotaGlobal.devices_present) {
#ifdef USE_SHUTTER
if (Settings.flag3.shutter_mode) {
if (Settings->flag3.shutter_mode) {
for (uint32_t k = 0; k < MAX_SHUTTERS; k++) {
if (0 == Settings.shutter_startrelay[k]) {
if (0 == Settings->shutter_startrelay[k]) {
break;
} else {
if (Settings.shutter_startrelay[k] > 0 && Settings.shutter_startrelay[k] <= MAX_SHUTTER_RELAYS) {
Shutter[Settings.shutter_startrelay[k]-1] = Shutter[Settings.shutter_startrelay[k]] = 1;
if (Settings->shutter_startrelay[k] > 0 && Settings->shutter_startrelay[k] <= MAX_SHUTTER_RELAYS) {
Shutter[Settings->shutter_startrelay[k]-1] = Shutter[Settings->shutter_startrelay[k]] = 1;
}
}
}
@ -308,8 +308,8 @@ void NewHAssDiscovery(void)
for (uint32_t i = 0; i < MAX_SWITCHES; i++) {
char sname[TOPSZ];
snprintf_P(sname, sizeof(sname), PSTR("\"%s\""), GetSwitchText(i).c_str());
snprintf_P(switch_mode, sizeof(switch_mode), PSTR("%s%s%d"), switch_mode, (i > 0 ? "," : ""), (PinUsed(GPIO_SWT1, i) & Settings.flag5.mqtt_switches) ? Settings.switchmode[i] : -1);
snprintf_P(switch_name, sizeof(switch_name), PSTR("%s%s%s"), switch_name, (i > 0 ? "," : ""), (PinUsed(GPIO_SWT1, i) & Settings.flag5.mqtt_switches) ? sname : PSTR("null"));
snprintf_P(switch_mode, sizeof(switch_mode), PSTR("%s%s%d"), switch_mode, (i > 0 ? "," : ""), (PinUsed(GPIO_SWT1, i) & Settings->flag5.mqtt_switches) ? Settings->switchmode[i] : -1);
snprintf_P(switch_name, sizeof(switch_name), PSTR("%s%s%s"), switch_name, (i > 0 ? "," : ""), (PinUsed(GPIO_SWT1, i) & Settings->flag5.mqtt_switches) ? sname : PSTR("null"));
}
stemp5[0] = '\0';
@ -318,13 +318,13 @@ void NewHAssDiscovery(void)
#ifdef ESP8266
if (i == 0 && (SONOFF_DUAL == TasmotaGlobal.module_type )) { SerialButton = true; }
#endif // ESP8266
snprintf_P(stemp5, sizeof(stemp5), PSTR("%s%s%d"), stemp5, (i > 0 ? "," : ""), (SerialButton ? 1 : (PinUsed(GPIO_KEY1, i)) & Settings.flag3.mqtt_buttons));
snprintf_P(stemp5, sizeof(stemp5), PSTR("%s%s%d"), stemp5, (i > 0 ? "," : ""), (SerialButton ? 1 : (PinUsed(GPIO_KEY1, i)) & Settings->flag3.mqtt_buttons));
SerialButton = false;
}
stemp6[0] = '\0';
#ifdef USE_SHUTTER
for (uint32_t i = 0; i < MAX_SHUTTERS; i++) {
snprintf_P(stemp6, sizeof(stemp6), PSTR("%s%s%d"), stemp6, (i > 0 ? "," : ""), Settings.shutter_options[i]);
snprintf_P(stemp6, sizeof(stemp6), PSTR("%s%s%d"), stemp6, (i > 0 ? "," : ""), Settings->shutter_options[i]);
}
#else
snprintf_P(stemp6, sizeof(stemp6), PSTR("0,0,0,0"));
@ -338,17 +338,17 @@ void NewHAssDiscovery(void)
// Send empty message if new discovery is disabled
TasmotaGlobal.masterlog_level = 4; // Hide topic on clean and remove use weblog 4 to show it
if (!Settings.flag.hass_discovery) { // HassDiscoveryRelays(relays)
if (!Settings->flag.hass_discovery) { // HassDiscoveryRelays(relays)
Response_P(HASS_DISCOVER_DEVICE, (uint32_t)WiFi.localIP(), SettingsText(SET_DEVICENAME),
stemp2, TasmotaGlobal.hostname, unique_id, ModuleName().c_str(), TuyaMod, iFanMod, GetStateText(0), GetStateText(1), GetStateText(2), GetStateText(3),
TasmotaGlobal.version, TasmotaGlobal.mqtt_topic, SettingsText(SET_MQTT_FULLTOPIC), PSTR(SUB_PREFIX), PSTR(PUB_PREFIX), PSTR(PUB_PREFIX2), Hass.RelLst, switch_mode, switch_name,
stemp5, Settings.flag.mqtt_response, Settings.flag.button_swap, Settings.flag.button_single, Settings.flag.decimal_text, Settings.flag.not_power_linked,
Settings.flag.hass_light, Settings.flag3.pwm_multi_channels, Settings.flag3.mqtt_buttons, Settings.flag4.alexa_ct_range, Settings.flag5.mqtt_switches,
Settings.flag5.fade_fixed_duration, light_controller.isCTRGBLinked(), Light.subtype, stemp6);
stemp5, Settings->flag.mqtt_response, Settings->flag.button_swap, Settings->flag.button_single, Settings->flag.decimal_text, Settings->flag.not_power_linked,
Settings->flag.hass_light, Settings->flag3.pwm_multi_channels, Settings->flag3.mqtt_buttons, Settings->flag4.alexa_ct_range, Settings->flag5.mqtt_switches,
Settings->flag5.fade_fixed_duration, light_controller.isCTRGBLinked(), Light.subtype, stemp6);
}
MqttPublish(stopic, true);
if (!Settings.flag.hass_discovery) {
if (!Settings->flag.hass_discovery) {
snprintf_P(stopic, sizeof(stopic), PSTR("tasmota/discovery/%s/sensors"), unique_id);
Response_P(PSTR("{\"sn\":"));
MqttShowSensor();
@ -404,7 +404,7 @@ void HAssAnnounceRelayLight(void)
char unique_id[30];
bool LightControl = light_controller.isCTRGBLinked(); // SetOption37 - Color remapping for led channels, also provides an option for allowing independent handling of RGB and white channels
bool PwmMulti = Settings.flag3.pwm_multi_channels; // SetOption68 - Multi-channel PWM instead of a single light
bool PwmMulti = Settings->flag3.pwm_multi_channels; // SetOption68 - Multi-channel PWM instead of a single light
bool is_topic_light = false; // Switch HAss domain between Lights and Relays
bool ind_light = false; // Controls Separated Lights when SetOption37 is >= 128
bool ct_light = false; // Controls a CT Light when SetOption37 is >= 128
@ -440,11 +440,11 @@ void HAssAnnounceRelayLight(void)
}
#ifdef USE_SHUTTER
if (Settings.flag3.shutter_mode) {
if (Settings->flag3.shutter_mode) {
for (uint32_t i = 0; i < MAX_SHUTTERS; i++) {
if (Settings.shutter_startrelay[i] > 0 && Settings.shutter_startrelay[i] <= MAX_SHUTTER_RELAYS) {
bitSet(shutter_mask, Settings.shutter_startrelay[i] -1);
bitSet(shutter_mask, Settings.shutter_startrelay[i]);
if (Settings->shutter_startrelay[i] > 0 && Settings->shutter_startrelay[i] <= MAX_SHUTTER_RELAYS) {
bitSet(shutter_mask, Settings->shutter_startrelay[i] -1);
bitSet(shutter_mask, Settings->shutter_startrelay[i]);
}
}
}
@ -467,7 +467,7 @@ void HAssAnnounceRelayLight(void)
RelayX = true;
}
#endif //USE_MCP230xx_OUTPUT
is_topic_light = Settings.flag.hass_light && RelayX || TasmotaGlobal.light_type && !RelayX || PwmMod || (TuyaDim > 0 && TuyaMod); // SetOption30 - Enforce HAss autodiscovery as light
is_topic_light = Settings->flag.hass_light && RelayX || TasmotaGlobal.light_type && !RelayX || PwmMod || (TuyaDim > 0 && TuyaMod); // SetOption30 - Enforce HAss autodiscovery as light
ResponseClear(); // Clear retained message
// Clear "other" topic first in case the device has been reconfigured from light to switch or vice versa
@ -486,7 +486,7 @@ void HAssAnnounceRelayLight(void)
err_flag = true;
AddLog(LOG_LEVEL_ERROR, PSTR("%s"), kHAssError2);
} else {
if (Settings.flag.hass_discovery && (RelayX || (Light.device > 0) && (max_lights > 0)) && !err_flag )
if (Settings->flag.hass_discovery && (RelayX || (Light.device > 0) && (max_lights > 0)) && !err_flag )
{ // SetOption19 - Control Home Assistant automatic discovery (See SetOption59)
char name[TOPSZ]; // friendlyname(33) + " " + index
char value_template[33];
@ -503,7 +503,7 @@ void HAssAnnounceRelayLight(void)
snprintf_P(name, sizeof(name), PSTR ("%s"), SettingsText(SET_FRIENDLYNAME1 + i-1));
}
GetPowerDevice(value_template, i, sizeof(value_template), Settings.flag.device_index_enable); // SetOption26 - Switch between POWER or POWER1
GetPowerDevice(value_template, i, sizeof(value_template), Settings->flag.device_index_enable); // SetOption26 - Switch between POWER or POWER1
GetTopic_P(command_topic, CMND, TasmotaGlobal.mqtt_topic, value_template);
GetTopic_P(state_topic, TELE, TasmotaGlobal.mqtt_topic, D_RSLT_STATE);
GetTopic_P(availability_topic, TELE, TasmotaGlobal.mqtt_topic, S_LWT);
@ -521,7 +521,7 @@ void HAssAnnounceRelayLight(void)
if (i >= Light.device) {
if (!RelayX || PwmMod || (TuyaDim > 0 && TuyaMod)) {
char *brightness_command_topic = stemp1;
strncpy_P(stemp3, Settings.flag.not_power_linked ? PSTR("last") : PSTR("brightness"), sizeof(stemp3)); // SetOption20 - Control power in relation to Dimmer/Color/Ct changes
strncpy_P(stemp3, Settings->flag.not_power_linked ? PSTR("last") : PSTR("brightness"), sizeof(stemp3)); // SetOption20 - Control power in relation to Dimmer/Color/Ct changes
char channel_num[9];
if (PwmMulti) { // SetOption68 - Multi-channel PWM instead of a single light
snprintf_P(channel_num, sizeof(channel_num), PSTR("Channel%d"), i);
@ -599,7 +599,7 @@ void HAssAnnouncerTriggers(uint8_t device, uint8_t present, uint8_t key, uint8_t
TasmotaGlobal.masterlog_level = ShowTopic = 4; // Hide topic on clean and remove use weblog 4 to see it
if (Settings.flag.hass_discovery && present) { // SetOption19 - Control Home Assistantautomatic discovery (See SetOption59)
if (Settings->flag.hass_discovery && present) { // SetOption19 - Control Home Assistantautomatic discovery (See SetOption59)
char name[TOPSZ]; // friendlyname(33) + " " + "BTN" + " " + index
char value_template[33];
char prefix[TOPSZ];
@ -608,7 +608,7 @@ void HAssAnnouncerTriggers(uint8_t device, uint8_t present, uint8_t key, uint8_t
char jsoname[8];
ShowTopic = 0; // Show the new generated topic
GetPowerDevice(value_template, device + 1, sizeof(value_template), key + Settings.flag.device_index_enable); // Force index for Switch 1, Index on Button1 is controlled by SetOption26 - Switch between POWER or POWER1
GetPowerDevice(value_template, device + 1, sizeof(value_template), key + Settings->flag.device_index_enable); // Force index for Switch 1, Index on Button1 is controlled by SetOption26 - Switch between POWER or POWER1
snprintf_P(jsoname, sizeof(jsoname), PSTR("%s%d"), key ? "SWITCH" : "BUTTON", device + 1);
GetTopic_P(state_topic, STAT, TasmotaGlobal.mqtt_topic, jsoname);
GetTopic_P(availability_topic, TELE, TasmotaGlobal.mqtt_topic, S_LWT);
@ -656,7 +656,7 @@ void HAssAnnouncerBinSensors(uint8_t device, uint8_t present, uint8_t dual, uint
TasmotaGlobal.masterlog_level = ShowTopic = 4; // Hide topic on clean and remove use weblog 4 to see it
if (Settings.flag.hass_discovery && present ) { // SetOption19 - Control Home Assistantautomatic discovery (See SetOption59)
if (Settings->flag.hass_discovery && present ) { // SetOption19 - Control Home Assistantautomatic discovery (See SetOption59)
if (!toggle || dual) {
char name[TOPSZ]; // friendlyname(33) + " " + "BTN" + " " + index
char value_template[33];
@ -667,7 +667,7 @@ void HAssAnnouncerBinSensors(uint8_t device, uint8_t present, uint8_t dual, uint
ShowTopic = 0;
GetPowerDevice(value_template, device + 1, sizeof(value_template), 1 + Settings.flag.device_index_enable); // Force index for Switch 1, Index on Button1 is controlled by SetOption26 - Switch between POWER or POWER1
GetPowerDevice(value_template, device + 1, sizeof(value_template), 1 + Settings->flag.device_index_enable); // Force index for Switch 1, Index on Button1 is controlled by SetOption26 - Switch between POWER or POWER1
snprintf_P(jsoname, sizeof(jsoname), PSTR("SWITCH%d"), device + 1);
GetTopic_P(state_topic, STAT, TasmotaGlobal.mqtt_topic, jsoname);
GetTopic_P(availability_topic, TELE, TasmotaGlobal.mqtt_topic, S_LWT);
@ -683,7 +683,7 @@ void HAssAnnouncerBinSensors(uint8_t device, uint8_t present, uint8_t dual, uint
#ifdef DEEPSLEEP_LWT_HA_DISCOVERY
TryResponseAppend_P(HASS_DISCOVER_SENSOR_LWT, availability_topic);
#else
if (Settings.deepsleep == 0)
if (Settings->deepsleep == 0)
{
TryResponseAppend_P(HASS_DISCOVER_SENSOR_LWT, availability_topic);
}
@ -734,7 +734,7 @@ void HAssAnnounceSwitches(void)
// Trigger types: "0 = none | 1 = button_short_press | 2 = button_long_press | 3 = button_double_press";
uint8_t swmode = Settings.switchmode[switch_index];
uint8_t swmode = Settings->switchmode[switch_index];
switch (swmode) {
case FOLLOW:
@ -804,10 +804,10 @@ void HAssAnnounceButtons(void)
// Trigger types: 10 = button_short_press | 11 = button_double_press | 12 = button_triple_press | 13 = button_quadruple_press | 14 = button_quintuple_press | 3 = button_long_press
if (!Settings.flag3.mqtt_buttons) { // Enable Buttons for discovery [SetOption73] - Decouple button from relay and send just mqtt topic
if (!Settings->flag3.mqtt_buttons) { // Enable Buttons for discovery [SetOption73] - Decouple button from relay and send just mqtt topic
button_present = 0;
} else {
if (Settings.flag.button_single) { // [SetOption13] Immediate action on button press, just SINGLE trigger
if (Settings->flag.button_single) { // [SetOption13] Immediate action on button press, just SINGLE trigger
single = 1;
}
}
@ -829,7 +829,7 @@ void HAssAnnounceSensor(const char *sensorname, const char *subsensortype, const
NoAlNumToUnderscore(subname, MultiSubName); //Replace all non alphaumeric characters to '_' to avoid topic name issues
snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%s"), ESP_getChipId(), sensorname, subname);
snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/sensor/%s/config"), unique_id);
if (Settings.flag.hass_discovery)
if (Settings->flag.hass_discovery)
{ // SetOption19 - Control Home Assistantautomatic discovery (See SetOption59)
char name[TOPSZ]; // friendlyname(33) + " " + sensorname(20?) + " " + sensortype(20?)
char prefix[TOPSZ];
@ -845,7 +845,7 @@ void HAssAnnounceSensor(const char *sensorname, const char *subsensortype, const
#ifdef DEEPSLEEP_LWT_HA_DISCOVERY
TryResponseAppend_P(HASS_DISCOVER_SENSOR_LWT, availability_topic);
#else
if (Settings.deepsleep == 0)
if (Settings->deepsleep == 0)
{
TryResponseAppend_P(HASS_DISCOVER_SENSOR_LWT, availability_topic);
}
@ -984,7 +984,7 @@ void HAssAnnounceShutters(void)
snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_SHT_%d"), ESP_getChipId(), i + 1);
snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/cover/%s/config"), unique_id);
if (Settings.flag.hass_discovery && Settings.flag3.shutter_mode && Settings.shutter_startrelay[i] > 0 && Settings.shutter_startrelay[i] <= MAX_SHUTTER_RELAYS) {
if (Settings->flag.hass_discovery && Settings->flag3.shutter_mode && Settings->shutter_startrelay[i] > 0 && Settings->shutter_startrelay[i] <= MAX_SHUTTER_RELAYS) {
ShowTopic = 0; // Show the new generated topic
if (i > MAX_FRIENDLYNAMES) {
snprintf_P(stemp1, sizeof(stemp1), PSTR("%s Shutter %d"), SettingsText(SET_DEVICENAME), i + 1);
@ -1029,7 +1029,7 @@ void HAssAnnounceDeviceInfoAndStatusSensor(void)
snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_status"), ESP_getChipId());
snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/sensor/%s/config"), unique_id);
if (Settings.flag.hass_discovery)
if (Settings->flag.hass_discovery)
{ // SetOption19 - Control Home Assistantautomatic discovery (See SetOption59)
char name[TOPSZ]; // friendlyname(33) + " " + "status"
char prefix[TOPSZ];
@ -1050,7 +1050,7 @@ void HAssAnnounceDeviceInfoAndStatusSensor(void)
TasmotaGlobal.masterlog_level = ShowTopic;
MqttPublish(stopic, true);
if (!Settings.flag.hass_discovery) {
if (!Settings->flag.hass_discovery) {
TasmotaGlobal.masterlog_level = 0;
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_LOG "Home Assistant MQTT Discovery disabled."));
}
@ -1071,17 +1071,17 @@ void HAssPublishStatus(void)
void HAssDiscovery(void)
{
// Configure Tasmota for default Home Assistant parameters to keep discovery message as short as possible
if (Settings.flag.hass_discovery)
if (Settings->flag.hass_discovery)
{ // SetOption19 - Control Home Assistant automatic discovery (See SetOption59)
Settings.flag.mqtt_response = 0; // SetOption4 - Switch between MQTT RESULT or COMMAND - Response always as RESULT and not as uppercase command
Settings.flag.decimal_text = 1; // SetOption17 - Switch between decimal or hexadecimal output - Respond with decimal color values
Settings.flag3.hass_tele_on_power = 1; // SetOption59 - Send tele/%topic%/STATE in addition to stat/%topic%/RESULT - send tele/STATE message as stat/RESULT
Settings->flag.mqtt_response = 0; // SetOption4 - Switch between MQTT RESULT or COMMAND - Response always as RESULT and not as uppercase command
Settings->flag.decimal_text = 1; // SetOption17 - Switch between decimal or hexadecimal output - Respond with decimal color values
Settings->flag3.hass_tele_on_power = 1; // SetOption59 - Send tele/%topic%/STATE in addition to stat/%topic%/RESULT - send tele/STATE message as stat/RESULT
// the purpose of that is so that if HA is restarted, state in HA will be correct within one teleperiod otherwise state
// will not be correct until the device state is changed this is why in the patterns for switch and light, we tell HA to trigger on STATE, not RESULT.
//Settings.light_scheme = 0; // To just control color it needs to be Scheme 0 (on hold due to new light configuration)
//Settings->light_scheme = 0; // To just control color it needs to be Scheme 0 (on hold due to new light configuration)
}
if (Settings.flag.hass_discovery || (1 == hass_mode))
if (Settings->flag.hass_discovery || (1 == hass_mode))
{ // SetOption19 - Control Home Assistantautomatic discovery (See SetOption59)
hass_mode = 2; // Needed for generating bluetooth entities for MI_ESP32
// Send info about buttons
@ -1114,7 +1114,7 @@ void HAssDiscover(void)
void HAssAnyKey(void)
{
if (!Settings.flag.hass_discovery) { return; } // SetOption19 - Control Home Assistantautomatic discovery (See SetOption59)
if (!Settings->flag.hass_discovery) { return; } // SetOption19 - Control Home Assistantautomatic discovery (See SetOption59)
uint32_t key = (XdrvMailbox.payload >> 16) & 0xFF; // 0 = KEY_BUTTON, 1 = KEY_SWITCH
uint32_t device = XdrvMailbox.payload & 0xFF; // Device number or 1 if more Buttons than Devices
uint32_t state = (XdrvMailbox.payload >> 8) & 0xFF; // 0 = Off, 1 = On, 2 = Toggle, 3 = Hold, 10,11,12,13 and 14 for Button Multipress
@ -1157,7 +1157,7 @@ bool HAssMqttLWT(void)
if (strncasecmp_P(XdrvMailbox.topic, PSTR(HOME_ASSISTANT_LWT_TOPIC), strlen(HOME_ASSISTANT_LWT_TOPIC)) != 0) {
return false;
}
if (Settings.flag.hass_discovery && (strncasecmp_P(XdrvMailbox.data, PSTR("online"), strlen("online")) == 0) && (XdrvMailbox.data_len == 6)) {
if (Settings->flag.hass_discovery && (strncasecmp_P(XdrvMailbox.data, PSTR("online"), strlen("online")) == 0) && (XdrvMailbox.data_len == 6)) {
MqttPublishTeleState();
return true;
} else { return false; }
@ -1167,7 +1167,7 @@ void HassLwtSubscribe(bool hasslwt)
{
char htopic[TOPSZ];
snprintf_P(htopic, sizeof(htopic), PSTR(HOME_ASSISTANT_LWT_TOPIC));
if (hasslwt && (Settings.flag.hass_discovery)) {
if (hasslwt && (Settings->flag.hass_discovery)) {
MqttSubscribe(htopic);
} else { MqttUnsubscribe(htopic); }
}
@ -1180,7 +1180,7 @@ bool Xdrv12(uint8_t function)
{
bool result = false;
bool hasslwt = HOME_ASSISTANT_LWT_SUBSCRIBE;
if (Settings.flag.mqtt_enabled)
if (Settings->flag.mqtt_enabled)
{ // SetOption3 - Enable MQTT
switch (function)
{
@ -1194,10 +1194,10 @@ bool Xdrv12(uint8_t function)
NewHAssDiscovery(); // Send the topics for Home Assistant Official Integration
}
}
else if (Settings.flag.hass_discovery && Settings.tele_period)
else if (Settings->flag.hass_discovery && Settings->tele_period)
{ // SetOption19 - Control Home Assistantautomatic discovery (See SetOption59)
hass_tele_period++;
if (hass_tele_period >= Settings.tele_period)
if (hass_tele_period >= Settings->tele_period)
{
hass_tele_period = 0;
ResponseClear();
@ -1210,16 +1210,16 @@ bool Xdrv12(uint8_t function)
break;
/*
case FUNC_MQTT_INIT:
hass_mode = 0; // Discovery only if Settings.flag.hass_discovery is set
hass_mode = 0; // Discovery only if Settings->flag.hass_discovery is set
TasmotaGlobal.discovery_counter = 10; // Delayed discovery
// if (!Settings.flag.hass_discovery) {
// if (!Settings->flag.hass_discovery) {
// NewHAssDiscovery();
// }
break;
*/
case FUNC_MQTT_SUBSCRIBE:
HassLwtSubscribe(hasslwt);
hass_mode = 0; // Discovery only if Settings.flag.hass_discovery is set
hass_mode = 0; // Discovery only if Settings->flag.hass_discovery is set
TasmotaGlobal.discovery_counter = (0 == Mqtt.initial_connection_state) ? 1 : 10; // Delayed discovery
break;
case FUNC_MQTT_DATA:

View File

@ -253,7 +253,7 @@ bool disp_subscribed = false;
void DisplayInit(uint8_t mode)
{
if (renderer) {
renderer->DisplayInit(mode, Settings.display_size, Settings.display_rotate, Settings.display_font);
renderer->DisplayInit(mode, Settings->display_size, Settings->display_rotate, Settings->display_font);
}
else {
dsp_init = mode;
@ -1396,11 +1396,11 @@ void DisplayFreeScreenBuffer(void)
void DisplayAllocScreenBuffer(void)
{
if (!disp_screen_buffer_cols) {
disp_screen_buffer_rows = Settings.display_rows;
disp_screen_buffer_rows = Settings->display_rows;
disp_screen_buffer = (char**)malloc(sizeof(*disp_screen_buffer) * disp_screen_buffer_rows);
if (disp_screen_buffer != nullptr) {
for (uint32_t i = 0; i < disp_screen_buffer_rows; i++) {
disp_screen_buffer[i] = (char*)malloc(sizeof(*disp_screen_buffer[i]) * (Settings.display_cols[0] +1));
disp_screen_buffer[i] = (char*)malloc(sizeof(*disp_screen_buffer[i]) * (Settings->display_cols[0] +1));
if (disp_screen_buffer[i] == nullptr) {
DisplayFreeScreenBuffer();
break;
@ -1408,7 +1408,7 @@ void DisplayAllocScreenBuffer(void)
}
}
if (disp_screen_buffer != nullptr) {
disp_screen_buffer_cols = Settings.display_cols[0] +1;
disp_screen_buffer_cols = Settings->display_cols[0] +1;
DisplayClearScreenBuffer();
}
}
@ -1457,7 +1457,7 @@ void DisplayAllocLogBuffer(void)
disp_log_buffer = (char**)malloc(sizeof(*disp_log_buffer) * DISPLAY_LOG_ROWS);
if (disp_log_buffer != nullptr) {
for (uint32_t i = 0; i < DISPLAY_LOG_ROWS; i++) {
disp_log_buffer[i] = (char*)malloc(sizeof(*disp_log_buffer[i]) * (Settings.display_cols[0] +1));
disp_log_buffer[i] = (char*)malloc(sizeof(*disp_log_buffer[i]) * (Settings->display_cols[0] +1));
if (disp_log_buffer[i] == nullptr) {
DisplayFreeLogBuffer();
break;
@ -1465,7 +1465,7 @@ void DisplayAllocLogBuffer(void)
}
}
if (disp_log_buffer != nullptr) {
disp_log_buffer_cols = Settings.display_cols[0] +1;
disp_log_buffer_cols = Settings->display_cols[0] +1;
DisplayClearLogBuffer();
}
}
@ -1504,10 +1504,10 @@ char* DisplayLogBuffer(char temp_code)
void DisplayLogBufferInit(void)
{
if (Settings.display_mode) {
if (Settings->display_mode) {
disp_log_buffer_idx = 0;
disp_log_buffer_ptr = 0;
disp_refresh = Settings.display_refresh;
disp_refresh = Settings->display_refresh;
snprintf_P(disp_temp, sizeof(disp_temp), PSTR("%c"), TempUnit());
snprintf_P(disp_pres, sizeof(disp_pres), PressureUnit().c_str());
@ -1517,7 +1517,7 @@ void DisplayLogBufferInit(void)
char buffer[40];
snprintf_P(buffer, sizeof(buffer), PSTR(D_VERSION " %s%s"), TasmotaGlobal.version, TasmotaGlobal.image_name);
DisplayLogBufferAdd(buffer);
snprintf_P(buffer, sizeof(buffer), PSTR("Display mode %d"), Settings.display_mode);
snprintf_P(buffer, sizeof(buffer), PSTR("Display mode %d"), Settings->display_mode);
DisplayLogBufferAdd(buffer);
snprintf_P(buffer, sizeof(buffer), PSTR(D_CMND_HOSTNAME " %s"), NetworkHostname());
@ -1527,7 +1527,7 @@ void DisplayLogBufferInit(void)
ext_snprintf_P(buffer, sizeof(buffer), PSTR("IP %_I"), (uint32_t)NetworkAddress());
DisplayLogBufferAdd(buffer);
if (!TasmotaGlobal.global_state.wifi_down) {
snprintf_P(buffer, sizeof(buffer), PSTR(D_JSON_SSID " %s"), SettingsText(SET_STASSID1 + Settings.sta_active));
snprintf_P(buffer, sizeof(buffer), PSTR(D_JSON_SSID " %s"), SettingsText(SET_STASSID1 + Settings->sta_active));
DisplayLogBufferAdd(buffer);
snprintf_P(buffer, sizeof(buffer), PSTR(D_JSON_RSSI " %d%%"), WifiGetRssiAsQuality(WiFi.RSSI()));
DisplayLogBufferAdd(buffer);
@ -1571,10 +1571,10 @@ const char kSensorQuantity[] PROGMEM =
void DisplayJsonValue(const char* topic, const char* device, const char* mkey, const char* value)
{
char quantity[TOPSZ];
char buffer[Settings.display_cols[0] +1];
char spaces[Settings.display_cols[0]];
char source[Settings.display_cols[0] - Settings.display_cols[1]];
char svalue[Settings.display_cols[1] +1];
char buffer[Settings->display_cols[0] +1];
char spaces[Settings->display_cols[0]];
char source[Settings->display_cols[0] - Settings->display_cols[1]];
char svalue[Settings->display_cols[1] +1];
#ifdef USE_DEBUG_DRIVER
ShowFreeMem(PSTR("DisplayJsonValue"));
@ -1698,7 +1698,7 @@ void DisplayMqttSubscribe(void)
* - home/%prefix%/%topic%
* - home/level2/%prefix%/%topic% etc.
*/
if (Settings.display_model && (Settings.display_mode &0x04)) {
if (Settings->display_model && (Settings->display_mode &0x04)) {
char stopic[TOPSZ];
char ntopic[TOPSZ];
@ -1730,7 +1730,7 @@ bool DisplayMqttData(void)
snprintf_P(stopic, sizeof(stopic) , PSTR("%s/"), SettingsText(SET_MQTTPREFIX3)); // tele/
char *tp = strstr(XdrvMailbox.topic, stopic);
if (tp) { // tele/tasmota/SENSOR
if (Settings.display_mode &0x04) {
if (Settings->display_mode &0x04) {
tp = tp + strlen(stopic); // tasmota/SENSOR
char *topic = strtok(tp, "/"); // tasmota
DisplayAnalyzeJson(topic, XdrvMailbox.data);
@ -1743,7 +1743,7 @@ bool DisplayMqttData(void)
void DisplayLocalSensor(void)
{
if ((Settings.display_mode &0x02) && (0 == TasmotaGlobal.tele_period)) {
if ((Settings->display_mode &0x02) && (0 == TasmotaGlobal.tele_period)) {
char no_topic[1] = { 0 };
#ifdef MQTT_DATA_STRING
// DisplayAnalyzeJson(TasmotaGlobal.mqtt_topic, TasmotaGlobal.mqtt_data.c_str()); // Add local topic
@ -1771,8 +1771,8 @@ void DisplayInitDriver(void)
#endif // USE_MULTI_DISPLAY
if (renderer) {
renderer->setTextFont(Settings.display_font);
renderer->setTextSize(Settings.display_size);
renderer->setTextFont(Settings->display_font);
renderer->setTextSize(Settings->display_size);
// force opaque mode
renderer->setDrawMode(0);
@ -1793,19 +1793,19 @@ void DisplayInitDriver(void)
for (uint8_t count = 0; count < NUM_GRAPHS; count++) { graph[count] = 0; }
#endif
// AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "Display model %d"), Settings.display_model);
// AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "Display model %d"), Settings->display_model);
if (Settings.display_model) {
if (Settings->display_model) {
TasmotaGlobal.devices_present++;
if (!PinUsed(GPIO_BACKLIGHT)) {
if (TasmotaGlobal.light_type && (4 == Settings.display_model)) {
if (TasmotaGlobal.light_type && (4 == Settings->display_model)) {
TasmotaGlobal.devices_present--; // Assume PWM channel is used for backlight
}
}
disp_device = TasmotaGlobal.devices_present;
#ifndef USE_DISPLAY_MODES1TO5
Settings.display_mode = 0;
Settings->display_mode = 0;
#else
DisplayLogBufferInit();
#endif // USE_DISPLAY_MODES1TO5
@ -1818,7 +1818,7 @@ void DisplaySetPower(void)
//AddLog(LOG_LEVEL_DEBUG, PSTR("DSP: Power %d"), disp_power);
if (Settings.display_model) {
if (Settings->display_model) {
if (!renderer) {
XdspCall(FUNC_DISPLAY_POWER);
} else {
@ -1835,50 +1835,50 @@ void CmndDisplay(void) {
Response_P(PSTR("{\"" D_PRFX_DISPLAY "\":{\"" D_CMND_DISP_MODEL "\":%d,\"" D_CMND_DISP_TYPE "\":%d,\"" D_CMND_DISP_WIDTH "\":%d,\"" D_CMND_DISP_HEIGHT "\":%d,\""
D_CMND_DISP_MODE "\":%d,\"" D_CMND_DISP_DIMMER "\":%d,\"" D_CMND_DISP_SIZE "\":%d,\"" D_CMND_DISP_FONT "\":%d,\""
D_CMND_DISP_ROTATE "\":%d,\"" D_CMND_DISP_INVERT "\":%d,\"" D_CMND_DISP_REFRESH "\":%d,\"" D_CMND_DISP_COLS "\":[%d,%d],\"" D_CMND_DISP_ROWS "\":%d}}"),
Settings.display_model, Settings.display_options.type, Settings.display_width, Settings.display_height,
Settings.display_mode, changeUIntScale(Settings.display_dimmer, 0, 15, 0, 100), Settings.display_size, Settings.display_font,
Settings.display_rotate, Settings.display_options.invert, Settings.display_refresh, Settings.display_cols[0], Settings.display_cols[1], Settings.display_rows);
Settings->display_model, Settings->display_options.type, Settings->display_width, Settings->display_height,
Settings->display_mode, changeUIntScale(Settings->display_dimmer, 0, 15, 0, 100), Settings->display_size, Settings->display_font,
Settings->display_rotate, Settings->display_options.invert, Settings->display_refresh, Settings->display_cols[0], Settings->display_cols[1], Settings->display_rows);
}
void CmndDisplayModel(void) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < DISPLAY_MAX_DRIVERS)) {
uint32_t last_display_model = Settings.display_model;
Settings.display_model = XdrvMailbox.payload;
uint32_t last_display_model = Settings->display_model;
Settings->display_model = XdrvMailbox.payload;
if (XdspCall(FUNC_DISPLAY_MODEL)) {
TasmotaGlobal.restart_flag = 2; // Restart to re-init interface and add/Remove MQTT subscribe
} else {
Settings.display_model = last_display_model;
Settings->display_model = last_display_model;
}
}
ResponseCmndNumber(Settings.display_model);
ResponseCmndNumber(Settings->display_model);
}
void CmndDisplayType(void) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 7)) {
Settings.display_options.type = XdrvMailbox.payload;
Settings->display_options.type = XdrvMailbox.payload;
TasmotaGlobal.restart_flag = 2;
}
ResponseCmndNumber(Settings.display_options.type);
ResponseCmndNumber(Settings->display_options.type);
}
void CmndDisplayWidth(void) {
if (XdrvMailbox.payload > 0) {
if (XdrvMailbox.payload != Settings.display_width) {
Settings.display_width = XdrvMailbox.payload;
if (XdrvMailbox.payload != Settings->display_width) {
Settings->display_width = XdrvMailbox.payload;
TasmotaGlobal.restart_flag = 2; // Restart to re-init width
}
}
ResponseCmndNumber(Settings.display_width);
ResponseCmndNumber(Settings->display_width);
}
void CmndDisplayHeight(void) {
if (XdrvMailbox.payload > 0) {
if (XdrvMailbox.payload != Settings.display_height) {
Settings.display_height = XdrvMailbox.payload;
if (XdrvMailbox.payload != Settings->display_height) {
Settings->display_height = XdrvMailbox.payload;
TasmotaGlobal.restart_flag = 2; // Restart to re-init height
}
}
ResponseCmndNumber(Settings.display_height);
ResponseCmndNumber(Settings->display_height);
}
void CmndDisplayMode(void) {
@ -1891,13 +1891,13 @@ void CmndDisplayMode(void) {
* 5 = Mqtt up and time Mqtt (incl local) sensors and time Mqtt (incl local) sensors and time
*/
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 5)) {
uint32_t last_display_mode = Settings.display_mode;
Settings.display_mode = XdrvMailbox.payload;
uint32_t last_display_mode = Settings->display_mode;
Settings->display_mode = XdrvMailbox.payload;
if (disp_subscribed != (Settings.display_mode &0x04)) {
if (disp_subscribed != (Settings->display_mode &0x04)) {
TasmotaGlobal.restart_flag = 2; // Restart to Add/Remove MQTT subscribe
} else {
if (last_display_mode && !Settings.display_mode) { // Switch to mode 0
if (last_display_mode && !Settings->display_mode) { // Switch to mode 0
DisplayInit(DISPLAY_INIT_MODE);
if (renderer) renderer->fillScreen(bg_color);
else DisplayClear();
@ -1908,88 +1908,88 @@ void CmndDisplayMode(void) {
}
}
#endif // USE_DISPLAY_MODES1TO5
ResponseCmndNumber(Settings.display_mode);
ResponseCmndNumber(Settings->display_mode);
}
void CmndDisplayDimmer(void) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) {
Settings.display_dimmer = changeUIntScale(XdrvMailbox.payload, 0, 100, 0, 15); // Correction for Domoticz (0 - 15)
if (Settings.display_dimmer && !(disp_power)) {
Settings->display_dimmer = changeUIntScale(XdrvMailbox.payload, 0, 100, 0, 15); // Correction for Domoticz (0 - 15)
if (Settings->display_dimmer && !(disp_power)) {
ExecuteCommandPower(disp_device, POWER_ON, SRC_DISPLAY);
}
else if (!Settings.display_dimmer && disp_power) {
else if (!Settings->display_dimmer && disp_power) {
ExecuteCommandPower(disp_device, POWER_OFF, SRC_DISPLAY);
}
if (renderer) {
renderer->dim(Settings.display_dimmer);
renderer->dim(Settings->display_dimmer);
} else {
XdspCall(FUNC_DISPLAY_DIM);
}
}
ResponseCmndNumber(changeUIntScale(Settings.display_dimmer, 0, 15, 0, 100));
ResponseCmndNumber(changeUIntScale(Settings->display_dimmer, 0, 15, 0, 100));
}
void CmndDisplaySize(void) {
if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 4)) {
Settings.display_size = XdrvMailbox.payload;
if (renderer) renderer->setTextSize(Settings.display_size);
//else DisplaySetSize(Settings.display_size);
Settings->display_size = XdrvMailbox.payload;
if (renderer) renderer->setTextSize(Settings->display_size);
//else DisplaySetSize(Settings->display_size);
}
ResponseCmndNumber(Settings.display_size);
ResponseCmndNumber(Settings->display_size);
}
void CmndDisplayFont(void) {
if ((XdrvMailbox.payload >=0) && (XdrvMailbox.payload <= 4)) {
Settings.display_font = XdrvMailbox.payload;
if (renderer) renderer->setTextFont(Settings.display_font);
//else DisplaySetFont(Settings.display_font);
Settings->display_font = XdrvMailbox.payload;
if (renderer) renderer->setTextFont(Settings->display_font);
//else DisplaySetFont(Settings->display_font);
}
ResponseCmndNumber(Settings.display_font);
ResponseCmndNumber(Settings->display_font);
}
void CmndDisplayRotate(void) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 4)) {
if ((Settings.display_rotate) != XdrvMailbox.payload) {
if ((Settings->display_rotate) != XdrvMailbox.payload) {
/*
// Needs font info regarding height and width
if ((Settings.display_rotate &1) != (XdrvMailbox.payload &1)) {
uint8_t temp_rows = Settings.display_rows;
Settings.display_rows = Settings.display_cols[0];
Settings.display_cols[0] = temp_rows;
if ((Settings->display_rotate &1) != (XdrvMailbox.payload &1)) {
uint8_t temp_rows = Settings->display_rows;
Settings->display_rows = Settings->display_cols[0];
Settings->display_cols[0] = temp_rows;
#ifdef USE_DISPLAY_MODES1TO5
DisplayReAllocScreenBuffer();
#endif // USE_DISPLAY_MODES1TO5
}
*/
Settings.display_rotate = XdrvMailbox.payload;
Settings->display_rotate = XdrvMailbox.payload;
DisplayInit(DISPLAY_INIT_MODE);
#ifdef USE_DISPLAY_MODES1TO5
DisplayLogBufferInit();
#endif // USE_DISPLAY_MODES1TO5
}
}
ResponseCmndNumber(Settings.display_rotate);
ResponseCmndNumber(Settings->display_rotate);
}
void CmndDisplayInvert(void) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) {
Settings.display_options.invert = XdrvMailbox.payload;
if (renderer) renderer->invertDisplay(Settings.display_options.invert);
Settings->display_options.invert = XdrvMailbox.payload;
if (renderer) renderer->invertDisplay(Settings->display_options.invert);
}
ResponseCmndNumber(Settings.display_options.invert);
ResponseCmndNumber(Settings->display_options.invert);
}
void CmndDisplayRefresh(void) {
if ((XdrvMailbox.payload >= 1) && (XdrvMailbox.payload <= 7)) {
Settings.display_refresh = XdrvMailbox.payload;
Settings->display_refresh = XdrvMailbox.payload;
}
ResponseCmndNumber(Settings.display_refresh);
ResponseCmndNumber(Settings->display_refresh);
}
void CmndDisplayColumns(void) {
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 2)) {
if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= DISPLAY_MAX_COLS)) {
Settings.display_cols[XdrvMailbox.index -1] = XdrvMailbox.payload;
Settings->display_cols[XdrvMailbox.index -1] = XdrvMailbox.payload;
#ifdef USE_DISPLAY_MODES1TO5
if (1 == XdrvMailbox.index) {
DisplayLogBufferInit();
@ -1997,27 +1997,27 @@ void CmndDisplayColumns(void) {
}
#endif // USE_DISPLAY_MODES1TO5
}
ResponseCmndIdxNumber(Settings.display_cols[XdrvMailbox.index -1]);
ResponseCmndIdxNumber(Settings->display_cols[XdrvMailbox.index -1]);
}
}
void CmndDisplayRows(void) {
if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= DISPLAY_MAX_ROWS)) {
Settings.display_rows = XdrvMailbox.payload;
Settings->display_rows = XdrvMailbox.payload;
#ifdef USE_DISPLAY_MODES1TO5
DisplayLogBufferInit();
DisplayReAllocScreenBuffer();
#endif // USE_DISPLAY_MODES1TO5
}
ResponseCmndNumber(Settings.display_rows);
ResponseCmndNumber(Settings->display_rows);
}
void CmndDisplayAddress(void) {
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 8)) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 255)) {
Settings.display_address[XdrvMailbox.index -1] = XdrvMailbox.payload;
Settings->display_address[XdrvMailbox.index -1] = XdrvMailbox.payload;
}
ResponseCmndIdxNumber(Settings.display_address[XdrvMailbox.index -1]);
ResponseCmndIdxNumber(Settings->display_address[XdrvMailbox.index -1]);
}
}
@ -2033,7 +2033,7 @@ void CmndDisplayBlinkrate(void) {
#ifdef USE_UFILESYS
void CmndDisplayBatch(void) {
if (XdrvMailbox.data_len > 0) {
if (!Settings.display_mode) {
if (!Settings->display_mode) {
Display_Text_From_File(XdrvMailbox.data);
}
ResponseCmndChar(XdrvMailbox.data);
@ -2046,9 +2046,9 @@ void CmndDisplayText(void) {
#ifndef USE_DISPLAY_MODES1TO5
DisplayText();
#else
if(Settings.display_model == 15) {
if(Settings->display_model == 15) {
XdspCall(FUNC_DISPLAY_SEVENSEG_TEXT);
} else if (!Settings.display_mode) {
} else if (!Settings->display_mode) {
DisplayText();
} else {
DisplayLogBufferAdd(XdrvMailbox.data);
@ -2703,7 +2703,7 @@ bool Xdrv13(uint8_t function)
DisplayInitDriver();
break;
case FUNC_EVERY_50_MSECOND:
if (Settings.display_model) { XdspCall(FUNC_DISPLAY_EVERY_50_MSECOND); }
if (Settings->display_model) { XdspCall(FUNC_DISPLAY_EVERY_50_MSECOND); }
break;
case FUNC_SET_POWER:
DisplaySetPower();
@ -2718,7 +2718,7 @@ bool Xdrv13(uint8_t function)
#endif // USE_DT_VARS
#ifdef USE_DISPLAY_MODES1TO5
if (Settings.display_model && Settings.display_mode) { XdspCall(FUNC_DISPLAY_EVERY_SECOND); }
if (Settings->display_model && Settings->display_mode) { XdspCall(FUNC_DISPLAY_EVERY_SECOND); }
#endif
break;
case FUNC_AFTER_TELEPERIOD:

View File

@ -147,8 +147,8 @@ void CmndTuyaSend(void) {
} else if (XdrvMailbox.index == 8) {
TuyaRequestState(8);
} else if (XdrvMailbox.index == 9) { // TuyaSend Topic Toggle
Settings.tuyamcu_topic = !Settings.tuyamcu_topic;
AddLog(LOG_LEVEL_INFO, PSTR("TYA: TuyaMCU Stat Topic %s"), (Settings.tuyamcu_topic ? PSTR("enabled") : PSTR("disabled")));
Settings->tuyamcu_topic = !Settings->tuyamcu_topic;
AddLog(LOG_LEVEL_INFO, PSTR("TYA: TuyaMCU Stat Topic %s"), (Settings->tuyamcu_topic ? PSTR("enabled") : PSTR("disabled")));
} else {
if (XdrvMailbox.data_len > 0) {
@ -204,8 +204,8 @@ void CmndTuyaMcu(void) {
if (TuyaGetDpId(TUYA_MCU_FUNC_CT) != 0) { TuyaAddMcuFunc(TUYA_MCU_FUNC_CT, 0); }
if (TuyaGetDpId(TUYA_MCU_FUNC_RGB) != 0) { TuyaAddMcuFunc(TUYA_MCU_FUNC_RGB, 0); }
if (TuyaGetDpId(TUYA_MCU_FUNC_WHITE) != 0) { TuyaAddMcuFunc(TUYA_MCU_FUNC_WHITE, 0); }
Settings.flag3.pwm_multi_channels = 1;
} else { Settings.flag3.pwm_multi_channels = 0; }
Settings->flag3.pwm_multi_channels = 1;
} else { Settings->flag3.pwm_multi_channels = 0; }
TuyaAddMcuFunc(parm[0], parm[1]);
TasmotaGlobal.restart_flag = 2;
} else {
@ -216,11 +216,11 @@ void CmndTuyaMcu(void) {
Response_P(PSTR("{\"%s\":["), XdrvMailbox.command); // Builds TuyaMCU
bool added = false;
for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) {
if (Settings.tuya_fnid_map[i].fnid != 0) {
if (Settings->tuya_fnid_map[i].fnid != 0) {
if (added) {
ResponseAppend_P(PSTR(","));
}
ResponseAppend_P(PSTR("{\"fnId\":%d,\"dpId\":%d}" ), Settings.tuya_fnid_map[i].fnid, Settings.tuya_fnid_map[i].dpid);
ResponseAppend_P(PSTR("{\"fnId\":%d,\"dpId\":%d}" ), Settings->tuya_fnid_map[i].fnid, Settings->tuya_fnid_map[i].dpid);
added = true;
}
}
@ -235,21 +235,21 @@ void CmndTuyaRgb(void) { // Command to control the RGB format
if (payload < 0 || payload > 3 || TuyaGetDpId(TUYA_MCU_FUNC_RGB) == 0) {
return;
} else {
if (payload != Settings.tuya_fnid_map[230].dpid) { // fnid 230 is reserved for RGB
Settings.tuya_fnid_map[230].fnid = 230;
Settings.tuya_fnid_map[230].dpid = payload;
if (payload != Settings->tuya_fnid_map[230].dpid) { // fnid 230 is reserved for RGB
Settings->tuya_fnid_map[230].fnid = 230;
Settings->tuya_fnid_map[230].dpid = payload;
}
}
}
ResponseCmndNumber(Settings.tuya_fnid_map[230].dpid);
ResponseCmndNumber(Settings->tuya_fnid_map[230].dpid);
}
void CmndTuyaTempSetRes(void)
{
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) {
Settings.mbflag2.temperature_set_res = XdrvMailbox.payload;
Settings->mbflag2.temperature_set_res = XdrvMailbox.payload;
}
ResponseCmndNumber(Settings.mbflag2.temperature_set_res);
ResponseCmndNumber(Settings->mbflag2.temperature_set_res);
}
void CmndTuyaEnum(void) { // Command to control up to four type 4 Enum
@ -261,7 +261,7 @@ void CmndTuyaEnum(void) { // Command to control up to four type 4 Enum
}
if (XdrvMailbox.data_len > 0) {
if (payload < 0 || payload > Settings.tuya_fnid_map[EnumIdx + 230].dpid ) {
if (payload < 0 || payload > Settings->tuya_fnid_map[EnumIdx + 230].dpid ) {
return;
} else {
if (payload != Tuya.EnumState[EnumIdx-1]) {
@ -298,8 +298,8 @@ void CmndTuyaEnumList(void) { // Command to declare the number of items in list
}
if ((parm[0] >= 1 && parm[0] <= 4) && (parm[1] >= 1 && parm[1] <= 31)) {
uint16_t idx = parm[0] + 230; // fnid 231, 232, 233 and 234 are reserved for enum
Settings.tuya_fnid_map[idx].fnid = idx;
Settings.tuya_fnid_map[idx].dpid = parm[1];
Settings->tuya_fnid_map[idx].fnid = idx;
Settings->tuya_fnid_map[idx].dpid = parm[1];
}
}
if ((TuyaGetDpId(TUYA_MCU_FUNC_ENUM1) != 0) || (TuyaGetDpId(TUYA_MCU_FUNC_ENUM3) != 0) ||
@ -310,9 +310,9 @@ void CmndTuyaEnumList(void) { // Command to declare the number of items in list
if (TuyaGetDpId(TUYA_MCU_FUNC_ENUM1 + i) != 0) {
if (added) {
ResponseAppend_P(PSTR(","));
if ( Settings.tuya_fnid_map[i + 231].dpid > 31 ) { Settings.tuya_fnid_map[i + 231].dpid = 0; } // default to 0 it the value exceed the range
if ( Settings->tuya_fnid_map[i + 231].dpid > 31 ) { Settings->tuya_fnid_map[i + 231].dpid = 0; } // default to 0 it the value exceed the range
}
ResponseAppend_P(PSTR("\"Enum%d\":%d"), i + 1, Settings.tuya_fnid_map[i + 231].dpid); // fnid 231, 232, 233 and 234 are reserved for Enum
ResponseAppend_P(PSTR("\"Enum%d\":%d"), i + 1, Settings->tuya_fnid_map[i + 231].dpid); // fnid 231, 232, 233 and 234 are reserved for Enum
added = true;
}
}
@ -356,22 +356,22 @@ void TuyaAddMcuFunc(uint8_t fnId, uint8_t dpId) {
if (fnId == 0 || dpId == 0) { // Delete entry
for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) {
if ((dpId > 0 && Settings.tuya_fnid_map[i].dpid == dpId) || (fnId > TUYA_MCU_FUNC_NONE && Settings.tuya_fnid_map[i].fnid == fnId)) {
Settings.tuya_fnid_map[i].fnid = TUYA_MCU_FUNC_NONE;
Settings.tuya_fnid_map[i].dpid = 0;
if ((dpId > 0 && Settings->tuya_fnid_map[i].dpid == dpId) || (fnId > TUYA_MCU_FUNC_NONE && Settings->tuya_fnid_map[i].fnid == fnId)) {
Settings->tuya_fnid_map[i].fnid = TUYA_MCU_FUNC_NONE;
Settings->tuya_fnid_map[i].dpid = 0;
break;
}
}
} else { // Add or update
for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) {
if (Settings.tuya_fnid_map[i].dpid == dpId || Settings.tuya_fnid_map[i].dpid == 0 || Settings.tuya_fnid_map[i].fnid == fnId || Settings.tuya_fnid_map[i].fnid == 0) {
if (Settings->tuya_fnid_map[i].dpid == dpId || Settings->tuya_fnid_map[i].dpid == 0 || Settings->tuya_fnid_map[i].fnid == fnId || Settings->tuya_fnid_map[i].fnid == 0) {
if (!added) { // Update entry if exisiting entry or add
Settings.tuya_fnid_map[i].fnid = fnId;
Settings.tuya_fnid_map[i].dpid = dpId;
Settings->tuya_fnid_map[i].fnid = fnId;
Settings->tuya_fnid_map[i].dpid = dpId;
added = true;
} else if (Settings.tuya_fnid_map[i].dpid == dpId || Settings.tuya_fnid_map[i].fnid == fnId) { // Remove existing entry if added to empty place
Settings.tuya_fnid_map[i].fnid = TUYA_MCU_FUNC_NONE;
Settings.tuya_fnid_map[i].dpid = 0;
} else if (Settings->tuya_fnid_map[i].dpid == dpId || Settings->tuya_fnid_map[i].fnid == fnId) { // Remove existing entry if added to empty place
Settings->tuya_fnid_map[i].fnid = TUYA_MCU_FUNC_NONE;
Settings->tuya_fnid_map[i].dpid = 0;
}
}
}
@ -381,8 +381,8 @@ void TuyaAddMcuFunc(uint8_t fnId, uint8_t dpId) {
void UpdateDevices() {
for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) {
uint8_t fnId = Settings.tuya_fnid_map[i].fnid;
if (fnId > TUYA_MCU_FUNC_NONE && Settings.tuya_fnid_map[i].dpid > 0) {
uint8_t fnId = Settings->tuya_fnid_map[i].fnid;
if (fnId > TUYA_MCU_FUNC_NONE && Settings->tuya_fnid_map[i].dpid > 0) {
if (fnId >= TUYA_MCU_FUNC_REL1 && fnId <= TUYA_MCU_FUNC_REL8) { //Relay
bitClear(TasmotaGlobal.rel_inverted, fnId - TUYA_MCU_FUNC_REL1);
@ -408,8 +408,8 @@ inline bool TuyaFuncIdValid(uint8_t fnId) {
}
uint8_t TuyaGetFuncId(uint8_t dpid) {
for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) {
if (Settings.tuya_fnid_map[i].dpid == dpid) {
return Settings.tuya_fnid_map[i].fnid;
if (Settings->tuya_fnid_map[i].dpid == dpid) {
return Settings->tuya_fnid_map[i].fnid;
}
}
return TUYA_MCU_FUNC_NONE;
@ -417,8 +417,8 @@ uint8_t TuyaGetFuncId(uint8_t dpid) {
uint8_t TuyaGetDpId(uint8_t fnId) {
for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) {
if (Settings.tuya_fnid_map[i].fnid == fnId) {
return Settings.tuya_fnid_map[i].dpid;
if (Settings->tuya_fnid_map[i].fnid == fnId) {
return Settings->tuya_fnid_map[i].dpid;
}
}
return 0;
@ -563,7 +563,7 @@ bool TuyaSetChannels(void)
}
if (LT_SERIAL2 == TasmotaGlobal.light_type || LT_RGBWC == TasmotaGlobal.light_type) {
idx = 1;
if (LT_SERIAL2 == TasmotaGlobal.light_type && Settings.flag3.pwm_multi_channels && (TuyaGetDpId(TUYA_MCU_FUNC_DIMMER2) != 0)) {
if (LT_SERIAL2 == TasmotaGlobal.light_type && Settings->flag3.pwm_multi_channels && (TuyaGetDpId(TUYA_MCU_FUNC_DIMMER2) != 0)) {
// Special setup for dual dimmer (like the MOES 2 Way Dimmer) emulating 2 PWM channels
Tuya.Snapshot[0] = changeUIntScale(Light.current_color[0], 0, 255, 0, 100);
Tuya.Snapshot[1] = changeUIntScale(Light.current_color[1], 0, 255, 0, 100);
@ -603,7 +603,7 @@ bool TuyaSetChannels(void)
// 2 Type 2 Uppercase - 00FF00FFFF6464
// 3 Type 2 Lowercase - 00e420ffff6464
uint8_t RGBType = Settings.tuya_fnid_map[230].dpid; // Select the type of RGB payload
uint8_t RGBType = Settings->tuya_fnid_map[230].dpid; // Select the type of RGB payload
char scolor[7];
LightGetColor(scolor, 1); // Always get the color in hex format
light_state.getHSB(&hue, &sat, &bri);
@ -650,7 +650,7 @@ void LightSerialDuty(uint16_t duty, char *hex_char, uint8_t TuyaIdx)
if (TuyaIdx > 0 && TuyaIdx <= 2) {
if (TuyaIdx == 2) {
if (!Settings.flag3.pwm_multi_channels) {
if (!Settings->flag3.pwm_multi_channels) {
CTLight = true;
dpid = TuyaGetDpId(TUYA_MCU_FUNC_CT);
} else { dpid = TuyaGetDpId(TUYA_MCU_FUNC_DIMMER2); }
@ -662,10 +662,10 @@ void LightSerialDuty(uint16_t duty, char *hex_char, uint8_t TuyaIdx)
if (duty > 0 && !Tuya.ignore_dim && TuyaSerial && dpid > 0) {
if (TuyaIdx == 2 && CTLight) {
duty = changeUIntScale(duty, Tuya.CTMin, Tuya.CTMax, Settings.dimmer_hw_max, 0);
} else { duty = changeUIntScale(duty, 0, 100, 0, Settings.dimmer_hw_max); }
duty = changeUIntScale(duty, Tuya.CTMin, Tuya.CTMax, Settings->dimmer_hw_max, 0);
} else { duty = changeUIntScale(duty, 0, 100, 0, Settings->dimmer_hw_max); }
if (duty < Settings.dimmer_hw_min) { duty = Settings.dimmer_hw_min; } // dimming acts odd below 25(10%) - this mirrors the threshold set on the faceplate itself
if (duty < Settings->dimmer_hw_min) { duty = Settings->dimmer_hw_min; } // dimming acts odd below 25(10%) - this mirrors the threshold set on the faceplate itself
Tuya.ignore_dimmer_cmd_timeout = millis() + 250; // Ignore serial received dim commands for the next 250ms
if (Tuya.ModeSet && (TuyaGetDpId(TUYA_MCU_FUNC_MODESET) != 0) && TasmotaGlobal.light_type > LT_RGB) {
TuyaSendEnum(TuyaGetDpId(TUYA_MCU_FUNC_MODESET), 0);
@ -677,9 +677,9 @@ void LightSerialDuty(uint16_t duty, char *hex_char, uint8_t TuyaIdx)
Tuya.ignore_dim = false; // reset flag
if (TuyaIdx == 2 && CTLight) {
duty = changeUIntScale(duty, Tuya.CTMin, Tuya.CTMax, Settings.dimmer_hw_max, 0);
duty = changeUIntScale(duty, Tuya.CTMin, Tuya.CTMax, Settings->dimmer_hw_max, 0);
} else {
duty = changeUIntScale(duty, 0, 100, 0, Settings.dimmer_hw_max);
duty = changeUIntScale(duty, 0, 100, 0, Settings->dimmer_hw_max);
}
AddLog(LOG_LEVEL_DEBUG, PSTR("TYA: Send dim skipped value %d for dpid %d"), duty, dpid); // due to 0 or already set
} else {
@ -717,7 +717,7 @@ void TuyaRequestState(uint8_t state_type)
void TuyaResetWifi(void)
{
if (!Settings.flag.button_restrict) { // SetOption1 - Control button multipress
if (!Settings->flag.button_restrict) { // SetOption1 - Control button multipress
char scmnd[20];
snprintf_P(scmnd, sizeof(scmnd), D_CMND_WIFICONFIG " %d", 2);
ExecuteCommand(scmnd, SRC_BUTTON);
@ -768,7 +768,7 @@ void TuyaProcessStatePacket(void) {
if (fnId >= TUYA_MCU_FUNC_REL1 && fnId <= TUYA_MCU_FUNC_REL8) {
AddLog(LOG_LEVEL_DEBUG, PSTR("TYA: RX Relay-%d --> MCU State: %s Current State:%s"), fnId - TUYA_MCU_FUNC_REL1 + 1, Tuya.buffer[dpidStart + 4]?"On":"Off",bitRead(TasmotaGlobal.power, fnId - TUYA_MCU_FUNC_REL1)?"On":"Off");
if ((TasmotaGlobal.power || Settings.light_dimmer > 0) && (Tuya.buffer[dpidStart + 4] != bitRead(TasmotaGlobal.power, fnId - TUYA_MCU_FUNC_REL1))) {
if ((TasmotaGlobal.power || Settings->light_dimmer > 0) && (Tuya.buffer[dpidStart + 4] != bitRead(TasmotaGlobal.power, fnId - TUYA_MCU_FUNC_REL1))) {
if (!Tuya.buffer[dpidStart + 4]) { PowerOff = true; }
ExecuteCommandPower(fnId - TUYA_MCU_FUNC_REL1 + 1, Tuya.buffer[dpidStart + 4], SRC_SWITCH); // send SRC_SWITCH? to use as flag to prevent loop from inbound states from faceplate interaction
}
@ -812,11 +812,11 @@ void TuyaProcessStatePacket(void) {
if (fnId > 74) {
res = 0;
} else if (fnId > 72) {
res = Settings.flag2.humidity_resolution;
res = Settings->flag2.humidity_resolution;
} else if (fnId == 72) {
res = Settings.mbflag2.temperature_set_res;
res = Settings->mbflag2.temperature_set_res;
} else {
res = Settings.flag2.temperature_resolution;
res = Settings->flag2.temperature_resolution;
}
GetTextIndexed(sname, sizeof(sname), (fnId-71), kTuyaSensors);
ResponseClear(); // Clear retained message
@ -829,10 +829,10 @@ void TuyaProcessStatePacket(void) {
if (fnId == TUYA_MCU_FUNC_DIMMER2 || fnId == TUYA_MCU_FUNC_REPORT2 || fnId == TUYA_MCU_FUNC_CT) { dimIndex = 1; }
if (dimIndex == 1 && !Settings.flag3.pwm_multi_channels) {
Tuya.Levels[1] = changeUIntScale(packetValue, 0, Settings.dimmer_hw_max, Tuya.CTMax, Tuya.CTMin);
if (dimIndex == 1 && !Settings->flag3.pwm_multi_channels) {
Tuya.Levels[1] = changeUIntScale(packetValue, 0, Settings->dimmer_hw_max, Tuya.CTMax, Tuya.CTMin);
} else {
Tuya.Levels[dimIndex] = changeUIntScale(packetValue, 0, Settings.dimmer_hw_max, 0, 100);
Tuya.Levels[dimIndex] = changeUIntScale(packetValue, 0, Settings->dimmer_hw_max, 0, 100);
}
AddLog(LOG_LEVEL_DEBUG, PSTR("TYA: RX value %d from dpId %d "), packetValue, Tuya.buffer[dpidStart]);
@ -842,13 +842,13 @@ void TuyaProcessStatePacket(void) {
(fnId == TUYA_MCU_FUNC_CT) || (fnId == TUYA_MCU_FUNC_WHITE)) {
if (Tuya.ignore_dimmer_cmd_timeout < millis()) {
if ((TasmotaGlobal.power || Settings.flag3.tuya_apply_o20) && ((Tuya.Levels[dimIndex] > 0) && (Tuya.Levels[dimIndex] != Tuya.Snapshot[dimIndex]))) { // SetOption54 - Apply SetOption20 settings to Tuya device
if ((TasmotaGlobal.power || Settings->flag3.tuya_apply_o20) && ((Tuya.Levels[dimIndex] > 0) && (Tuya.Levels[dimIndex] != Tuya.Snapshot[dimIndex]))) { // SetOption54 - Apply SetOption20 settings to Tuya device
Tuya.ignore_dim = true;
TasmotaGlobal.skip_light_fade = true;
scmnd[0] = '\0';
if ((fnId == TUYA_MCU_FUNC_DIMMER) || (fnId == TUYA_MCU_FUNC_REPORT1)) {
if (Settings.flag3.pwm_multi_channels && (abs(Tuya.Levels[0] - changeUIntScale(Light.current_color[0], 0, 255, 0, 100))) > 1) {
if (Settings->flag3.pwm_multi_channels && (abs(Tuya.Levels[0] - changeUIntScale(Light.current_color[0], 0, 255, 0, 100))) > 1) {
snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_CHANNEL "1 %d"), Tuya.Levels[0]);
}
else if ((abs(Tuya.Levels[0] - light_state.getDimmer())) > 1) {
@ -856,7 +856,7 @@ void TuyaProcessStatePacket(void) {
}
}
if (((fnId == TUYA_MCU_FUNC_DIMMER2) || (fnId == TUYA_MCU_FUNC_REPORT2)) &&
Settings.flag3.pwm_multi_channels && (abs(Tuya.Levels[1] - changeUIntScale(Light.current_color[1], 0, 255, 0, 100))) > 1) {
Settings->flag3.pwm_multi_channels && (abs(Tuya.Levels[1] - changeUIntScale(Light.current_color[1], 0, 255, 0, 100))) > 1) {
snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_CHANNEL "2 %d"), Tuya.Levels[1]);
}
if ((fnId == TUYA_MCU_FUNC_CT) && (abs(Tuya.Levels[1] - light_state.getCT())) > 1) {
@ -900,7 +900,7 @@ void TuyaProcessStatePacket(void) {
const unsigned char *dpData = (unsigned char*)&Tuya.buffer[dpidStart + 4];
if ((TuyaGetDpId(TUYA_MCU_FUNC_RGB) != 0)) {
uint8_t RGBType = Settings.tuya_fnid_map[230].dpid; // Select the type of hex configured
uint8_t RGBType = Settings->tuya_fnid_map[230].dpid; // Select the type of hex configured
char RgbData[15];
char RGB[7];
char HSB1[5], HSB2[5], HSB3[5];
@ -1025,16 +1025,16 @@ void TuyaNormalPowerModePacketProcess(void)
uint8_t key1_gpio = Tuya.buffer[7];
bool key1_set = false;
bool led1_set = false;
for (uint32_t i = 0; i < nitems(Settings.my_gp.io); i++) {
if (Settings.my_gp.io[i] == AGPIO(GPIO_LED1)) led1_set = true;
else if (Settings.my_gp.io[i] == AGPIO(GPIO_KEY1)) key1_set = true;
for (uint32_t i = 0; i < nitems(Settings->my_gp.io); i++) {
if (Settings->my_gp.io[i] == AGPIO(GPIO_LED1)) led1_set = true;
else if (Settings->my_gp.io[i] == AGPIO(GPIO_KEY1)) key1_set = true;
}
if (!Settings.my_gp.io[led1_gpio] && !led1_set) {
Settings.my_gp.io[led1_gpio] = AGPIO(GPIO_LED1);
if (!Settings->my_gp.io[led1_gpio] && !led1_set) {
Settings->my_gp.io[led1_gpio] = AGPIO(GPIO_LED1);
TasmotaGlobal.restart_flag = 2;
}
if (!Settings.my_gp.io[key1_gpio] && !key1_set) {
Settings.my_gp.io[key1_gpio] = AGPIO(GPIO_KEY1);
if (!Settings->my_gp.io[key1_gpio] && !key1_set) {
Settings->my_gp.io[key1_gpio] = AGPIO(GPIO_KEY1);
TasmotaGlobal.restart_flag = 2;
}
}
@ -1059,8 +1059,8 @@ bool TuyaModuleSelected(void)
if (!PinUsed(GPIO_TUYA_RX) || !PinUsed(GPIO_TUYA_TX)) { // fallback to hardware-serial if not explicitly selected
SetPin(1, AGPIO(GPIO_TUYA_TX));
SetPin(3, AGPIO(GPIO_TUYA_RX));
Settings.my_gp.io[1] = AGPIO(GPIO_TUYA_TX);
Settings.my_gp.io[3] = AGPIO(GPIO_TUYA_RX);
Settings->my_gp.io[1] = AGPIO(GPIO_TUYA_TX);
Settings->my_gp.io[3] = AGPIO(GPIO_TUYA_RX);
TasmotaGlobal.restart_flag = 2;
}
@ -1071,8 +1071,8 @@ bool TuyaModuleSelected(void)
bool relaySet = false;
for (uint8_t i = 0 ; i < MAX_TUYA_FUNCTIONS; i++) {
if ((Settings.tuya_fnid_map[i].fnid >= TUYA_MCU_FUNC_REL1 && Settings.tuya_fnid_map[i].fnid <= TUYA_MCU_FUNC_REL8 ) ||
(Settings.tuya_fnid_map[i].fnid >= TUYA_MCU_FUNC_REL1_INV && Settings.tuya_fnid_map[i].fnid <= TUYA_MCU_FUNC_REL8_INV )) {
if ((Settings->tuya_fnid_map[i].fnid >= TUYA_MCU_FUNC_REL1 && Settings->tuya_fnid_map[i].fnid <= TUYA_MCU_FUNC_REL8 ) ||
(Settings->tuya_fnid_map[i].fnid >= TUYA_MCU_FUNC_REL1_INV && Settings->tuya_fnid_map[i].fnid <= TUYA_MCU_FUNC_REL8_INV )) {
relaySet = true;
TasmotaGlobal.devices_present++;
}
@ -1111,7 +1111,7 @@ bool TuyaModuleSelected(void)
if (TuyaGetDpId(TUYA_MCU_FUNC_LOWPOWER_MODE) != 0) {
Tuya.low_power_mode = true;
Settings.flag3.fast_power_cycle_disable = true; // SetOption65 - Disable fast power cycle detection for device reset
Settings->flag3.fast_power_cycle_disable = true; // SetOption65 - Disable fast power cycle detection for device reset
}
UpdateDevices();
@ -1121,7 +1121,7 @@ bool TuyaModuleSelected(void)
void TuyaInit(void)
{
int baudrate = 9600;
if (Settings.flag4.tuyamcu_baudrate) { baudrate = 115200; } // SetOption97 - Set Baud rate for TuyaMCU serial communication (0 = 9600 or 1 = 115200)
if (Settings->flag4.tuyamcu_baudrate) { baudrate = 115200; } // SetOption97 - Set Baud rate for TuyaMCU serial communication (0 = 9600 or 1 = 115200)
Tuya.buffer = (char*)(malloc(TUYA_BUFFER_SIZE));
if (Tuya.buffer != nullptr) {
@ -1224,7 +1224,7 @@ void TuyaSerialInput(void)
}
ResponseAppend_P(PSTR("}}"));
if (Settings.flag3.tuya_serial_mqtt_publish) { // SetOption66 - Enable TuyaMcuReceived messages over Mqtt
if (Settings->flag3.tuya_serial_mqtt_publish) { // SetOption66 - Enable TuyaMcuReceived messages over Mqtt
MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_TUYA_MCU_RECEIVED));
} else {
#ifdef MQTT_DATA_STRING
@ -1235,7 +1235,7 @@ void TuyaSerialInput(void)
}
XdrvRulesProcess(0);
if (dpId != 0 && Settings.tuyamcu_topic) { // Publish a /STAT Topic ready to use for any home automation system
if (dpId != 0 && Settings->tuyamcu_topic) { // Publish a /STAT Topic ready to use for any home automation system
if (!Tuya.SuspendTopic) {
char scommand[13];
snprintf_P(scommand, sizeof(scommand), PSTR("DpType%uId%u"), dpDataType, dpId);
@ -1388,11 +1388,11 @@ void TuyaSensorsShow(bool json)
if (sensor > 74) {
res = 0;
} else if (sensor > 72) {
res = Settings.flag2.humidity_resolution;
res = Settings->flag2.humidity_resolution;
} else if (sensor == 72) {
res = Settings.mbflag2.temperature_set_res;
res = Settings->mbflag2.temperature_set_res;
} else {
res = Settings.flag2.temperature_resolution;
res = Settings->flag2.temperature_resolution;
}
GetTextIndexed(sname, sizeof(sname), (sensor-71), kTuyaSensors);
@ -1405,18 +1405,18 @@ void TuyaSensorsShow(bool json)
if (TuyaGetDpId(sensor) != 0) {
switch (sensor) {
case 71:
WSContentSend_Temp("", TuyaAdjustedTemperature(Tuya.Sensors[0], Settings.flag2.temperature_resolution));
WSContentSend_Temp("", TuyaAdjustedTemperature(Tuya.Sensors[0], Settings->flag2.temperature_resolution));
break;
case 72:
WSContentSend_PD(PSTR("{s}" D_TEMPERATURE " Set{m}%s " D_UNIT_DEGREE "%c{e}"),
dtostrfd(TuyaAdjustedTemperature(Tuya.Sensors[1], Settings.mbflag2.temperature_set_res), Settings.mbflag2.temperature_set_res, tempval), TempUnit());
dtostrfd(TuyaAdjustedTemperature(Tuya.Sensors[1], Settings->mbflag2.temperature_set_res), Settings->mbflag2.temperature_set_res, tempval), TempUnit());
break;
case 73:
WSContentSend_PD(HTTP_SNS_HUM, "", dtostrfd(TuyaAdjustedTemperature(Tuya.Sensors[2], Settings.flag2.humidity_resolution), Settings.flag2.humidity_resolution, tempval));
WSContentSend_PD(HTTP_SNS_HUM, "", dtostrfd(TuyaAdjustedTemperature(Tuya.Sensors[2], Settings->flag2.humidity_resolution), Settings->flag2.humidity_resolution, tempval));
break;
case 74:
WSContentSend_PD(PSTR("{s}" D_HUMIDITY " Set{m}%s " D_UNIT_PERCENT "{e}"),
dtostrfd(TuyaAdjustedTemperature(Tuya.Sensors[3], Settings.flag2.humidity_resolution), Settings.flag2.humidity_resolution, tempval));
dtostrfd(TuyaAdjustedTemperature(Tuya.Sensors[3], Settings->flag2.humidity_resolution), Settings->flag2.humidity_resolution, tempval));
break;
case 75:
WSContentSend_PD(HTTP_SNS_ILLUMINANCE, "", Tuya.Sensors[4]);

View File

@ -63,7 +63,7 @@ void RfReceiveCheck(void) {
rf_lasttime = now;
char stemp[16];
if (Settings.flag.rf_receive_decimal) { // SetOption28 - RF receive data format (0 = hexadecimal, 1 = decimal)
if (Settings->flag.rf_receive_decimal) { // SetOption28 - RF receive data format (0 = hexadecimal, 1 = decimal)
snprintf_P(stemp, sizeof(stemp), PSTR("%u"), (uint32_t)data);
} else {
snprintf_P(stemp, sizeof(stemp), PSTR("\"0x%lX\""), (uint32_t)data);
@ -86,10 +86,10 @@ void RfInit(void) {
if (PinUsed(GPIO_RFRECV)) {
pinMode( Pin(GPIO_RFRECV), INPUT);
mySwitch.enableReceive(Pin(GPIO_RFRECV));
if (!Settings.rf_protocol_mask) {
Settings.rf_protocol_mask = (1ULL << mySwitch.getNumProtos()) -1;
if (!Settings->rf_protocol_mask) {
Settings->rf_protocol_mask = (1ULL << mySwitch.getNumProtos()) -1;
}
mySwitch.setReceiveProtocolMask(Settings.rf_protocol_mask);
mySwitch.setReceiveProtocolMask(Settings->rf_protocol_mask);
}
}
@ -107,9 +107,9 @@ void CmndRfProtocol(void) {
if (XdrvMailbox.payload >= 0) {
thisdat = (1ULL << (XdrvMailbox.index -1));
if (XdrvMailbox.payload &1) {
Settings.rf_protocol_mask |= thisdat;
Settings->rf_protocol_mask |= thisdat;
} else {
Settings.rf_protocol_mask &= ~thisdat;
Settings->rf_protocol_mask &= ~thisdat;
}
}
else if (XdrvMailbox.data_len > 0) {
@ -118,24 +118,24 @@ void CmndRfProtocol(void) {
} else {
if (XdrvMailbox.data_len > 0) {
if ('A' == toupper(XdrvMailbox.data[0])) {
Settings.rf_protocol_mask = (1ULL << mySwitch.getNumProtos()) -1;
Settings->rf_protocol_mask = (1ULL << mySwitch.getNumProtos()) -1;
} else {
thisdat = strtoull(XdrvMailbox.data, nullptr, 0);
if ((thisdat > 0) || ('0' == XdrvMailbox.data[0])) {
Settings.rf_protocol_mask = thisdat;
Settings->rf_protocol_mask = thisdat;
} else {
return; // Not a number
}
}
}
}
mySwitch.setReceiveProtocolMask(Settings.rf_protocol_mask);
mySwitch.setReceiveProtocolMask(Settings->rf_protocol_mask);
// AddLog(LOG_LEVEL_INFO, PSTR("RFR: CmndRfProtocol:: Start responce"));
Response_P(PSTR("{\"" D_CMND_RFPROTOCOL "\":\""));
bool gotone = false;
thisdat = 1;
for (uint32_t i = 0; i < mySwitch.getNumProtos(); i++) {
if (Settings.rf_protocol_mask & thisdat) {
if (Settings->rf_protocol_mask & thisdat) {
ResponseAppend_P(PSTR("%s%d"), (gotone) ? "," : "", i+1);
gotone = true;
}

View File

@ -64,8 +64,8 @@ void PS16DZSerialSendUpdateCommand(void)
{
uint8_t light_state_dimmer = light_state.getDimmer();
// Dimming acts odd below 10% - this mirrors the threshold set on the faceplate itself
light_state_dimmer = (light_state_dimmer < Settings.dimmer_hw_min) ? Settings.dimmer_hw_min : light_state_dimmer;
light_state_dimmer = (light_state_dimmer > Settings.dimmer_hw_max) ? Settings.dimmer_hw_max : light_state_dimmer;
light_state_dimmer = (light_state_dimmer < Settings->dimmer_hw_min) ? Settings->dimmer_hw_min : light_state_dimmer;
light_state_dimmer = (light_state_dimmer > Settings->dimmer_hw_max) ? Settings->dimmer_hw_max : light_state_dimmer;
char tx_buffer[80];
snprintf_P(tx_buffer, sizeof(tx_buffer), PSTR("AT+UPDATE=\"sequence\":\"%d%03d\",\"switch\":\"%s\",\"bright\":%d"),
@ -130,7 +130,7 @@ void PS16DZSerialInput(void)
// AddLog(LOG_LEVEL_DEBUG, PSTR("PSZ: Brightness %d"), Ps16dz.dimmer);
is_brightness_change = Ps16dz.dimmer != Settings.light_dimmer;
is_brightness_change = Ps16dz.dimmer != Settings->light_dimmer;
if (TasmotaGlobal.power && (Ps16dz.dimmer > 0) && is_brightness_change) {
snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), Ps16dz.dimmer);
ExecuteCommand(scmnd, SRC_SWITCH);
@ -154,10 +154,10 @@ void PS16DZSerialInput(void)
else if (!strncmp(Ps16dz.rx_buffer+3, "SETTING", 7)) {
// AT+SETTING=enterESPTOUCH - When ON button is held for over 5 seconds
// AT+SETTING=exitESPTOUCH - When ON button is pressed
if (!Settings.flag.button_restrict) { // SetOption1 - Control button multipress
if (!Settings->flag.button_restrict) { // SetOption1 - Control button multipress
int state = WIFI_MANAGER;
if (!strncmp(Ps16dz.rx_buffer+10, "=exit", 5)) { state = WIFI_RETRY; }
if (state != Settings.sta_config) {
if (state != Settings->sta_config) {
snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_WIFICONFIG " %d"), state);
ExecuteCommand(scmnd, SRC_BUTTON);
}

View File

@ -479,7 +479,7 @@ char prev_y_str[24] = "\0";
uint8_t getLocalLightSubtype(uint8_t device) {
if (TasmotaGlobal.light_type) {
if (device >= Light.device) {
if (Settings.flag3.pwm_multi_channels) { // SetOption68 - Enable multi-channels PWM instead of Color PWM
if (Settings->flag3.pwm_multi_channels) { // SetOption68 - Enable multi-channels PWM instead of Color PWM
return LST_SINGLE; // If SetOption68, each channel acts like a dimmer
} else {
return Light.subtype; // the actual light
@ -511,7 +511,7 @@ void HueLightStatus1(uint8_t device, String *response)
#ifdef USE_SHUTTER
if (ShutterState(device)) {
bri = (float)((Settings.shutter_options[device-1] & 1) ? 100 - Settings.shutter_position[device-1] : Settings.shutter_position[device-1]) / 100;
bri = (float)((Settings->shutter_options[device-1] & 1) ? 100 - Settings->shutter_position[device-1] : Settings->shutter_position[device-1]) / 100;
}
#endif
@ -591,7 +591,7 @@ void HueLightStatus2(uint8_t device, String *response)
UnishoxStrings msg(HUE_LIGHTS);
snprintf_P(buf, buf_size, msg[HUE_LIGHTS_STATUS_JSON2],
EscapeJSONString(fname).c_str(),
EscapeJSONString(Settings.user_template_name).c_str(),
EscapeJSONString(Settings->user_template_name).c_str(),
PSTR("Tasmota"),
GetHueDeviceId(device).c_str());
*response += buf;
@ -663,7 +663,7 @@ uint32_t DecodeLightId(uint32_t hue_id, uint16_t * shortaddr = nullptr)
// Check if the Echo device is of 1st generation, which triggers different results
inline uint32_t findEchoGeneration(void) {
// don't try to guess from User-Agent anymore but use SetOption109
return Settings.flag4.alexa_gen_1 ? 1 : 2;
return Settings->flag4.alexa_gen_1 ? 1 : 2;
}
void HueGlobalConfig(String *path) {
@ -761,7 +761,7 @@ void HueLightsCommand(uint8_t device, uint32_t device_id, String &response) {
}
if (TasmotaGlobal.light_type && (local_light_subtype >= LST_SINGLE)) {
if (!Settings.flag3.pwm_multi_channels) { // SetOption68 - Enable multi-channels PWM instead of Color PWM
if (!Settings->flag3.pwm_multi_channels) { // SetOption68 - Enable multi-channels PWM instead of Color PWM
light_state.getHSB(&hue, &sat, nullptr);
bri = light_state.getBri(); // get the combined bri for CT and RGB, not only the RGB one
ct = light_state.getCT();
@ -879,12 +879,12 @@ void HueLightsCommand(uint8_t device, uint32_t device_id, String &response) {
if (change) {
#ifdef USE_SHUTTER
if (ShutterState(device)) {
AddLog(LOG_LEVEL_DEBUG, PSTR("Settings.shutter_invert: %d"), Settings.shutter_options[device-1] & 1);
AddLog(LOG_LEVEL_DEBUG, PSTR("Settings->shutter_invert: %d"), Settings->shutter_options[device-1] & 1);
ShutterSetPosition(device, bri * 100.0f );
} else
#endif
if (TasmotaGlobal.light_type && (local_light_subtype > LST_NONE)) { // not relay
if (!Settings.flag3.pwm_multi_channels) { // SetOption68 - Enable multi-channels PWM instead of Color PWM
if (!Settings->flag3.pwm_multi_channels) { // SetOption68 - Enable multi-channels PWM instead of Color PWM
if (g_gotct) {
light_controller.changeCTB(ct, bri);
} else {
@ -1085,9 +1085,9 @@ bool Xdrv20(uint8_t function)
bool result = false;
#if defined(USE_SCRIPT_HUE) || defined(USE_ZIGBEE)
if ((EMUL_HUE == Settings.flag2.emulation)) {
if ((EMUL_HUE == Settings->flag2.emulation)) {
#else
if (TasmotaGlobal.devices_present && (EMUL_HUE == Settings.flag2.emulation)) {
if (TasmotaGlobal.devices_present && (EMUL_HUE == Settings->flag2.emulation)) {
#endif
switch (function) {
case FUNC_WEB_ADD_HANDLER:

View File

@ -346,7 +346,7 @@ bool Xdrv21(uint8_t function)
{
bool result = false;
if (TasmotaGlobal.devices_present && (EMUL_WEMO == Settings.flag2.emulation)) {
if (TasmotaGlobal.devices_present && (EMUL_WEMO == Settings->flag2.emulation)) {
switch (function) {
case FUNC_WEB_ADD_HANDLER:
WebServer_on(PSTR("/upnp/control/basicevent1"), HandleUpnpEvent, HTTP_POST);

View File

@ -431,7 +431,7 @@ bool Xdrv21(uint8_t function)
{
bool result = false;
if (TasmotaGlobal.devices_present && (EMUL_WEMO == Settings.flag2.emulation)) {
if (TasmotaGlobal.devices_present && (EMUL_WEMO == Settings->flag2.emulation)) {
switch (function) {
case FUNC_LOOP:
for (uint32_t i = 1; i < numOfWemoSwitch; i++) { // Handle devices web server

View File

@ -135,7 +135,7 @@ void SonoffIfanReceived(void)
}
if (6 == mode) {
// AA 55 01 06 00 01 01 09 - Buzzer
Settings.flag3.buzzer_enable = !Settings.flag3.buzzer_enable; // SetOption67 - Enable buzzer when available
Settings->flag3.buzzer_enable = !Settings->flag3.buzzer_enable; // SetOption67 - Enable buzzer when available
}
if (7 == mode) {
// AA 55 01 07 00 01 01 0A - Rf long press - forget RF codes

View File

@ -516,15 +516,15 @@ void Z_Devices::jsonAppend(uint16_t shortaddr, const Z_attribute_list &attr_list
// internal function to publish device information with respect to all `SetOption`s
//
void Z_Device::jsonPublishAttrList(const char * json_prefix, const Z_attribute_list &attr_list) const {
bool use_fname = (Settings.flag4.zigbee_use_names) && (friendlyName); // should we replace shortaddr with friendlyname?
bool use_fname = (Settings->flag4.zigbee_use_names) && (friendlyName); // should we replace shortaddr with friendlyname?
ResponseClear(); // clear string
// Do we prefix with `ZbReceived`?
if (!Settings.flag4.remove_zbreceived && !Settings.flag5.zb_received_as_subtopic) {
if (!Settings->flag4.remove_zbreceived && !Settings->flag5.zb_received_as_subtopic) {
Response_P(PSTR("{\"%s\":"), json_prefix);
}
// What key do we use, shortaddr or name?
if (!Settings.flag5.zb_omit_json_addr) {
if (!Settings->flag5.zb_omit_json_addr) {
if (use_fname) {
ResponseAppend_P(PSTR("{\"%s\":"), friendlyName);
} else {
@ -542,46 +542,46 @@ void Z_Device::jsonPublishAttrList(const char * json_prefix, const Z_attribute_l
// Add all other attributes
ResponseAppend_P(PSTR("%s}"), attr_list.toString(false).c_str());
if (!Settings.flag5.zb_omit_json_addr) {
if (!Settings->flag5.zb_omit_json_addr) {
ResponseAppend_P(PSTR("}"));
}
if (!Settings.flag4.remove_zbreceived && !Settings.flag5.zb_received_as_subtopic) {
if (!Settings->flag4.remove_zbreceived && !Settings->flag5.zb_received_as_subtopic) {
ResponseAppend_P(PSTR("}"));
}
if (Settings.flag4.zigbee_distinct_topics) {
if (Settings->flag4.zigbee_distinct_topics) {
char subtopic[TOPSZ];
if (Settings.flag4.zb_topic_fname && friendlyName && strlen(friendlyName)) {
if (Settings->flag4.zb_topic_fname && friendlyName && strlen(friendlyName)) {
// Clean special characters
char stemp[TOPSZ];
strlcpy(stemp, friendlyName, sizeof(stemp));
MakeValidMqtt(0, stemp);
if (Settings.flag5.zigbee_hide_bridge_topic) {
if (Settings->flag5.zigbee_hide_bridge_topic) {
snprintf_P(subtopic, sizeof(subtopic), PSTR("%s"), stemp);
} else {
snprintf_P(subtopic, sizeof(subtopic), PSTR("%s/%s"), TasmotaGlobal.mqtt_topic, stemp);
}
} else {
if (Settings.flag5.zigbee_hide_bridge_topic) {
if (Settings->flag5.zigbee_hide_bridge_topic) {
snprintf_P(subtopic, sizeof(subtopic), PSTR("%04X"), shortaddr);
} else {
snprintf_P(subtopic, sizeof(subtopic), PSTR("%s/%04X"), TasmotaGlobal.mqtt_topic, shortaddr);
}
}
if (Settings.flag5.zb_topic_endpoint) {
if (Settings->flag5.zb_topic_endpoint) {
if (attr_list.isValidSrcEp()) {
snprintf_P(subtopic, sizeof(subtopic), PSTR("%s_%d"), subtopic, attr_list.src_ep);
}
}
char stopic[TOPSZ];
if (Settings.flag5.zb_received_as_subtopic)
if (Settings->flag5.zb_received_as_subtopic)
GetTopic_P(stopic, TELE, subtopic, json_prefix);
else
GetTopic_P(stopic, TELE, subtopic, PSTR(D_RSLT_SENSOR));
MqttPublish(stopic, Settings.flag.mqtt_sensor_retain);
MqttPublish(stopic, Settings->flag.mqtt_sensor_retain);
} else {
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain);
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings->flag.mqtt_sensor_retain);
}
XdrvRulesProcess(0); // apply rules
}
@ -665,7 +665,7 @@ Z_Device & Z_Devices::parseDeviceFromName(const char * param, uint16_t * parsed_
// Add "Device":"0x1234","Name":"FrienflyName"
void Z_Device::jsonAddDeviceNamme(Z_attribute_list & attr_list) const {
const char * fname = friendlyName;
bool use_fname = (Settings.flag4.zigbee_use_names) && (fname); // should we replace shortaddr with friendlyname?
bool use_fname = (Settings->flag4.zigbee_use_names) && (fname); // should we replace shortaddr with friendlyname?
attr_list.addAttributePMEM(PSTR(D_JSON_ZIGBEE_DEVICE)).setHex32(shortaddr);
if (fname) {

View File

@ -748,7 +748,7 @@ public:
_frame_control.b.frame_type, _frame_control.b.direction, _frame_control.b.disable_def_resp,
_manuf_code, _transact_seq, _cmd_id,
&_payload);
if (Settings.flag3.tuya_serial_mqtt_publish) {
if (Settings->flag3.tuya_serial_mqtt_publish) {
MqttPublishPrefixTopicRulesProcess_P(TELE, PSTR(D_RSLT_SENSOR));
} else {
#ifdef MQTT_DATA_STRING
@ -1374,7 +1374,7 @@ void ZCLFrame::computeSyntheticAttributes(Z_attribute_list& attr_list) {
case 0x04030000: // SeaPressure
{
int16_t pressure = attr.getInt();
int16_t pressure_sealevel = (pressure / FastPrecisePow(1.0 - ((float)Settings.altitude / 44330.0f), 5.255f)) - 21.6f;
int16_t pressure_sealevel = (pressure / FastPrecisePow(1.0 - ((float)Settings->altitude / 44330.0f), 5.255f)) - 21.6f;
attr_list.addAttribute(0x0403, 0xFFF0).setInt(pressure_sealevel);
// We create a synthetic attribute 0403/FFF0 to indicate sea level
}
@ -1672,7 +1672,7 @@ void ZCLFrame::parseClusterSpecificCommand(Z_attribute_list& attr_list) {
zigbee_devices.setTimer(_srcaddr, 0 /* groupaddr */, USE_ZIGBEE_DEBOUNCE_COMMANDS, 0 /*clusterid*/, _srcendpoint, Z_CAT_DEBOUNCE_CMD, 0, &Z_ResetDebounce);
convertClusterSpecific(attr_list, _cluster_id, _cmd_id, _frame_control.b.direction, _srcaddr, _srcendpoint, _payload);
if (!Settings.flag5.zb_disable_autoquery) {
if (!Settings->flag5.zb_disable_autoquery) {
// read attributes unless disabled
if (!_frame_control.b.direction) { // only handle server->client (i.e. device->coordinator)
if (_wasbroadcast) { // only update for broadcast messages since we don't see unicast from device to device and we wouldn't know the target
@ -1995,7 +1995,7 @@ void Z_postProcessAttributes(uint16_t shortaddr, uint16_t src_ep, class Z_attrib
for (auto &attr : attr_list) {
// add endpoint suffix if needed
if ((Settings.flag4.zb_index_ep) && (src_ep != 1) && (count_ep > 1)) {
if ((Settings->flag4.zb_index_ep) && (src_ep != 1) && (count_ep > 1)) {
// we need to add suffix if the suffix is not already different from 1
if (attr.key_suffix == 1) {
attr.key_suffix = src_ep;

View File

@ -439,7 +439,7 @@ void convertClusterSpecific(class Z_attribute_list &attr_list, uint16_t cluster,
// do we send command with endpoint suffix
char command_suffix[4] = { 0x00 }; // empty string by default
// if SO101 and multiple endpoints, append endpoint number
if (Settings.flag4.zb_index_ep) {
if (Settings->flag4.zb_index_ep) {
if (zigbee_devices.getShortAddr(shortaddr).countEndpoints() > 0) {
snprintf_P(command_suffix, sizeof(command_suffix), PSTR("%d"), srcendpoint);
}

View File

@ -521,7 +521,7 @@ int32_t EZ_GotoIfResetConfig(uint8_t value) {
// If router goto ZIGBEE_LABEL_START_ROUTER
// If device goto ZIGBEE_LABEL_START_DEVICE
int32_t Z_SwitchDeviceType(int32_t res, SBuffer &buf) {
switch (Settings.zb_pan_id) {
switch (Settings->zb_pan_id) {
case 0xFFFF: return ZIGBEE_LABEL_INIT_ROUTER;
case 0xFFFE: return ZIGBEE_LABEL_INIT_DEVICE;
default: return 0; // continue
@ -764,7 +764,7 @@ int32_t Z_ReceiveSimpleDesc(int32_t res, const SBuffer &buf) {
// device is reachable
zigbee_devices.deviceWasReached(nwkAddr);
if (!Settings.flag4.zb_disable_autobind) {
if (!Settings->flag4.zb_disable_autobind) {
Z_AutoBindDefer(nwkAddr, endpoint, buf, numInIndex, numInCluster, numOutIndex, numOutCluster);
}
@ -2071,7 +2071,7 @@ void Z_Query_Bulb(uint16_t shortaddr, uint32_t &wait_ms) {
// Send messages to query the state of each Hue emulated light
//
int32_t Z_Query_Bulbs(uint8_t value) {
if (!Settings.flag5.zb_disable_autoquery) {
if (!Settings->flag5.zb_disable_autoquery) {
// Scan all devices and send deferred requests to know the state of bulbs
uint32_t wait_ms = 1000; // start with 1.0 s delay
for (uint32_t i = 0; i < zigbee_devices.devicesSize(); i++) {
@ -2145,10 +2145,10 @@ void ZCLFrame::autoResponder(const uint16_t *attr_list_ids, size_t attr_len) {
attr.setUInt((Rtc.utc_time > START_VALID_TIME) ? 0x02 : 0x00);
break;
case 0x000A0002: // TimeZone
attr.setUInt(Settings.toffset[0] * 60);
attr.setUInt(Settings->toffset[0] * 60);
break;
case 0x000A0007: // LocalTime // TODO take DST
attr.setUInt(Settings.toffset[0] * 60 + ((Rtc.utc_time > START_VALID_TIME) ? Rtc.utc_time - 946684800 : Rtc.utc_time));
attr.setUInt(Settings->toffset[0] * 60 + ((Rtc.utc_time > START_VALID_TIME) ? Rtc.utc_time - 946684800 : Rtc.utc_time));
break;
}
if (!attr.isNone()) {

View File

@ -149,7 +149,7 @@ void ZigbeeInputLoop(void) {
SBuffer znp_buffer = zigbee_buffer->subBuffer(2, zigbee_frame_len - 3); // remove SOF, LEN and FCS
Response_P(PSTR("{\"" D_JSON_ZIGBEEZNPRECEIVED "\":\"%_B\"}"), &znp_buffer);
if (Settings.flag3.tuya_serial_mqtt_publish) {
if (Settings->flag3.tuya_serial_mqtt_publish) {
MqttPublishPrefixTopicRulesProcess_P(TELE, PSTR(D_RSLT_SENSOR));
} else {
#ifdef MQTT_DATA_STRING
@ -567,7 +567,7 @@ void ZigbeeProcessInputEZSP(SBuffer &buf) {
// log message
Response_P(PSTR("{\"" D_JSON_ZIGBEE_EZSP_RECEIVED "\":\"%_B\"}"), &buf);
if (Settings.flag3.tuya_serial_mqtt_publish) {
if (Settings->flag3.tuya_serial_mqtt_publish) {
MqttPublishPrefixTopicRulesProcess_P(TELE, PSTR(D_RSLT_SENSOR));
} else {
// demote less interesting messages to LOG_LEVEL_DEBUG

View File

@ -488,7 +488,7 @@ bool ZigbeeUploadXmodem(void) {
case ZBU_DONE: { // *** Clean up and restart to disable bootloader and use new firmware
ZigbeeUploadSetBootloader(1); // Disable bootloader and reset MCU - should happen at restart
if (1 == TasmotaGlobal.sleep) {
TasmotaGlobal.sleep = Settings.sleep; // Restore loop sleep
TasmotaGlobal.sleep = Settings->sleep; // Restore loop sleep
}
// TasmotaGlobal.restart_flag = 2; // Restart to disable bootloader and use new firmware
if (ZbUpload.buffer) { free(ZbUpload.buffer); ZbUpload.buffer = nullptr; }

View File

@ -74,7 +74,7 @@ void ZigbeeInit(void)
// #pragma GCC diagnostic pop
// Check if settings in Flash are set
if (PinUsed(GPIO_ZIGBEE_RX) && PinUsed(GPIO_ZIGBEE_TX)) {
if (0 == Settings.zb_channel) {
if (0 == Settings->zb_channel) {
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE D_ZIGBEE_RANDOMIZING_ZBCONFIG));
uint64_t mac64 = 0; // stuff mac address into 64 bits
WiFi.macAddress((uint8_t*) &mac64);
@ -89,17 +89,17 @@ void ZigbeeInit(void)
uint16_t pan_id = (mac64 & 0x3FFF);
if (0x0000 == pan_id) { pan_id = 0x0001; } // avoid extreme values
if (0x3FFF == pan_id) { pan_id = 0x3FFE; } // avoid extreme values
Settings.zb_pan_id = pan_id;
Settings->zb_pan_id = pan_id;
Settings.zb_ext_panid = 0xCCCCCCCC00000000L | (mac64 & 0x00000000FFFFFFFFL);
Settings.zb_precfgkey_l = (mac64 << 32) | (esp_id << 16) | flash_id;
Settings.zb_precfgkey_h = (mac64 << 32) | (esp_id << 16) | flash_id;
Settings.zb_channel = USE_ZIGBEE_CHANNEL;
Settings.zb_txradio_dbm = USE_ZIGBEE_TXRADIO_DBM;
Settings->zb_ext_panid = 0xCCCCCCCC00000000L | (mac64 & 0x00000000FFFFFFFFL);
Settings->zb_precfgkey_l = (mac64 << 32) | (esp_id << 16) | flash_id;
Settings->zb_precfgkey_h = (mac64 << 32) | (esp_id << 16) | flash_id;
Settings->zb_channel = USE_ZIGBEE_CHANNEL;
Settings->zb_txradio_dbm = USE_ZIGBEE_TXRADIO_DBM;
}
if (Settings.zb_txradio_dbm < 0) {
Settings.zb_txradio_dbm = -Settings.zb_txradio_dbm;
if (Settings->zb_txradio_dbm < 0) {
Settings->zb_txradio_dbm = -Settings->zb_txradio_dbm;
#ifdef USE_ZIGBEE_EZSP
EZ_reset_config = true; // force reconfigure of EZSP
#endif
@ -119,10 +119,10 @@ void ZigbeeInit(void)
// update commands with the current settings
#ifdef USE_ZIGBEE_ZNP
ZNP_UpdateConfig(Settings.zb_channel, Settings.zb_pan_id, Settings.zb_ext_panid, Settings.zb_precfgkey_l, Settings.zb_precfgkey_h);
ZNP_UpdateConfig(Settings->zb_channel, Settings->zb_pan_id, Settings->zb_ext_panid, Settings->zb_precfgkey_l, Settings->zb_precfgkey_h);
#endif
#ifdef USE_ZIGBEE_EZSP
EZ_UpdateConfig(Settings.zb_channel, Settings.zb_pan_id, Settings.zb_ext_panid, Settings.zb_precfgkey_l, Settings.zb_precfgkey_h, Settings.zb_txradio_dbm);
EZ_UpdateConfig(Settings->zb_channel, Settings->zb_pan_id, Settings->zb_ext_panid, Settings->zb_precfgkey_l, Settings->zb_precfgkey_h, Settings->zb_txradio_dbm);
#endif
ZigbeeInitSerial();
@ -149,7 +149,7 @@ void CmndZbReset(void) {
eraseZigbeeDevices();
// no break - this is intended
case 2: // fall through
Settings.zb_txradio_dbm = - abs(Settings.zb_txradio_dbm);
Settings->zb_txradio_dbm = - abs(Settings->zb_txradio_dbm);
TasmotaGlobal.restart_flag = 2;
#ifdef USE_ZIGBEE_ZNP
ResponseCmndChar_P(PSTR(D_JSON_ZIGBEE_CC2530 " " D_JSON_RESET_AND_RESTARTING));
@ -209,7 +209,7 @@ void zigbeeZCLSendCmd(class ZCLMessage &zcl) {
// now set the timer, if any, to read back the state later
if (zcl.clusterSpecific) {
if (!Settings.flag5.zb_disable_autoquery) {
if (!Settings->flag5.zb_disable_autoquery) {
// read back attribute value unless it is disabled
sendHueUpdate(zcl.shortaddr, zcl.groupaddr, zcl.cluster, zcl.endpoint);
}
@ -1595,12 +1595,12 @@ void CmndZbData(void) {
void CmndZbConfig(void) {
// ZbConfig
// ZbConfig {"Channel":11,"PanID":"0x1A63","ExtPanID":"0xCCCCCCCCCCCCCCCC","KeyL":"0x0F0D0B0907050301L","KeyH":"0x0D0C0A0806040200L"}
uint8_t zb_channel = Settings.zb_channel;
uint16_t zb_pan_id = Settings.zb_pan_id;
uint64_t zb_ext_panid = Settings.zb_ext_panid;
uint64_t zb_precfgkey_l = Settings.zb_precfgkey_l;
uint64_t zb_precfgkey_h = Settings.zb_precfgkey_h;
int8_t zb_txradio_dbm = Settings.zb_txradio_dbm;
uint8_t zb_channel = Settings->zb_channel;
uint16_t zb_pan_id = Settings->zb_pan_id;
uint64_t zb_ext_panid = Settings->zb_ext_panid;
uint64_t zb_precfgkey_l = Settings->zb_precfgkey_l;
uint64_t zb_precfgkey_h = Settings->zb_precfgkey_h;
int8_t zb_txradio_dbm = Settings->zb_txradio_dbm;
// if (zigbee.init_phase) { ResponseCmndChar_P(PSTR(D_ZIGBEE_NOT_STARTED)); return; }
RemoveSpace(XdrvMailbox.data);
@ -1627,18 +1627,18 @@ void CmndZbConfig(void) {
}
// Check if a parameter was changed after all
if ( (zb_channel != Settings.zb_channel) ||
(zb_pan_id != Settings.zb_pan_id) ||
(zb_ext_panid != Settings.zb_ext_panid) ||
(zb_precfgkey_l != Settings.zb_precfgkey_l) ||
(zb_precfgkey_h != Settings.zb_precfgkey_h) ||
(zb_txradio_dbm != Settings.zb_txradio_dbm) ) {
Settings.zb_channel = zb_channel;
Settings.zb_pan_id = zb_pan_id;
Settings.zb_ext_panid = zb_ext_panid;
Settings.zb_precfgkey_l = zb_precfgkey_l;
Settings.zb_precfgkey_h = zb_precfgkey_h;
Settings.zb_txradio_dbm = zb_txradio_dbm;
if ( (zb_channel != Settings->zb_channel) ||
(zb_pan_id != Settings->zb_pan_id) ||
(zb_ext_panid != Settings->zb_ext_panid) ||
(zb_precfgkey_l != Settings->zb_precfgkey_l) ||
(zb_precfgkey_h != Settings->zb_precfgkey_h) ||
(zb_txradio_dbm != Settings->zb_txradio_dbm) ) {
Settings->zb_channel = zb_channel;
Settings->zb_pan_id = zb_pan_id;
Settings->zb_ext_panid = zb_ext_panid;
Settings->zb_precfgkey_l = zb_precfgkey_l;
Settings->zb_precfgkey_h = zb_precfgkey_h;
Settings->zb_txradio_dbm = zb_txradio_dbm;
TasmotaGlobal.restart_flag = 2; // save and reboot
}
}

View File

@ -47,12 +47,12 @@ void BuzzerSet(uint32_t state) {
state = !state;
}
if (Settings.flag4.buzzer_freq_mode) { // SetOption111 - Enable frequency output mode for buzzer
if (Settings->flag4.buzzer_freq_mode) { // SetOption111 - Enable frequency output mode for buzzer
static uint8_t last_state = 0;
if (last_state != state) {
// Set 50% duty cycle for frequency output
// Set 0% (or 100% for inverted PWM) duty cycle which turns off frequency output either way
analogWrite(Pin(GPIO_BUZZER), (state) ? Settings.pwm_range / 2 : 0); // set duty cycle for frequency output
analogWrite(Pin(GPIO_BUZZER), (state) ? Settings->pwm_range / 2 : 0); // set duty cycle for frequency output
last_state = state;
}
} else {
@ -90,15 +90,15 @@ void BuzzerBeep(uint32_t count, uint32_t on, uint32_t off, uint32_t tune, uint32
Buzzer.count = count * 2; // Start buzzer
AddLog(LOG_LEVEL_DEBUG, PSTR("BUZ: Count %d(%d), Time %d/%d, Tune 0x%08X(0x%08X), Size %d, Mode %d"),
count, Buzzer.count, on, off, tune, Buzzer.tune, Buzzer.tune_size, Settings.flag4.buzzer_freq_mode);
count, Buzzer.count, on, off, tune, Buzzer.tune, Buzzer.tune_size, Settings->flag4.buzzer_freq_mode);
Buzzer.enable = (Buzzer.count > 0);
if (Buzzer.enable) {
Buzzer.sleep = TasmotaGlobal.sleep;
if (Settings.sleep > PWM_MAX_SLEEP) {
if (Settings->sleep > PWM_MAX_SLEEP) {
TasmotaGlobal.sleep = PWM_MAX_SLEEP; // Set a maxumum value of 10 milliseconds to ensure that buzzer periods are a bit more accurate
} else {
TasmotaGlobal.sleep = Settings.sleep; // Or keep the current sleep if it's lower than 10
TasmotaGlobal.sleep = Settings->sleep; // Or keep the current sleep if it's lower than 10
}
} else {
TasmotaGlobal.sleep = Buzzer.sleep; // Restore original sleep
@ -118,7 +118,7 @@ void BuzzerBeep(uint32_t count) {
}
void BuzzerEnabledBeep(uint32_t count, uint32_t duration) {
if (Settings.flag3.buzzer_enable) { // SetOption67 - Enable buzzer when available
if (Settings->flag3.buzzer_enable) { // SetOption67 - Enable buzzer when available
BuzzerBeep(count, duration, 1, 0, 0);
}
}

View File

@ -91,11 +91,11 @@ void AriluxRfHandler(void)
Arilux.rf_last_time = now;
uint16_t hostcode = Arilux.rf_received_value >> 8 & 0xFFFF;
if (Settings.rf_code[1][6] == Settings.rf_code[1][7]) {
Settings.rf_code[1][6] = hostcode >> 8 & 0xFF;
Settings.rf_code[1][7] = hostcode & 0xFF;
if (Settings->rf_code[1][6] == Settings->rf_code[1][7]) {
Settings->rf_code[1][6] = hostcode >> 8 & 0xFF;
Settings->rf_code[1][7] = hostcode & 0xFF;
}
uint16_t stored_hostcode = Settings.rf_code[1][6] << 8 | Settings.rf_code[1][7];
uint16_t stored_hostcode = Settings->rf_code[1][6] << 8 | Settings->rf_code[1][7];
// DEBUG_DRIVER_LOG(PSTR(D_LOG_RFR D_HOST D_CODE " 0x%04X, " D_RECEIVED " 0x%06X"), stored_hostcode, Arilux.rf_received_value);
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_RFR D_HOST D_CODE " 0x%04X, " D_RECEIVED " 0x%06X"), stored_hostcode, Arilux.rf_received_value);
@ -148,8 +148,8 @@ void AriluxRfInit(void)
{
if (PinUsed(GPIO_ARIRFRCV) && PinUsed(GPIO_ARIRFSEL)) {
if (TasmotaGlobal.module_changed) {
Settings.rf_code[1][6] = 0;
Settings.rf_code[1][7] = 0;
Settings->rf_code[1][6] = 0;
Settings->rf_code[1][7] = 0;
}
Arilux.rf_received_value = 0;

View File

@ -147,7 +147,7 @@ void ShutterRtc50mS(void)
case SHT_PWM_VALUE:
ShutterUpdateVelocity(i);
Shutter[i].real_position += Shutter[i].direction > 0 ? Shutter[i].pwm_velocity : (Shutter[i].direction < 0 ? -Shutter[i].pwm_velocity : 0);
Shutter[i].pwm_value = SHT_DIV_ROUND((Settings.shutter_pwmrange[1][i]-Settings.shutter_pwmrange[0][i]) * Shutter[i].real_position , Shutter[i].open_max)+Settings.shutter_pwmrange[0][i];
Shutter[i].pwm_value = SHT_DIV_ROUND((Settings->shutter_pwmrange[1][i]-Settings->shutter_pwmrange[0][i]) * Shutter[i].real_position , Shutter[i].open_max)+Settings->shutter_pwmrange[0][i];
analogWrite(Pin(GPIO_PWM1, i), Shutter[i].pwm_value);
break;
@ -166,32 +166,32 @@ void ShutterRtc50mS(void)
int32_t ShutterPercentToRealPosition(int16_t percent, uint32_t index)
{
if (Settings.shutter_set50percent[index] != 50) {
return (percent <= 5) ? Settings.shuttercoeff[2][index] * percent*10 : (Settings.shuttercoeff[1][index] * percent + (Settings.shuttercoeff[0][index]*10))*10;
if (Settings->shutter_set50percent[index] != 50) {
return (percent <= 5) ? Settings->shuttercoeff[2][index] * percent*10 : (Settings->shuttercoeff[1][index] * percent + (Settings->shuttercoeff[0][index]*10))*10;
} else {
int64_t realpos;
// check against DIV 0
for (uint32_t j = 0; j < 5; j++) {
if (0 == Settings.shuttercoeff[j][index]) {
if (0 == Settings->shuttercoeff[j][index]) {
AddLog(LOG_LEVEL_ERROR, PSTR("SHT: RESET/INIT CALIBRATION MATRIX DIV 0"));
for (uint32_t k = 0; k < 5; k++) {
Settings.shuttercoeff[k][index] = SHT_DIV_ROUND(calibrate_pos[k+1] * 1000, calibrate_pos[5]);
Settings->shuttercoeff[k][index] = SHT_DIV_ROUND(calibrate_pos[k+1] * 1000, calibrate_pos[5]);
}
}
}
for (uint32_t k = 0; k < 5; k++) {
if ((percent * 10) >= Settings.shuttercoeff[k][index]) {
if ((percent * 10) >= Settings->shuttercoeff[k][index]) {
realpos = SHT_DIV_ROUND(Shutter[index].open_max * calibrate_pos[k+1], 100);
//AddLog(LOG_LEVEL_ERROR, PSTR("SHT: Realposition TEMP1: %d, %d %%, coeff %d"), realpos, percent, Settings.shuttercoeff[k][index]);
//AddLog(LOG_LEVEL_ERROR, PSTR("SHT: Realposition TEMP1: %d, %d %%, coeff %d"), realpos, percent, Settings->shuttercoeff[k][index]);
} else {
//AddLog(LOG_LEVEL_ERROR, PSTR("SHT: Shutter[%d].open_max: %d"),index, Shutter[index].open_max);
if (0 == k) {
realpos = SHT_DIV_ROUND((int64_t)percent * Shutter[index].open_max * calibrate_pos[k+1], Settings.shuttercoeff[k][index]*10 );
//AddLog(LOG_LEVEL_ERROR, PSTR("SHT: Realposition TEMP3: %d, %d %%, coeff %d"), realpos, percent, Settings.shuttercoeff[k][index]);
realpos = SHT_DIV_ROUND((int64_t)percent * Shutter[index].open_max * calibrate_pos[k+1], Settings->shuttercoeff[k][index]*10 );
//AddLog(LOG_LEVEL_ERROR, PSTR("SHT: Realposition TEMP3: %d, %d %%, coeff %d"), realpos, percent, Settings->shuttercoeff[k][index]);
} else {
//uint32_t addon = ( percent*10 - Settings.shuttercoeff[k-1][index] ) * Shutter[index].open_max * (calibrate_pos[k+1] - calibrate_pos[k]) / (Settings.shuttercoeff[k][index] -Settings.shuttercoeff[k-1][index]) / 100;
//AddLog(LOG_LEVEL_ERROR, PSTR("SHT: Realposition TEMP2: %d, %d %%, coeff %d"), addon, (calibrate_pos[k+1] - calibrate_pos[k]), (Settings.shuttercoeff[k][index] -Settings.shuttercoeff[k-1][index]));
realpos += SHT_DIV_ROUND(((int64_t)percent*10 - Settings.shuttercoeff[k-1][index] ) * Shutter[index].open_max * (calibrate_pos[k+1] - calibrate_pos[k]), (Settings.shuttercoeff[k][index] - Settings.shuttercoeff[k-1][index])*100);
//uint32_t addon = ( percent*10 - Settings->shuttercoeff[k-1][index] ) * Shutter[index].open_max * (calibrate_pos[k+1] - calibrate_pos[k]) / (Settings->shuttercoeff[k][index] -Settings->shuttercoeff[k-1][index]) / 100;
//AddLog(LOG_LEVEL_ERROR, PSTR("SHT: Realposition TEMP2: %d, %d %%, coeff %d"), addon, (calibrate_pos[k+1] - calibrate_pos[k]), (Settings->shuttercoeff[k][index] -Settings->shuttercoeff[k-1][index]));
realpos += SHT_DIV_ROUND(((int64_t)percent*10 - Settings->shuttercoeff[k-1][index] ) * Shutter[index].open_max * (calibrate_pos[k+1] - calibrate_pos[k]), (Settings->shuttercoeff[k][index] - Settings->shuttercoeff[k-1][index])*100);
}
break;
}
@ -202,23 +202,23 @@ int32_t ShutterPercentToRealPosition(int16_t percent, uint32_t index)
uint8_t ShutterRealToPercentPosition(int32_t realpos, uint32_t index)
{
if (Settings.shutter_set50percent[index] != 50) {
return (Settings.shuttercoeff[2][index] * 5 > realpos/10) ? SHT_DIV_ROUND(realpos/10, Settings.shuttercoeff[2][index]) : SHT_DIV_ROUND(realpos/10-Settings.shuttercoeff[0][index]*10, Settings.shuttercoeff[1][index]);
if (Settings->shutter_set50percent[index] != 50) {
return (Settings->shuttercoeff[2][index] * 5 > realpos/10) ? SHT_DIV_ROUND(realpos/10, Settings->shuttercoeff[2][index]) : SHT_DIV_ROUND(realpos/10-Settings->shuttercoeff[0][index]*10, Settings->shuttercoeff[1][index]);
} else {
int64_t realpercent;
for (uint32_t j = 0; j < 5; j++) {
if (realpos >= Shutter[index].open_max * calibrate_pos[j+1] / 100) {
realpercent = SHT_DIV_ROUND(Settings.shuttercoeff[j][index], 10);
realpercent = SHT_DIV_ROUND(Settings->shuttercoeff[j][index], 10);
//AddLog(LOG_LEVEL_ERROR, PSTR("SHT: Realpercent TEMP1: %d %%, %d, coeff %d"), realpercent, realpos, Shutter[index].open_max * calibrate_pos[j+1] / 100);
} else {
//AddLog(LOG_LEVEL_ERROR, PSTR("SHT: Shutter[%d].open_max: %d"),index, Shutter[index].open_max);
if (0 == j) {
realpercent = SHT_DIV_ROUND(((int64_t)realpos - SHT_DIV_ROUND(Shutter[index].open_max * calibrate_pos[j], 100)) * Settings.shuttercoeff[j][index], calibrate_pos[j+1]/10*Shutter[index].open_max);
realpercent = SHT_DIV_ROUND(((int64_t)realpos - SHT_DIV_ROUND(Shutter[index].open_max * calibrate_pos[j], 100)) * Settings->shuttercoeff[j][index], calibrate_pos[j+1]/10*Shutter[index].open_max);
} else {
//uint16_t addon = ( realpos - (Shutter[index].open_max * calibrate_pos[j] / 100) ) * 10 * (Settings.shuttercoeff[j][index] - Settings.shuttercoeff[j-1][index]) / (calibrate_pos[j+1] - calibrate_pos[j])/Shutter[index].open_max;
//uint16_t addon = ( realpercent*10 - Settings.shuttercoeff[j-1][index] ) * Shutter[index].open_max * (calibrate_pos[j+1] - calibrate_pos[j]) / (Settings.shuttercoeff[j][index] -Settings.shuttercoeff[j-1][index]) / 100;
//AddLog(LOG_LEVEL_ERROR, PSTR("SHT: Realpercent TEMP2: %d %%, delta %d, %d, coeff %d"), addon,( realpos - (Shutter[index].open_max * calibrate_pos[j] / 100) ) , (calibrate_pos[j+1] - calibrate_pos[j])* Shutter[index].open_max/100, (Settings.shuttercoeff[j][index] -Settings.shuttercoeff[j-1][index]));
realpercent += SHT_DIV_ROUND(((int64_t)realpos - SHT_DIV_ROUND(Shutter[index].open_max * calibrate_pos[j], 100)) * (Settings.shuttercoeff[j][index] - Settings.shuttercoeff[j-1][index]), (calibrate_pos[j+1] - calibrate_pos[j])/10*Shutter[index].open_max) ;
//uint16_t addon = ( realpos - (Shutter[index].open_max * calibrate_pos[j] / 100) ) * 10 * (Settings->shuttercoeff[j][index] - Settings->shuttercoeff[j-1][index]) / (calibrate_pos[j+1] - calibrate_pos[j])/Shutter[index].open_max;
//uint16_t addon = ( realpercent*10 - Settings->shuttercoeff[j-1][index] ) * Shutter[index].open_max * (calibrate_pos[j+1] - calibrate_pos[j]) / (Settings->shuttercoeff[j][index] -Settings->shuttercoeff[j-1][index]) / 100;
//AddLog(LOG_LEVEL_ERROR, PSTR("SHT: Realpercent TEMP2: %d %%, delta %d, %d, coeff %d"), addon,( realpos - (Shutter[index].open_max * calibrate_pos[j] / 100) ) , (calibrate_pos[j+1] - calibrate_pos[j])* Shutter[index].open_max/100, (Settings->shuttercoeff[j][index] -Settings->shuttercoeff[j-1][index]));
realpercent += SHT_DIV_ROUND(((int64_t)realpos - SHT_DIV_ROUND(Shutter[index].open_max * calibrate_pos[j], 100)) * (Settings->shuttercoeff[j][index] - Settings->shuttercoeff[j-1][index]), (calibrate_pos[j+1] - calibrate_pos[j])/10*Shutter[index].open_max) ;
}
break;
}
@ -236,20 +236,20 @@ void ShutterInit(void)
// if shutter 4 is unused
if (Settings.shutter_startrelay[MAX_SHUTTERS -1] == 0) {
ShutterGlobal.open_velocity_max = Settings.shuttercoeff[4][3] > 0 ? Settings.shuttercoeff[4][3] : ShutterGlobal.open_velocity_max;
if (Settings->shutter_startrelay[MAX_SHUTTERS -1] == 0) {
ShutterGlobal.open_velocity_max = Settings->shuttercoeff[4][3] > 0 ? Settings->shuttercoeff[4][3] : ShutterGlobal.open_velocity_max;
}
for (uint32_t i = 0; i < MAX_SHUTTERS; i++) {
// set startrelay to 1 on first init, but only to shutter 1. 90% usecase
Settings.shutter_startrelay[i] = (Settings.shutter_startrelay[i] == 0 && i == 0? 1 : Settings.shutter_startrelay[i]);
if (Settings.shutter_startrelay[i] && (Settings.shutter_startrelay[i] <= MAX_RELAYS )) {
Settings->shutter_startrelay[i] = (Settings->shutter_startrelay[i] == 0 && i == 0? 1 : Settings->shutter_startrelay[i]);
if (Settings->shutter_startrelay[i] && (Settings->shutter_startrelay[i] <= MAX_RELAYS )) {
TasmotaGlobal.shutters_present++;
// Add the two relays to the mask to knaw they belong to shutters
ShutterGlobal.RelayShutterMask |= 3 << (Settings.shutter_startrelay[i] -1) ;
ShutterGlobal.RelayShutterMask |= 3 << (Settings->shutter_startrelay[i] -1) ;
// All shutters must have same mode. Switch OR Pulse. N
switch (Settings.pulse_timer[i]) {
switch (Settings->pulse_timer[i]) {
case 0:
Shutter[i].switch_mode = SHT_SWITCH;
break;
@ -258,13 +258,13 @@ void ShutterInit(void)
break;
}
if (Settings.shutter_mode == SHT_UNDEF) {
if (Settings->shutter_mode == SHT_UNDEF) {
bool relay_in_interlock = false;
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Mode undef.. calculate..."));
for (uint32_t j = 0; j < MAX_INTERLOCKS * Settings.flag.interlock; j++) { // CMND_INTERLOCK - Enable/disable interlock
//AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Interlock state i=%d %d, flag %d, Shuttermask %d, MaskedIL %d"),i, Settings.interlock[i], Settings.flag.interlock,ShutterGlobal.RelayShutterMask, Settings.interlock[i]&ShutterGlobal.RelayShutterMask);
if (Settings.interlock[j] && (Settings.interlock[j] & ShutterGlobal.RelayShutterMask)) {
for (uint32_t j = 0; j < MAX_INTERLOCKS * Settings->flag.interlock; j++) { // CMND_INTERLOCK - Enable/disable interlock
//AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Interlock state i=%d %d, flag %d, Shuttermask %d, MaskedIL %d"),i, Settings->interlock[i], Settings->flag.interlock,ShutterGlobal.RelayShutterMask, Settings->interlock[i]&ShutterGlobal.RelayShutterMask);
if (Settings->interlock[j] && (Settings->interlock[j] & ShutterGlobal.RelayShutterMask)) {
//AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Relay in Interlock group"));
relay_in_interlock = true;
}
@ -280,44 +280,44 @@ void ShutterInit(void)
}
} else {
ShutterGlobal.position_mode = Settings.shutter_mode;
ShutterGlobal.position_mode = Settings->shutter_mode;
}
// main function for stepper and servos to control velocity and acceleration.
TickerShutter.attach_ms(50, ShutterRtc50mS );
// default the 50 percent should not have any impact without changing it. set to 60
Settings.shutter_set50percent[i] = (Settings.shutter_set50percent[i] > 0) ? Settings.shutter_set50percent[i] : 50;
Settings->shutter_set50percent[i] = (Settings->shutter_set50percent[i] > 0) ? Settings->shutter_set50percent[i] : 50;
// use 10 sec. as default to allow everybody to play without deep initialize
Shutter[i].open_time = Settings.shutter_opentime[i] = (Settings.shutter_opentime[i] > 0) ? Settings.shutter_opentime[i] : 100;
Shutter[i].close_time = Settings.shutter_closetime[i] = (Settings.shutter_closetime[i] > 0) ? Settings.shutter_closetime[i] : 100;
Shutter[i].open_time = Settings->shutter_opentime[i] = (Settings->shutter_opentime[i] > 0) ? Settings->shutter_opentime[i] : 100;
Shutter[i].close_time = Settings->shutter_closetime[i] = (Settings->shutter_closetime[i] > 0) ? Settings->shutter_closetime[i] : 100;
// Update Calculation 20 because time interval is 0.05 sec ans time is in 0.1sec
Shutter[i].open_max = STEPS_PER_SECOND * RESOLUTION * Shutter[i].open_time / 10;
Shutter[i].close_velocity = Shutter[i].open_max / Shutter[i].close_time / 2 ;
// calculate a ramp slope at the first 5 percent to compensate that shutters move with down part later than the upper part
if (Settings.shutter_set50percent[i] != 50) {
Settings.shuttercoeff[1][i] = Shutter[i].open_max/10 * (100 - Settings.shutter_set50percent[i] ) / 5000 ;
Settings.shuttercoeff[0][i] = Shutter[i].open_max/100 - (Settings.shuttercoeff[1][i] * 10);
Settings.shuttercoeff[2][i] = (int32_t)(Settings.shuttercoeff[0][i]*10 + 5 * Settings.shuttercoeff[1][i]) / 5;
//AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Shtr%d Shutter[i].open_max %d, 50perc:%d, 0:%d, 1:%d 2:%d"), i, Shutter[i].open_max, Settings.shutter_set50percent[i], Settings.shuttercoeff[0][i],Settings.shuttercoeff[1][i],Settings.shuttercoeff[2][i]);
if (Settings->shutter_set50percent[i] != 50) {
Settings->shuttercoeff[1][i] = Shutter[i].open_max/10 * (100 - Settings->shutter_set50percent[i] ) / 5000 ;
Settings->shuttercoeff[0][i] = Shutter[i].open_max/100 - (Settings->shuttercoeff[1][i] * 10);
Settings->shuttercoeff[2][i] = (int32_t)(Settings->shuttercoeff[0][i]*10 + 5 * Settings->shuttercoeff[1][i]) / 5;
//AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Shtr%d Shutter[i].open_max %d, 50perc:%d, 0:%d, 1:%d 2:%d"), i, Shutter[i].open_max, Settings->shutter_set50percent[i], Settings->shuttercoeff[0][i],Settings->shuttercoeff[1][i],Settings->shuttercoeff[2][i]);
}
ShutterGlobal.RelayShutterMask |= 3 << (Settings.shutter_startrelay[i] -1);
ShutterGlobal.RelayShutterMask |= 3 << (Settings->shutter_startrelay[i] -1);
Shutter[i].real_position = ShutterPercentToRealPosition(Settings.shutter_position[i], i);
Shutter[i].real_position = ShutterPercentToRealPosition(Settings->shutter_position[i], i);
Shutter[i].start_position = Shutter[i].target_position = Shutter[i].real_position;
Shutter[i].motordelay = Settings.shutter_motordelay[i];
Shutter[i].lastdirection = (50 < Settings.shutter_position[i]) ? 1 : -1;
Shutter[i].motordelay = Settings->shutter_motordelay[i];
Shutter[i].lastdirection = (50 < Settings->shutter_position[i]) ? 1 : -1;
switch (ShutterGlobal.position_mode) {
case SHT_PWM_VALUE:
ShutterGlobal.open_velocity_max = RESOLUTION;
// Initiate pwm range with defaults if not already set.
Settings.shutter_pwmrange[0][i] = Settings.shutter_pwmrange[0][i] > 0 ? Settings.shutter_pwmrange[0][i] : pwm_min;
Settings.shutter_pwmrange[1][i] = Settings.shutter_pwmrange[1][i] > 0 ? Settings.shutter_pwmrange[1][i] : pwm_max;
Settings->shutter_pwmrange[0][i] = Settings->shutter_pwmrange[0][i] > 0 ? Settings->shutter_pwmrange[0][i] : pwm_min;
Settings->shutter_pwmrange[1][i] = Settings->shutter_pwmrange[1][i] > 0 ? Settings->shutter_pwmrange[1][i] : pwm_max;
break;
}
Shutter[i].close_velocity_max = ShutterGlobal.open_velocity_max*Shutter[i].open_time / Shutter[i].close_time;
@ -325,14 +325,14 @@ void ShutterInit(void)
//AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shtr%d Openvel %d, Closevel: %d"),i, ShutterGlobal.open_velocity_max, Shutter[i].close_velocity_max);
AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Shtr%d Init. Pos %d, Inverted %d, Locked %d, End stop time enabled %d, webButtons inverted %d"),
i+1, Shutter[i].real_position,
(Settings.shutter_options[i]&1) ? 1 : 0, (Settings.shutter_options[i]&2) ? 1 : 0, (Settings.shutter_options[i]&4) ? 1 : 0, (Settings.shutter_options[i]&8) ? 1 : 0);
(Settings->shutter_options[i]&1) ? 1 : 0, (Settings->shutter_options[i]&2) ? 1 : 0, (Settings->shutter_options[i]&4) ? 1 : 0, (Settings->shutter_options[i]&8) ? 1 : 0);
} else {
// terminate loop at first INVALID Shutter[i].
break;
}
ShutterLimitRealAndTargetPositions(i);
Settings.shutter_accuracy = 1;
Settings->shutter_accuracy = 1;
}
}
@ -355,7 +355,7 @@ void ShutterReportPosition(bool always, uint32_t index)
}
if (i && index == MAX_SHUTTERS) { ResponseAppend_P(PSTR(",")); }
uint32_t target = ShutterRealToPercentPosition(Shutter[i].target_position, i);
ResponseAppend_P(JSON_SHUTTER_POS, i+1, (Settings.shutter_options[i] & 1) ? 100-position : position, Shutter[i].direction,(Settings.shutter_options[i] & 1) ? 100-target : target );
ResponseAppend_P(JSON_SHUTTER_POS, i+1, (Settings->shutter_options[i] & 1) ? 100-position : position, Shutter[i].direction,(Settings->shutter_options[i] & 1) ? 100-target : target );
}
ResponseJsonEnd();
if (always || (TasmotaGlobal.rules_flag.shutter_moving)) {
@ -449,21 +449,21 @@ void ShutterPowerOff(uint8_t i) {
ShutterDecellerateForStop(i);
switch (Shutter[i].switch_mode) {
case SHT_SWITCH:
if ((1 << (Settings.shutter_startrelay[i]-1)) & TasmotaGlobal.power) {
ExecuteCommandPowerShutter(Settings.shutter_startrelay[i], 0, SRC_SHUTTER);
if ((1 << (Settings->shutter_startrelay[i]-1)) & TasmotaGlobal.power) {
ExecuteCommandPowerShutter(Settings->shutter_startrelay[i], 0, SRC_SHUTTER);
}
if ((1 << (Settings.shutter_startrelay[i])) & TasmotaGlobal.power) {
ExecuteCommandPowerShutter(Settings.shutter_startrelay[i]+1, 0, SRC_SHUTTER);
if ((1 << (Settings->shutter_startrelay[i])) & TasmotaGlobal.power) {
ExecuteCommandPowerShutter(Settings->shutter_startrelay[i]+1, 0, SRC_SHUTTER);
}
break;
case SHT_PULSE:
uint8_t cur_relay = Settings.shutter_startrelay[i] + (Shutter[i].direction == 1 ? 0 : (uint8_t)(ShutterGlobal.position_mode == SHT_TIME)) ;
uint8_t cur_relay = Settings->shutter_startrelay[i] + (Shutter[i].direction == 1 ? 0 : (uint8_t)(ShutterGlobal.position_mode == SHT_TIME)) ;
// we have a momentary switch here. Needs additional pulse on same relay after the end
if ((SRC_PULSETIMER == TasmotaGlobal.last_source || SRC_SHUTTER == TasmotaGlobal.last_source || SRC_WEBGUI == TasmotaGlobal.last_source)) {
ExecuteCommandPowerShutter(cur_relay, 1, SRC_SHUTTER);
// switch off direction relay to make it power less
if (((1 << (Settings.shutter_startrelay[i])) & TasmotaGlobal.power) && Settings.shutter_startrelay[i]+1 != cur_relay) {
ExecuteCommandPowerShutter(Settings.shutter_startrelay[i]+1, 0, SRC_SHUTTER);
if (((1 << (Settings->shutter_startrelay[i])) & TasmotaGlobal.power) && Settings->shutter_startrelay[i]+1 != cur_relay) {
ExecuteCommandPowerShutter(Settings->shutter_startrelay[i]+1, 0, SRC_SHUTTER);
}
} else {
TasmotaGlobal.last_source = SRC_SHUTTER;
@ -511,7 +511,7 @@ void ShutterUpdatePosition(void)
}
ShutterPowerOff(i);
ShutterLimitRealAndTargetPositions(i);
Settings.shutter_position[i] = ShutterRealToPercentPosition(Shutter[i].real_position, i);
Settings->shutter_position[i] = ShutterRealToPercentPosition(Shutter[i].real_position, i);
Shutter[i].start_position = Shutter[i].real_position;
ShutterLogPos(i);
@ -519,8 +519,8 @@ void ShutterUpdatePosition(void)
// sending MQTT result to broker
snprintf_P(scommand, sizeof(scommand),PSTR(D_SHUTTER "%d"), i+1);
GetTopic_P(stopic, STAT, TasmotaGlobal.mqtt_topic, scommand);
Response_P("%d", (Settings.shutter_options[i] & 1) ? 100 - Settings.shutter_position[i]: Settings.shutter_position[i]);
MqttPublish(stopic, Settings.flag.mqtt_power_retain); // CMND_POWERRETAIN
Response_P("%d", (Settings->shutter_options[i] & 1) ? 100 - Settings->shutter_position[i]: Settings->shutter_position[i]);
MqttPublish(stopic, Settings->flag.mqtt_power_retain); // CMND_POWERRETAIN
ShutterReportPosition(true, i);
TasmotaGlobal.rules_flag.shutter_moved = 1;
XdrvRulesProcess(0);
@ -533,8 +533,8 @@ bool ShutterState(uint32_t device) {
if (device > 4) { return false; }
device--;
device &= 3;
return (Settings.flag3.shutter_mode && // SetOption80 - Enable shutter support
(ShutterGlobal.RelayShutterMask & (1 << (Settings.shutter_startrelay[device]-1))) );
return (Settings->flag3.shutter_mode && // SetOption80 - Enable shutter support
(ShutterGlobal.RelayShutterMask & (1 << (Settings->shutter_startrelay[device]-1))) );
}
void ShutterAllowPreStartProcedure(uint8_t i)
@ -620,10 +620,10 @@ void ShutterRelayChanged(void)
char stemp1[10];
for (uint32_t i = 0; i < TasmotaGlobal.shutters_present; i++) {
power_t powerstate_local = (TasmotaGlobal.power >> (Settings.shutter_startrelay[i] -1)) & 3;
power_t powerstate_local = (TasmotaGlobal.power >> (Settings->shutter_startrelay[i] -1)) & 3;
// SRC_IGNORE added because INTERLOCK function bite causes this as last source for changing the relay.
//uint8 manual_relays_changed = ((ShutterGlobal.RelayCurrentMask >> (Settings.shutter_startrelay[i] -1)) & 3) && SRC_IGNORE != TasmotaGlobal.last_source && SRC_SHUTTER != TasmotaGlobal.last_source && SRC_PULSETIMER != TasmotaGlobal.last_source ;
uint8 manual_relays_changed = ((ShutterGlobal.RelayCurrentMask >> (Settings.shutter_startrelay[i] -1)) & 3) && SRC_SHUTTER != TasmotaGlobal.last_source && SRC_PULSETIMER != TasmotaGlobal.last_source ;
//uint8 manual_relays_changed = ((ShutterGlobal.RelayCurrentMask >> (Settings->shutter_startrelay[i] -1)) & 3) && SRC_IGNORE != TasmotaGlobal.last_source && SRC_SHUTTER != TasmotaGlobal.last_source && SRC_PULSETIMER != TasmotaGlobal.last_source ;
uint8 manual_relays_changed = ((ShutterGlobal.RelayCurrentMask >> (Settings->shutter_startrelay[i] -1)) & 3) && SRC_SHUTTER != TasmotaGlobal.last_source && SRC_PULSETIMER != TasmotaGlobal.last_source ;
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shtr%d, Source %s, Powerstate %ld, RelayMask %d, ManualChange %d"),
i+1, GetTextIndexed(stemp1, sizeof(stemp1), TasmotaGlobal.last_source, kCommandSource), powerstate_local,ShutterGlobal.RelayCurrentMask,manual_relays_changed);
if (manual_relays_changed) {
@ -695,7 +695,7 @@ bool ShutterButtonIsSimultaneousHold(uint32_t button_index, uint32_t shutter_ind
// check for simultaneous shutter button hold
uint32 min_shutterbutton_hold_timer = -1; // -1 == max(uint32)
for (uint32_t i = 0; i < MAX_SHUTTER_KEYS; i++) {
if ((button_index != i) && (Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index) && (Button.hold_timer[i] < min_shutterbutton_hold_timer))
if ((button_index != i) && (Settings->shutter_button[i] & (1<<31)) && ((Settings->shutter_button[i] & 0x03) == shutter_index) && (Button.hold_timer[i] < min_shutterbutton_hold_timer))
min_shutterbutton_hold_timer = Button.hold_timer[i];
}
return ((-1 != min_shutterbutton_hold_timer) && (min_shutterbutton_hold_timer > (Button.hold_timer[button_index]>>1)));
@ -707,11 +707,11 @@ void ShutterButtonHandler(void)
uint8_t button = XdrvMailbox.payload;
uint8_t press_index;
uint32_t button_index = XdrvMailbox.index;
uint8_t shutter_index = Settings.shutter_button[button_index] & 0x03;
uint16_t loops_per_second = 1000 / Settings.button_debounce; // ButtonDebounce (50)
uint8_t shutter_index = Settings->shutter_button[button_index] & 0x03;
uint16_t loops_per_second = 1000 / Settings->button_debounce; // ButtonDebounce (50)
if ((PRESSED == button) && (NOT_PRESSED == Button.last_state[button_index])) {
if (Settings.flag.button_single) { // SetOption13 (0) - Allow only single button press for immediate action
if (Settings->flag.button_single) { // SetOption13 (0) - Allow only single button press for immediate action
buttonState = SHT_PRESSED_MULTI;
press_index = 1;
} else {
@ -732,19 +732,19 @@ void ShutterButtonHandler(void)
Button.hold_timer[button_index] = 0;
} else {
Button.hold_timer[button_index]++;
if (!Settings.flag.button_single) { // SetOption13 (0) - Allow only single button press for immediate action
if (Settings.param[P_HOLD_IGNORE] > 0) { // SetOption40 (0) - Do not ignore button hold
if (Button.hold_timer[button_index] > loops_per_second * Settings.param[P_HOLD_IGNORE] / 10) {
if (!Settings->flag.button_single) { // SetOption13 (0) - Allow only single button press for immediate action
if (Settings->param[P_HOLD_IGNORE] > 0) { // SetOption40 (0) - Do not ignore button hold
if (Button.hold_timer[button_index] > loops_per_second * Settings->param[P_HOLD_IGNORE] / 10) {
Button.hold_timer[button_index] = 0; // Reset button hold counter to stay below hold trigger
Button.press_counter[button_index] = 0; // Discard button press to disable functionality
}
}
if ((Button.press_counter[button_index]<99) && (Button.hold_timer[button_index] == loops_per_second * Settings.param[P_HOLD_TIME] / 10)) { // press still valid && SetOption32 (40) - Button hold
if ((Button.press_counter[button_index]<99) && (Button.hold_timer[button_index] == loops_per_second * Settings->param[P_HOLD_TIME] / 10)) { // press still valid && SetOption32 (40) - Button hold
// check for simultaneous shutter button hold
if (ShutterButtonIsSimultaneousHold(button_index, shutter_index)) {
// simultaneous shutter button hold detected
for (uint32_t i = 0; i < MAX_SHUTTER_KEYS; i++)
if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index))
if ((Settings->shutter_button[i] & (1<<31)) && ((Settings->shutter_button[i] & 0x03) == shutter_index))
Button.press_counter[i] = 99; // Remember to discard further action for press & hold within button timings
press_index = 0;
buttonState = SHT_PRESSED_HOLD_SIMULTANEOUS;
@ -755,7 +755,7 @@ void ShutterButtonHandler(void)
}
Button.press_counter[button_index] = 0;
}
if ((Button.press_counter[button_index]==0) && (Button.hold_timer[button_index] == loops_per_second * IMMINENT_RESET_FACTOR * Settings.param[P_HOLD_TIME] / 10)) { // SetOption32 (40) - Button held for factor times longer
if ((Button.press_counter[button_index]==0) && (Button.hold_timer[button_index] == loops_per_second * IMMINENT_RESET_FACTOR * Settings->param[P_HOLD_TIME] / 10)) { // SetOption32 (40) - Button held for factor times longer
press_index = -1;
// check for simultaneous shutter button extend hold
if (ShutterButtonIsSimultaneousHold(button_index, shutter_index)) {
@ -768,7 +768,7 @@ void ShutterButtonHandler(void)
}
}
if (!Settings.flag.button_single) { // SetOption13 (0) - Allow multi-press
if (!Settings->flag.button_single) { // SetOption13 (0) - Allow multi-press
if (Button.window_timer[button_index]) {
Button.window_timer[button_index]--;
} else {
@ -778,8 +778,8 @@ void ShutterButtonHandler(void)
uint32 min_shutterbutton_press_counter = -1; // -1 == max(uint32)
for (uint32_t i = 0; i < MAX_SHUTTER_KEYS; i++) {
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: ShutterButton[i] %ld, ShutterIndex %d, ButtonPressCounter[i] %d, minShutterButtonPressCounter %d, i %d"),
Settings.shutter_button[i], shutter_index, Button.press_counter[i] , min_shutterbutton_press_counter, i);
if ((button_index != i) && (Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index) && (i != button_index) && (Button.press_counter[i] < min_shutterbutton_press_counter)) {
Settings->shutter_button[i], shutter_index, Button.press_counter[i] , min_shutterbutton_press_counter, i);
if ((button_index != i) && (Settings->shutter_button[i] & (1<<31)) && ((Settings->shutter_button[i] & 0x03) == shutter_index) && (i != button_index) && (Button.press_counter[i] < min_shutterbutton_press_counter)) {
min_shutterbutton_press_counter = Button.press_counter[i];
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: minShutterButtonPressCounter %d"), min_shutterbutton_press_counter);
}
@ -789,7 +789,7 @@ void ShutterButtonHandler(void)
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Simultanous press detected"));
press_index = Button.press_counter[button_index];
for (uint32_t i = 0; i < MAX_SHUTTER_KEYS; i++)
if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) != shutter_index))
if ((Settings->shutter_button[i] & (1<<31)) && ((Settings->shutter_button[i] & 0x03) != shutter_index))
Button.press_counter[i] = 99; // Remember to discard further action for press & hold within button timings
buttonState = SHT_PRESSED_MULTI_SIMULTANEOUS;
}
@ -805,11 +805,11 @@ void ShutterButtonHandler(void)
}
if (buttonState != SHT_NOT_PRESSED) {
if ((!Settings.flag.button_restrict) && (((press_index>=5) && (press_index<=7)) || (buttonState == SHT_PRESSED_EXT_HOLD) || (buttonState == SHT_PRESSED_EXT_HOLD_SIMULTANEOUS))){
if ((!Settings->flag.button_restrict) && (((press_index>=5) && (press_index<=7)) || (buttonState == SHT_PRESSED_EXT_HOLD) || (buttonState == SHT_PRESSED_EXT_HOLD_SIMULTANEOUS))){
// check number of buttons for this shutter
uint8_t shutter_index_num_buttons = 0;
for (uint32_t i = 0; i < MAX_SHUTTER_KEYS; i++) {
if ((Settings.shutter_button[i] & (1<<31)) && ((Settings.shutter_button[i] & 0x03) == shutter_index)) {
if ((Settings->shutter_button[i] & (1<<31)) && ((Settings->shutter_button[i] & 0x03) == shutter_index)) {
shutter_index_num_buttons++;
}
}
@ -830,7 +830,7 @@ void ShutterButtonHandler(void)
}
}
if (buttonState <= SHT_PRESSED_IMMEDIATE) {
if (Settings.shutter_startrelay[shutter_index] && Settings.shutter_startrelay[shutter_index] <9) {
if (Settings->shutter_startrelay[shutter_index] && Settings->shutter_startrelay[shutter_index] <9) {
uint8_t pos_press_index = (buttonState == SHT_PRESSED_HOLD) ? 3 : (press_index-1);
if (pos_press_index>3) pos_press_index=3;
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Shtr%d, Button %d = %d (single=1, double=2, tripple=3, hold=4)"), shutter_index+1, button_index+1, pos_press_index+1);
@ -844,7 +844,7 @@ void ShutterButtonHandler(void)
XdrvMailbox.payload = XdrvMailbox.index;
CmndShutterStop();
} else {
uint8_t position = (Settings.shutter_button[button_index]>>(6*pos_press_index + 2)) & 0x03f;
uint8_t position = (Settings->shutter_button[button_index]>>(6*pos_press_index + 2)) & 0x03f;
if (position) {
if (Shutter[shutter_index].direction) {
XdrvMailbox.payload = XdrvMailbox.index;
@ -858,23 +858,23 @@ void ShutterButtonHandler(void)
} else {
CmndShutterPosition();
}
if (Settings.shutter_button[button_index] & ((0x01<<26)<<pos_press_index)) {
if (Settings->shutter_button[button_index] & ((0x01<<26)<<pos_press_index)) {
// MQTT broadcast to grouptopic
char scommand[CMDSZ];
char stopic[TOPSZ];
for (uint32_t i = 0; i < MAX_SHUTTERS; i++) {
if ((i==shutter_index) || (Settings.shutter_button[button_index] & (0x01<<30))) {
if ((i==shutter_index) || (Settings->shutter_button[button_index] & (0x01<<30))) {
snprintf_P(scommand, sizeof(scommand),PSTR("ShutterPosition%d"), i+1);
GetGroupTopic_P(stopic, scommand, SET_MQTT_GRP_TOPIC);
Response_P("%d", position);
MqttPublish(stopic, false);
}
} // for (uint32_t)
} // if (Settings.shutter)
} // if (Settings->shutter)
} // ende else
} // if (position)
} // end else
} // if if (Settings.shutter_startrelay[shutter_index]
} // if if (Settings->shutter_startrelay[shutter_index]
}
Response_P(PSTR("{"));
ResponseAppend_P(JSON_SHUTTER_BUTTON, shutter_index+1, (buttonState <= SHT_PRESSED_EXT_HOLD) ? (button_index+1) : 0, press_index);
@ -998,7 +998,7 @@ void CmndShutterStopToggleDir(void)
void CmndShutterStop(void)
{
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= TasmotaGlobal.shutters_present)) {
if (!(Settings.shutter_options[XdrvMailbox.index-1] & 2)) {
if (!(Settings->shutter_options[XdrvMailbox.index-1] & 2)) {
if ((1 == XdrvMailbox.index) && (XdrvMailbox.payload != -99)) {
XdrvMailbox.index = XdrvMailbox.payload;
}
@ -1035,7 +1035,7 @@ void CmndShutterIncDec(void)
void CmndShutterPosition(void)
{
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= TasmotaGlobal.shutters_present)) {
if (!(Settings.shutter_options[XdrvMailbox.index-1] & 2)) {
if (!(Settings->shutter_options[XdrvMailbox.index-1] & 2)) {
uint32_t index = XdrvMailbox.index-1;
//limit the payload
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: Pos. in: payload %s (%d), payload %d, idx %d, src %d"), XdrvMailbox.data , XdrvMailbox.data_len, XdrvMailbox.payload , XdrvMailbox.index, TasmotaGlobal.last_source );
@ -1069,16 +1069,16 @@ void CmndShutterPosition(void)
int8_t target_pos_percent = (XdrvMailbox.payload < 0) ? (XdrvMailbox.payload == -99 ? ShutterRealToPercentPosition(Shutter[index].real_position, index) : 0) : ((XdrvMailbox.payload > 100) ? 100 : XdrvMailbox.payload);
// webgui still send also on inverted shutter the native position.
target_pos_percent = ((Settings.shutter_options[index] & 1) && (SRC_WEBGUI != TasmotaGlobal.last_source)) ? 100 - target_pos_percent : target_pos_percent;
target_pos_percent = ((Settings->shutter_options[index] & 1) && (SRC_WEBGUI != TasmotaGlobal.last_source)) ? 100 - target_pos_percent : target_pos_percent;
if (XdrvMailbox.payload != -99) {
//target_pos_percent = (Settings.shutter_options[index] & 1) ? 100 - target_pos_percent : target_pos_percent;
//target_pos_percent = (Settings->shutter_options[index] & 1) ? 100 - target_pos_percent : target_pos_percent;
Shutter[index].target_position = ShutterPercentToRealPosition(target_pos_percent, index);
//Shutter[i].accelerator[index] = ShutterGlobal.open_velocity_max / ((Shutter[i].motordelay[index] > 0) ? Shutter[i].motordelay[index] : 1);
//Shutter[i].target_position[index] = XdrvMailbox.payload < 5 ? Settings.shuttercoeff[2][index] * XdrvMailbox.payload : Settings.shuttercoeff[1][index] * XdrvMailbox.payload + Settings.shuttercoeff[0,index];
//Shutter[i].target_position[index] = XdrvMailbox.payload < 5 ? Settings->shuttercoeff[2][index] * XdrvMailbox.payload : Settings->shuttercoeff[1][index] * XdrvMailbox.payload + Settings->shuttercoeff[0,index];
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SHT: lastsource %d:, real %d, target %d, payload %d"), TasmotaGlobal.last_source, Shutter[index].real_position ,Shutter[index].target_position,target_pos_percent);
}
if ( (target_pos_percent >= 0) && (target_pos_percent <= 100) && abs(Shutter[index].target_position - Shutter[index].real_position ) / Shutter[index].close_velocity > 2) {
if (Settings.shutter_options[index] & 4) {
if (Settings->shutter_options[index] & 4) {
if (0 == target_pos_percent) Shutter[index].target_position -= 1 * RESOLUTION * STEPS_PER_SECOND;
if (100 == target_pos_percent) Shutter[index].target_position += 1 * RESOLUTION * STEPS_PER_SECOND;
}
@ -1095,18 +1095,18 @@ void CmndShutterPosition(void)
case SHT_TIME_UP_DOWN:
if (!ShutterGlobal.skip_relay_change) {
// Code for shutters with circuit safe configuration, switch the direction Relay
ExecuteCommandPowerShutter(Settings.shutter_startrelay[index] +1, new_shutterdirection == 1 ? 0 : 1, SRC_SHUTTER);
ExecuteCommandPowerShutter(Settings->shutter_startrelay[index] +1, new_shutterdirection == 1 ? 0 : 1, SRC_SHUTTER);
// power on
ExecuteCommandPowerShutter(Settings.shutter_startrelay[index], 1, SRC_SHUTTER);
ExecuteCommandPowerShutter(Settings->shutter_startrelay[index], 1, SRC_SHUTTER);
}
//if (ShutterGlobal.position_mode != SHT_TIME_UP_DOWN) ExecuteCommandPowerShutter(Settings.shutter_startrelay[index]+2, 1, SRC_SHUTTER);
//if (ShutterGlobal.position_mode != SHT_TIME_UP_DOWN) ExecuteCommandPowerShutter(Settings->shutter_startrelay[index]+2, 1, SRC_SHUTTER);
break;
case SHT_TIME:
if (!ShutterGlobal.skip_relay_change) {
if ( (TasmotaGlobal.power >> (Settings.shutter_startrelay[index] -1)) & 3 > 0 ) {
ExecuteCommandPowerShutter(Settings.shutter_startrelay[index] + (new_shutterdirection == 1 ? 1 : 0), Shutter[index].switch_mode == SHT_SWITCH ? 0 : 1, SRC_SHUTTER);
if ( (TasmotaGlobal.power >> (Settings->shutter_startrelay[index] -1)) & 3 > 0 ) {
ExecuteCommandPowerShutter(Settings->shutter_startrelay[index] + (new_shutterdirection == 1 ? 1 : 0), Shutter[index].switch_mode == SHT_SWITCH ? 0 : 1, SRC_SHUTTER);
}
ExecuteCommandPowerShutter(Settings.shutter_startrelay[index] + (new_shutterdirection == 1 ? 0 : 1), 1, SRC_SHUTTER);
ExecuteCommandPowerShutter(Settings->shutter_startrelay[index] + (new_shutterdirection == 1 ? 0 : 1), 1, SRC_SHUTTER);
}
break;
case SHT_TIME_GARAGE:
@ -1114,15 +1114,15 @@ void CmndShutterPosition(void)
if (new_shutterdirection == Shutter[index].lastdirection) {
AddLog(LOG_LEVEL_INFO, PSTR("SHT: Garage not move in this direction: %d"), Shutter[index].switch_mode == SHT_PULSE);
for (uint8_t k=0 ; k <= (uint8_t)(Shutter[index].switch_mode == SHT_PULSE) ; k++) {
ExecuteCommandPowerShutter(Settings.shutter_startrelay[index], 1, SRC_SHUTTER);
ExecuteCommandPowerShutter(Settings->shutter_startrelay[index], 1, SRC_SHUTTER);
delay(500);
ExecuteCommandPowerShutter(Settings.shutter_startrelay[index], 0, SRC_SHUTTER);
ExecuteCommandPowerShutter(Settings->shutter_startrelay[index], 0, SRC_SHUTTER);
delay(500);
}
// reset shutter time to avoid 2 seconds above count as runtime
Shutter[index].time = 0;
} // if (new_shutterdirection == Shutter[i].lastdirection[index])
ExecuteCommandPowerShutter(Settings.shutter_startrelay[index], 1, SRC_SHUTTER);
ExecuteCommandPowerShutter(Settings->shutter_startrelay[index], 1, SRC_SHUTTER);
} // if (!ShutterGlobal.skip_relay_change)
break;
} // switch (ShutterGlobal.position_mode)
@ -1134,7 +1134,7 @@ void CmndShutterPosition(void)
}
XdrvMailbox.index = index +1; // Fix random index for ShutterClose
if (XdrvMailbox.command)
ResponseCmndIdxNumber((Settings.shutter_options[index] & 1) ? 100 - target_pos_percent : target_pos_percent);
ResponseCmndIdxNumber((Settings->shutter_options[index] & 1) ? 100 - target_pos_percent : target_pos_percent);
} else {
ShutterReportPosition(true, MAX_SHUTTERS);
if (XdrvMailbox.command)
@ -1159,11 +1159,11 @@ void CmndShutterOpenTime(void)
{
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= TasmotaGlobal.shutters_present)) {
if (XdrvMailbox.data_len > 0) {
Settings.shutter_opentime[XdrvMailbox.index -1] = (uint16_t)(10 * CharToFloat(XdrvMailbox.data));
Settings->shutter_opentime[XdrvMailbox.index -1] = (uint16_t)(10 * CharToFloat(XdrvMailbox.data));
ShutterInit();
}
char time_chr[10];
dtostrfd((float)(Settings.shutter_opentime[XdrvMailbox.index -1]) / 10, 1, time_chr);
dtostrfd((float)(Settings->shutter_opentime[XdrvMailbox.index -1]) / 10, 1, time_chr);
ResponseCmndIdxChar(time_chr);
}
}
@ -1172,11 +1172,11 @@ void CmndShutterCloseTime(void)
{
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= TasmotaGlobal.shutters_present)) {
if (XdrvMailbox.data_len > 0) {
Settings.shutter_closetime[XdrvMailbox.index -1] = (uint16_t)(10 * CharToFloat(XdrvMailbox.data));
Settings->shutter_closetime[XdrvMailbox.index -1] = (uint16_t)(10 * CharToFloat(XdrvMailbox.data));
ShutterInit();
}
char time_chr[10];
dtostrfd((float)(Settings.shutter_closetime[XdrvMailbox.index -1]) / 10, 1, time_chr);
dtostrfd((float)(Settings->shutter_closetime[XdrvMailbox.index -1]) / 10, 1, time_chr);
ResponseCmndIdxChar(time_chr);
}
}
@ -1185,11 +1185,11 @@ void CmndShutterMotorDelay(void)
{
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= TasmotaGlobal.shutters_present)) {
if (XdrvMailbox.data_len > 0) {
Settings.shutter_motordelay[XdrvMailbox.index -1] = (uint16_t)(STEPS_PER_SECOND * CharToFloat(XdrvMailbox.data));
Settings->shutter_motordelay[XdrvMailbox.index -1] = (uint16_t)(STEPS_PER_SECOND * CharToFloat(XdrvMailbox.data));
ShutterInit();
}
char time_chr[10];
dtostrfd((float)(Settings.shutter_motordelay[XdrvMailbox.index -1]) / STEPS_PER_SECOND, 2, time_chr);
dtostrfd((float)(Settings->shutter_motordelay[XdrvMailbox.index -1]) / STEPS_PER_SECOND, 2, time_chr);
ResponseCmndIdxChar(time_chr);
}
}
@ -1198,7 +1198,7 @@ void CmndShutterMode(void)
{
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= MAX_MODES)) {
ShutterGlobal.position_mode = XdrvMailbox.payload;
Settings.shutter_mode = XdrvMailbox.payload;
Settings->shutter_mode = XdrvMailbox.payload;
ShutterInit();
}
ResponseCmndNumber(ShutterGlobal.position_mode);
@ -1208,17 +1208,17 @@ void CmndShutterRelay(void)
{
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_SHUTTERS)) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 64)) {
Settings.shutter_startrelay[XdrvMailbox.index -1] = XdrvMailbox.payload;
Settings->shutter_startrelay[XdrvMailbox.index -1] = XdrvMailbox.payload;
if (XdrvMailbox.payload > 0) {
ShutterGlobal.RelayShutterMask |= 3 << (XdrvMailbox.payload - 1);
} else {
ShutterGlobal.RelayShutterMask ^= 3 << (Settings.shutter_startrelay[XdrvMailbox.index -1] - 1);
ShutterGlobal.RelayShutterMask ^= 3 << (Settings->shutter_startrelay[XdrvMailbox.index -1] - 1);
}
Settings.shutter_startrelay[XdrvMailbox.index -1] = XdrvMailbox.payload;
Settings->shutter_startrelay[XdrvMailbox.index -1] = XdrvMailbox.payload;
ShutterInit();
// if payload is 0 to disable the relay there must be a reboot. Otherwhise does not work
}
ResponseCmndIdxNumber(Settings.shutter_startrelay[XdrvMailbox.index -1]);
ResponseCmndIdxNumber(Settings->shutter_startrelay[XdrvMailbox.index -1]);
}
}
@ -1315,21 +1315,21 @@ void CmndShutterButton(void)
if (button_index==-1) {
// remove all buttons for this shutter
for (uint32_t i=0 ; i < MAX_SHUTTER_KEYS ; i++)
if ((Settings.shutter_button[i]&0x3) == (XdrvMailbox.index-1))
Settings.shutter_button[i] = 0;
if ((Settings->shutter_button[i]&0x3) == (XdrvMailbox.index-1))
Settings->shutter_button[i] = 0;
} else {
if (setting) {
// anything was set
setting |= (1<<31);
setting |= (XdrvMailbox.index-1) & 0x3;
}
Settings.shutter_button[button_index-1] = setting;
Settings->shutter_button[button_index-1] = setting;
}
}
}
char setting_chr[30*MAX_SHUTTER_KEYS] = "-", *setting_chr_ptr = setting_chr;
for (uint32_t i=0 ; i < MAX_SHUTTER_KEYS ; i++) {
setting = Settings.shutter_button[i];
setting = Settings->shutter_button[i];
if ((setting&(1<<31)) && ((setting&0x3) == (XdrvMailbox.index-1))) {
if (*setting_chr_ptr == 0)
setting_chr_ptr += sprintf_P(setting_chr_ptr, PSTR("|"));
@ -1363,11 +1363,11 @@ void CmndShutterSetHalfway(void)
{
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= TasmotaGlobal.shutters_present)) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) {
Settings.shutter_set50percent[XdrvMailbox.index -1] = (Settings.shutter_options[XdrvMailbox.index -1] & 1) ? 100 - XdrvMailbox.payload : XdrvMailbox.payload;
Settings.shuttercoeff[0][XdrvMailbox.index -1] = 0;
Settings->shutter_set50percent[XdrvMailbox.index -1] = (Settings->shutter_options[XdrvMailbox.index -1] & 1) ? 100 - XdrvMailbox.payload : XdrvMailbox.payload;
Settings->shuttercoeff[0][XdrvMailbox.index -1] = 0;
ShutterInit();
}
ResponseCmndIdxNumber((Settings.shutter_options[XdrvMailbox.index -1] & 1) ? 100 - Settings.shutter_set50percent[XdrvMailbox.index -1] : Settings.shutter_set50percent[XdrvMailbox.index -1]);
ResponseCmndIdxNumber((Settings->shutter_options[XdrvMailbox.index -1] & 1) ? 100 - Settings->shutter_set50percent[XdrvMailbox.index -1] : Settings->shutter_set50percent[XdrvMailbox.index -1]);
}
}
@ -1376,7 +1376,7 @@ void CmndShutterFrequency(void)
if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 20000)) {
ShutterGlobal.open_velocity_max = XdrvMailbox.payload;
if (TasmotaGlobal.shutters_present < 4) {
Settings.shuttercoeff[4][3] = ShutterGlobal.open_velocity_max;
Settings->shuttercoeff[4][3] = ShutterGlobal.open_velocity_max;
}
ShutterInit();
}
@ -1388,7 +1388,7 @@ void CmndShutterSetClose(void)
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= TasmotaGlobal.shutters_present)) {
Shutter[XdrvMailbox.index -1].real_position = 0;
ShutterStartInit(XdrvMailbox.index -1, 0, 0);
Settings.shutter_position[XdrvMailbox.index -1] = 0;
Settings->shutter_position[XdrvMailbox.index -1] = 0;
ResponseCmndIdxChar(D_CONFIGURATION_RESET);
}
}
@ -1398,7 +1398,7 @@ void CmndShutterSetOpen(void)
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= TasmotaGlobal.shutters_present)) {
Shutter[XdrvMailbox.index -1].real_position = Shutter[XdrvMailbox.index -1].open_max;
ShutterStartInit(XdrvMailbox.index -1, 0, Shutter[XdrvMailbox.index -1].open_max);
Settings.shutter_position[XdrvMailbox.index -1] = 100;
Settings->shutter_position[XdrvMailbox.index -1] = 100;
ResponseCmndIdxChar(D_CONFIGURATION_RESET);
}
}
@ -1420,14 +1420,14 @@ void CmndShutterPwmRange(void)
if ((field <= 0) || (field > 1023)) {
break;
}
Settings.shutter_pwmrange[i][XdrvMailbox.index -1] = field;
Settings->shutter_pwmrange[i][XdrvMailbox.index -1] = field;
}
AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Shtr%d Init1. pwmmin %d, pwmmax %d"), XdrvMailbox.index , Settings.shutter_pwmrange[0][XdrvMailbox.index -1], Settings.shutter_pwmrange[1][XdrvMailbox.index -1]);
AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Shtr%d Init1. pwmmin %d, pwmmax %d"), XdrvMailbox.index , Settings->shutter_pwmrange[0][XdrvMailbox.index -1], Settings->shutter_pwmrange[1][XdrvMailbox.index -1]);
ShutterInit();
ResponseCmndIdxChar(XdrvMailbox.data);
} else {
char setting_chr[30] = "0";
snprintf_P(setting_chr, sizeof(setting_chr), PSTR("Shutter %d: min:%d max:%d"), XdrvMailbox.index, Settings.shutter_pwmrange[0][XdrvMailbox.index -1], Settings.shutter_pwmrange[1][XdrvMailbox.index -1]);
snprintf_P(setting_chr, sizeof(setting_chr), PSTR("Shutter %d: min:%d max:%d"), XdrvMailbox.index, Settings->shutter_pwmrange[0][XdrvMailbox.index -1], Settings->shutter_pwmrange[1][XdrvMailbox.index -1]);
ResponseCmndIdxChar(setting_chr);
}
}
@ -1452,16 +1452,16 @@ void CmndShutterCalibration(void)
}
messwerte[i] = field;
}
Settings.shutter_set50percent[XdrvMailbox.index -1] = 50;
Settings->shutter_set50percent[XdrvMailbox.index -1] = 50;
for (i = 0; i < 5; i++) {
Settings.shuttercoeff[i][XdrvMailbox.index -1] = SHT_DIV_ROUND((uint32_t)messwerte[i] * 1000, messwerte[4]);
AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Shuttercoeff %d, i %d, Value %d, MeasuredValue %d"), i,XdrvMailbox.index -1,Settings.shuttercoeff[i][XdrvMailbox.index -1], messwerte[i]);
Settings->shuttercoeff[i][XdrvMailbox.index -1] = SHT_DIV_ROUND((uint32_t)messwerte[i] * 1000, messwerte[4]);
AddLog(LOG_LEVEL_DEBUG, PSTR("SHT: Shuttercoeff %d, i %d, Value %d, MeasuredValue %d"), i,XdrvMailbox.index -1,Settings->shuttercoeff[i][XdrvMailbox.index -1], messwerte[i]);
}
ShutterInit();
ResponseCmndIdxChar(XdrvMailbox.data);
} else {
char setting_chr[30] = "0";
snprintf_P(setting_chr, sizeof(setting_chr), PSTR("%d %d %d %d %d"), Settings.shuttercoeff[0][XdrvMailbox.index -1], Settings.shuttercoeff[1][XdrvMailbox.index -1], Settings.shuttercoeff[2][XdrvMailbox.index -1], Settings.shuttercoeff[3][XdrvMailbox.index -1], Settings.shuttercoeff[4][XdrvMailbox.index -1]);
snprintf_P(setting_chr, sizeof(setting_chr), PSTR("%d %d %d %d %d"), Settings->shuttercoeff[0][XdrvMailbox.index -1], Settings->shuttercoeff[1][XdrvMailbox.index -1], Settings->shuttercoeff[2][XdrvMailbox.index -1], Settings->shuttercoeff[3][XdrvMailbox.index -1], Settings->shuttercoeff[4][XdrvMailbox.index -1]);
ResponseCmndIdxChar(setting_chr);
}
}
@ -1470,11 +1470,11 @@ void CmndShutterCalibration(void)
void ShutterOptionsSetHelper(uint16_t option){
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= TasmotaGlobal.shutters_present)) {
if (XdrvMailbox.payload == 0) {
Settings.shutter_options[XdrvMailbox.index -1] &= ~(option);
Settings->shutter_options[XdrvMailbox.index -1] &= ~(option);
} else if (XdrvMailbox.payload == 1) {
Settings.shutter_options[XdrvMailbox.index -1] |= (option);
Settings->shutter_options[XdrvMailbox.index -1] |= (option);
}
ResponseCmndIdxNumber((Settings.shutter_options[XdrvMailbox.index -1] & option) ? 1 : 0);
ResponseCmndIdxNumber((Settings->shutter_options[XdrvMailbox.index -1] & option) ? 1 : 0);
}
}
@ -1502,7 +1502,7 @@ bool Xdrv27(uint8_t function)
{
bool result = false;
if (Settings.flag3.shutter_mode) { // SetOption80 - Enable shutter support
if (Settings->flag3.shutter_mode) { // SetOption80 - Enable shutter support
switch (function) {
case FUNC_PRE_INIT:
ShutterInit();
@ -1520,8 +1520,8 @@ bool Xdrv27(uint8_t function)
break;
case FUNC_JSON_APPEND:
for (uint8_t i = 0; i < TasmotaGlobal.shutters_present; i++) {
uint8_t position = (Settings.shutter_options[i] & 1) ? 100 - Settings.shutter_position[i] : Settings.shutter_position[i];
uint8_t target = (Settings.shutter_options[i] & 1) ? 100 - ShutterRealToPercentPosition(Shutter[i].target_position, i) : ShutterRealToPercentPosition(Shutter[i].target_position, i);
uint8_t position = (Settings->shutter_options[i] & 1) ? 100 - Settings->shutter_position[i] : Settings->shutter_position[i];
uint8_t target = (Settings->shutter_options[i] & 1) ? 100 - ShutterRealToPercentPosition(Shutter[i].target_position, i) : ShutterRealToPercentPosition(Shutter[i].target_position, i);
ResponseAppend_P(",");
ResponseAppend_P(JSON_SHUTTER_POS, i+1, position, Shutter[i].direction,target);
@ -1557,7 +1557,7 @@ bool Xdrv27(uint8_t function)
}
break;
case FUNC_BUTTON_PRESSED:
if (Settings.shutter_button[XdrvMailbox.index] & (1<<31)) {
if (Settings->shutter_button[XdrvMailbox.index] & (1<<31)) {
ShutterButtonHandler();
result = true;
}
@ -1580,7 +1580,7 @@ void CmndShutterUnitTest(void) {
uint32_t result = 0;
char svalue[50]; // Command and number parameter
Settings.shuttercoeff[0][0] = 0;
Settings->shuttercoeff[0][0] = 0;
for (uint8_t i=0; i<2 ; i++){
snprintf_P(svalue, sizeof(svalue), PSTR(D_PRFX_SHUTTER D_CMND_SHUTTER_OPENTIME "%d %d"), 1, 12);
ExecuteCommand(svalue, SRC_SHUTTER);
@ -1601,7 +1601,7 @@ void CmndShutterUnitTest(void) {
} else {
AddLog(LOG_LEVEL_ERROR, PSTR("SHT: ShutterPercentToRealPosition: FAIL"));
}
Settings.shuttercoeff[0][0] = 0;
Settings->shuttercoeff[0][0] = 0;
for (uint8_t i=0; i<2 ; i++){
snprintf_P(svalue, sizeof(svalue), PSTR(D_PRFX_SHUTTER D_CMND_SHUTTER_OPENTIME "%d %d"), 1, 12);
ExecuteCommand(svalue, SRC_SHUTTER);

View File

@ -125,21 +125,21 @@ void Pcf8574Init(void)
uint8_t gpio = Pcf8574Read(idx);
Pcf8574.pin_mask[idx] = gpio;
#ifdef USE_PCF8574_MQTTINPUT
Pcf8574.last_input[idx] = gpio & ~Settings.pcf8574_config[idx];
Pcf8574.last_input[idx] = gpio & ~Settings->pcf8574_config[idx];
#endif // #ifdef USE_PCF8574_MQTTINPUT
//AddLog(LOG_LEVEL_DEBUG, PSTR("PCF: PCF-%d config=0x%02x, gpio=0x%02X"), idx +1, Settings.pcf8574_config[idx], gpio);
//AddLog(LOG_LEVEL_DEBUG, PSTR("PCF: PCF-%d config=0x%02x, gpio=0x%02X"), idx +1, Settings->pcf8574_config[idx], gpio);
for (uint32_t i = 0; i < 8; i++, gpio>>=1) {
uint8_t _result = Settings.pcf8574_config[idx] >> i &1;
//AddLog(LOG_LEVEL_DEBUG, PSTR("PCF: I2C shift i %d: %d. Powerstate: %d, TasmotaGlobal.devices_present: %d"), i,_result, Settings.power>>i&1, TasmotaGlobal.devices_present);
uint8_t _result = Settings->pcf8574_config[idx] >> i &1;
//AddLog(LOG_LEVEL_DEBUG, PSTR("PCF: I2C shift i %d: %d. Powerstate: %d, TasmotaGlobal.devices_present: %d"), i,_result, Settings->power>>i&1, TasmotaGlobal.devices_present);
if (_result > 0) {
Pcf8574.pin[TasmotaGlobal.devices_present] = i + 8 * idx;
bitWrite(TasmotaGlobal.rel_inverted, TasmotaGlobal.devices_present, Settings.flag3.pcf8574_ports_inverted); // SetOption81 - Invert all ports on PCF8574 devices
if (!Settings.flag.save_state && !Settings.flag3.no_power_feedback) { // SetOption63 - Don't scan relay power state at restart - #5594 and #5663
bitWrite(TasmotaGlobal.rel_inverted, TasmotaGlobal.devices_present, Settings->flag3.pcf8574_ports_inverted); // SetOption81 - Invert all ports on PCF8574 devices
if (!Settings->flag.save_state && !Settings->flag3.no_power_feedback) { // SetOption63 - Don't scan relay power state at restart - #5594 and #5663
//AddLog(LOG_LEVEL_DEBUG, PSTR("PCF: Set power from from chip state"));
uint8_t power_state = Settings.flag3.pcf8574_ports_inverted ? 1 & ~gpio : 1 & gpio;
uint8_t power_state = Settings->flag3.pcf8574_ports_inverted ? 1 & ~gpio : 1 & gpio;
bitWrite(TasmotaGlobal.power, TasmotaGlobal.devices_present, power_state);
bitWrite(Settings.power, TasmotaGlobal.devices_present, power_state);
bitWrite(Settings->power, TasmotaGlobal.devices_present, power_state);
}
//else AddLog(LOG_LEVEL_DEBUG, PSTR("PCF: DON'T set power from chip state"));
TasmotaGlobal.devices_present++;
@ -147,7 +147,7 @@ void Pcf8574Init(void)
}
}
}
//AddLog(LOG_LEVEL_DEBUG, PSTR("PCF: Settings.power=0x%08X, TasmotaGlobal.power=0x%08X"), Settings.power, TasmotaGlobal.power);
//AddLog(LOG_LEVEL_DEBUG, PSTR("PCF: Settings->power=0x%08X, TasmotaGlobal.power=0x%08X"), Settings->power, TasmotaGlobal.power);
AddLog(LOG_LEVEL_INFO, PSTR("PCF: Total devices %d, PCF8574 output ports %d"), Pcf8574.max_devices, Pcf8574.max_connected_ports);
}
}
@ -191,7 +191,7 @@ void HandlePcf8574(void)
WSContentStart_P(D_CONFIGURE_PCF8574);
WSContentSendStyle();
WSContentSend_P(HTTP_FORM_I2C_PCF8574_1, (Settings.flag3.pcf8574_ports_inverted) ? PSTR(" checked") : ""); // SetOption81 - Invert all ports on PCF8574 devices
WSContentSend_P(HTTP_FORM_I2C_PCF8574_1, (Settings->flag3.pcf8574_ports_inverted) ? PSTR(" checked") : ""); // SetOption81 - Invert all ports on PCF8574 devices
WSContentSend_P(HTTP_TABLE100);
for (uint32_t idx = 0; idx < Pcf8574.max_devices; idx++) {
for (uint32_t idx2 = 0; idx2 < 8; idx2++) { // 8 ports on PCF8574
@ -200,8 +200,8 @@ void HandlePcf8574(void)
idx +1, idx2,
idx2 + 8*idx,
idx2 + 8*idx,
((helper & Settings.pcf8574_config[idx]) >> idx2 == 0) ? PSTR(" selected ") : " ",
((helper & Settings.pcf8574_config[idx]) >> idx2 == 1) ? PSTR(" selected ") : " "
((helper & Settings->pcf8574_config[idx]) >> idx2 == 0) ? PSTR(" selected ") : " ",
((helper & Settings->pcf8574_config[idx]) >> idx2 == 1) ? PSTR(" selected ") : " "
);
}
}
@ -230,7 +230,7 @@ void Pcf8574Show(bool json)
if(!json) {
for (int idx = 0 ; idx < Pcf8574.max_devices ; idx++)
{
uint8_t input_mask = ~Settings.pcf8574_config[idx]; //invert to 1 = input
uint8_t input_mask = ~Settings->pcf8574_config[idx]; //invert to 1 = input
uint8_t gpio = Pcf8574Read(idx);
for (int pin = 0 ; pin < 8 ; ++pin, input_mask>>=1, gpio>>=1)
{
@ -249,7 +249,7 @@ void Pcf8574CheckForInputChange(void)
{
for (int idx = 0 ; idx < Pcf8574.max_devices ; idx++)
{
uint8_t input_mask = ~Settings.pcf8574_config[idx]; //invert to 1 = input
uint8_t input_mask = ~Settings->pcf8574_config[idx]; //invert to 1 = input
uint8_t input = Pcf8574Read(idx) & input_mask;
uint8_t last_input = Pcf8574.last_input[idx];
if (input != last_input) { // don't scan bits if no change (EVERY_50_MS !)
@ -257,7 +257,7 @@ void Pcf8574CheckForInputChange(void)
if (bitRead(input_mask,pin) && bitRead(input,pin) != bitRead(last_input,pin)) {
ResponseTime_P(PSTR(",\"PCF8574%c%d_INP\":{\"D%i\":%i}}"), IndexSeparator(), idx +1, pin, bitRead(input,pin));
MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, PSTR("PCF8574_INP"));
if (Settings.flag3.hass_tele_on_power) { // SetOption59 - Send tele/%topic%/SENSOR in addition to stat/%topic%/RESULT
if (Settings->flag3.hass_tele_on_power) { // SetOption59 - Send tele/%topic%/SENSOR in addition to stat/%topic%/RESULT
MqttPublishSensor();
}
}
@ -275,10 +275,10 @@ void Pcf8574SaveSettings(void)
//AddLog(LOG_LEVEL_DEBUG, PSTR("PCF: Start working on Save arguements: inverted:%d")), Webserver->hasArg("b1");
Settings.flag3.pcf8574_ports_inverted = Webserver->hasArg("b1"); // SetOption81 - Invert all ports on PCF8574 devices
Settings->flag3.pcf8574_ports_inverted = Webserver->hasArg("b1"); // SetOption81 - Invert all ports on PCF8574 devices
for (byte idx = 0; idx < Pcf8574.max_devices; idx++) {
byte count=0;
byte n = Settings.pcf8574_config[idx];
byte n = Settings->pcf8574_config[idx];
while(n!=0) {
n = n&(n-1);
count++;
@ -291,15 +291,15 @@ void Pcf8574SaveSettings(void)
WebGetArg(stemp, tmp, sizeof(tmp));
byte _value = (!strlen(tmp)) ? 0 : atoi(tmp);
if (_value) {
Settings.pcf8574_config[idx] = Settings.pcf8574_config[idx] | 1 << i;
Settings->pcf8574_config[idx] = Settings->pcf8574_config[idx] | 1 << i;
TasmotaGlobal.devices_present++;
Pcf8574.max_connected_ports++;
} else {
Settings.pcf8574_config[idx] = Settings.pcf8574_config[idx] & ~(1 << i );
Settings->pcf8574_config[idx] = Settings->pcf8574_config[idx] & ~(1 << i );
}
}
//Settings.pcf8574_config[0] = (!strlen(webServer->arg("i2cs0").c_str())) ? 0 : atoi(webServer->arg("i2cs0").c_str());
//AddLog(LOG_LEVEL_INFO, PSTR("PCF: I2C Board: %d, Config: %2x")), idx, Settings.pcf8574_config[idx];
//Settings->pcf8574_config[0] = (!strlen(webServer->arg("i2cs0").c_str())) ? 0 : atoi(webServer->arg("i2cs0").c_str());
//AddLog(LOG_LEVEL_INFO, PSTR("PCF: I2C Board: %d, Config: %2x")), idx, Settings->pcf8574_config[idx];
}
}

View File

@ -49,8 +49,8 @@ uint8_t deepsleep_flag = 0;
bool DeepSleepEnabled(void)
{
if ((Settings.deepsleep < 10) || (Settings.deepsleep > DEEPSLEEP_MAX)) {
Settings.deepsleep = 0; // Issue #6961
if ((Settings->deepsleep < 10) || (Settings->deepsleep > DEEPSLEEP_MAX)) {
Settings->deepsleep = 0; // Issue #6961
return false; // Disabled
}
@ -95,7 +95,7 @@ void DeepSleepPrepare(void)
if ((RtcSettings.nextwakeup == 0) ||
(RtcSettings.deepsleep_slip < 9000) ||
(RtcSettings.deepsleep_slip > 11000) ||
(RtcSettings.nextwakeup > (UtcTime() + Settings.deepsleep))) {
(RtcSettings.nextwakeup > (UtcTime() + Settings->deepsleep))) {
AddLog(LOG_LEVEL_ERROR, PSTR("DSL: Reset wrong settings wakeup: %ld, slip %ld"), RtcSettings.nextwakeup, RtcSettings.deepsleep_slip );
RtcSettings.nextwakeup = 0;
RtcSettings.deepsleep_slip = 10000;
@ -107,19 +107,19 @@ void DeepSleepPrepare(void)
// Allow 10% of deepsleep error to count as valid deepsleep; expecting 3-4%
// if more then 10% timeslip = 0 == non valid wakeup; maybe manual
timeslip = (timeslip < -(int32_t)Settings.deepsleep) ? 0 : (timeslip > (int32_t)Settings.deepsleep) ? 0 : 1;
timeslip = (timeslip < -(int32_t)Settings->deepsleep) ? 0 : (timeslip > (int32_t)Settings->deepsleep) ? 0 : 1;
if (timeslip) {
RtcSettings.deepsleep_slip = (Settings.deepsleep + RtcSettings.nextwakeup - UtcTime()) * RtcSettings.deepsleep_slip / tmax((Settings.deepsleep - (millis() / 1000)),5);
RtcSettings.deepsleep_slip = (Settings->deepsleep + RtcSettings.nextwakeup - UtcTime()) * RtcSettings.deepsleep_slip / tmax((Settings->deepsleep - (millis() / 1000)),5);
// Avoid crazy numbers. Again maximum 10% deviation.
RtcSettings.deepsleep_slip = tmin(tmax(RtcSettings.deepsleep_slip, 9000), 11000);
RtcSettings.nextwakeup += Settings.deepsleep;
RtcSettings.nextwakeup += Settings->deepsleep;
}
// It may happen that wakeup in just <5 seconds in future
// In this case also add deepsleep to nextwakeup
if (RtcSettings.nextwakeup <= (UtcTime() - DEEPSLEEP_MIN_TIME)) {
// ensure nextwakeup is at least in the future
RtcSettings.nextwakeup += (((UtcTime() + DEEPSLEEP_MIN_TIME - RtcSettings.nextwakeup) / Settings.deepsleep) + 1) * Settings.deepsleep;
RtcSettings.nextwakeup += (((UtcTime() + DEEPSLEEP_MIN_TIME - RtcSettings.nextwakeup) / Settings->deepsleep) + 1) * Settings->deepsleep;
}
String dt = GetDT(RtcSettings.nextwakeup + LocalTime() - UtcTime()); // 2017-03-07T11:08:02
@ -179,16 +179,16 @@ void CmndDeepsleepTime(void)
{
if ((0 == XdrvMailbox.payload) ||
((XdrvMailbox.payload > 10) && (XdrvMailbox.payload < DEEPSLEEP_MAX))) {
Settings.deepsleep = XdrvMailbox.payload;
Settings->deepsleep = XdrvMailbox.payload;
RtcSettings.nextwakeup = 0;
deepsleep_flag = (0 == XdrvMailbox.payload) ? 0 : DEEPSLEEP_START_COUNTDOWN;
if (deepsleep_flag) {
if (!Settings.tele_period) {
Settings.tele_period = TELE_PERIOD; // Need teleperiod to go back to sleep
if (!Settings->tele_period) {
Settings->tele_period = TELE_PERIOD; // Need teleperiod to go back to sleep
}
}
}
ResponseCmndNumber(Settings.deepsleep);
ResponseCmndNumber(Settings->deepsleep);
}
/*********************************************************************************************\
@ -204,7 +204,7 @@ bool Xdrv29(uint8_t function)
DeepSleepEverySecond();
break;
case FUNC_AFTER_TELEPERIOD:
if (DeepSleepEnabled() && !deepsleep_flag && (Settings.tele_period == 10 || Settings.tele_period == 300 || UpTime() > Settings.tele_period)) {
if (DeepSleepEnabled() && !deepsleep_flag && (Settings->tele_period == 10 || Settings->tele_period == 300 || UpTime() > Settings->tele_period)) {
deepsleep_flag = DEEPSLEEP_START_COUNTDOWN; // Start deepsleep in 4 seconds
}
break;

View File

@ -350,9 +350,9 @@ void ExsPacketProcess(void)
*/
bool ExsModuleSelected(void)
{
Settings.light_correction = 0;
Settings.flag.mqtt_serial = 0; // CMND_SERIALSEND and CMND_SERIALLOG
Settings.flag3.pwm_multi_channels = 1; // SetOption68 - Enable multi-channels PWM instead of Color PWM
Settings->light_correction = 0;
Settings->flag.mqtt_serial = 0; // CMND_SERIALSEND and CMND_SERIALLOG
Settings->flag3.pwm_multi_channels = 1; // SetOption68 - Enable multi-channels PWM instead of Color PWM
SetSeriallog(LOG_LEVEL_NONE);
TasmotaGlobal.devices_present = +2;

View File

@ -419,12 +419,12 @@ void TasmotaClient_Init(void) {
uint8_t len = TasmotaClient_receiveData(buffer, sizeof(buffer)); // 99 17 34 01 02 00 00 00
if (len == sizeof(TClientSettings)) {
memcpy(&TClientSettings, &buffer, sizeof(TClientSettings));
if (TASMOTA_CLIENT_LIB_VERSION == TClientSettings.features_version) {
if (TASMOTA_CLIENT_LIB_VERSION == TClientSettings->features_version) {
TClient.type = true;
AddLog(LOG_LEVEL_INFO, PSTR("TCL: Version %u"), TClientSettings.features_version);
AddLog(LOG_LEVEL_INFO, PSTR("TCL: Version %u"), TClientSettings->features_version);
} else {
if ((!TClient.unsupported) && (TClientSettings.features_version > 0)) {
AddLog(LOG_LEVEL_INFO, PSTR("TCL: Version %u not supported!"), TClientSettings.features_version);
if ((!TClient.unsupported) && (TClientSettings->features_version > 0)) {
AddLog(LOG_LEVEL_INFO, PSTR("TCL: Version %u not supported!"), TClientSettings->features_version);
TClient.unsupported = true;
}
}
@ -437,7 +437,7 @@ bool TasmotaClient_Available(void) {
}
void TasmotaClient_Show(void) {
if ((TClient.type) && (TClientSettings.features.func_json_append)) {
if ((TClient.type) && (TClientSettings->features.func_json_append)) {
TasmotaClient_sendCmnd(CMND_JSON, 0);
char buffer[100];
@ -540,19 +540,19 @@ bool Xdrv31(uint8_t function) {
if (TasmotaClient_Serial->available()) {
TasmotaClient_ProcessIn();
}
if (TClientSettings.features.func_every_100_msecond) {
if (TClientSettings->features.func_every_100_msecond) {
TasmotaClient_sendCmnd(CMND_FUNC_EVERY_100_MSECOND, 0);
}
}
break;
case FUNC_EVERY_SECOND:
if ((TClient.type) && (TClientSettings.features.func_every_second)) {
if ((TClient.type) && (TClientSettings->features.func_every_second)) {
TasmotaClient_sendCmnd(CMND_FUNC_EVERY_SECOND, 0);
}
TasmotaClient_Init();
break;
case FUNC_JSON_APPEND:
if ((TClient.type) && (TClientSettings.features.func_json_append)) {
if ((TClient.type) && (TClientSettings->features.func_json_append)) {
TasmotaClient_Show();
}
break;

View File

@ -44,8 +44,8 @@ struct {
void HotPlugInit(void)
{
// If empty eeprom is 0xFF by default
if (Settings.hotplug_scan == 0xFF) { Settings.hotplug_scan = 0; }
if (Settings.hotplug_scan != 0) {
if (Settings->hotplug_scan == 0xFF) { Settings->hotplug_scan = 0; }
if (Settings->hotplug_scan != 0) {
Hotplug.enabled = true;
Hotplug.timeout = 1; // First scan in a second
} else
@ -57,7 +57,7 @@ void HotPlugEverySecond(void)
if (Hotplug.enabled) {
if (Hotplug.timeout == 0) {
XsnsCall(FUNC_HOTPLUG_SCAN);
Hotplug.timeout = Settings.hotplug_scan;
Hotplug.timeout = Settings->hotplug_scan;
}
Hotplug.timeout--;
}
@ -70,10 +70,10 @@ void HotPlugEverySecond(void)
void CmndHotPlugTime(void)
{
if (XdrvMailbox.payload <= HOTPLUG_MAX) {
Settings.hotplug_scan = XdrvMailbox.payload;
Settings->hotplug_scan = XdrvMailbox.payload;
HotPlugInit();
}
ResponseCmndNumber(Settings.hotplug_scan);
ResponseCmndNumber(Settings->hotplug_scan);
}
/*********************************************************************************************\

View File

@ -84,26 +84,26 @@ struct remote_pwm_dimmer * active_remote_pwm_dimmer;
void PWMModulePreInit(void)
{
Settings.seriallog_level = 0;
Settings.flag.mqtt_serial = 0; // Disable serial logging
Settings.ledstate = 0; // Disable LED usage
Settings->seriallog_level = 0;
Settings->flag.mqtt_serial = 0; // Disable serial logging
Settings->ledstate = 0; // Disable LED usage
// If the module was just changed to PWM Dimmer, set the defaults.
if (TasmotaGlobal.module_changed) {
Settings.flag.pwm_control = true; // SetOption15 - Switch between commands PWM or COLOR/DIMMER/CT/CHANNEL
Settings.bri_power_on = Settings.bri_preset_low = Settings.bri_preset_high = 0;
Settings->flag.pwm_control = true; // SetOption15 - Switch between commands PWM or COLOR/DIMMER/CT/CHANNEL
Settings->bri_power_on = Settings->bri_preset_low = Settings->bri_preset_high = 0;
}
// Previous versions of PWM Dimmer used SetOption32 - Button held for factor times longer as the
// hold time. The hold time is now fixed and SetOption32 is used as normal including to
// determine how long a button is held before a reset command is executed. If SetOption32 is
// still 5, change it to 40 (the default).
if (Settings.param[P_HOLD_TIME] == 5) Settings.param[P_HOLD_TIME] = 40;
if (Settings->param[P_HOLD_TIME] == 5) Settings->param[P_HOLD_TIME] = 40;
// Make sure the brightness level settings are sensible.
if (!Settings.bri_power_on) Settings.bri_power_on = 128;
if (!Settings.bri_preset_low) Settings.bri_preset_low = 10;
if (Settings.bri_preset_high < Settings.bri_preset_low) Settings.bri_preset_high = 255;
if (!Settings->bri_power_on) Settings->bri_power_on = 128;
if (!Settings->bri_preset_low) Settings->bri_preset_low = 10;
if (Settings->bri_preset_high < Settings->bri_preset_low) Settings->bri_preset_high = 255;
PWMDimmerSetPoweredOffLed();
@ -113,8 +113,8 @@ void PWMModulePreInit(void)
#ifdef USE_PWM_DIMMER_REMOTE
// If remote device mode is enabled, set the device group count to the number of buttons
// present.
if (Settings.flag4.multiple_device_groups) {
Settings.flag4.device_groups_enabled = true;
if (Settings->flag4.multiple_device_groups) {
Settings->flag4.device_groups_enabled = true;
device_group_count = 0;
for (uint32_t button_index = 0; button_index < MAX_PWM_DIMMER_KEYS; button_index++) {
@ -149,7 +149,7 @@ void PWMDimmerSetBrightnessLeds(int32_t bri)
uint32_t mask = 1;
int32_t led;
for (led = 0; led < TasmotaGlobal.leds_present; led++) {
if (Settings.ledmask & mask) leds++;
if (Settings->ledmask & mask) leds++;
mask <<= 1;
}
@ -158,8 +158,8 @@ void PWMDimmerSetBrightnessLeds(int32_t bri)
if (leds) {
led_timeout_seconds = 5;
if (bri < 0) {
bri = ((bri == -2 && Settings.flag4.led_timeout) || !Light.power ? 0 : light_state.getBri());
if (!bri || !Settings.flag4.led_timeout) led_timeout_seconds = 0;
bri = ((bri == -2 && Settings->flag4.led_timeout) || !Light.power ? 0 : light_state.getBri());
if (!bri || !Settings->flag4.led_timeout) led_timeout_seconds = 0;
}
uint32_t step = 256 / (leds + 1);
@ -174,10 +174,10 @@ void PWMDimmerSetBrightnessLeds(int32_t bri)
led++;
mask <<= 1;
if (!mask) mask = 1;
if (Settings.ledmask & mask) break;
if (Settings->ledmask & mask) break;
}
pwm_led_bri = changeUIntScale((bri > level ? bri - level : 0), 0, step, 0, Settings.pwm_range);
analogWrite(Pin(GPIO_LED1, led), bitRead(TasmotaGlobal.led_inverted, led) ? Settings.pwm_range - pwm_led_bri : pwm_led_bri);
pwm_led_bri = changeUIntScale((bri > level ? bri - level : 0), 0, step, 0, Settings->pwm_range);
analogWrite(Pin(GPIO_LED1, led), bitRead(TasmotaGlobal.led_inverted, led) ? Settings->pwm_range - pwm_led_bri : pwm_led_bri);
}
}
}
@ -186,7 +186,7 @@ void PWMDimmerSetPoweredOffLed(void)
{
// Set the powered-off LED state.
if (PinUsed(GPIO_LEDLNK)) {
bool power_off_led_on = !TasmotaGlobal.power && Settings.flag4.powered_off_led;
bool power_off_led_on = !TasmotaGlobal.power && Settings->flag4.powered_off_led;
if (TasmotaGlobal.ledlnk_inverted) power_off_led_on ^= 1;
digitalWrite(Pin(GPIO_LEDLNK), power_off_led_on);
}
@ -233,28 +233,28 @@ void PWMDimmerHandleDevGroupItem(void)
remote_pwm_dimmer->bri_power_on = value;
if (is_local)
#endif // USE_PWM_DIMMER_REMOTE
Settings.bri_power_on = value;
Settings->bri_power_on = value;
break;
case DGR_ITEM_BRI_PRESET_LOW:
#ifdef USE_PWM_DIMMER_REMOTE
remote_pwm_dimmer->bri_preset_low = value;
if (is_local)
#endif // USE_PWM_DIMMER_REMOTE
Settings.bri_preset_low = value;
Settings->bri_preset_low = value;
break;
case DGR_ITEM_BRI_PRESET_HIGH:
#ifdef USE_PWM_DIMMER_REMOTE
remote_pwm_dimmer->bri_preset_high = value;
if (is_local)
#endif // USE_PWM_DIMMER_REMOTE
Settings.bri_preset_high = value;
Settings->bri_preset_high = value;
break;
case DGR_ITEM_STATUS:
#ifdef USE_PWM_DIMMER_REMOTE
if (is_local)
#endif // USE_PWM_DIMMER_REMOTE
SendDeviceGroupMessage(0, DGR_MSGTYP_UPDATE, DGR_ITEM_BRI_POWER_ON, Settings.bri_power_on,
DGR_ITEM_BRI_PRESET_LOW, Settings.bri_preset_low, DGR_ITEM_BRI_PRESET_HIGH, Settings.bri_preset_high);
SendDeviceGroupMessage(0, DGR_MSGTYP_UPDATE, DGR_ITEM_BRI_POWER_ON, Settings->bri_power_on,
DGR_ITEM_BRI_PRESET_LOW, Settings->bri_preset_low, DGR_ITEM_BRI_PRESET_HIGH, Settings->bri_preset_high);
#ifdef USE_PWM_DIMMER_REMOTE
else
SendDeviceGroupMessage(-device_group_index, DGR_MSGTYP_UPDATE, DGR_ITEM_POWER, remote_pwm_dimmer->power_on,
@ -328,7 +328,7 @@ void PWMDimmerHandleButton(uint32_t button_index, bool pressed)
power_on_bri = active_remote_pwm_dimmer->bri = active_remote_pwm_dimmer->bri_preset_low;
else
#endif // USE_PWM_DIMMER_REMOTE
power_on_bri = Settings.bri_preset_low;
power_on_bri = Settings->bri_preset_low;
button_hold_time[button_index] = now + 500;
}
}
@ -349,7 +349,7 @@ void PWMDimmerHandleButton(uint32_t button_index, bool pressed)
// Otherwise, if the power is on and remote mode is enabled, adjust the brightness. Set the
// direction based on which button is pressed. The new brightness will be calculated below.
else if (power_is_on && Settings.flag4.multiple_device_groups) {
else if (power_is_on && Settings->flag4.multiple_device_groups) {
bri_offset = (is_down_button ? -1 : 1);
}
@ -387,13 +387,13 @@ void PWMDimmerHandleButton(uint32_t button_index, bool pressed)
// Toggle the powered-off LED option.
if (down_button_tapped) {
Settings.flag4.led_timeout ^= 1;
if (Light.power) PWMDimmerSetBrightnessLeds(Settings.flag4.led_timeout ? 0 : -1);
Settings->flag4.led_timeout ^= 1;
if (Light.power) PWMDimmerSetBrightnessLeds(Settings->flag4.led_timeout ? 0 : -1);
}
// Toggle the LED timeout.
else {
Settings.flag4.powered_off_led ^= 1;
Settings->flag4.powered_off_led ^= 1;
PWMDimmerSetPoweredOffLed();
}
#ifdef USE_PWM_DIMMER_REMOTE
@ -431,7 +431,7 @@ void PWMDimmerHandleButton(uint32_t button_index, bool pressed)
power_on_bri = active_remote_pwm_dimmer->bri_power_on;
else
#endif // USE_PWM_DIMMER_REMOTE
power_on_bri = Settings.bri_power_on;
power_on_bri = Settings->bri_power_on;
}
}
@ -485,7 +485,7 @@ void PWMDimmerHandleButton(uint32_t button_index, bool pressed)
power_on_bri = active_remote_pwm_dimmer->bri = (is_down_button ? active_remote_pwm_dimmer->bri_preset_low : active_remote_pwm_dimmer->bri_preset_high);
else
#endif // USE_PWM_DIMMER_REMOTE
power_on_bri = (is_down_button ? Settings.bri_preset_low : Settings.bri_preset_high);
power_on_bri = (is_down_button ? Settings->bri_preset_low : Settings->bri_preset_high);
}
}
}
@ -501,7 +501,7 @@ void PWMDimmerHandleButton(uint32_t button_index, bool pressed)
else
#endif // USE_PWM_DIMMER_REMOTE
bri = light_state.getBri();
int32_t new_bri = bri + bri_offset * (Settings.light_correction ? 4 : bri / 16 + 1);
int32_t new_bri = bri + bri_offset * (Settings->light_correction ? 4 : bri / 16 + 1);
if (bri_offset > 0) {
if (new_bri > 255) new_bri = 255;
@ -525,13 +525,13 @@ void PWMDimmerHandleButton(uint32_t button_index, bool pressed)
ignore_dgr_sends = true;
#endif // USE_DEVICE_GROUPS
light_state.setBri(new_bri);
Settings.light_dimmer = light_state.BriToDimmer(new_bri);
Settings->light_dimmer = light_state.BriToDimmer(new_bri);
LightAnimate();
TasmotaGlobal.skip_light_fade = false;
#ifdef USE_DEVICE_GROUPS
ignore_dgr_sends = false;
#endif // USE_DEVICE_GROUPS
Settings.bri_power_on = new_bri;
Settings->bri_power_on = new_bri;
#ifdef USE_PWM_DIMMER_REMOTE
}
#endif // USE_PWM_DIMMER_REMOTE
@ -571,7 +571,7 @@ void PWMDimmerHandleButton(uint32_t button_index, bool pressed)
else {
#endif // USE_PWM_DIMMER_REMOTE
light_state.setBri(power_on_bri);
Settings.light_dimmer = light_state.BriToDimmer(power_on_bri);
Settings->light_dimmer = light_state.BriToDimmer(power_on_bri);
#ifdef USE_DEVICE_GROUPS
Light.devgrp_no_channels_out = true;
#endif // USE_DEVICE_GROUPS
@ -622,7 +622,7 @@ void PWMDimmerHandleButton(uint32_t button_index, bool pressed)
char topic[TOPSZ];
Response_P(PSTR("Trigger%u"), mqtt_trigger);
#ifdef USE_DEVICE_GROUPS
if (Settings.flag4.device_groups_enabled) {
if (Settings->flag4.device_groups_enabled) {
snprintf_P(topic, sizeof(topic), PSTR("cmnd/%s/EVENT"), device_groups[power_button_index].group_name);
MqttPublish(topic);
}
@ -649,7 +649,7 @@ void PWMDimmerHandleButton(uint32_t button_index, bool pressed)
light_controller.saveSettings();
}
if (state_updated && Settings.flag3.hass_tele_on_power) { // SetOption59 - Send tele/%topic%/STATE in addition to stat/%topic%/RESULT
if (state_updated && Settings->flag3.hass_tele_on_power) { // SetOption59 - Send tele/%topic%/STATE in addition to stat/%topic%/RESULT
#ifdef USE_PWM_DIMMER_REMOTE
if (!active_remote_pwm_dimmer)
#endif // USE_PWM_DIMMER_REMOTE
@ -667,8 +667,8 @@ void CmndBriPreset(void)
bool valid = true;
uint32_t value;
uint8_t parm[2];
parm[0] = Settings.bri_preset_low;
parm[1] = Settings.bri_preset_high;
parm[0] = Settings->bri_preset_low;
parm[1] = Settings->bri_preset_high;
char * ptr = XdrvMailbox.data;
for (uint32_t i = 0; i < 2; i++) {
while (*ptr == ' ') ptr++;
@ -691,29 +691,29 @@ void CmndBriPreset(void)
}
if (valid && !*ptr) {
if (parm[0] < parm[1]) {
Settings.bri_preset_low = parm[0];
Settings.bri_preset_high = parm[1];
Settings->bri_preset_low = parm[0];
Settings->bri_preset_high = parm[1];
} else
{
Settings.bri_preset_low = parm[1];
Settings.bri_preset_high = parm[0];
Settings->bri_preset_low = parm[1];
Settings->bri_preset_high = parm[0];
}
#ifdef USE_DEVICE_GROUPS
SendDeviceGroupMessage(0, DGR_MSGTYP_UPDATE, DGR_ITEM_BRI_PRESET_LOW, Settings.bri_preset_low, DGR_ITEM_BRI_PRESET_HIGH, Settings.bri_preset_high);
SendDeviceGroupMessage(0, DGR_MSGTYP_UPDATE, DGR_ITEM_BRI_PRESET_LOW, Settings->bri_preset_low, DGR_ITEM_BRI_PRESET_HIGH, Settings->bri_preset_high);
#endif // USE_DEVICE_GROUPS
}
}
Response_P(PSTR("{\"" D_CMND_BRI_PRESET "\":{\"Low\":%d,\"High\":%d}}"), Settings.bri_preset_low, Settings.bri_preset_high);
Response_P(PSTR("{\"" D_CMND_BRI_PRESET "\":{\"Low\":%d,\"High\":%d}}"), Settings->bri_preset_low, Settings->bri_preset_high);
}
#ifdef USE_DEVICE_GROUPS
void CmndPWMDimmerPWMs(void)
{
if (XdrvMailbox.data_len > 0 && XdrvMailbox.payload <= 5) {
Settings.pwm_dimmer_cfg.pwm_count = XdrvMailbox.payload - 1;
Settings->pwm_dimmer_cfg.pwm_count = XdrvMailbox.payload - 1;
TasmotaGlobal.restart_flag = 2;
}
Response_P(PSTR("{\"" D_CMND_PWM_DIMMER_PWMS "\":%u}"), Settings.pwm_dimmer_cfg.pwm_count + 1);
Response_P(PSTR("{\"" D_CMND_PWM_DIMMER_PWMS "\":%u}"), Settings->pwm_dimmer_cfg.pwm_count + 1);
}
#endif // USE_DEVICE_GROUPS
@ -772,7 +772,7 @@ bool Xdrv35(uint8_t function)
// Top 0 1 1 0
// Middle 1 2 15 0
// Bottom 15 3 15 1
if (!buttons_pressed && Settings.flag4.multiple_device_groups) {
if (!buttons_pressed && Settings->flag4.multiple_device_groups) {
power_button_index = button_index;
down_button_index = (Pin(GPIO_KEY1, power_button_index) == 15 ? TasmotaGlobal.gpio_pin[1] : TasmotaGlobal.gpio_pin[15]) - 32;
active_remote_pwm_dimmer = nullptr;
@ -786,7 +786,7 @@ bool Xdrv35(uint8_t function)
buttons_pressed++;
if (buttons_pressed > 1) multibutton_in_progress = true;
uint32_t hold_delay = 250;
if (button_index == power_button_index) hold_delay = Settings.param[P_HOLD_TIME] * 10;
if (button_index == power_button_index) hold_delay = Settings->param[P_HOLD_TIME] * 10;
button_hold_time[button_index] = now + hold_delay;
}

View File

@ -73,10 +73,10 @@ void CmdSet(void)
if (param[i] < 1) { param[i] = 1; } // msb, lsb, serial, counter
}
DEBUG_DRIVER_LOG(LOG_LEVEL_DEBUG_MORE, PSTR("params: %08x %08x %08x %08x"), param[0], param[1], param[2], param[3]);
Settings.keeloq_master_msb = param[0];
Settings.keeloq_master_lsb = param[1];
Settings.keeloq_serial = param[2];
Settings.keeloq_count = param[3];
Settings->keeloq_master_msb = param[0];
Settings->keeloq_master_lsb = param[1];
Settings->keeloq_serial = param[2];
Settings->keeloq_count = param[3];
jaroliftDevice.serial = param[2];
jaroliftDevice.count = param[3];
@ -93,7 +93,7 @@ void CmdSet(void)
void GenerateDeviceCryptKey()
{
Keeloq k(Settings.keeloq_master_msb, Settings.keeloq_master_lsb);
Keeloq k(Settings->keeloq_master_msb, Settings->keeloq_master_lsb);
jaroliftDevice.device_key_msb = k.decrypt(jaroliftDevice.serial | 0x60000000L);
jaroliftDevice.device_key_lsb = k.decrypt(jaroliftDevice.serial | 0x20000000L);
@ -118,7 +118,7 @@ void CmdSendButton(void)
CreateKeeloqPacket();
jaroliftDevice.count++;
Settings.keeloq_count = jaroliftDevice.count;
Settings->keeloq_count = jaroliftDevice.count;
for(int repeat = 0; repeat <= 1; repeat++)
{
@ -256,8 +256,8 @@ void KeeloqInit()
pinMode(jaroliftDevice.port_tx, OUTPUT);
pinMode(jaroliftDevice.port_rx, INPUT_PULLUP);
jaroliftDevice.serial = Settings.keeloq_serial;
jaroliftDevice.count = Settings.keeloq_count;
jaroliftDevice.serial = Settings->keeloq_serial;
jaroliftDevice.count = Settings->keeloq_count;
GenerateDeviceCryptKey();
}

View File

@ -147,8 +147,8 @@ bool SonoffD1SendPower(void)
bool SonoffD1SendDimmer(void)
{
uint8_t dimmer = LightGetDimmer(1);
dimmer = (dimmer < Settings.dimmer_hw_min) ? Settings.dimmer_hw_min : dimmer;
dimmer = (dimmer > Settings.dimmer_hw_max) ? Settings.dimmer_hw_max : dimmer;
dimmer = (dimmer < Settings->dimmer_hw_min) ? Settings->dimmer_hw_min : dimmer;
dimmer = (dimmer > Settings->dimmer_hw_max) ? Settings->dimmer_hw_max : dimmer;
if (dimmer != SnfD1.dimmer) {
SnfD1.dimmer = dimmer;

View File

@ -318,7 +318,7 @@ String TelegramExecuteCommand(const char *svalue) {
}
void TelegramLoop(void) {
if (!TasmotaGlobal.global_state.network_down && (Settings.sbflag1.telegram_recv_enable || Settings.sbflag1.telegram_echo_enable)) {
if (!TasmotaGlobal.global_state.network_down && (Settings->sbflag1.telegram_recv_enable || Settings->sbflag1.telegram_echo_enable)) {
switch (Telegram.state) {
case 0:
TelegramInit();
@ -331,7 +331,7 @@ void TelegramLoop(void) {
Telegram.state++;
break;
case 2:
if (Settings.sbflag1.telegram_echo_enable) {
if (Settings->sbflag1.telegram_echo_enable) {
if (Telegram.retry && (Telegram.index < Telegram.message_count)) {
if (TelegramSendMessage(Telegram.message[Telegram.index].chat_id, Telegram.message[Telegram.index].text)) {
Telegram.index++;
@ -392,24 +392,24 @@ void CmndTmState(void) {
switch (XdrvMailbox.payload) {
case 0: // Off
case 1: // On
Settings.sbflag1.telegram_send_enable = XdrvMailbox.payload &1;
Settings->sbflag1.telegram_send_enable = XdrvMailbox.payload &1;
break;
case 2: // Off
case 3: // On
Settings.sbflag1.telegram_recv_enable = XdrvMailbox.payload &1;
Settings->sbflag1.telegram_recv_enable = XdrvMailbox.payload &1;
break;
case 4: // Off
case 5: // On
Settings.sbflag1.telegram_echo_enable = XdrvMailbox.payload &1;
Settings->sbflag1.telegram_echo_enable = XdrvMailbox.payload &1;
break;
}
}
}
Response_P(PSTR("{\"%s\":{\"Send\":\"%s\",\"Receive\":\"%s\",\"Echo\":\"%s\"}}"),
XdrvMailbox.command,
GetStateText(Settings.sbflag1.telegram_send_enable),
GetStateText(Settings.sbflag1.telegram_recv_enable),
GetStateText(Settings.sbflag1.telegram_echo_enable));
GetStateText(Settings->sbflag1.telegram_send_enable),
GetStateText(Settings->sbflag1.telegram_recv_enable),
GetStateText(Settings->sbflag1.telegram_echo_enable));
}
void CmndTmPoll(void) {
@ -437,7 +437,7 @@ void CmndTmChatId(void) {
}
void CmndTmSend(void) {
if (!Settings.sbflag1.telegram_send_enable || !strlen(SettingsText(SET_TELEGRAM_CHATID))) {
if (!Settings->sbflag1.telegram_send_enable || !strlen(SettingsText(SET_TELEGRAM_CHATID))) {
ResponseCmndFailed();
return;
}

View File

@ -125,9 +125,9 @@ void TCPInit(void) {
tcp_buf = (uint8_t*) malloc(TCP_BRIDGE_BUF_SIZE);
if (!tcp_buf) { AddLog(LOG_LEVEL_ERROR, PSTR(D_LOG_TCP "could not allocate buffer")); return; }
if (!Settings.tcp_baudrate) { Settings.tcp_baudrate = 115200 / 1200; }
if (!Settings->tcp_baudrate) { Settings->tcp_baudrate = 115200 / 1200; }
TCPSerial = new TasmotaSerial(Pin(GPIO_TCP_RX), Pin(GPIO_TCP_TX), TasmotaGlobal.seriallog_level ? 1 : 2, 0, TCP_BRIDGE_BUF_SIZE); // set a receive buffer of 256 bytes
TCPSerial->begin(Settings.tcp_baudrate * 1200);
TCPSerial->begin(Settings->tcp_baudrate * 1200);
if (TCPSerial->hardwareSerial()) {
ClaimSerial();
}
@ -170,10 +170,10 @@ void CmndTCPStart(void) {
void CmndTCPBaudrate(void) {
if ((XdrvMailbox.payload >= 1200) && (XdrvMailbox.payload <= 115200)) {
XdrvMailbox.payload /= 1200; // Make it a valid baudrate
Settings.tcp_baudrate = XdrvMailbox.payload;
TCPSerial->begin(Settings.tcp_baudrate * 1200); // Reinitialize serial port with new baud rate
Settings->tcp_baudrate = XdrvMailbox.payload;
TCPSerial->begin(Settings->tcp_baudrate * 1200); // Reinitialize serial port with new baud rate
}
ResponseCmndNumber(Settings.tcp_baudrate * 1200);
ResponseCmndNumber(Settings->tcp_baudrate * 1200);
}
/*********************************************************************************************\

View File

@ -573,12 +573,12 @@ void MLX90640every100msec(){
void MLX90640Show(uint8_t json)
{
char amb_tstr[FLOATSZ];
dtostrfd(MLX90640.Ta, Settings.flag2.temperature_resolution, amb_tstr);
dtostrfd(MLX90640.Ta, Settings->flag2.temperature_resolution, amb_tstr);
if (json) {
ResponseAppend_P(PSTR(",\"MLX90640\":{\"" D_JSON_TEMPERATURE "\":[%s"), amb_tstr);
for(int i = 0;i<MLX90640_POI_NUM;i++){
char obj_tstr[FLOATSZ];
dtostrfd(MLX90640.To[MLX90640.pois[i*2]+(MLX90640.pois[(i*2)+1]*32)], Settings.flag2.temperature_resolution, obj_tstr);
dtostrfd(MLX90640.To[MLX90640.pois[i*2]+(MLX90640.pois[(i*2)+1]*32)], Settings->flag2.temperature_resolution, obj_tstr);
ResponseAppend_P(PSTR(",%s"),obj_tstr);
// AddLog(LOG_LEVEL_DEBUG, PSTR("Array pos: %u"),MLX90640.pois[i*2]+(MLX90640.pois[(i*2)+1]*32));
AddLog(LOG_LEVEL_DEBUG, PSTR("POI-%u: x: %u, y: %u"),i+1,MLX90640.pois[i*2],MLX90640.pois[(i*2)+1]);

View File

@ -103,12 +103,12 @@ struct miel_hvac_data {
CTASSERT(sizeof(struct miel_hvac_data) == 16);
CTASSERT(offsetof(struct miel_hvac_data, data.settings.power) == 3);
CTASSERT(offsetof(struct miel_hvac_data, data.settings.mode) == 4);
CTASSERT(offsetof(struct miel_hvac_data, data.settings.temp) == 5);
CTASSERT(offsetof(struct miel_hvac_data, data.settings.fan) == 6);
CTASSERT(offsetof(struct miel_hvac_data, data.settings.vane) == 7);
CTASSERT(offsetof(struct miel_hvac_data, data.settings.widevane) == 10);
CTASSERT(offsetof(struct miel_hvac_data, data.Settings->power) == 3);
CTASSERT(offsetof(struct miel_hvac_data, data.Settings->mode) == 4);
CTASSERT(offsetof(struct miel_hvac_data, data.Settings->temp) == 5);
CTASSERT(offsetof(struct miel_hvac_data, data.Settings->fan) == 6);
CTASSERT(offsetof(struct miel_hvac_data, data.Settings->vane) == 7);
CTASSERT(offsetof(struct miel_hvac_data, data.Settings->widevane) == 10);
CTASSERT(offsetof(struct miel_hvac_data, data.roomtemp.temp) == 3);
@ -854,7 +854,7 @@ static void
miel_hvac_publish_settings(struct miel_hvac_softc *sc)
{
const struct miel_hvac_data_settings *set =
&sc->sc_settings.data.settings;
&sc->sc_Settings->data.settings;
char hex[(sizeof(sc->sc_settings) + 1) * 2];
char temp[33];
const char *name;
@ -873,7 +873,7 @@ miel_hvac_publish_settings(struct miel_hvac_softc *sc)
}
dtostrfd(ConvertTemp(miel_hvac_temp2deg(set->temp)),
Settings.flag2.temperature_resolution, temp);
Settings->flag2.temperature_resolution, temp);
ResponseAppend_P(PSTR(",\"" D_JSON_IRHVAC_TEMP "\":%s"), temp);
name = miel_hvac_map_byval(set->fan,
@ -1078,7 +1078,7 @@ miel_hvac_sensor(struct miel_hvac_softc *sc)
char room_temp[33];
dtostrfd(ConvertTemp(temp),
Settings.flag2.temperature_resolution, room_temp);
Settings->flag2.temperature_resolution, room_temp);
ResponseAppend_P(PSTR("\"" D_JSON_TEMPERATURE "\":%s"),
room_temp);

View File

@ -429,7 +429,7 @@ bool ShdSyncState()
#ifdef SHELLY_DIMMER_DEBUG
AddLog(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME "Serial %p"), ShdSerial);
AddLog(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME "Set Brightness Want %d, Is %d"), Shd.req_brightness, Shd.dimmer.brightness);
AddLog(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME "Set Fade Want %d, Is %d"), Settings.light_speed, Shd.dimmer.fade_rate);
AddLog(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME "Set Fade Want %d, Is %d"), Settings->light_speed, Shd.dimmer.fade_rate);
#endif // SHELLY_DIMMER_DEBUG
if (!ShdSerial)
@ -438,7 +438,7 @@ bool ShdSyncState()
#ifdef SHELLY_HW_DIMMING
// TODO(jamesturton): HW dimming seems to conflict with SW dimming. See how
// we can disbale SW dimming when using HW dimming.
if (Settings.light_speed != Shd.dimmer.fade_rate)
if (Settings->light_speed != Shd.dimmer.fade_rate)
{
ShdSetBrightnessFade();
ShdDebugState();
@ -758,7 +758,7 @@ bool ShdSetChannels(void)
uint16_t brightness = ((uint32_t *)XdrvMailbox.data)[0];
// Use dimmer_hw_min and dimmer_hw_max to constrain our values if the light should be on
if (brightness > 0)
brightness = changeUIntScale(brightness, 0, 255, Settings.dimmer_hw_min * 10, Settings.dimmer_hw_max * 10);
brightness = changeUIntScale(brightness, 0, 255, Settings->dimmer_hw_min * 10, Settings->dimmer_hw_max * 10);
Shd.req_brightness = brightness;
ShdDebugState();
@ -793,7 +793,7 @@ void CmndShdLeadingEdge(void)
if (XdrvMailbox.payload == 0 || XdrvMailbox.payload == 1)
{
Shd.leading_edge = 2 - XdrvMailbox.payload;
Settings.shd_leading_edge = XdrvMailbox.payload;
Settings->shd_leading_edge = XdrvMailbox.payload;
#ifdef SHELLY_DIMMER_DEBUG
if (Shd.leading_edge == 1)
AddLog(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME "Set to trailing edge"));
@ -803,7 +803,7 @@ void CmndShdLeadingEdge(void)
ShdSendSettings();
}
ShdSaveSettings();
ResponseCmndNumber(Settings.shd_leading_edge);
ResponseCmndNumber(Settings->shd_leading_edge);
}
void CmndShdWarmupBrightness(void)
@ -811,14 +811,14 @@ void CmndShdWarmupBrightness(void)
if ((10 <= XdrvMailbox.payload) && (XdrvMailbox.payload <= 100))
{
Shd.warmup_brightness = XdrvMailbox.payload * 10;
Settings.shd_warmup_brightness = XdrvMailbox.payload;
Settings->shd_warmup_brightness = XdrvMailbox.payload;
#ifdef SHELLY_DIMMER_DEBUG
AddLog(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME "Set warmup brightness to %d%%"), XdrvMailbox.payload);
#endif // SHELLY_DIMMER_DEBUG
ShdSendSettings();
}
ShdSaveSettings();
ResponseCmndNumber(Settings.shd_warmup_brightness);
ResponseCmndNumber(Settings->shd_warmup_brightness);
}
void CmndShdWarmupTime(void)
@ -826,14 +826,14 @@ void CmndShdWarmupTime(void)
if ((20 <= XdrvMailbox.payload) && (XdrvMailbox.payload <= 200))
{
Shd.warmup_time = XdrvMailbox.payload;
Settings.shd_warmup_time = XdrvMailbox.payload;
Settings->shd_warmup_time = XdrvMailbox.payload;
#ifdef SHELLY_DIMMER_DEBUG
AddLog(LOG_LEVEL_DEBUG, PSTR(SHD_LOGNAME "Set warmup time to %dms"), XdrvMailbox.payload);
#endif // SHELLY_DIMMER_DEBUG
ShdSendSettings();
}
ShdSaveSettings();
ResponseCmndNumber(Settings.shd_warmup_time);
ResponseCmndNumber(Settings->shd_warmup_time);
}
#endif // SHELLY_CMDS

View File

@ -41,7 +41,7 @@ extern "C" {
map_insert_float(vm, "total", Energy.total);
// Energy.phase_count
map_insert_float(vm, "power", Energy.active_power[0]);
map_insert_float(vm, "yesterday", (float)Settings.energy_kWhyesterday / 100000);
map_insert_float(vm, "yesterday", (float)Settings->energy_kWhyesterday / 100000);
map_insert_float(vm, "today", Energy.daily);
map_insert_float(vm, "activepower", Energy.active_power[0]);
map_insert_float(vm, "apparentpower", Energy.active_power[0]);

View File

@ -640,7 +640,7 @@ void HandleBerryConsole(void)
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP "Berry " D_CONSOLE));
WSContentStart_P(PSTR("Berry " D_CONSOLE));
WSContentSend_P(HTTP_SCRIPT_BERRY_CONSOLE, Settings.web_refresh);
WSContentSend_P(HTTP_SCRIPT_BERRY_CONSOLE, Settings->web_refresh);
WSContentSend_P(HTTP_SCRIPT_BERRY_CONSOLE2);
WSContentSendStyle();
WSContentFlush();
@ -673,7 +673,7 @@ void HandleBerryConsole(void)
// bool cflg = (index);
// char* line;
// size_t len;
// while (GetLog(Settings.weblog_level, &index, &line, &len)) {
// while (GetLog(Settings->weblog_level, &index, &line, &len)) {
// if (cflg) { WSContentSend_P(PSTR("\n")); }
// WSContentFlush();
// Webserver->sendContent(line, len -1);

View File

@ -99,8 +99,8 @@ void InitTimeFromRTC(void) {
TIME_T tmpTime;
TasmotaGlobal.ntp_force_sync = true; // Force to sync with ntp
BreakTime(Rtc.utc_time, tmpTime);
Rtc.daylight_saving_time = RuleToTime(Settings.tflag[1], RtcTime.year);
Rtc.standard_time = RuleToTime(Settings.tflag[0], RtcTime.year);
Rtc.daylight_saving_time = RuleToTime(Settings->tflag[1], RtcTime.year);
Rtc.standard_time = RuleToTime(Settings->tflag[0], RtcTime.year);
AddLog(LOG_LEVEL_INFO, PSTR("I2C: Set time from BM8563 to RTC (" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"),
GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_DST).c_str(), GetDateAndTime(DT_STD).c_str());
if (Rtc.local_time < START_VALID_TIME) { // 2016-01-01

View File

@ -952,9 +952,9 @@ int SafeAddLog_P(uint32_t loglevel, PGM_P formatP, ...) {
int added = 0;
// if the log would not be output do nothing here.
if ((loglevel > Settings.weblog_level) &&
if ((loglevel > Settings->weblog_level) &&
(loglevel > TasmotaGlobal.seriallog_level) &&
(loglevel > Settings.mqttlog_level) &&
(loglevel > Settings->mqttlog_level) &&
(loglevel > TasmotaGlobal.syslog_level)){
return added;
}
@ -2251,7 +2251,7 @@ void BLEEvery50mSecond(){
static void stopStartBLE(){
// dont start of disabled
uint8_t enable = (Settings.flag5.mi32_enable || BLEEnableUnsaved) && BLEEnableMask;
uint8_t enable = (Settings->flag5.mi32_enable || BLEEnableUnsaved) && BLEEnableMask;
if (enable != BLEMasterEnable){
if (enable){
@ -2309,7 +2309,7 @@ static void BLEEverySecond(bool restart){
if (BLERestartTasmota == 2){
if (!BLERestartTasmotaReason) BLERestartTasmotaReason = BLE_RESTART_TEAMOTA_REASON_UNKNOWN;
Response_P(PSTR("{\"reboot\":\"%s\"}"), BLERestartTasmotaReason);
MqttPublishPrefixTopicRulesProcess_P(TELE, PSTR("BLE"), Settings.flag.mqtt_sensor_retain);
MqttPublishPrefixTopicRulesProcess_P(TELE, PSTR("BLE"), Settings->flag.mqtt_sensor_retain);
AddLog(LOG_LEVEL_ERROR,PSTR("BLE: Failure! Restarting Tasmota in %d seconds because %s"), BLERestartTasmota, BLERestartTasmotaReason);
}
@ -2322,7 +2322,7 @@ static void BLEEverySecond(bool restart){
if (BLERestartBLEReason){ // just use the ptr as the trigger to send MQTT
Response_P(PSTR("{\"blerestart\":\"%s\"}"), BLERestartBLEReason);
MqttPublishPrefixTopicRulesProcess_P(TELE, PSTR("BLE"), Settings.flag.mqtt_sensor_retain);
MqttPublishPrefixTopicRulesProcess_P(TELE, PSTR("BLE"), Settings->flag.mqtt_sensor_retain);
AddLog(LOG_LEVEL_ERROR,PSTR("BLE: Failure! Restarting BLE Stack because %s"), BLERestartBLEReason);
BLERestartBLEReason = nullptr;
}
@ -3187,7 +3187,7 @@ static void BLEPostMQTT(bool onlycompleted) {
if (prepOperation && !onlycompleted){
std::string out = BLETriggerResponse(prepOperation);
Response_P(PSTR("%s"), out.c_str());
MqttPublishPrefixTopicRulesProcess_P(TELE, PSTR("BLE"), Settings.flag.mqtt_sensor_retain);
MqttPublishPrefixTopicRulesProcess_P(TELE, PSTR("BLE"), Settings->flag.mqtt_sensor_retain);
#ifdef BLE_ESP32_DEBUG
if (BLEDebugMode > 0) AddLog(LOG_LEVEL_INFO,PSTR("BLE: prep sent %s"), out.c_str());
#endif
@ -3207,7 +3207,7 @@ static void BLEPostMQTT(bool onlycompleted) {
std::string out = BLETriggerResponse(toSend);
localmutex.give();
Response_P(PSTR("%s"), out.c_str());
MqttPublishPrefixTopicRulesProcess_P(TELE, PSTR("BLE"), Settings.flag.mqtt_sensor_retain);
MqttPublishPrefixTopicRulesProcess_P(TELE, PSTR("BLE"), Settings->flag.mqtt_sensor_retain);
#ifdef BLE_ESP32_DEBUG
if (BLEDebugMode > 0) AddLog(LOG_LEVEL_INFO,PSTR("BLE: queued %d sent %s"), i, out.c_str());
#endif
@ -3229,7 +3229,7 @@ static void BLEPostMQTT(bool onlycompleted) {
std::string out = BLETriggerResponse(toSend);
localmutex.give();
Response_P(PSTR("%s"), out.c_str());
MqttPublishPrefixTopicRulesProcess_P(TELE, PSTR("BLE"), Settings.flag.mqtt_sensor_retain);
MqttPublishPrefixTopicRulesProcess_P(TELE, PSTR("BLE"), Settings->flag.mqtt_sensor_retain);
#ifdef BLE_ESP32_DEBUG
if (BLEDebugMode > 0) AddLog(LOG_LEVEL_INFO,PSTR("BLE: curr %d sent %s"), i, out.c_str());
#endif
@ -3252,7 +3252,7 @@ static void BLEPostMQTT(bool onlycompleted) {
#endif
std::string out = BLETriggerResponse(toSend);
Response_P(PSTR("%s"), out.c_str());
MqttPublishPrefixTopicRulesProcess_P(TELE, PSTR("BLE"), Settings.flag.mqtt_sensor_retain);
MqttPublishPrefixTopicRulesProcess_P(TELE, PSTR("BLE"), Settings->flag.mqtt_sensor_retain);
// we alreayd removed this from the queues, so now delete
delete toSend;
//break;
@ -3262,7 +3262,7 @@ static void BLEPostMQTT(bool onlycompleted) {
}
} else {
Response_P(PSTR("{\"BLEOperation\":{}}"));
MqttPublishPrefixTopicRulesProcess_P(TELE, PSTR("BLE"), Settings.flag.mqtt_sensor_retain);
MqttPublishPrefixTopicRulesProcess_P(TELE, PSTR("BLE"), Settings->flag.mqtt_sensor_retain);
}
}
@ -3391,7 +3391,7 @@ static void BLEShowStats(){
ResponseAppend_P(PSTR("{\"%s\":\"%s\"}"), tmp, aliases[i]->name);
}
ResponseAppend_P(PSTR("]}"));
MqttPublishPrefixTopicRulesProcess_P(TELE, PSTR("BLE"), Settings.flag.mqtt_sensor_retain);
MqttPublishPrefixTopicRulesProcess_P(TELE, PSTR("BLE"), Settings->flag.mqtt_sensor_retain);
}*/
void BLEAliasListResp(){
@ -3548,7 +3548,7 @@ void HandleBleConfiguration(void)
#ifdef BLE_ESP32_DEBUG
AddLog(LOG_LEVEL_DEBUG, PSTR("BLE: SETTINGS SAVE"));
#endif
Settings.flag5.mi32_enable = Webserver->hasArg("e0"); //
Settings->flag5.mi32_enable = Webserver->hasArg("e0"); //
BLEScanActiveMode = (Webserver->hasArg("e1")?1:0); //
SettingsSaveAll();
@ -3564,7 +3564,7 @@ void HandleBleConfiguration(void)
WSContentSendStyle_P(HTTP_BLE_DEV_STYLE);
//WSContentSendStyle();
WSContentSend_P(HTTP_FORM_BLE,
(Settings.flag5.mi32_enable) ? " checked" : "",
(Settings->flag5.mi32_enable) ? " checked" : "",
(BLEScanActiveMode) ? " checked" : ""
);
WSContentSend_P(HTTP_FORM_END);
@ -3626,7 +3626,7 @@ int ExtRestartBLEIfEnabled(){
bool Xdrv79(uint8_t function)
{
//if (!Settings.flag5.mi32_enable) { return false; } // SetOption115 - Enable ESP32 BLE BLE
//if (!Settings->flag5.mi32_enable) { return false; } // SetOption115 - Enable ESP32 BLE BLE
bool result = false;

View File

@ -284,11 +284,11 @@ uint32_t WcSetup(int32_t fsiz) {
sensor_t * wc_s = esp_camera_sensor_get();
wc_s->set_vflip(wc_s, Settings.webcam_config.flip);
wc_s->set_hmirror(wc_s, Settings.webcam_config.mirror);
wc_s->set_brightness(wc_s, Settings.webcam_config.brightness -2); // up the brightness just a bit
wc_s->set_saturation(wc_s, Settings.webcam_config.saturation -2); // lower the saturation
wc_s->set_contrast(wc_s, Settings.webcam_config.contrast -2); // keep contrast
wc_s->set_vflip(wc_s, Settings->webcam_config.flip);
wc_s->set_hmirror(wc_s, Settings->webcam_config.mirror);
wc_s->set_brightness(wc_s, Settings->webcam_config.brightness -2); // up the brightness just a bit
wc_s->set_saturation(wc_s, Settings->webcam_config.saturation -2); // lower the saturation
wc_s->set_contrast(wc_s, Settings->webcam_config.contrast -2); // keep contrast
// drop down frame size for higher initial frame rate
wc_s->set_framesize(wc_s, (framesize_t)fsiz);
@ -700,7 +700,7 @@ void HandleImageBasic(void) {
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_HTTP "Capture image"));
if (Settings.webcam_config.stream) {
if (Settings->webcam_config.stream) {
if (!Wc.CamServer) {
WcStreamControl();
}
@ -861,8 +861,8 @@ uint32_t WcSetStreamserver(uint32_t flag) {
}
void WcStreamControl() {
WcSetStreamserver(Settings.webcam_config.stream);
WcSetup(Settings.webcam_config.resolution);
WcSetStreamserver(Settings->webcam_config.stream);
WcSetup(Settings->webcam_config.resolution);
}
/*********************************************************************************************/
@ -879,7 +879,7 @@ void WcLoop(void) {
#endif
#ifdef ENABLE_RTSPSERVER
if (Settings.webcam_config.rtsp && !TasmotaGlobal.global_state.wifi_down && Wc.up) {
if (Settings->webcam_config.rtsp && !TasmotaGlobal.global_state.wifi_down && Wc.up) {
if (!Wc.rtsp_start) {
Wc.rtspp = new WiFiServer(8554);
Wc.rtspp->begin();
@ -927,7 +927,7 @@ void WcPicSetup(void) {
}
void WcShowStream(void) {
if (Settings.webcam_config.stream) {
if (Settings->webcam_config.stream) {
// if (!Wc.CamServer || !Wc.up) {
if (!Wc.CamServer) {
WcStreamControl();
@ -941,14 +941,14 @@ void WcShowStream(void) {
}
void WcInit(void) {
if (!Settings.webcam_config.data) {
Settings.webcam_config.stream = 1;
Settings.webcam_config.resolution = FRAMESIZE_QVGA;
Settings.webcam_config.flip = 0;
Settings.webcam_config.mirror = 0;
Settings.webcam_config.saturation = 0; // -2
Settings.webcam_config.brightness = 3; // 1
Settings.webcam_config.contrast = 2; // 0
if (!Settings->webcam_config.data) {
Settings->webcam_config.stream = 1;
Settings->webcam_config.resolution = FRAMESIZE_QVGA;
Settings->webcam_config.flip = 0;
Settings->webcam_config.mirror = 0;
Settings->webcam_config.saturation = 0; // -2
Settings->webcam_config.brightness = 3; // 1
Settings->webcam_config.contrast = 2; // 0
}
}
@ -991,69 +991,69 @@ void CmndWebcam(void) {
",\"" D_CMND_RTSP "\":%d"
#endif // ENABLE_RTSPSERVER
"}}"),
Settings.webcam_config.stream, Settings.webcam_config.resolution, Settings.webcam_config.mirror,
Settings.webcam_config.flip,
Settings.webcam_config.saturation -2, Settings.webcam_config.brightness -2, Settings.webcam_config.contrast -2
Settings->webcam_config.stream, Settings->webcam_config.resolution, Settings->webcam_config.mirror,
Settings->webcam_config.flip,
Settings->webcam_config.saturation -2, Settings->webcam_config.brightness -2, Settings->webcam_config.contrast -2
#ifdef ENABLE_RTSPSERVER
, Settings.webcam_config.rtsp
, Settings->webcam_config.rtsp
#endif // ENABLE_RTSPSERVER
);
}
void CmndWebcamStream(void) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) {
Settings.webcam_config.stream = XdrvMailbox.payload;
if (!Settings.webcam_config.stream) { WcStreamControl(); } // Stop stream
Settings->webcam_config.stream = XdrvMailbox.payload;
if (!Settings->webcam_config.stream) { WcStreamControl(); } // Stop stream
}
ResponseCmndStateText(Settings.webcam_config.stream);
ResponseCmndStateText(Settings->webcam_config.stream);
}
void CmndWebcamResolution(void) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < FRAMESIZE_FHD)) {
Settings.webcam_config.resolution = XdrvMailbox.payload;
WcSetOptions(0, Settings.webcam_config.resolution);
Settings->webcam_config.resolution = XdrvMailbox.payload;
WcSetOptions(0, Settings->webcam_config.resolution);
}
ResponseCmndNumber(Settings.webcam_config.resolution);
ResponseCmndNumber(Settings->webcam_config.resolution);
}
void CmndWebcamMirror(void) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) {
Settings.webcam_config.mirror = XdrvMailbox.payload;
WcSetOptions(3, Settings.webcam_config.mirror);
Settings->webcam_config.mirror = XdrvMailbox.payload;
WcSetOptions(3, Settings->webcam_config.mirror);
}
ResponseCmndStateText(Settings.webcam_config.mirror);
ResponseCmndStateText(Settings->webcam_config.mirror);
}
void CmndWebcamFlip(void) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) {
Settings.webcam_config.flip = XdrvMailbox.payload;
WcSetOptions(2, Settings.webcam_config.flip);
Settings->webcam_config.flip = XdrvMailbox.payload;
WcSetOptions(2, Settings->webcam_config.flip);
}
ResponseCmndStateText(Settings.webcam_config.flip);
ResponseCmndStateText(Settings->webcam_config.flip);
}
void CmndWebcamSaturation(void) {
if ((XdrvMailbox.payload >= -2) && (XdrvMailbox.payload <= 2)) {
Settings.webcam_config.saturation = XdrvMailbox.payload +2;
WcSetOptions(6, Settings.webcam_config.saturation -2);
Settings->webcam_config.saturation = XdrvMailbox.payload +2;
WcSetOptions(6, Settings->webcam_config.saturation -2);
}
ResponseCmndNumber(Settings.webcam_config.saturation -2);
ResponseCmndNumber(Settings->webcam_config.saturation -2);
}
void CmndWebcamBrightness(void) {
if ((XdrvMailbox.payload >= -2) && (XdrvMailbox.payload <= 2)) {
Settings.webcam_config.brightness = XdrvMailbox.payload +2;
WcSetOptions(5, Settings.webcam_config.brightness -2);
Settings->webcam_config.brightness = XdrvMailbox.payload +2;
WcSetOptions(5, Settings->webcam_config.brightness -2);
}
ResponseCmndNumber(Settings.webcam_config.brightness -2);
ResponseCmndNumber(Settings->webcam_config.brightness -2);
}
void CmndWebcamContrast(void) {
if ((XdrvMailbox.payload >= -2) && (XdrvMailbox.payload <= 2)) {
Settings.webcam_config.contrast = XdrvMailbox.payload +2;
WcSetOptions(4, Settings.webcam_config.contrast -2);
Settings->webcam_config.contrast = XdrvMailbox.payload +2;
WcSetOptions(4, Settings->webcam_config.contrast -2);
}
ResponseCmndNumber(Settings.webcam_config.contrast -2);
ResponseCmndNumber(Settings->webcam_config.contrast -2);
}
void CmndWebcamInit(void) {
@ -1064,10 +1064,10 @@ void CmndWebcamInit(void) {
#ifdef ENABLE_RTSPSERVER
void CmndWebRtsp(void) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) {
Settings.webcam_config.rtsp = XdrvMailbox.payload;
Settings->webcam_config.rtsp = XdrvMailbox.payload;
TasmotaGlobal.restart_flag = 2;
}
ResponseCmndStateText(Settings.webcam_config.rtsp);
ResponseCmndStateText(Settings->webcam_config.rtsp);
}
#endif // ENABLE_RTSPSERVER

View File

@ -96,9 +96,9 @@ void EthernetEvent(WiFiEvent_t event) {
case SYSTEM_EVENT_ETH_GOT_IP:
AddLog(LOG_LEVEL_DEBUG, PSTR("ETH: Mac %s, IPAddress %_I, Hostname %s"),
ETH.macAddress().c_str(), (uint32_t)ETH.localIP(), eth_hostname);
Settings.ipv4_address[1] = (uint32_t)ETH.gatewayIP();
Settings.ipv4_address[2] = (uint32_t)ETH.subnetMask();
Settings.ipv4_address[3] = (uint32_t)ETH.dnsIP();
Settings->ipv4_address[1] = (uint32_t)ETH.gatewayIP();
Settings->ipv4_address[2] = (uint32_t)ETH.subnetMask();
Settings->ipv4_address[3] = (uint32_t)ETH.dnsIP();
TasmotaGlobal.global_state.eth_down = 0;
break;
case SYSTEM_EVENT_ETH_DISCONNECTED:
@ -115,16 +115,16 @@ void EthernetEvent(WiFiEvent_t event) {
}
void EthernetInit(void) {
if (!Settings.flag4.network_ethernet) { return; }
if (!Settings->flag4.network_ethernet) { return; }
if (!PinUsed(GPIO_ETH_PHY_MDC) && !PinUsed(GPIO_ETH_PHY_MDIO)) {
AddLog(LOG_LEVEL_DEBUG, PSTR("ETH: No ETH MDC and/or ETH MDIO GPIO defined"));
return;
}
if (WT32_ETH01 == TasmotaGlobal.module_type) {
Settings.eth_address = 1; // EthAddress
Settings.eth_type = ETH_PHY_LAN8720; // EthType
Settings.eth_clk_mode = ETH_CLOCK_GPIO0_IN; // EthClockMode
Settings->eth_address = 1; // EthAddress
Settings->eth_type = ETH_PHY_LAN8720; // EthType
Settings->eth_clk_mode = ETH_CLOCK_GPIO0_IN; // EthClockMode
}
// snprintf_P(Eth.hostname, sizeof(Eth.hostname), PSTR("%s_eth"), TasmotaGlobal.hostname);
@ -136,7 +136,7 @@ void EthernetInit(void) {
int eth_power = Pin(GPIO_ETH_PHY_POWER);
int eth_mdc = Pin(GPIO_ETH_PHY_MDC);
int eth_mdio = Pin(GPIO_ETH_PHY_MDIO);
if (!ETH.begin(Settings.eth_address, eth_power, eth_mdc, eth_mdio, (eth_phy_type_t)Settings.eth_type, (eth_clock_mode_t)Settings.eth_clk_mode)) {
if (!ETH.begin(Settings->eth_address, eth_power, eth_mdc, eth_mdio, (eth_phy_type_t)Settings->eth_type, (eth_clock_mode_t)Settings->eth_clk_mode)) {
AddLog(LOG_LEVEL_DEBUG, PSTR("ETH: Bad PHY type or init error"));
};
}
@ -170,37 +170,37 @@ void (* const EthernetCommand[])(void) PROGMEM = {
void CmndEthernet(void)
{
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) {
Settings.flag4.network_ethernet = XdrvMailbox.payload;
Settings->flag4.network_ethernet = XdrvMailbox.payload;
TasmotaGlobal.restart_flag = 2;
}
ResponseCmndStateText(Settings.flag4.network_ethernet);
ResponseCmndStateText(Settings->flag4.network_ethernet);
}
void CmndEthAddress(void)
{
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 31)) {
Settings.eth_address = XdrvMailbox.payload;
Settings->eth_address = XdrvMailbox.payload;
TasmotaGlobal.restart_flag = 2;
}
ResponseCmndNumber(Settings.eth_address);
ResponseCmndNumber(Settings->eth_address);
}
void CmndEthType(void)
{
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) {
Settings.eth_type = XdrvMailbox.payload;
Settings->eth_type = XdrvMailbox.payload;
TasmotaGlobal.restart_flag = 2;
}
ResponseCmndNumber(Settings.eth_type);
ResponseCmndNumber(Settings->eth_type);
}
void CmndEthClockMode(void)
{
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) {
Settings.eth_clk_mode = XdrvMailbox.payload;
Settings->eth_clk_mode = XdrvMailbox.payload;
TasmotaGlobal.restart_flag = 2;
}
ResponseCmndNumber(Settings.eth_clk_mode);
ResponseCmndNumber(Settings->eth_clk_mode);
}
/*********************************************************************************************\

View File

@ -304,13 +304,13 @@ int32_t ttgo_sleeptime;
esp_light_sleep_start();
} else {
ttgo_globs.ttgo_power->setPowerOutPut(0xFF, false);
Settings.deepsleep = -ttgo_sleeptime;
Settings->deepsleep = -ttgo_sleeptime;
#ifdef USE_DEEPSLEEP
RtcSettings.nextwakeup = 0;
deepsleep_flag = (0 == XdrvMailbox.payload) ? 0 : DEEPSLEEP_START_COUNTDOWN;
if (deepsleep_flag) {
if (!Settings.tele_period) {
Settings.tele_period = TELE_PERIOD; // Need teleperiod to go back to sleep
if (!Settings->tele_period) {
Settings->tele_period = TELE_PERIOD; // Need teleperiod to go back to sleep
}
}
#endif

View File

@ -245,8 +245,8 @@ void Core2Init(void) {
TIME_T tmpTime;
TasmotaGlobal.ntp_force_sync = true; // Force to sync with ntp
BreakTime(Rtc.utc_time, tmpTime);
Rtc.daylight_saving_time = RuleToTime(Settings.tflag[1], RtcTime.year);
Rtc.standard_time = RuleToTime(Settings.tflag[0], RtcTime.year);
Rtc.daylight_saving_time = RuleToTime(Settings->tflag[1], RtcTime.year);
Rtc.standard_time = RuleToTime(Settings->tflag[0], RtcTime.year);
AddLog(LOG_LEVEL_INFO, PSTR("CR2: Set time from BM8563 to RTC (" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"),
GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_DST).c_str(), GetDateAndTime(DT_STD).c_str());
if (Rtc.local_time < START_VALID_TIME) { // 2016-01-01
@ -284,11 +284,11 @@ void Core2EverySecond(void) {
void Core2Show(uint32_t json) {
if (json) {
ResponseAppend_P(PSTR(",\"Core2\":{\"VBV\":%*_f,\"VBC\":%*_f,\"BV\":%*_f,\"BC\":%*_f,\"" D_JSON_TEMPERATURE "\":%*_f}"),
Settings.flag2.voltage_resolution, &core2_adc.vbus_v,
Settings.flag2.current_resolution, &core2_adc.vbus_c,
Settings.flag2.voltage_resolution, &core2_adc.batt_v,
Settings.flag2.current_resolution, &core2_adc.batt_c,
Settings.flag2.temperature_resolution, &core2_adc.temp);
Settings->flag2.voltage_resolution, &core2_adc.vbus_v,
Settings->flag2.current_resolution, &core2_adc.vbus_c,
Settings->flag2.voltage_resolution, &core2_adc.batt_v,
Settings->flag2.current_resolution, &core2_adc.batt_c,
Settings->flag2.temperature_resolution, &core2_adc.temp);
} else {
WSContentSend_Voltage("VBus", core2_adc.vbus_v);
WSContentSend_CurrentMA("VBus", core2_adc.vbus_c);

View File

@ -61,16 +61,16 @@ void CmndDrvText(void) {
if (!XdrvMailbox.usridx) {
// Command DrvText
for (uint32_t i = 0; i < DRV98_MAX_DRV_TEXT; i++) {
AddLog(LOG_LEVEL_DEBUG, PSTR("DRV: DrvText%02d %s"), i, Drv98Settings.drv_text[i]);
AddLog(LOG_LEVEL_DEBUG, PSTR("DRV: DrvText%02d %s"), i, Drv98Settings->drv_text[i]);
}
ResponseCmndDone();
} else {
// Command DrvText<index> <text>
uint32_t index = XdrvMailbox.index -1;
if (XdrvMailbox.data_len > 0) {
snprintf_P(Drv98Settings.drv_text[index], sizeof(Drv98Settings.drv_text[index]), XdrvMailbox.data);
snprintf_P(Drv98Settings->drv_text[index], sizeof(Drv98Settings->drv_text[index]), XdrvMailbox.data);
}
ResponseCmndIdxChar(Drv98Settings.drv_text[index]);
ResponseCmndIdxChar(Drv98Settings->drv_text[index]);
}
}
}
@ -90,27 +90,27 @@ void DrvDemoSettingsDefault(void) {
AddLog(LOG_LEVEL_INFO, PSTR("DRV: " D_USE_DEFAULTS));
memset(&Drv98Settings, 0x00, sizeof(Drv98Settings));
Drv98Settings.version = DRV98_VERSION;
Drv98Settings->version = DRV98_VERSION;
// Init any other parameter in struct Drv98Settings
snprintf_P(Drv98Settings.drv_text[0], sizeof(Drv98Settings.drv_text[0]), PSTR("Azalea"));
snprintf_P(Drv98Settings->drv_text[0], sizeof(Drv98Settings->drv_text[0]), PSTR("Azalea"));
}
void DrvDemoSettingsDelta(void) {
// Fix possible setting deltas
if (Drv98Settings.version != DRV98_VERSION) { // Fix version dependent changes
if (Drv98Settings->version != DRV98_VERSION) { // Fix version dependent changes
if (Settings.version < 0x01010100) {
if (Settings->version < 0x01010100) {
AddLog(LOG_LEVEL_INFO, PSTR("DRV: Update oldest version restore"));
}
if (Settings.version < 0x01010101) {
if (Settings->version < 0x01010101) {
AddLog(LOG_LEVEL_INFO, PSTR("DRV: Update old version restore"));
}
// Set current version and save settings
Drv98Settings.version = DRV98_VERSION;
Drv98Settings->version = DRV98_VERSION;
DrvDemoSettingsSave();
}
}
@ -142,15 +142,15 @@ void DrvDemoSettingsLoad(void) {
AddLog(LOG_LEVEL_INFO, PSTR("DRV: ERROR File system not enabled"));
#endif // USE_UFILESYS
Drv98Settings.crc32 = DrvDemoSettingsCrc32();
Drv98Settings->crc32 = DrvDemoSettingsCrc32();
}
void DrvDemoSettingsSave(void) {
// Called from FUNC_SAVE_SETTINGS every SaveData second and at restart
if (DrvDemoSettingsCrc32() != Drv98Settings.crc32) {
if (DrvDemoSettingsCrc32() != Drv98Settings->crc32) {
// Try to save file /.drvset098
Drv98Settings.crc32 = DrvDemoSettingsCrc32();
Drv98Settings->crc32 = DrvDemoSettingsCrc32();
char filename[20];
// Use for sensors:

View File

@ -365,8 +365,8 @@ void DebugCfgDump(char* parms)
uint16_t col;
char *p;
uint8_t *buffer = (uint8_t *) &Settings;
maxrow = ((sizeof(Settings)+CFG_COLS)/CFG_COLS);
uint8_t *buffer = (uint8_t *) Settings;
maxrow = ((sizeof(TSettings)+CFG_COLS)/CFG_COLS);
uint16_t srow = strtol(parms, &p, 16) / CFG_COLS;
uint16_t mrow = strtol(p, &p, 10);
@ -411,10 +411,10 @@ void DebugCfgPeek(char* parms)
char *p;
uint16_t address = strtol(parms, &p, 16);
if (address > sizeof(Settings)) address = sizeof(Settings) -4;
if (address > sizeof(TSettings)) address = sizeof(TSettings) -4;
address = (address >> 2) << 2;
uint8_t *buffer = (uint8_t *) &Settings;
uint8_t *buffer = (uint8_t *) Settings;
uint8_t data8 = buffer[address];
uint16_t data16 = (buffer[address +1] << 8) + buffer[address];
uint32_t data32 = (buffer[address +3] << 24) + (buffer[address +2] << 16) + data16;
@ -437,12 +437,12 @@ void DebugCfgPoke(char* parms)
char *p;
uint16_t address = strtol(parms, &p, 16);
if (address > sizeof(Settings)) address = sizeof(Settings) -4;
if (address > sizeof(TSettings)) address = sizeof(TSettings) -4;
address = (address >> 2) << 2;
uint32_t data = strtol(p, &p, 16);
uint8_t *buffer = (uint8_t *) &Settings;
uint8_t *buffer = (uint8_t *) Settings;
uint32_t data32 = (buffer[address +3] << 24) + (buffer[address +2] << 16) + (buffer[address +1] << 8) + buffer[address];
uint8_t *nbuffer = (uint8_t *) &data;
@ -562,7 +562,7 @@ void CmndSetSensor(void)
{
if (XdrvMailbox.index < MAX_XSNS_DRIVERS) {
if (XdrvMailbox.payload >= 0) {
bitWrite(Settings.sensors[XdrvMailbox.index / 32], XdrvMailbox.index % 32, XdrvMailbox.payload &1);
bitWrite(Settings->sensors[XdrvMailbox.index / 32], XdrvMailbox.index % 32, XdrvMailbox.payload &1);
if (1 == XdrvMailbox.payload) {
TasmotaGlobal.restart_flag = 2; // To safely re-enable a sensor currently most sensor need to follow complete restart init cycle
}

View File

@ -58,23 +58,23 @@ void LcdInit(uint8_t mode)
void LcdInitDriver(void) {
if (!TasmotaGlobal.i2c_enabled) { return; }
if (!Settings.display_model) {
if (!Settings->display_model) {
if (I2cSetDevice(LCD_ADDRESS1)) {
Settings.display_address[0] = LCD_ADDRESS1;
Settings.display_model = XDSP_01;
Settings->display_address[0] = LCD_ADDRESS1;
Settings->display_model = XDSP_01;
}
else if (I2cSetDevice(LCD_ADDRESS2)) {
Settings.display_address[0] = LCD_ADDRESS2;
Settings.display_model = XDSP_01;
Settings->display_address[0] = LCD_ADDRESS2;
Settings->display_model = XDSP_01;
}
}
if (XDSP_01 == Settings.display_model) {
I2cSetActiveFound(Settings.display_address[0], "LCD");
if (XDSP_01 == Settings->display_model) {
I2cSetActiveFound(Settings->display_address[0], "LCD");
Settings.display_width = Settings.display_cols[0];
Settings.display_height = Settings.display_rows;
lcd = new LiquidCrystal_I2C(Settings.display_address[0], Settings.display_cols[0], Settings.display_rows);
Settings->display_width = Settings->display_cols[0];
Settings->display_height = Settings->display_rows;
lcd = new LiquidCrystal_I2C(Settings->display_address[0], Settings->display_cols[0], Settings->display_rows);
#ifdef USE_DISPLAY_MODES1TO5
DisplayAllocScreenBuffer();
@ -111,17 +111,17 @@ void LcdDisplayOnOff()
void LcdCenter(uint8_t row, char* txt)
{
char line[Settings.display_cols[0] +2];
char line[Settings->display_cols[0] +2];
int len = strlen(txt);
int offset = 0;
if (len >= Settings.display_cols[0]) {
len = Settings.display_cols[0];
if (len >= Settings->display_cols[0]) {
len = Settings->display_cols[0];
} else {
offset = (Settings.display_cols[0] - len) / 2;
offset = (Settings->display_cols[0] - len) / 2;
}
memset(line, 0x20, Settings.display_cols[0]);
line[Settings.display_cols[0]] = 0;
memset(line, 0x20, Settings->display_cols[0]);
line[Settings->display_cols[0]] = 0;
for (uint32_t i = 0; i < len; i++) {
line[offset +i] = txt[i];
}
@ -135,12 +135,12 @@ bool LcdPrintLog(void)
disp_refresh--;
if (!disp_refresh) {
disp_refresh = Settings.display_refresh;
disp_refresh = Settings->display_refresh;
if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); }
char* txt = DisplayLogBuffer('\337');
if (txt != nullptr) {
uint8_t last_row = Settings.display_rows -1;
uint8_t last_row = Settings->display_rows -1;
for (uint32_t i = 0; i < last_row; i++) {
strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols);
@ -163,7 +163,7 @@ bool LcdPrintLog(void)
void LcdTime(void)
{
char line[Settings.display_cols[0] +1];
char line[Settings->display_cols[0] +1];
snprintf_P(line, sizeof(line), PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second);
LcdCenter(0, line);
@ -173,8 +173,8 @@ void LcdTime(void)
void LcdRefresh(void) // Every second
{
if (Settings.display_mode) { // Mode 0 is User text
switch (Settings.display_mode) {
if (Settings->display_mode) { // Mode 0 is User text
switch (Settings->display_mode) {
case 1: // Time
LcdTime();
break;
@ -206,7 +206,7 @@ bool Xdsp01(uint8_t function)
if (FUNC_DISPLAY_INIT_DRIVER == function) {
LcdInitDriver();
}
else if (XDSP_01 == Settings.display_model) {
else if (XDSP_01 == Settings->display_model) {
switch (function) {
case FUNC_DISPLAY_MODEL:
result = true;

View File

@ -50,33 +50,33 @@ extern uint8_t *buffer;
void SSD1306InitDriver(void) {
if (!TasmotaGlobal.i2c_enabled) { return; }
if (!Settings.display_model) {
if (!Settings->display_model) {
if (I2cSetDevice(OLED_ADDRESS1)) {
Settings.display_address[0] = OLED_ADDRESS1;
Settings.display_model = XDSP_02;
Settings->display_address[0] = OLED_ADDRESS1;
Settings->display_model = XDSP_02;
}
else if (I2cSetDevice(OLED_ADDRESS2)) {
Settings.display_address[0] = OLED_ADDRESS2;
Settings.display_model = XDSP_02;
Settings->display_address[0] = OLED_ADDRESS2;
Settings->display_model = XDSP_02;
}
}
if (XDSP_02 == Settings.display_model) {
I2cSetActiveFound(Settings.display_address[0], "SSD1306");
if (XDSP_02 == Settings->display_model) {
I2cSetActiveFound(Settings->display_address[0], "SSD1306");
if ((Settings.display_width != 64) && (Settings.display_width != 96) && (Settings.display_width != 128)) {
Settings.display_width = 128;
if ((Settings->display_width != 64) && (Settings->display_width != 96) && (Settings->display_width != 128)) {
Settings->display_width = 128;
}
if ((Settings.display_height != 16) && (Settings.display_height != 32) && (Settings.display_height != 48) && (Settings.display_height != 64)) {
Settings.display_height = 64;
if ((Settings->display_height != 16) && (Settings->display_height != 32) && (Settings->display_height != 48) && (Settings->display_height != 64)) {
Settings->display_height = 64;
}
// init renderer
// oled1306 = new Adafruit_SSD1306(SSD1306_LCDWIDTH,SSD1306_LCDHEIGHT);
oled1306 = new Adafruit_SSD1306(Settings.display_width, Settings.display_height, &Wire, Pin(GPIO_OLED_RESET));
oled1306->begin(SSD1306_SWITCHCAPVCC, Settings.display_address[0], Pin(GPIO_OLED_RESET) >= 0);
oled1306 = new Adafruit_SSD1306(Settings->display_width, Settings->display_height, &Wire, Pin(GPIO_OLED_RESET));
oled1306->begin(SSD1306_SWITCHCAPVCC, Settings->display_address[0], Pin(GPIO_OLED_RESET) >= 0);
renderer = oled1306;
renderer->DisplayInit(DISPLAY_INIT_MODE, Settings.display_size, Settings.display_rotate, Settings.display_font);
renderer->DisplayInit(DISPLAY_INIT_MODE, Settings->display_size, Settings->display_rotate, Settings->display_font);
renderer->setTextColor(1,0);
#ifdef SHOW_SPLASH
@ -99,15 +99,15 @@ void Ssd1306PrintLog(void)
{
disp_refresh--;
if (!disp_refresh) {
disp_refresh = Settings.display_refresh;
disp_refresh = Settings->display_refresh;
if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); }
char* txt = DisplayLogBuffer('\370');
if (txt != NULL) {
uint8_t last_row = Settings.display_rows -1;
uint8_t last_row = Settings->display_rows -1;
renderer->clearDisplay();
renderer->setTextSize(Settings.display_size);
renderer->setTextSize(Settings->display_size);
renderer->setCursor(0,0);
for (byte i = 0; i < last_row; i++) {
strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols);
@ -129,8 +129,8 @@ void Ssd1306Time(void)
char line[12];
renderer->clearDisplay();
renderer->setTextSize(Settings.display_size);
renderer->setTextFont(Settings.display_font);
renderer->setTextSize(Settings->display_size);
renderer->setTextFont(Settings->display_font);
renderer->setCursor(0, 0);
snprintf_P(line, sizeof(line), PSTR(" %02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); // [ 12:34:56 ]
renderer->println(line);
@ -144,8 +144,8 @@ void Ssd1306Refresh(void) // Every second
{
if (!renderer) return;
if (Settings.display_mode) { // Mode 0 is User text
switch (Settings.display_mode) {
if (Settings->display_mode) { // Mode 0 is User text
switch (Settings->display_mode) {
case 1: // Time
Ssd1306Time();
break;
@ -174,7 +174,7 @@ bool Xdsp02(byte function)
if (FUNC_DISPLAY_INIT_DRIVER == function) {
SSD1306InitDriver();
}
else if (XDSP_02 == Settings.display_model) {
else if (XDSP_02 == Settings->display_model) {
switch (function) {
#ifdef USE_DISPLAY_MODES1TO5
case FUNC_DISPLAY_EVERY_SECOND:

View File

@ -67,7 +67,7 @@ void MatrixFixed(char* txt)
matrix[i]->clear();
matrix[i]->setCursor(-i *8, 0);
matrix[i]->print(txt);
matrix[i]->setBrightness(Settings.display_dimmer);
matrix[i]->setBrightness(Settings->display_dimmer);
}
MatrixWrite();
}
@ -82,7 +82,7 @@ void MatrixCenter(char* txt)
matrix[i]->clear();
matrix[i]->setCursor(-(i *8)+offset, 0);
matrix[i]->print(txt);
matrix[i]->setBrightness(Settings.display_dimmer);
matrix[i]->setBrightness(Settings->display_dimmer);
}
MatrixWrite();
}
@ -97,16 +97,16 @@ void MatrixScrollLeft(char* txt, int loop)
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "[%s]"), txt);
disp_refresh = Settings.display_refresh;
disp_refresh = Settings->display_refresh;
case 2:
disp_refresh--;
if (!disp_refresh) {
disp_refresh = Settings.display_refresh;
disp_refresh = Settings->display_refresh;
for (uint32_t i = 0; i < mtx_matrices; i++) {
matrix[i]->clear();
matrix[i]->setCursor(mtx_x - i *8, 0);
matrix[i]->print(txt);
matrix[i]->setBrightness(Settings.display_dimmer);
matrix[i]->setBrightness(Settings->display_dimmer);
}
MatrixWrite();
// Move text position left by 1 pixel.
@ -134,11 +134,11 @@ void MatrixScrollUp(char* txt, int loop)
// Vertical position of text -- starts off left bottom edge
mtx_y = 8;
mtx_counter = 0;
disp_refresh = Settings.display_refresh;
disp_refresh = Settings->display_refresh;
case 2:
disp_refresh--;
if (!disp_refresh) {
disp_refresh = Settings.display_refresh;
disp_refresh = Settings->display_refresh;
strlcpy(tmpbuf, txt, sizeof(tmpbuf));
char *p = strtok(tmpbuf, separators);
while (p != nullptr && wordcounter < 40) {
@ -151,7 +151,7 @@ void MatrixScrollUp(char* txt, int loop)
matrix[i]->setCursor(-i *8, mtx_y + (j *8));
matrix[i]->println(words[j]);
}
matrix[i]->setBrightness(Settings.display_dimmer);
matrix[i]->setBrightness(Settings->display_dimmer);
}
MatrixWrite();
if (((mtx_y %8) == 0) && mtx_counter) {
@ -171,11 +171,11 @@ void MatrixScrollUp(char* txt, int loop)
void MatrixInitMode(void)
{
for (uint32_t i = 0; i < mtx_matrices; i++) {
matrix[i]->setRotation(Settings.display_rotate); // 1
matrix[i]->setBrightness(Settings.display_dimmer);
matrix[i]->setRotation(Settings->display_rotate); // 1
matrix[i]->setBrightness(Settings->display_dimmer);
matrix[i]->blinkRate(0); // 0 - 3
matrix[i]->setTextWrap(false); // Allow text to run off edges
// matrix[i]->setTextSize(Settings.display_size);
// matrix[i]->setTextSize(Settings->display_size);
// matrix[i]->setTextColor(LED_RED);
matrix[i]->cp437(true);
}
@ -199,26 +199,26 @@ void MatrixInitDriver(void) {
mtx_buffer = (char*)(malloc(MTX_MAX_SCREEN_BUFFER));
if (mtx_buffer != nullptr) {
if (!Settings.display_model) {
if (I2cSetDevice(Settings.display_address[1])) {
Settings.display_model = XDSP_03;
if (!Settings->display_model) {
if (I2cSetDevice(Settings->display_address[1])) {
Settings->display_model = XDSP_03;
}
}
if (XDSP_03 == Settings.display_model) {
if (XDSP_03 == Settings->display_model) {
mtx_state = 1;
for (mtx_matrices = 0; mtx_matrices < 8; mtx_matrices++) {
if (Settings.display_address[mtx_matrices]) {
I2cSetActiveFound(Settings.display_address[mtx_matrices], "8x8Matrix");
if (Settings->display_address[mtx_matrices]) {
I2cSetActiveFound(Settings->display_address[mtx_matrices], "8x8Matrix");
matrix[mtx_matrices] = new Adafruit_8x8matrix();
matrix[mtx_matrices]->begin(Settings.display_address[mtx_matrices]);
matrix[mtx_matrices]->begin(Settings->display_address[mtx_matrices]);
} else {
break;
}
}
Settings.display_width = mtx_matrices * 8;
Settings.display_height = 8;
Settings->display_width = mtx_matrices * 8;
Settings->display_height = 8;
MatrixInitMode();
@ -292,7 +292,7 @@ void MatrixPrintLog(uint8_t direction)
void MatrixRefresh(void) // Every second
{
if (disp_power) {
switch (Settings.display_mode) {
switch (Settings->display_mode) {
case 0: {
switch (mtx_mode) {
case 0:
@ -342,7 +342,7 @@ bool Xdsp03(uint8_t function)
if (FUNC_DISPLAY_INIT_DRIVER == function) {
MatrixInitDriver();
}
else if (XDSP_03 == Settings.display_model) {
else if (XDSP_03 == Settings->display_model) {
switch (function) {
case FUNC_DISPLAY_MODEL:
result = true;

View File

@ -43,7 +43,7 @@ bool tft_init_done = false;
void Core2DisplayPower(uint8_t on);
void Core2DisplayDim(uint8_t dim);
//Settings.display_options.type = ILIMODE_9341;
//Settings->display_options.type = ILIMODE_9341;
/*********************************************************************************************/
@ -54,17 +54,17 @@ void ILI9341_InitDriver()
if (PinUsed(GPIO_ILI9341_CS) || PinUsed(GPIO_ILI9341_DC) &&
(TasmotaGlobal.spi_enabled || TasmotaGlobal.soft_spi_enabled)) {
Settings.display_model = XDSP_04;
Settings->display_model = XDSP_04;
if (Settings.display_width != ILI9341_TFTWIDTH) {
Settings.display_width = ILI9341_TFTWIDTH;
if (Settings->display_width != ILI9341_TFTWIDTH) {
Settings->display_width = ILI9341_TFTWIDTH;
}
if (Settings.display_height != ILI9341_TFTHEIGHT) {
Settings.display_height = ILI9341_TFTHEIGHT;
if (Settings->display_height != ILI9341_TFTHEIGHT) {
Settings->display_height = ILI9341_TFTHEIGHT;
}
if (!Settings.display_options.type || (Settings.display_options.type >= ILIMODE_MAX)) {
Settings.display_options.type = ILIMODE_9341;
if (!Settings->display_options.type || (Settings->display_options.type >= ILIMODE_MAX)) {
Settings->display_options.type = ILIMODE_9341;
}
// default colors
@ -75,11 +75,11 @@ void ILI9341_InitDriver()
if (TasmotaGlobal.soft_spi_enabled) {
// Init renderer, may use hardware spi, however we use SSPI defintion because SD card uses SPI definition (2 spi busses)
if (PinUsed(GPIO_SSPI_MOSI) && PinUsed(GPIO_SSPI_MISO) && PinUsed(GPIO_SSPI_SCLK)) {
ili9341_2 = new ILI9341_2(Pin(GPIO_ILI9341_CS), Pin(GPIO_SSPI_MOSI), Pin(GPIO_SSPI_MISO), Pin(GPIO_SSPI_SCLK), Pin(GPIO_OLED_RESET), Pin(GPIO_ILI9341_DC), Pin(GPIO_BACKLIGHT), 2, Settings.display_options.type & 3);
ili9341_2 = new ILI9341_2(Pin(GPIO_ILI9341_CS), Pin(GPIO_SSPI_MOSI), Pin(GPIO_SSPI_MISO), Pin(GPIO_SSPI_SCLK), Pin(GPIO_OLED_RESET), Pin(GPIO_ILI9341_DC), Pin(GPIO_BACKLIGHT), 2, Settings->display_options.type & 3);
}
} else if (TasmotaGlobal.spi_enabled) {
if (PinUsed(GPIO_ILI9341_DC)) {
ili9341_2 = new ILI9341_2(Pin(GPIO_ILI9341_CS), Pin(GPIO_SPI_MOSI), Pin(GPIO_SPI_MISO), Pin(GPIO_SPI_CLK), Pin(GPIO_OLED_RESET), Pin(GPIO_ILI9341_DC), Pin(GPIO_BACKLIGHT), 1, Settings.display_options.type & 3);
ili9341_2 = new ILI9341_2(Pin(GPIO_ILI9341_CS), Pin(GPIO_SPI_MOSI), Pin(GPIO_SPI_MISO), Pin(GPIO_SPI_CLK), Pin(GPIO_OLED_RESET), Pin(GPIO_ILI9341_DC), Pin(GPIO_BACKLIGHT), 1, Settings->display_options.type & 3);
}
}
@ -88,7 +88,7 @@ void ILI9341_InitDriver()
return;
}
ili9341_2->init(Settings.display_width, Settings.display_height);
ili9341_2->init(Settings->display_width, Settings->display_height);
renderer = ili9341_2;
#ifdef USE_M5STACK_CORE2
@ -96,22 +96,22 @@ void ILI9341_InitDriver()
renderer->SetDimCB(Core2DisplayDim);
#endif
renderer->DisplayInit(DISPLAY_INIT_MODE, Settings.display_size, Settings.display_rotate, Settings.display_font);
renderer->dim(Settings.display_dimmer);
renderer->DisplayInit(DISPLAY_INIT_MODE, Settings->display_size, Settings->display_rotate, Settings->display_font);
renderer->dim(Settings->display_dimmer);
#ifdef SHOW_SPLASH
// Welcome text
renderer->setTextFont(2);
renderer->setTextSize(1);
renderer->setTextColor(ILI9341_WHITE, ILI9341_BLACK);
renderer->DrawStringAt(50, (Settings.display_height/2)-12, (Settings.display_options.type & 3)==ILIMODE_9341?"ILI9341 TFT!":"ILI9342 TFT!", ILI9341_WHITE, 0);
renderer->DrawStringAt(50, (Settings->display_height/2)-12, (Settings->display_options.type & 3)==ILIMODE_9341?"ILI9341 TFT!":"ILI9342 TFT!", ILI9341_WHITE, 0);
delay(1000);
#endif // SHOW_SPLASH
color_type = COLOR_COLOR;
#ifdef USE_DISPLAY_MODES1TO5
if (Settings.display_rotate) {
if (Settings->display_rotate) {
DisplayAllocScreenBuffer();
}
Ili9341InitMode();
@ -238,8 +238,8 @@ uint16_t tft_scroll = TFT_TOP;
uint16_t tft_cols = 0;
bool Ili9341Header(void) {
if (Settings.display_cols[0] != tft_cols) {
tft_cols = Settings.display_cols[0];
if (Settings->display_cols[0] != tft_cols) {
tft_cols = Settings->display_cols[0];
if (tft_cols > 17) {
tft_top = TFT_TOP;
tft_bottom = TFT_BOTTOM;
@ -254,14 +254,14 @@ bool Ili9341Header(void) {
}
void Ili9341InitMode(void) {
// renderer->setRotation(Settings.display_rotate); // 0
// renderer->setRotation(Settings->display_rotate); // 0
#ifdef USE_DISPLAY_ILI9341
// renderer->invertDisplay(0);
#endif
renderer->fillScreen(ILI9341_BLACK);
renderer->setTextWrap(false); // Allow text to run off edges
renderer->cp437(true);
if (!Settings.display_mode) {
if (!Settings->display_mode) {
renderer->setCursor(0, 0);
renderer->setTextColor(ILI9341_WHITE, ILI9341_BLACK);
renderer->setTextSize(1);
@ -277,19 +277,19 @@ void Ili9341InitMode(void) {
void Ili9341PrintLog(void) {
disp_refresh--;
if (!disp_refresh) {
disp_refresh = Settings.display_refresh;
if (Settings.display_rotate) {
disp_refresh = Settings->display_refresh;
if (Settings->display_rotate) {
if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); }
}
char* txt = DisplayLogBuffer('\370');
if (txt != nullptr) {
uint8_t size = Settings.display_size;
uint8_t size = Settings->display_size;
uint16_t theight = size * TFT_FONT_HEIGTH;
renderer->setTextSize(size);
renderer->setTextColor(ILI9341_CYAN, ILI9341_BLACK); // Add background color to solve flicker
if (!Settings.display_rotate) { // Use hardware scroll
if (!Settings->display_rotate) { // Use hardware scroll
renderer->setCursor(0, tft_scroll);
renderer->fillRect(0, tft_scroll, renderer->width(), theight, ILI9341_BLACK); // Erase line
renderer->print(txt);
@ -299,7 +299,7 @@ void Ili9341PrintLog(void) {
}
renderer->scrollTo(tft_scroll);
} else {
uint8_t last_row = Settings.display_rows -1;
uint8_t last_row = Settings->display_rows -1;
tft_scroll = (tft_top) ? theight : 0; // Start below header
renderer->setCursor(0, tft_scroll);
@ -321,18 +321,18 @@ void Ili9341PrintLog(void) {
}
void ILI9341_Refresh(void) { // Every second
if (Settings.display_mode) { // Mode 0 is User text
if (Settings->display_mode) { // Mode 0 is User text
// 24-04-2017 13:45:43 = 19 + 1 ('\0') = 20
// 24-04-2017 13:45 = 16 + 1 ('\0') = 17
if (Ili9341Header()) {
char tftdt[Settings.display_cols[0] +1];
char tftdt[Settings->display_cols[0] +1];
char date4[11]; // 24-04-2017
uint8_t time_size = (Settings.display_cols[0] >= 20) ? 9 : 6; // 13:45:43 or 13:45
char spaces[Settings.display_cols[0] - (8 + time_size)];
uint8_t time_size = (Settings->display_cols[0] >= 20) ? 9 : 6; // 13:45:43 or 13:45
char spaces[Settings->display_cols[0] - (8 + time_size)];
char time[time_size]; // 13:45:43
renderer->setTextSize(Settings.display_size);
renderer->setTextSize(Settings->display_size);
renderer->setTextColor(ILI9341_YELLOW, ILI9341_RED); // Add background color to solve flicker
renderer->setCursor(0, 0);
@ -347,7 +347,7 @@ void ILI9341_Refresh(void) { // Every second
renderer->setCursor(0, 0);
}
switch (Settings.display_mode) {
switch (Settings->display_mode) {
case 1: // Text
case 2: // Local
case 3: // Local
@ -371,7 +371,7 @@ bool Xdsp04(uint8_t function)
if (FUNC_DISPLAY_INIT_DRIVER == function) {
ILI9341_InitDriver();
}
else if (tft_init_done && (XDSP_04 == Settings.display_model)) {
else if (tft_init_done && (XDSP_04 == Settings->display_model)) {
switch (function) {
case FUNC_DISPLAY_MODEL:
result = true;

View File

@ -48,13 +48,13 @@ void EpdInitDriver29(void) {
if (PinUsed(GPIO_EPAPER29_CS) &&
((TasmotaGlobal.soft_spi_enabled & SPI_MOSI) || (TasmotaGlobal.spi_enabled & SPI_MOSI))) {
Settings.display_model = XDSP_05;
Settings->display_model = XDSP_05;
if (Settings.display_width != EPD_WIDTH) {
Settings.display_width = EPD_WIDTH;
if (Settings->display_width != EPD_WIDTH) {
Settings->display_width = EPD_WIDTH;
}
if (Settings.display_height != EPD_HEIGHT) {
Settings.display_height = EPD_HEIGHT;
if (Settings->display_height != EPD_HEIGHT) {
Settings->display_height = EPD_HEIGHT;
}
// init renderer
@ -72,7 +72,7 @@ void EpdInitDriver29(void) {
epd->Init(DISPLAY_INIT_FULL);
epd->Init(DISPLAY_INIT_PARTIAL);
renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font);
renderer->DisplayInit(DISPLAY_INIT_MODE,Settings->display_size,Settings->display_rotate,Settings->display_font);
renderer->setTextColor(1,0);
@ -104,18 +104,18 @@ void EpdPrintLog29(void)
disp_refresh--;
if (!disp_refresh) {
disp_refresh = Settings.display_refresh;
//if (Settings.display_rotate) {
disp_refresh = Settings->display_refresh;
//if (Settings->display_rotate) {
if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); }
//}
char* txt = DisplayLogBuffer('\040');
if (txt != nullptr) {
uint8_t size = Settings.display_size;
uint8_t size = Settings->display_size;
uint16_t theight = size * EPD_FONT_HEIGTH;
renderer->setTextFont(size);
uint8_t last_row = Settings.display_rows -1;
uint8_t last_row = Settings->display_rows -1;
// epd_scroll = theight; // Start below header
epd_scroll = 0; // Start at top with no header
@ -136,13 +136,13 @@ void EpdPrintLog29(void)
void EpdRefresh29(void) // Every second
{
if (Settings.display_mode) { // Mode 0 is User text
if (Settings->display_mode) { // Mode 0 is User text
if (!renderer) return;
/*
char tftdt[Settings.display_cols[0] +1];
char tftdt[Settings->display_cols[0] +1];
char date4[11]; // 24-04-2017
char space[Settings.display_cols[0] - 17];
char space[Settings->display_cols[0] - 17];
char time[9]; // 13:45:43
EpdSetFont(1);
@ -155,7 +155,7 @@ void EpdRefresh29(void) // Every second
EpdDrawStringAt(0, 0, tftdt, COLORED, 0);
*/
switch (Settings.display_mode) {
switch (Settings->display_mode) {
case 1: // Text
case 2: // Local
case 3: // Local
@ -183,7 +183,7 @@ bool Xdsp05(uint8_t function)
if (FUNC_DISPLAY_INIT_DRIVER == function) {
EpdInitDriver29();
}
else if (epd_init_done && (XDSP_05 == Settings.display_model)) {
else if (epd_init_done && (XDSP_05 == Settings->display_model)) {
switch (function) {
case FUNC_DISPLAY_MODEL:
result = true;

View File

@ -45,13 +45,13 @@ void EpdInitDriver42() {
if (PinUsed(GPIO_EPAPER42_CS) &&
((TasmotaGlobal.soft_spi_enabled & SPI_MOSI) || (TasmotaGlobal.spi_enabled & SPI_MOSI))) {
Settings.display_model = XDSP_06;
Settings->display_model = XDSP_06;
if (Settings.display_width != EPD_WIDTH42) {
Settings.display_width = EPD_WIDTH42;
if (Settings->display_width != EPD_WIDTH42) {
Settings->display_width = EPD_WIDTH42;
}
if (Settings.display_height != EPD_HEIGHT42) {
Settings.display_height = EPD_HEIGHT42;
if (Settings->display_height != EPD_HEIGHT42) {
Settings->display_height = EPD_HEIGHT42;
}
// init renderer
@ -73,7 +73,7 @@ void EpdInitDriver42() {
// whiten display with full update, takes 4 seconds
epd42->Init(DISPLAY_INIT_FULL);
renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font);
renderer->DisplayInit(DISPLAY_INIT_MODE,Settings->display_size,Settings->display_rotate,Settings->display_font);
epd42->ClearFrame();
renderer->Updateframe();
@ -104,7 +104,7 @@ void EpdInitDriver42() {
void EpdRefresh42() // Every second
{
if (Settings.display_mode) { // Mode 0 is User text
if (Settings->display_mode) { // Mode 0 is User text
}
}
@ -123,7 +123,7 @@ bool Xdsp06(uint8_t function)
if (FUNC_DISPLAY_INIT_DRIVER == function) {
EpdInitDriver42();
}
else if (epd42_init_done && (XDSP_06 == Settings.display_model)) {
else if (epd42_init_done && (XDSP_06 == Settings->display_model)) {
switch (function) {
case FUNC_DISPLAY_MODEL:
result = true;

View File

@ -50,31 +50,31 @@ Adafruit_SH1106 *oled1106;
void SH1106InitDriver() {
if (!TasmotaGlobal.i2c_enabled) { return; }
if (!Settings.display_model) {
if (!Settings->display_model) {
if (I2cSetDevice(OLED_ADDRESS1)) {
Settings.display_address[0] = OLED_ADDRESS1;
Settings.display_model = XDSP_07;
Settings->display_address[0] = OLED_ADDRESS1;
Settings->display_model = XDSP_07;
}
else if (I2cSetDevice(OLED_ADDRESS2)) {
Settings.display_address[0] = OLED_ADDRESS2;
Settings.display_model = XDSP_07;
Settings->display_address[0] = OLED_ADDRESS2;
Settings->display_model = XDSP_07;
}
}
if (XDSP_07 == Settings.display_model) {
I2cSetActiveFound(Settings.display_address[0], "SH1106");
if (XDSP_07 == Settings->display_model) {
I2cSetActiveFound(Settings->display_address[0], "SH1106");
if (Settings.display_width != SH1106_LCDWIDTH) {
Settings.display_width = SH1106_LCDWIDTH;
if (Settings->display_width != SH1106_LCDWIDTH) {
Settings->display_width = SH1106_LCDWIDTH;
}
if (Settings.display_height != SH1106_LCDHEIGHT) {
Settings.display_height = SH1106_LCDHEIGHT;
if (Settings->display_height != SH1106_LCDHEIGHT) {
Settings->display_height = SH1106_LCDHEIGHT;
}
// init renderer
oled1106 = new Adafruit_SH1106(SH1106_LCDWIDTH,SH1106_LCDHEIGHT);
renderer = oled1106;
renderer->Begin(SH1106_SWITCHCAPVCC, Settings.display_address[0],0);
renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font);
renderer->Begin(SH1106_SWITCHCAPVCC, Settings->display_address[0],0);
renderer->DisplayInit(DISPLAY_INIT_MODE,Settings->display_size,Settings->display_rotate,Settings->display_font);
renderer->setTextColor(1,0);
#ifdef SHOW_SPLASH
@ -98,15 +98,15 @@ void SH1106PrintLog(void)
{
disp_refresh--;
if (!disp_refresh) {
disp_refresh = Settings.display_refresh;
disp_refresh = Settings->display_refresh;
if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); }
char* txt = DisplayLogBuffer('\370');
if (txt != NULL) {
uint8_t last_row = Settings.display_rows -1;
uint8_t last_row = Settings->display_rows -1;
renderer->clearDisplay();
renderer->setTextSize(Settings.display_size);
renderer->setTextSize(Settings->display_size);
renderer->setCursor(0,0);
for (byte i = 0; i < last_row; i++) {
strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols);
@ -128,8 +128,8 @@ void SH1106Time(void)
char line[12];
renderer->clearDisplay();
renderer->setTextSize(Settings.display_size);
renderer->setTextFont(Settings.display_font);
renderer->setTextSize(Settings->display_size);
renderer->setTextFont(Settings->display_font);
renderer->setCursor(0, 0);
snprintf_P(line, sizeof(line), PSTR(" %02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); // [ 12:34:56 ]
renderer->println(line);
@ -142,8 +142,8 @@ void SH1106Time(void)
void SH1106Refresh(void) // Every second
{
if (!renderer) return;
if (Settings.display_mode) { // Mode 0 is User text
switch (Settings.display_mode) {
if (Settings->display_mode) { // Mode 0 is User text
switch (Settings->display_mode) {
case 1: // Time
SH1106Time();
break;
@ -172,7 +172,7 @@ bool Xdsp07(uint8_t function)
if (FUNC_DISPLAY_INIT_DRIVER == function) {
SH1106InitDriver();
}
else if (XDSP_07 == Settings.display_model) {
else if (XDSP_07 == Settings->display_model) {
switch (function) {
case FUNC_DISPLAY_MODEL:

View File

@ -48,13 +48,13 @@ extern const uint16_t picture[];
void ILI9488_InitDriver(void) {
if (PinUsed(GPIO_ILI9488_CS) && (TasmotaGlobal.spi_enabled & SPI_MOSI)) {
Settings.display_model = XDSP_08;
Settings->display_model = XDSP_08;
if (Settings.display_width != ILI9488_TFTWIDTH) {
Settings.display_width = ILI9488_TFTWIDTH;
if (Settings->display_width != ILI9488_TFTWIDTH) {
Settings->display_width = ILI9488_TFTWIDTH;
}
if (Settings.display_height != ILI9488_TFTHEIGHT) {
Settings.display_height = ILI9488_TFTHEIGHT;
if (Settings->display_height != ILI9488_TFTHEIGHT) {
Settings->display_height = ILI9488_TFTHEIGHT;
}
// default colors
@ -71,8 +71,8 @@ void ILI9488_InitDriver(void) {
ili9488->begin();
renderer = ili9488;
renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font);
renderer->dim(Settings.display_dimmer);
renderer->DisplayInit(DISPLAY_INIT_MODE,Settings->display_size,Settings->display_rotate,Settings->display_font);
renderer->dim(Settings->display_dimmer);
#ifdef SHOW_SPLASH
// Welcome text
@ -145,7 +145,7 @@ bool Xdsp08(uint8_t function)
if (FUNC_DISPLAY_INIT_DRIVER == function) {
ILI9488_InitDriver();
}
else if (ili9488_init_done && (XDSP_08 == Settings.display_model)) {
else if (ili9488_init_done && (XDSP_08 == Settings->display_model)) {
switch (function) {
case FUNC_DISPLAY_MODEL:
result = true;

View File

@ -71,7 +71,7 @@ void ILI9488_InitDriver(void) {
if (!renderer) return;
Settings.display_model = XDSP_08;
Settings->display_model = XDSP_08;
ili9488_init_done = true;
}
@ -88,7 +88,7 @@ bool Xdsp08(uint8_t function)
if (FUNC_DISPLAY_INIT_DRIVER == function) {
ILI9488_InitDriver();
}
else if (ili9488_init_done && (XDSP_08 == Settings.display_model)) {
else if (ili9488_init_done && (XDSP_08 == Settings->display_model)) {
switch (function) {
case FUNC_DISPLAY_MODEL:
result = true;

View File

@ -43,13 +43,13 @@ void SSD1351_InitDriver() {
if (PinUsed(GPIO_SSD1351_CS) &&
((TasmotaGlobal.soft_spi_enabled & SPI_MOSI) || (TasmotaGlobal.spi_enabled & SPI_MOSI))) {
Settings.display_model = XDSP_09;
Settings->display_model = XDSP_09;
if (Settings.display_width != SSD1351_WIDTH) {
Settings.display_width = SSD1351_WIDTH;
if (Settings->display_width != SSD1351_WIDTH) {
Settings->display_width = SSD1351_WIDTH;
}
if (Settings.display_height != SSD1351_HEIGHT) {
Settings.display_height = SSD1351_HEIGHT;
if (Settings->display_height != SSD1351_HEIGHT) {
Settings->display_height = SSD1351_HEIGHT;
}
// default colors
@ -67,8 +67,8 @@ void SSD1351_InitDriver() {
delay(100);
ssd1351->begin();
renderer = ssd1351;
renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font);
renderer->dim(Settings.display_dimmer);
renderer->DisplayInit(DISPLAY_INIT_MODE,Settings->display_size,Settings->display_rotate,Settings->display_font);
renderer->dim(Settings->display_dimmer);
#ifdef SHOW_SPLASH
// Welcome text
@ -90,15 +90,15 @@ void SSD1351_InitDriver() {
void SSD1351PrintLog(void) {
disp_refresh--;
if (!disp_refresh) {
disp_refresh = Settings.display_refresh;
disp_refresh = Settings->display_refresh;
if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); }
char* txt = DisplayLogBuffer('\370');
if (txt != NULL) {
uint8_t last_row = Settings.display_rows -1;
uint8_t last_row = Settings->display_rows -1;
renderer->clearDisplay();
renderer->setTextSize(Settings.display_size);
renderer->setTextSize(Settings->display_size);
renderer->setCursor(0,0);
for (byte i = 0; i < last_row; i++) {
strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols);
@ -130,8 +130,8 @@ void SSD1351Time(void) {
}
void SSD1351Refresh(void) { // Every second
if (Settings.display_mode) { // Mode 0 is User text
switch (Settings.display_mode) {
if (Settings->display_mode) { // Mode 0 is User text
switch (Settings->display_mode) {
case 1: // Time
SSD1351Time();
break;
@ -157,7 +157,7 @@ bool Xdsp09(uint8_t function) {
if (FUNC_DISPLAY_INIT_DRIVER == function) {
SSD1351_InitDriver();
}
else if (ssd1351_init_done && (XDSP_09 == Settings.display_model)) {
else if (ssd1351_init_done && (XDSP_09 == Settings->display_model)) {
switch (function) {
case FUNC_DISPLAY_MODEL:
result = true;

View File

@ -42,13 +42,13 @@ RA8876 *ra8876;
void RA8876_InitDriver(void) {
if (PinUsed(GPIO_RA8876_CS) && (SPI_MOSI_MISO == TasmotaGlobal.spi_enabled)) {
Settings.display_model = XDSP_10;
Settings->display_model = XDSP_10;
if (Settings.display_width != RA8876_TFTWIDTH) {
Settings.display_width = RA8876_TFTWIDTH;
if (Settings->display_width != RA8876_TFTWIDTH) {
Settings->display_width = RA8876_TFTWIDTH;
}
if (Settings.display_height != RA8876_TFTHEIGHT) {
Settings.display_height = RA8876_TFTHEIGHT;
if (Settings->display_height != RA8876_TFTHEIGHT) {
Settings->display_height = RA8876_TFTHEIGHT;
}
// default colors
@ -60,8 +60,8 @@ void RA8876_InitDriver(void) {
ra8876->begin();
renderer = ra8876;
renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font);
renderer->dim(Settings.display_dimmer);
renderer->DisplayInit(DISPLAY_INIT_MODE,Settings->display_size,Settings->display_rotate,Settings->display_font);
renderer->dim(Settings->display_dimmer);
//testall();
#ifdef SHOW_SPLASH
@ -302,7 +302,7 @@ bool Xdsp10(uint8_t function)
if (FUNC_DISPLAY_INIT_DRIVER == function) {
RA8876_InitDriver();
}
else if (ra8876_init_done && (XDSP_10 == Settings.display_model)) {
else if (ra8876_init_done && (XDSP_10 == Settings->display_model)) {
switch (function) {
case FUNC_DISPLAY_MODEL:
result = true;

View File

@ -106,7 +106,7 @@ void SevensegLog(void)
void SevensegDim(void)
{
for (uint32_t i = 0; i < sevensegs; i++) {
sevenseg[i]->setBrightness(Settings.display_dimmer);
sevenseg[i]->setBrightness(Settings->display_dimmer);
}
}
@ -130,7 +130,7 @@ void SevensegClear(void)
void SevensegInitMode(void)
{
for (uint32_t i = 0; i < sevensegs; i++) {
sevenseg[i]->setBrightness(Settings.display_dimmer);
sevenseg[i]->setBrightness(Settings->display_dimmer);
sevenseg[i]->blinkRate(0);
}
SevensegClear();
@ -150,26 +150,26 @@ void SevensegInit(uint8_t mode)
void SevensegInitDriver(void) {
if (!TasmotaGlobal.i2c_enabled) { return; }
if (!Settings.display_model) {
if (I2cSetDevice(Settings.display_address[0])) {
Settings.display_model = XDSP_11;
if (!Settings->display_model) {
if (I2cSetDevice(Settings->display_address[0])) {
Settings->display_model = XDSP_11;
}
}
if (XDSP_11 == Settings.display_model) {
if (XDSP_11 == Settings->display_model) {
sevenseg_state = 1;
for (sevensegs = 0; sevensegs < 8; sevensegs++) {
if (Settings.display_address[sevensegs]) {
I2cSetActiveFound(Settings.display_address[sevensegs], "SevenSeg");
if (Settings->display_address[sevensegs]) {
I2cSetActiveFound(Settings->display_address[sevensegs], "SevenSeg");
sevenseg[sevensegs] = new Adafruit_7segment();
sevenseg[sevensegs]->begin(Settings.display_address[sevensegs]);
sevenseg[sevensegs]->begin(Settings->display_address[sevensegs]);
} else {
break;
}
}
Settings.display_width = 4;
Settings.display_height = sevensegs;
Settings->display_width = 4;
Settings->display_height = sevensegs;
SevensegInitMode();
}
@ -397,8 +397,8 @@ void SevensegTime(boolean time_24)
void SevensegRefresh(void) // Every second
{
if (disp_power) {
if (Settings.display_mode) { // Mode 0 is User text
switch (Settings.display_mode) {
if (Settings->display_mode) { // Mode 0 is User text
switch (Settings->display_mode) {
case 1: // Time 12
SevensegTime(false);
break;
@ -431,7 +431,7 @@ bool Xdsp11(uint8_t function)
if (FUNC_DISPLAY_INIT_DRIVER == function) {
SevensegInitDriver();
}
else if (XDSP_11 == Settings.display_model) {
else if (XDSP_11 == Settings->display_model) {
switch (function) {
case FUNC_DISPLAY_MODEL:
result = true;

View File

@ -64,13 +64,13 @@ void ST7789_InitDriver(void) {
if (PinUsed(GPIO_ST7789_DC) && // This device does not need CS which breaks SPI bus usage
((TasmotaGlobal.soft_spi_enabled & SPI_MOSI) || (TasmotaGlobal.spi_enabled & SPI_MOSI))) {
Settings.display_model = XDSP_12;
Settings->display_model = XDSP_12;
if (!Settings.display_width) {
Settings.display_width = 240;
if (!Settings->display_width) {
Settings->display_width = 240;
}
if (!Settings.display_height) {
Settings.display_height = 240;
if (!Settings->display_height) {
Settings->display_height = 240;
}
// default colors
@ -90,16 +90,16 @@ void ST7789_InitDriver(void) {
st7789 = new Arduino_ST7789(Pin(GPIO_ST7789_DC), Pin(GPIO_OLED_RESET), Pin(GPIO_ST7789_CS), bppin);
}
st7789->init(Settings.display_width,Settings.display_height);
st7789->init(Settings->display_width,Settings->display_height);
renderer = st7789;
renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font);
renderer->dim(Settings.display_dimmer);
renderer->DisplayInit(DISPLAY_INIT_MODE,Settings->display_size,Settings->display_rotate,Settings->display_font);
renderer->dim(Settings->display_dimmer);
#ifdef SHOW_SPLASH
// Welcome text
renderer->setTextColor(ST7789_WHITE,ST7789_BLACK);
renderer->setTextFont(2);
renderer->DrawStringAt(30, (Settings.display_height-12)/2, "ST7789 TFT!", ST7789_WHITE,0);
renderer->DrawStringAt(30, (Settings->display_height-12)/2, "ST7789 TFT!", ST7789_WHITE,0);
delay(1000);
#endif
@ -183,7 +183,7 @@ bool Xdsp12(uint8_t function)
if (FUNC_DISPLAY_INIT_DRIVER == function) {
ST7789_InitDriver();
}
else if (st7789_init_done && (XDSP_12 == Settings.display_model)) {
else if (st7789_init_done && (XDSP_12 == Settings->display_model)) {
switch (function) {
case FUNC_DISPLAY_MODEL:
result = true;

View File

@ -46,13 +46,13 @@ void SSD1331_InitDriver() {
if (PinUsed(GPIO_SSD1331_CS) && PinUsed(GPIO_SSD1331_DC) &&
((TasmotaGlobal.soft_spi_enabled & SPI_MOSI) || (TasmotaGlobal.spi_enabled & SPI_MOSI))) {
Settings.display_model = XDSP_14;
Settings->display_model = XDSP_14;
if (Settings.display_width != Adafruit_SSD1331::TFTWIDTH) {
Settings.display_width = Adafruit_SSD1331::TFTWIDTH;
if (Settings->display_width != Adafruit_SSD1331::TFTWIDTH) {
Settings->display_width = Adafruit_SSD1331::TFTWIDTH;
}
if (Settings.display_height != Adafruit_SSD1331::TFTHEIGHT) {
Settings.display_height = Adafruit_SSD1331::TFTHEIGHT;
if (Settings->display_height != Adafruit_SSD1331::TFTHEIGHT) {
Settings->display_height = Adafruit_SSD1331::TFTHEIGHT;
}
@ -72,8 +72,8 @@ void SSD1331_InitDriver() {
ssd1331->begin();
renderer = ssd1331;
// Rotation is currently broken, https://github.com/adafruit/Adafruit-SSD1331-OLED-Driver-Library-for-Arduino/issues/26
renderer->DisplayInit(DISPLAY_INIT_MODE, Settings.display_size, Settings.display_rotate, Settings.display_font);
renderer->dim(Settings.display_dimmer);
renderer->DisplayInit(DISPLAY_INIT_MODE, Settings->display_size, Settings->display_rotate, Settings->display_font);
renderer->dim(Settings->display_dimmer);
#ifdef SHOW_SPLASH
// Welcome text
@ -96,12 +96,12 @@ void SSD1331_InitDriver() {
void SSD1331PrintLog(bool withDateTime) {
disp_refresh--;
if (!disp_refresh) {
disp_refresh = Settings.display_refresh;
disp_refresh = Settings->display_refresh;
if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); }
char* txt = DisplayLogBuffer('\370');
if (txt != NULL) {
uint8_t last_row = Settings.display_rows -1;
uint8_t last_row = Settings->display_rows -1;
renderer->clearDisplay();
renderer->setCursor(0,0);
@ -144,8 +144,8 @@ void SSD1331Time(void) {
}
void SSD1331Refresh(void) { // Every second
if (Settings.display_mode) { // Mode 0 is User text
switch (Settings.display_mode) {
if (Settings->display_mode) { // Mode 0 is User text
switch (Settings->display_mode) {
case 1: // Time
SSD1331Time();
break;
@ -173,7 +173,7 @@ bool Xdsp14(uint8_t function) {
if (FUNC_DISPLAY_INIT_DRIVER == function) {
SSD1331_InitDriver();
}
else if (ssd1331_init_done && (XDSP_14 == Settings.display_model)) {
else if (ssd1331_init_done && (XDSP_14 == Settings->display_model)) {
switch (function) {
case FUNC_DISPLAY_MODEL:
result = true;

View File

@ -70,51 +70,51 @@
Clears the display, command: "DisplayClear"
DisplayNumber num [,position {0-(Settings.display_width-1))} [,leading_zeros {0|1} [,length {1 to Settings.display_width}]]]
DisplayNumber num [,position {0-(Settings->display_width-1))} [,leading_zeros {0|1} [,length {1 to Settings->display_width}]]]
Clears and then displays number without decimal. command e.g., "DisplayNumber 1234"
Control 'leading zeros', 'length' and 'position' with "DisplayNumber 1234, <position>, <leadingZeros>, <length>"
'leading zeros' can be 1 or 0 (default), 'length' can be 1 to Settings.display_width, 'position' can be 0 (left-most) to Settings.display_width (right-most).
'leading zeros' can be 1 or 0 (default), 'length' can be 1 to Settings->display_width, 'position' can be 0 (left-most) to Settings->display_width (right-most).
See function description below for more details.
DisplayNumberNC num [,position {0-(Settings.display_width-1))} [,leading_zeros {0|1} [,length {1 to Settings.display_width}]]]
DisplayNumberNC num [,position {0-(Settings->display_width-1))} [,leading_zeros {0|1} [,length {1 to Settings->display_width}]]]
Display integer number as above, but without clearing first. e.g., "DisplayNumberNC 1234". Usage is same as above.
DisplayFloat num [,position {0-(Settings.display_width-1)} [,precision {0-Settings.display_width} [,length {1 to Settings.display_width}]]]
DisplayFloat num [,position {0-(Settings->display_width-1)} [,precision {0-Settings->display_width} [,length {1 to Settings->display_width}]]]
Clears and then displays float (with decimal point) command e.g., "DisplayFloat 12.34"
See function description below for more details.
DisplayFloatNC num [,position {0-(Settings.display_width-1)} [,precision {0-Settings.display_width} [,length {1 to Settings.display_width}]]]
DisplayFloatNC num [,position {0-(Settings->display_width-1)} [,precision {0-Settings->display_width} [,length {1 to Settings->display_width}]]]
Displays float (with decimal point) as above, but without clearing first. command e.g., "DisplayFloatNC 12.34"
See function description below for more details.
DisplayRaw position {0-(Settings.display_width-1)},length {1 to Settings.display_width}, num1 [, num2[, num3[, num4[, ...upto Settings.display_width numbers]]]]]
DisplayRaw position {0-(Settings->display_width-1)},length {1 to Settings->display_width}, num1 [, num2[, num3[, num4[, ...upto Settings->display_width numbers]]]]]
Takes upto Settings.display_width comma-separated integers (0-255) and displays raw segments. Each number represents a
Takes upto Settings->display_width comma-separated integers (0-255) and displays raw segments. Each number represents a
7-segment digit. Each 8-bit number represents individual segments of a digit.
For example, the command "DisplayRaw 0, 4, 255, 255, 255, 255" would display "[8.8.8.8.]"
DisplayText text [, position {0-(Settings.display_width-1)} [,length {1 to Settings.display_width}]]
DisplayText text [, position {0-(Settings->display_width-1)} [,length {1 to Settings->display_width}]]
Clears and then displays basic text. command e.g., "DisplayText ajith vasudevan"
Control 'length' and 'position' with "DisplayText <text>, <position>, <length>"
'length' can be 1 to Settings.display_width, 'position' can be 0 (left-most) to Settings.display_width-1 (right-most)
'length' can be 1 to Settings->display_width, 'position' can be 0 (left-most) to Settings->display_width-1 (right-most)
A caret(^) symbol in the text input is dispayed as the degrees(°) symbol. This is useful for displaying Temperature!
For example, the command "DisplayText 22.5^" will display "22.5°".
DisplayTextNC text [, position {0-Settings.display_width-1} [,length {1 to Settings.display_width}]]
DisplayTextNC text [, position {0-Settings->display_width-1} [,length {1 to Settings->display_width}]]
Clears first, then displays text. Usage is same as above.
@ -207,39 +207,39 @@ void TM1637Init(void)
if (PinUsed(GPIO_TM1638CLK) && PinUsed(GPIO_TM1638DIO) && PinUsed(GPIO_TM1638STB))
{
TM1637Data.display_type = TM1638;
Settings.display_width = 8;
Settings->display_width = 8;
}
else if (PinUsed(GPIO_TM1637CLK) && PinUsed(GPIO_TM1637DIO))
{
TM1637Data.display_type = TM1637;
if ((!Settings.display_width || Settings.display_width > 6))
if ((!Settings->display_width || Settings->display_width > 6))
{
Settings.display_width = 4;
Settings.display_options.type = 0;
Settings->display_width = 4;
Settings->display_options.type = 0;
}
TM1637SetDigitOrder();
}
else if (PinUsed(GPIO_MAX7219DIN) && PinUsed(GPIO_MAX7219CLK) && PinUsed(GPIO_MAX7219CS))
{
TM1637Data.display_type = MAX7219;
Settings.display_width = 8;
Settings->display_width = 8;
}
else
{
return;
}
Settings.display_model = XDSP_15;
Settings.display_cols[0] = Settings.display_width;
Settings.display_height = 1;
Settings.display_rows = Settings.display_height;
if(!Settings.display_dimmer || Settings.display_dimmer < 2 || Settings.display_dimmer > 15) Settings.display_dimmer = 8;
Settings->display_model = XDSP_15;
Settings->display_cols[0] = Settings->display_width;
Settings->display_height = 1;
Settings->display_rows = Settings->display_height;
if(!Settings->display_dimmer || Settings->display_dimmer < 2 || Settings->display_dimmer > 15) Settings->display_dimmer = 8;
if (TM1637 == TM1637Data.display_type)
{
strcpy_P(TM1637Data.model_name, PSTR("TM1637"));
tm1637display = new SevenSegmentTM1637(Pin(GPIO_TM1637CLK), Pin(GPIO_TM1637DIO));
tm1637display->begin(Settings.display_width, 1);
tm1637display->begin(Settings->display_width, 1);
}
else if (TM1638 == TM1637Data.display_type)
{
@ -256,7 +256,7 @@ void TM1637Init(void)
TM1637ClearDisplay();
TM1637Dim();
TM1637Data.init_done = true;
AddLog(LOG_LEVEL_INFO, PSTR("DSP: %s with %d digits (type %d)"), TM1637Data.model_name, Settings.display_width, Settings.display_options.type);
AddLog(LOG_LEVEL_INFO, PSTR("DSP: %s with %d digits (type %d)"), TM1637Data.model_name, Settings->display_width, Settings->display_options.type);
}
// Function to display specified ascii char at specified position for MAX7219
@ -294,12 +294,12 @@ void displayMAX72197Seg(uint8_t pos, uint8_t seg)
// Function to fix order of hardware digits for different TM1637 variants
void TM1637SetDigitOrder(void) {
if (0 == Settings.display_options.type) {
if (0 == Settings->display_options.type) {
for (uint32_t i = 0; i < 6; i++) {
TM1637Data.digit_order[i] = i;
}
}
else if (1 == Settings.display_options.type) {
else if (1 == Settings->display_options.type) {
TM1637Data.digit_order[0] = 2;
TM1637Data.digit_order[1] = 1;
TM1637Data.digit_order[2] = 0;
@ -312,8 +312,8 @@ void TM1637SetDigitOrder(void) {
/*********************************************************************************************\
* Displays number without decimal, with/without leading zeros, specifying start-position
* and length, optionally skipping clearing display before displaying the number.
* commands: DisplayNumber num [,position {0-(Settings.display_width-1)} [,leading_zeros {0|1} [,length {1 to Settings.display_width}]]]
* DisplayNumberNC num [,position {0-(Settings.display_width-1)} [,leading_zeros {0|1} [,length {1 to Settings.display_width}]]] // "NC" --> "No Clear"
* commands: DisplayNumber num [,position {0-(Settings->display_width-1)} [,leading_zeros {0|1} [,length {1 to Settings->display_width}]]]
* DisplayNumberNC num [,position {0-(Settings->display_width-1)} [,leading_zeros {0|1} [,length {1 to Settings->display_width}]]] // "NC" --> "No Clear"
\*********************************************************************************************/
bool CmndTM1637Number(bool clear)
{
@ -343,7 +343,7 @@ bool CmndTM1637Number(bool clear)
num = atof(sNum);
}
if ((position < 0) || (position > (Settings.display_width - 1)))
if ((position < 0) || (position > (Settings->display_width - 1)))
position = 0;
AddLog(LOG_LEVEL_DEBUG, PSTR("TM7: num %d, pos %d, lead %d, len %d"), num, position, leadingzeros, length);
@ -355,8 +355,8 @@ bool CmndTM1637Number(bool clear)
snprintf_P(txt, sizeof(txt), PSTR("%d"), num);
if (!length)
length = strlen(txt);
if ((length < 0) || (length > Settings.display_width))
length = Settings.display_width;
if ((length < 0) || (length > Settings->display_width))
length = Settings->display_width;
char pad = (leadingzeros ? '0' : ' ');
uint32_t i = position;
@ -364,7 +364,7 @@ bool CmndTM1637Number(bool clear)
for (; i < position + (length - strlen(txt)); i++)
{
if (i > Settings.display_width)
if (i > Settings->display_width)
break;
if (TM1637 == TM1637Data.display_type)
{
@ -383,7 +383,7 @@ bool CmndTM1637Number(bool clear)
for (uint32_t j = 0; i < position + length; i++, j++)
{
if (i > Settings.display_width)
if (i > Settings->display_width)
break;
if (txt[j] == 0)
break;
@ -410,8 +410,8 @@ bool CmndTM1637Number(bool clear)
/*********************************************************************************************\
* Displays number with decimal, specifying position, precision and length,
* optionally skipping clearing display before displaying the number.
* commands: DisplayFloat num [,position {0-(Settings.display_width-1)} [,precision {0-Settings.display_width} [,length {1 to Settings.display_width}]]]
* DisplayFloatNC num [,position {0-(Settings.display_width-1)} [,precision {0-Settings.display_width} [,length {1 to Settings.display_width}]]] // "NC" --> "No Clear"
* commands: DisplayFloat num [,position {0-(Settings->display_width-1)} [,precision {0-Settings->display_width} [,length {1 to Settings->display_width}]]]
* DisplayFloatNC num [,position {0-(Settings->display_width-1)} [,precision {0-Settings->display_width} [,length {1 to Settings->display_width}]]] // "NC" --> "No Clear"
\*********************************************************************************************/
bool CmndTM1637Float(bool clear)
{
@ -421,7 +421,7 @@ bool CmndTM1637Float(bool clear)
char sPosition[CMD_MAX_LEN];
char sLength[CMD_MAX_LEN];
uint8_t length = 0;
uint8_t precision = Settings.display_width;
uint8_t precision = Settings->display_width;
uint8_t position = 0;
float fnum = 0.0f;
@ -442,10 +442,10 @@ bool CmndTM1637Float(bool clear)
fnum = atof(sNum);
}
if ((position < 0) || (position > (Settings.display_width - 1)))
if ((position < 0) || (position > (Settings->display_width - 1)))
position = 0;
if ((precision < 0) || (precision > Settings.display_width))
precision = Settings.display_width;
if ((precision < 0) || (precision > Settings->display_width))
precision = Settings->display_width;
if (clear)
TM1637ClearDisplay();
@ -455,8 +455,8 @@ bool CmndTM1637Float(bool clear)
if (!length)
length = strlen(txt);
if ((length <= 0) || (length > Settings.display_width))
length = Settings.display_width;
if ((length <= 0) || (length > Settings->display_width))
length = Settings->display_width;
AddLog(LOG_LEVEL_DEBUG, PSTR("TM7: num %4_f, prec %d, len %d"), &fnum, precision, length);
@ -474,7 +474,7 @@ bool CmndTM1637Float(bool clear)
i++;
length++;
}
if ((j + position) > Settings.display_width)
if ((j + position) > Settings->display_width)
break;
tm1637display->printRaw(rawBytes, 1, TM1637Data.digit_order[j + position]);
}
@ -539,12 +539,12 @@ void TM1637ClearDisplay(void)
if (TM1637 == TM1637Data.display_type)
{
unsigned char arr[] = {0};
for (int i = 0; i < Settings.display_width; i++)
for (int i = 0; i < Settings->display_width; i++)
tm1637display->printRaw(arr, 1, i);
}
else if (TM1638 == TM1637Data.display_type)
{
for (int i = 0; i < Settings.display_width; i++)
for (int i = 0; i < Settings->display_width; i++)
tm1638display->display7Seg(i, 0);
}
else if (MAX7219 == TM1637Data.display_type)
@ -618,7 +618,7 @@ void TM1637ScrollText(void)
uint8_t rawBytes[1];
for (uint32_t i = 0, j = TM1637Data.scroll_index; i < 1 + strlen(TM1637Data.scroll_text); i++, j++)
{
if (i > (Settings.display_width - 1))
if (i > (Settings->display_width - 1))
{
break;
}
@ -673,7 +673,7 @@ bool CmndTM1637Level(void)
return false;
}
uint8_t totalBars = 2 * Settings.display_width;
uint8_t totalBars = 2 * Settings->display_width;
AddLog(LOG_LEVEL_DEBUG, PSTR("TM7: TM1637Data.model_name %s CmndTM1637Level totalBars=%d"), TM1637Data.model_name, totalBars);
float barsToDisplay = totalBars * val / 100.0f;
char txt[5];
@ -709,8 +709,8 @@ bool CmndTM1637Level(void)
/*********************************************************************************************\
* Display arbitrary data on the display module
* Command: DisplayRaw position {0-(Settings.display_width-1)},length {1 to Settings.display_width}, a [, b[, c[, d[...upto Settings.display_width]]]]
* where a,b,c,d... are upto Settings.display_width numbers in the range 0-255, each number (byte)
* Command: DisplayRaw position {0-(Settings->display_width-1)},length {1 to Settings->display_width}, a [, b[, c[, d[...upto Settings->display_width]]]]
* where a,b,c,d... are upto Settings->display_width numbers in the range 0-255, each number (byte)
* corresponding to a single 7-segment digit. Within each byte, bit 0 is segment A,
* bit 1 is segment B etc. The function may either set the entire display
* or any desired part using the length and position parameters.
@ -762,9 +762,9 @@ bool CmndTM1637Raw(void)
if (!length)
length = ArgC() - 2;
if (length < 0 || length > Settings.display_width)
length = Settings.display_width;
if (position < 0 || position > (Settings.display_width - 1))
if (length < 0 || length > Settings->display_width)
length = Settings->display_width;
if (position < 0 || position > (Settings->display_width - 1))
position = 0;
AddLog(LOG_LEVEL_DEBUG, PSTR("TM7: a %d, b %d, c %d, d %d, e %d, f %d, len %d, pos %d"),
@ -775,7 +775,7 @@ bool CmndTM1637Raw(void)
uint8_t rawBytes[1];
for (uint32_t i = position; i < position + length; i++)
{
if (i > (Settings.display_width - 1))
if (i > (Settings->display_width - 1))
break;
rawBytes[0] = DATA[i - position];
tm1637display->printRaw(rawBytes, 1, TM1637Data.digit_order[i]);
@ -806,7 +806,7 @@ bool CmndTM1637Raw(void)
* Display a given string.
* Text can be placed at arbitrary location on the display using the length and
* position parameters without affecting the rest of the display.
* Command: DisplayText text [, position {0-(Settings.display_width-1)} [,length {1 to Settings.display_width}]]
* Command: DisplayText text [, position {0-(Settings->display_width-1)} [,length {1 to Settings->display_width}]]
\*********************************************************************************************/
bool CmndTM1637Text(bool clear)
{
@ -828,7 +828,7 @@ bool CmndTM1637Text(bool clear)
subStr(sString, XdrvMailbox.data, ",", 1);
}
if ((position < 0) || (position > (Settings.display_width - 1)))
if ((position < 0) || (position > (Settings->display_width - 1)))
position = 0;
AddLog(LOG_LEVEL_DEBUG, PSTR("TM7: sString %s, pos %d, len %d"), sString, position, length);
@ -838,8 +838,8 @@ bool CmndTM1637Text(bool clear)
if (!length)
length = strlen(sString);
if ((length < 0) || (length > Settings.display_width))
length = Settings.display_width;
if ((length < 0) || (length > Settings->display_width))
length = Settings->display_width;
uint32_t i = position;
if (TM1637 == TM1637Data.display_type)
@ -847,7 +847,7 @@ bool CmndTM1637Text(bool clear)
uint8_t rawBytes[1];
for (uint32_t j = 0; i < position + length; i++, j++)
{
if (i > (Settings.display_width - 1))
if (i > (Settings->display_width - 1))
break;
if (sString[j] == 0)
break;
@ -1074,8 +1074,8 @@ bool TM1637MainFunc(uint8_t fn)
void TM1637Dim(void)
{
// Settings.display_dimmer = 0 - 15
uint8_t brightness = Settings.display_dimmer >> 1; // 0 - 7
// Settings->display_dimmer = 0 - 15
uint8_t brightness = Settings->display_dimmer >> 1; // 0 - 7
if (TM1637 == TM1637Data.display_type)
{
@ -1097,7 +1097,7 @@ void TM1637Dim(void)
void TM1637Print(char *txt)
{
for (uint32_t i = 0; i < Settings.display_cols[0]; i++)
for (uint32_t i = 0; i < Settings->display_cols[0]; i++)
{
if (TM1637 == TM1637Data.display_type)
{
@ -1122,20 +1122,20 @@ void TM1637Print(char *txt)
void TM1637Center(char *txt)
{
char line[Settings.display_cols[0] + 2];
char line[Settings->display_cols[0] + 2];
int len = strlen(txt);
int offset = 0;
if (len >= Settings.display_cols[0])
if (len >= Settings->display_cols[0])
{
len = Settings.display_cols[0];
len = Settings->display_cols[0];
}
else
{
offset = (Settings.display_cols[0] - len) / 2;
offset = (Settings->display_cols[0] - len) / 2;
}
memset(line, 0x20, Settings.display_cols[0]);
line[Settings.display_cols[0]] = 0;
memset(line, 0x20, Settings->display_cols[0]);
line[Settings->display_cols[0]] = 0;
for (uint32_t i = 0; i < len; i++)
{
line[offset + i] = txt[i];
@ -1149,12 +1149,12 @@ bool TM1637PrintLog(void) {
disp_refresh--;
if (!disp_refresh) {
disp_refresh = Settings.display_refresh;
disp_refresh = Settings->display_refresh;
if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); }
char* txt = DisplayLogBuffer('\337');
if (txt != nullptr) {
uint8_t last_row = Settings.display_rows -1;
uint8_t last_row = Settings->display_rows -1;
strlcpy(disp_screen_buffer[last_row], txt, disp_screen_buffer_cols);
DisplayFillScreen(last_row);
@ -1172,13 +1172,13 @@ bool TM1637PrintLog(void) {
void TM1637Time(void)
{
char line[Settings.display_cols[0] + 1];
char line[Settings->display_cols[0] + 1];
if (Settings.display_cols[0] >= 8)
if (Settings->display_cols[0] >= 8)
{
snprintf_P(line, sizeof(line), PSTR("%02d %02d %02d"), RtcTime.hour, RtcTime.minute, RtcTime.second);
}
else if (Settings.display_cols[0] >= 6)
else if (Settings->display_cols[0] >= 6)
{
snprintf_P(line, sizeof(line), PSTR("%02d%02d%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second);
}
@ -1191,13 +1191,13 @@ void TM1637Time(void)
void TM1637Date(void)
{
char line[Settings.display_cols[0] + 1];
char line[Settings->display_cols[0] + 1];
if (Settings.display_cols[0] >= 8)
if (Settings->display_cols[0] >= 8)
{
snprintf_P(line, sizeof(line), PSTR("%02d-%02d-%02d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year - 2000);
}
else if (Settings.display_cols[0] >= 6)
else if (Settings->display_cols[0] >= 6)
{
snprintf_P(line, sizeof(line), PSTR("%02d%02d%02d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year - 2000);
}
@ -1210,12 +1210,12 @@ void TM1637Date(void)
void TM1637Refresh(void)
{ // Every second
if (!disp_power || !Settings.display_mode)
if (!disp_power || !Settings->display_mode)
{
return;
} // Mode 0 is User text
switch (Settings.display_mode)
switch (Settings->display_mode)
{
case 1: // Time
TM1637Time();
@ -1224,7 +1224,7 @@ void TM1637Refresh(void)
TM1637Date();
break;
case 3: // Time
if (TasmotaGlobal.uptime % Settings.display_refresh)
if (TasmotaGlobal.uptime % Settings->display_refresh)
{
TM1637Time();
}
@ -1259,12 +1259,12 @@ bool Xdsp15(uint8_t function)
{
TM1637Init();
}
else if (TM1637Data.init_done && (XDSP_15 == Settings.display_model))
else if (TM1637Data.init_done && (XDSP_15 == Settings->display_model))
{
switch (function)
{
case FUNC_DISPLAY_EVERY_50_MSECOND:
if (disp_power && !Settings.display_mode)
if (disp_power && !Settings->display_mode)
{
if (TM1637Data.scroll)
{
@ -1296,7 +1296,7 @@ bool Xdsp15(uint8_t function)
case FUNC_DISPLAY_SCROLLTEXT:
case FUNC_DISPLAY_SCROLLDELAY:
case FUNC_DISPLAY_CLOCK:
if (disp_power && !Settings.display_mode)
if (disp_power && !Settings->display_mode)
{
TM1637Data.show_clock = false;
result = TM1637MainFunc(function);

View File

@ -39,21 +39,21 @@ extern uint16_t bg_color;
void EpdInitDriver47(void) {
if (PinUsed(GPIO_EPD_DATA)) {
Settings.display_model = XDSP_16;
Settings->display_model = XDSP_16;
if (Settings.display_width != EPD47_WIDTH) {
Settings.display_width = EPD47_WIDTH;
if (Settings->display_width != EPD47_WIDTH) {
Settings->display_width = EPD47_WIDTH;
}
if (Settings.display_height != EPD47_HEIGHT) {
Settings.display_height = EPD47_HEIGHT;
if (Settings->display_height != EPD47_HEIGHT) {
Settings->display_height = EPD47_HEIGHT;
}
// init renderer
epd47 = new Epd47(Settings.display_width, Settings.display_height);
epd47 = new Epd47(Settings->display_width, Settings->display_height);
epd47->Init();
renderer = epd47;
renderer->DisplayInit(DISPLAY_INIT_MODE, Settings.display_size, Settings.display_rotate, Settings.display_font);
renderer->DisplayInit(DISPLAY_INIT_MODE, Settings->display_size, Settings->display_rotate, Settings->display_font);
renderer->setTextColor(EPD47_BLACK, EPD47_WHITE);
#ifdef SHOW_SPLASH
@ -283,7 +283,7 @@ bool Xdsp16(uint8_t function)
if (FUNC_DISPLAY_INIT_DRIVER == function) {
EpdInitDriver47();
}
else if (epd47_init_done && (XDSP_16 == Settings.display_model)) {
else if (epd47_init_done && (XDSP_16 == Settings->display_model)) {
switch (function) {
case FUNC_DISPLAY_MODEL:
result = true;

View File

@ -69,7 +69,7 @@ uDisplay *udisp;
if (TasmotaGlobal.gpio_optiona.udisplay_driver || desc) {
Settings.display_model = XDSP_17;
Settings->display_model = XDSP_17;
fbuff = (char*)calloc(DISPDESC_SIZE, 1);
@ -98,7 +98,7 @@ uDisplay *udisp;
#ifdef USE_SCRIPT
if (bitRead(Settings.rule_enabled, 0) && !ddesc) {
if (bitRead(Settings->rule_enabled, 0) && !ddesc) {
uint8_t dfound = Run_Scripter(">d",-2,0);
if (dfound == 99) {
char *lp = glob_script_mem.section_ptr + 2;
@ -111,9 +111,9 @@ uDisplay *udisp;
#endif // USE_SCRIPT
#ifdef USE_RULES
if (!bitRead(Settings.rule_enabled, 2) && !ddesc) {
if (!bitRead(Settings->rule_enabled, 2) && !ddesc) {
// only if rule3 is not enabled for rules
char *cp = Settings.rules[2];
char *cp = Settings->rules[2];
while (*cp == ' ') cp++;
memcpy(fbuff, cp, DISPDESC_SIZE - 1);
if (fbuff[0] == ':' && fbuff[1] == 'H') {
@ -300,8 +300,8 @@ uDisplay *udisp;
renderer = udisp->Init();
if (!renderer) return 0;
Settings.display_width = renderer->width();
Settings.display_height = renderer->height();
Settings->display_width = renderer->width();
Settings->display_height = renderer->height();
fg_color = renderer->fgcol();
bg_color = renderer->bgcol();
color_type = renderer->color_type();
@ -311,8 +311,8 @@ uDisplay *udisp;
renderer->SetDimCB(Core2DisplayDim);
#endif
renderer->DisplayInit(DISPLAY_INIT_MODE, Settings.display_size, Settings.display_rotate, Settings.display_font);
renderer->dim(Settings.display_dimmer);
renderer->DisplayInit(DISPLAY_INIT_MODE, Settings->display_size, Settings->display_rotate, Settings->display_font);
renderer->dim(Settings->display_dimmer);
#ifdef SHOW_SPLASH
renderer->Splash();
@ -354,15 +354,15 @@ void UDISP_PrintLog(void)
{
disp_refresh--;
if (!disp_refresh) {
disp_refresh = Settings.display_refresh;
disp_refresh = Settings->display_refresh;
if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); }
char* txt = DisplayLogBuffer('\370');
if (txt != NULL) {
uint8_t last_row = Settings.display_rows -1;
uint8_t last_row = Settings->display_rows -1;
renderer->clearDisplay();
renderer->setTextSize(Settings.display_size);
renderer->setTextSize(Settings->display_size);
renderer->setCursor(0,0);
for (byte i = 0; i < last_row; i++) {
strlcpy(disp_screen_buffer[i], disp_screen_buffer[i +1], disp_screen_buffer_cols);
@ -384,8 +384,8 @@ void UDISP_Time(void)
char line[12];
renderer->clearDisplay();
renderer->setTextSize(Settings.display_size);
renderer->setTextFont(Settings.display_font);
renderer->setTextSize(Settings->display_size);
renderer->setTextFont(Settings->display_font);
renderer->setCursor(0, 0);
snprintf_P(line, sizeof(line), PSTR(" %02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); // [ 12:34:56 ]
renderer->println(line);
@ -398,8 +398,8 @@ void UDISP_Time(void)
void UDISP_Refresh(void) // Every second
{
if (!renderer) return;
if (Settings.display_mode) { // Mode 0 is User text
switch (Settings.display_mode) {
if (Settings->display_mode) { // Mode 0 is User text
switch (Settings->display_mode) {
case 1: // Time
UDISP_Time();
break;
@ -425,7 +425,7 @@ bool Xdsp17(uint8_t function) {
if (FUNC_DISPLAY_INIT_DRIVER == function) {
Init_uDisplay(0, -1);
}
else if (udisp_init_done && (XDSP_17 == Settings.display_model)) {
else if (udisp_init_done && (XDSP_17 == Settings->display_model)) {
switch (function) {
case FUNC_DISPLAY_MODEL:
result = true;

View File

@ -209,8 +209,8 @@ void Ws2812StripShow(void)
RgbColor c;
#endif
if (Settings.light_correction) {
for (uint32_t i = 0; i < Settings.light_pixels; i++) {
if (Settings->light_correction) {
for (uint32_t i = 0; i < Settings->light_pixels; i++) {
c = strip->GetPixelColor(i);
c.R = ledGamma(c.R);
c.G = ledGamma(c.G);
@ -239,10 +239,10 @@ void Ws2812UpdatePixelColor(int position, struct WsColor hand_color, float offse
RgbColor color;
#endif
uint32_t mod_position = mod(position, (int)Settings.light_pixels);
uint32_t mod_position = mod(position, (int)Settings->light_pixels);
color = strip->GetPixelColor(mod_position);
float dimmer = 100 / (float)Settings.light_dimmer;
float dimmer = 100 / (float)Settings->light_dimmer;
color.R = tmin(color.R + ((hand_color.red / dimmer) * offset), 255);
color.G = tmin(color.G + ((hand_color.green / dimmer) * offset), 255);
color.B = tmin(color.B + ((hand_color.blue / dimmer) * offset), 255);
@ -251,16 +251,16 @@ void Ws2812UpdatePixelColor(int position, struct WsColor hand_color, float offse
void Ws2812UpdateHand(int position, uint32_t index)
{
uint32_t width = Settings.light_width;
if (index < WS_MARKER) { width = Settings.ws_width[index]; }
uint32_t width = Settings->light_width;
if (index < WS_MARKER) { width = Settings->ws_width[index]; }
if (!width) { return; } // Skip
position = (position + Settings.light_rotation) % Settings.light_pixels;
position = (position + Settings->light_rotation) % Settings->light_pixels;
if (Settings.flag.ws_clock_reverse) { // SetOption16 - Switch between clockwise or counter-clockwise
position = Settings.light_pixels -position;
if (Settings->flag.ws_clock_reverse) { // SetOption16 - Switch between clockwise or counter-clockwise
position = Settings->light_pixels -position;
}
WsColor hand_color = { Settings.ws_color[index][WS_RED], Settings.ws_color[index][WS_GREEN], Settings.ws_color[index][WS_BLUE] };
WsColor hand_color = { Settings->ws_color[index][WS_RED], Settings->ws_color[index][WS_GREEN], Settings->ws_color[index][WS_BLUE] };
Ws2812UpdatePixelColor(position, hand_color, 1);
@ -275,12 +275,12 @@ void Ws2812UpdateHand(int position, uint32_t index)
void Ws2812Clock(void)
{
strip->ClearTo(0); // Reset strip
int clksize = 60000 / (int)Settings.light_pixels;
int clksize = 60000 / (int)Settings->light_pixels;
Ws2812UpdateHand((RtcTime.second * 1000) / clksize, WS_SECOND);
Ws2812UpdateHand((RtcTime.minute * 1000) / clksize, WS_MINUTE);
Ws2812UpdateHand((((RtcTime.hour % 12) * 5000) + ((RtcTime.minute * 1000) / 12 )) / clksize, WS_HOUR);
if (Settings.ws_color[WS_MARKER][WS_RED] + Settings.ws_color[WS_MARKER][WS_GREEN] + Settings.ws_color[WS_MARKER][WS_BLUE]) {
if (Settings->ws_color[WS_MARKER][WS_RED] + Settings->ws_color[WS_MARKER][WS_GREEN] + Settings->ws_color[WS_MARKER][WS_BLUE]) {
for (uint32_t i = 0; i < 12; i++) {
Ws2812UpdateHand((i * 5000) / clksize, WS_MARKER);
}
@ -305,7 +305,7 @@ void Ws2812GradientColor(uint32_t schemenr, struct WsColor* mColor, uint32_t ran
start = (scheme.count -1) - start;
end = (scheme.count -1) - end;
}
float dimmer = 100 / (float)Settings.light_dimmer;
float dimmer = 100 / (float)Settings->light_dimmer;
float fmyRed = (float)wsmap(rangeIndex % gradRange, 0, gradRange, scheme.colors[start].red, scheme.colors[end].red) / dimmer;
float fmyGrn = (float)wsmap(rangeIndex % gradRange, 0, gradRange, scheme.colors[start].green, scheme.colors[end].green) / dimmer;
float fmyBlu = (float)wsmap(rangeIndex % gradRange, 0, gradRange, scheme.colors[start].blue, scheme.colors[end].blue) / dimmer;
@ -331,18 +331,18 @@ void Ws2812Gradient(uint32_t schemenr)
ColorScheme scheme = kSchemes[schemenr];
if (scheme.count < 2) { return; }
uint32_t repeat = kWsRepeat[Settings.light_width]; // number of scheme.count per ledcount
uint32_t range = (uint32_t)ceil((float)Settings.light_pixels / (float)repeat);
uint32_t repeat = kWsRepeat[Settings->light_width]; // number of scheme.count per ledcount
uint32_t range = (uint32_t)ceil((float)Settings->light_pixels / (float)repeat);
uint32_t gradRange = (uint32_t)ceil((float)range / (float)(scheme.count - 1));
uint32_t speed = ((Settings.light_speed * 2) -1) * (STATES / 10);
uint32_t speed = ((Settings->light_speed * 2) -1) * (STATES / 10);
uint32_t offset = speed > 0 ? Light.strip_timer_counter / speed : 0;
WsColor oldColor, currentColor;
Ws2812GradientColor(schemenr, &oldColor, range, gradRange, offset);
currentColor = oldColor;
speed = speed ? speed : 1; // should never happen, just avoid div0
for (uint32_t i = 0; i < Settings.light_pixels; i++) {
if (kWsRepeat[Settings.light_width] > 1) {
for (uint32_t i = 0; i < Settings->light_pixels; i++) {
if (kWsRepeat[Settings->light_width] > 1) {
Ws2812GradientColor(schemenr, &currentColor, range, gradRange, i + offset + 1);
}
// Blend old and current color based on time for smooth movement.
@ -371,15 +371,15 @@ void Ws2812Bars(uint32_t schemenr)
ColorScheme scheme = kSchemes[schemenr];
uint32_t maxSize = Settings.light_pixels / scheme.count;
if (kWidth[Settings.light_width] > maxSize) { maxSize = 0; }
uint32_t maxSize = Settings->light_pixels / scheme.count;
if (kWidth[Settings->light_width] > maxSize) { maxSize = 0; }
uint32_t speed = ((Settings.light_speed * 2) -1) * (STATES / 10);
uint32_t speed = ((Settings->light_speed * 2) -1) * (STATES / 10);
uint32_t offset = (speed > 0) ? Light.strip_timer_counter / speed : 0;
WsColor mcolor[scheme.count];
memcpy(mcolor, scheme.colors, sizeof(mcolor));
float dimmer = 100 / (float)Settings.light_dimmer;
float dimmer = 100 / (float)Settings->light_dimmer;
for (uint32_t i = 0; i < scheme.count; i++) {
float fmyRed = (float)mcolor[i].red / dimmer;
float fmyGrn = (float)mcolor[i].green / dimmer;
@ -389,8 +389,8 @@ void Ws2812Bars(uint32_t schemenr)
mcolor[i].blue = (uint8_t)fmyBlu;
}
uint32_t colorIndex = offset % scheme.count;
for (uint32_t i = 0; i < Settings.light_pixels; i++) {
if (maxSize) { colorIndex = ((i + offset) % (scheme.count * kWidth[Settings.light_width])) / kWidth[Settings.light_width]; }
for (uint32_t i = 0; i < Settings->light_pixels; i++) {
if (maxSize) { colorIndex = ((i + offset) % (scheme.count * kWidth[Settings->light_width])) / kWidth[Settings->light_width]; }
c.R = mcolor[colorIndex].red;
c.G = mcolor[colorIndex].green;
c.B = mcolor[colorIndex].blue;
@ -422,7 +422,7 @@ void Ws2812SetColor(uint32_t led, uint8_t red, uint8_t green, uint8_t blue, uint
strip->SetPixelColor(led -1, lcolor); // Led 1 is strip Led 0 -> substract offset 1
} else {
// strip->ClearTo(lcolor); // Set WS2812_MAX_LEDS pixels
for (uint32_t i = 0; i < Settings.light_pixels; i++) {
for (uint32_t i = 0; i < Settings->light_pixels; i++) {
strip->SetPixelColor(i, lcolor);
}
}
@ -448,7 +448,7 @@ char* Ws2812GetColor(uint32_t led, char* scolor)
sl_ledcolor[2] = lcolor.B;
scolor[0] = '\0';
for (uint32_t i = 0; i < Light.subtype; i++) {
if (Settings.flag.decimal_text) { // SetOption17 - Switch between decimal or hexadecimal output (0 = hexadecimal, 1 = decimal)
if (Settings->flag.decimal_text) { // SetOption17 - Switch between decimal or hexadecimal output (0 = hexadecimal, 1 = decimal)
snprintf_P(scolor, 25, PSTR("%s%s%d"), scolor, (i > 0) ? "," : "", sl_ledcolor[i]);
} else {
snprintf_P(scolor, 25, PSTR("%s%02X"), scolor, sl_ledcolor[i]);
@ -486,7 +486,7 @@ bool Ws2812SetChannels(void)
void Ws2812ShowScheme(void)
{
uint32_t scheme = Settings.light_scheme - Ws2812.scheme_offset;
uint32_t scheme = Settings->light_scheme - Ws2812.scheme_offset;
switch (scheme) {
case 0: // Clock
@ -496,7 +496,7 @@ void Ws2812ShowScheme(void)
}
break;
default:
if (1 == Settings.light_fade) {
if (1 == Settings->light_fade) {
Ws2812Gradient(scheme -1);
} else {
Ws2812Bars(scheme -1);
@ -536,7 +536,7 @@ void Ws2812ModuleSelected(void)
void CmndLed(void)
{
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= Settings.light_pixels)) {
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= Settings->light_pixels)) {
if (XdrvMailbox.data_len > 0) {
char *p;
uint16_t idx = XdrvMailbox.index;
@ -545,7 +545,7 @@ void CmndLed(void)
if (LightColorEntry(color, strlen(color))) {
Ws2812SetColor(idx, Light.entry_color[0], Light.entry_color[1], Light.entry_color[2], Light.entry_color[3]);
idx++;
if (idx > Settings.light_pixels) { break; }
if (idx > Settings->light_pixels) { break; }
} else {
break;
}
@ -560,20 +560,20 @@ void CmndLed(void)
void CmndPixels(void)
{
if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= WS2812_MAX_LEDS)) {
Settings.light_pixels = XdrvMailbox.payload;
Settings.light_rotation = 0;
Settings->light_pixels = XdrvMailbox.payload;
Settings->light_rotation = 0;
Ws2812Clear();
Light.update = true;
}
ResponseCmndNumber(Settings.light_pixels);
ResponseCmndNumber(Settings->light_pixels);
}
void CmndRotation(void)
{
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < Settings.light_pixels)) {
Settings.light_rotation = XdrvMailbox.payload;
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < Settings->light_pixels)) {
Settings->light_rotation = XdrvMailbox.payload;
}
ResponseCmndNumber(Settings.light_rotation);
ResponseCmndNumber(Settings->light_rotation);
}
void CmndWidth(void)
@ -581,14 +581,14 @@ void CmndWidth(void)
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 4)) {
if (1 == XdrvMailbox.index) {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 4)) {
Settings.light_width = XdrvMailbox.payload;
Settings->light_width = XdrvMailbox.payload;
}
ResponseCmndNumber(Settings.light_width);
ResponseCmndNumber(Settings->light_width);
} else {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 32)) {
Settings.ws_width[XdrvMailbox.index -2] = XdrvMailbox.payload;
Settings->ws_width[XdrvMailbox.index -2] = XdrvMailbox.payload;
}
ResponseCmndIdxNumber(Settings.ws_width[XdrvMailbox.index -2]);
ResponseCmndIdxNumber(Settings->ws_width[XdrvMailbox.index -2]);
}
}
}

View File

@ -124,7 +124,7 @@ bool Sm16716SetChannels(void)
for (uint32_t i = 3; i < Light.subtype; i++) {
if (PinUsed(GPIO_PWM1, i-3)) {
//AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "Cur_Col%d 10 bits %d, Pwm%d %d"), i, cur_col[i], i+1, curcol);
analogWrite(Pin(GPIO_PWM1, i-3), bitRead(TasmotaGlobal.pwm_inverted, i-3) ? Settings.pwm_range - cur_col_10bits[i] : cur_col_10bits[i]);
analogWrite(Pin(GPIO_PWM1, i-3), bitRead(TasmotaGlobal.pwm_inverted, i-3) ? Settings->pwm_range - cur_col_10bits[i] : cur_col_10bits[i]);
}
}
*/
@ -146,7 +146,7 @@ void Sm16716ModuleSelected(void)
/*
// init PWM
for (uint32_t i = 0; i < Light.subtype; i++) {
Settings.pwm_value[i] = 0; // Disable direct PWM control
Settings->pwm_value[i] = 0; // Disable direct PWM control
if (PinUsed(GPIO_PWM1, i)) {
#ifdef ESP8266
pinMode(Pin(GPIO_PWM1, i), OUTPUT);

View File

@ -167,9 +167,9 @@ bool SnfL1SerialInput(void) {
// AddLog(LOG_LEVEL_DEBUG, PSTR("SL1: Rcvd color R%d G%d B%d (R%d G%d B%d)"),
// Snfl1.color[0], Snfl1.color[1], Snfl1.color[2],
// Settings.light_color[0], Settings.light_color[1], Settings.light_color[2]);
// Settings->light_color[0], Settings->light_color[1], Settings->light_color[2]);
is_color_change = (Light.power && (memcmp(Snfl1.color, Settings.light_color, 3) != 0));
is_color_change = (Light.power && (memcmp(Snfl1.color, Settings->light_color, 3) != 0));
}
snprintf_P(cmnd_color, sizeof(cmnd_color), PSTR(D_CMND_COLOR "2 %02x%02x%02x"), Snfl1.color[0], Snfl1.color[1], Snfl1.color[2]);
}
@ -177,9 +177,9 @@ bool SnfL1SerialInput(void) {
else if (!strncmp(token2, "\"bright\"", 8)) {
uint8_t dimmer = atoi(token3);
// AddLog(LOG_LEVEL_DEBUG, PSTR("SL1: Rcvd dimmer %d (%d)"), dimmer, Settings.light_dimmer);
// AddLog(LOG_LEVEL_DEBUG, PSTR("SL1: Rcvd dimmer %d (%d)"), dimmer, Settings->light_dimmer);
is_brightness_change = (Light.power && (dimmer > 0) && (dimmer != Settings.light_dimmer));
is_brightness_change = (Light.power && (dimmer > 0) && (dimmer != Settings->light_dimmer));
snprintf_P(cmnd_dimmer, sizeof(cmnd_dimmer), PSTR(D_CMND_DIMMER " %d"), dimmer);
}
@ -187,7 +187,7 @@ bool SnfL1SerialInput(void) {
}
if (is_power_change) {
if (Settings.light_scheme > 0) {
if (Settings->light_scheme > 0) {
if (!switch_state) { // If power off RC button pressed stop schemes
char cmnd_scheme[20];
snprintf_P(cmnd_scheme, sizeof(cmnd_scheme), PSTR(D_CMND_SCHEME " 0"));
@ -201,13 +201,13 @@ bool SnfL1SerialInput(void) {
ExecuteCommand(cmnd_dimmer, SRC_REMOTE);
}
else if (Light.power && is_color_change) {
if (0 == Settings.light_scheme) { // Fix spurious color receptions when scheme > 0
if (Settings.light_fade) { // Disable fade as RC button colors overrule and are immediate supressing ghost colors
if (0 == Settings->light_scheme) { // Fix spurious color receptions when scheme > 0
if (Settings->light_fade) { // Disable fade as RC button colors overrule and are immediate supressing ghost colors
char cmnd_fade[20];
snprintf_P(cmnd_fade, sizeof(cmnd_fade), PSTR(D_CMND_FADE " 0"));
ExecuteCommand(cmnd_fade, SRC_REMOTE);
}
if (Settings.light_correction) { // Disable ledtable as RC button colors overrule and are immediate supressing ghost colors
if (Settings->light_correction) { // Disable ledtable as RC button colors overrule and are immediate supressing ghost colors
char cmnd_fade[20];
snprintf_P(cmnd_fade, sizeof(cmnd_fade), PSTR(D_CMND_LEDTABLE " 0"));
ExecuteCommand(cmnd_fade, SRC_REMOTE);

View File

@ -134,7 +134,7 @@ void HlwEvery200ms(void) {
Hlw.cf_pulse_counter = 0;
if (Hlw.cf_power_pulse_length && Energy.power_on && !Hlw.load_off) {
hlw_w = (Hlw.power_ratio * Settings.energy_power_calibration) / Hlw.cf_power_pulse_length ; // W *10
hlw_w = (Hlw.power_ratio * Settings->energy_power_calibration) / Hlw.cf_power_pulse_length ; // W *10
Energy.active_power[0] = (float)hlw_w / 10;
Hlw.power_retry = 1; // Workaround issue #5161
} else {
@ -179,7 +179,7 @@ void HlwEvery200ms(void) {
Hlw.cf1_voltage_pulse_length = cf1_pulse_length;
if (Hlw.cf1_voltage_pulse_length && Energy.power_on) { // If powered on always provide voltage
hlw_u = (Hlw.voltage_ratio * Settings.energy_voltage_calibration) / Hlw.cf1_voltage_pulse_length ; // V *10
hlw_u = (Hlw.voltage_ratio * Settings->energy_voltage_calibration) / Hlw.cf1_voltage_pulse_length ; // V *10
Energy.voltage[0] = (float)hlw_u / 10;
} else {
Energy.voltage[0] = 0;
@ -189,7 +189,7 @@ void HlwEvery200ms(void) {
Hlw.cf1_current_pulse_length = cf1_pulse_length;
if (Hlw.cf1_current_pulse_length && Energy.active_power[0]) { // No current if no power being consumed
hlw_i = (Hlw.current_ratio * Settings.energy_current_calibration) / Hlw.cf1_current_pulse_length; // mA
hlw_i = (Hlw.current_ratio * Settings->energy_current_calibration) / Hlw.cf1_current_pulse_length; // mA
Energy.current[0] = (float)hlw_i / 1000;
} else {
Energy.current[0] = 0;
@ -214,7 +214,7 @@ void HlwEverySecond(void) {
hlw_len = 10000 * 100 / Hlw.energy_period_counter; // Add *100 to fix rounding on loads at 3.6kW (#9160)
Hlw.energy_period_counter = 0;
if (hlw_len) {
Energy.kWhtoday_delta += (((Hlw.power_ratio * Settings.energy_power_calibration) / 36) * 100) / hlw_len;
Energy.kWhtoday_delta += (((Hlw.power_ratio * Settings->energy_power_calibration) / 36) * 100) / hlw_len;
EnergyUpdateToday();
}
}
@ -222,10 +222,10 @@ void HlwEverySecond(void) {
}
void HlwSnsInit(void) {
if (!Settings.energy_power_calibration || (4975 == Settings.energy_power_calibration)) {
Settings.energy_power_calibration = HLW_PREF_PULSE;
Settings.energy_voltage_calibration = HLW_UREF_PULSE;
Settings.energy_current_calibration = HLW_IREF_PULSE;
if (!Settings->energy_power_calibration || (4975 == Settings->energy_power_calibration)) {
Settings->energy_power_calibration = HLW_PREF_PULSE;
Settings->energy_voltage_calibration = HLW_UREF_PULSE;
Settings->energy_current_calibration = HLW_IREF_PULSE;
}
if (Hlw.model_type) {
@ -287,17 +287,17 @@ bool HlwCommand(void) {
}
else if (CMND_POWERSET == Energy.command_code) {
if (XdrvMailbox.data_len && Hlw.cf_power_pulse_length ) {
Settings.energy_power_calibration = ((uint32_t)(CharToFloat(XdrvMailbox.data) * 10) * Hlw.cf_power_pulse_length ) / Hlw.power_ratio;
Settings->energy_power_calibration = ((uint32_t)(CharToFloat(XdrvMailbox.data) * 10) * Hlw.cf_power_pulse_length ) / Hlw.power_ratio;
}
}
else if (CMND_VOLTAGESET == Energy.command_code) {
if (XdrvMailbox.data_len && Hlw.cf1_voltage_pulse_length ) {
Settings.energy_voltage_calibration = ((uint32_t)(CharToFloat(XdrvMailbox.data) * 10) * Hlw.cf1_voltage_pulse_length ) / Hlw.voltage_ratio;
Settings->energy_voltage_calibration = ((uint32_t)(CharToFloat(XdrvMailbox.data) * 10) * Hlw.cf1_voltage_pulse_length ) / Hlw.voltage_ratio;
}
}
else if (CMND_CURRENTSET == Energy.command_code) {
if (XdrvMailbox.data_len && Hlw.cf1_current_pulse_length) {
Settings.energy_current_calibration = ((uint32_t)(CharToFloat(XdrvMailbox.data)) * Hlw.cf1_current_pulse_length) / Hlw.current_ratio;
Settings->energy_current_calibration = ((uint32_t)(CharToFloat(XdrvMailbox.data)) * Hlw.cf1_current_pulse_length) / Hlw.current_ratio;
}
}
else serviced = false; // Unknown command

View File

@ -73,26 +73,26 @@ void CseReceived(void) {
}
// Get chip calibration data (coefficients) and use as initial defaults
if (HLW_UREF_PULSE == Settings.energy_voltage_calibration) {
if (HLW_UREF_PULSE == Settings->energy_voltage_calibration) {
long voltage_coefficient = 191200; // uSec
if (CSE_NOT_CALIBRATED != header) {
voltage_coefficient = Cse.rx_buffer[2] << 16 | Cse.rx_buffer[3] << 8 | Cse.rx_buffer[4];
}
Settings.energy_voltage_calibration = voltage_coefficient / CSE_UREF;
Settings->energy_voltage_calibration = voltage_coefficient / CSE_UREF;
}
if (HLW_IREF_PULSE == Settings.energy_current_calibration) {
if (HLW_IREF_PULSE == Settings->energy_current_calibration) {
long current_coefficient = 16140; // uSec
if (CSE_NOT_CALIBRATED != header) {
current_coefficient = Cse.rx_buffer[8] << 16 | Cse.rx_buffer[9] << 8 | Cse.rx_buffer[10];
}
Settings.energy_current_calibration = current_coefficient;
Settings->energy_current_calibration = current_coefficient;
}
if (HLW_PREF_PULSE == Settings.energy_power_calibration) {
if (HLW_PREF_PULSE == Settings->energy_power_calibration) {
long power_coefficient = 5364000; // uSec
if (CSE_NOT_CALIBRATED != header) {
power_coefficient = Cse.rx_buffer[14] << 16 | Cse.rx_buffer[15] << 8 | Cse.rx_buffer[16];
}
Settings.energy_power_calibration = power_coefficient / CSE_PREF;
Settings->energy_power_calibration = power_coefficient / CSE_PREF;
}
uint8_t adjustement = Cse.rx_buffer[20];
@ -103,7 +103,7 @@ void CseReceived(void) {
if (Energy.power_on) { // Powered on
if (adjustement & 0x40) { // Voltage valid
Energy.voltage[0] = (float)(Settings.energy_voltage_calibration * CSE_UREF) / (float)Cse.voltage_cycle;
Energy.voltage[0] = (float)(Settings->energy_voltage_calibration * CSE_UREF) / (float)Cse.voltage_cycle;
}
if (adjustement & 0x10) { // Power valid
Cse.power_invalid = 0;
@ -113,13 +113,13 @@ void CseReceived(void) {
if (0 == Cse.power_cycle_first) { Cse.power_cycle_first = Cse.power_cycle; } // Skip first incomplete Cse.power_cycle
if (Cse.power_cycle_first != Cse.power_cycle) {
Cse.power_cycle_first = -1;
Energy.active_power[0] = (float)(Settings.energy_power_calibration * CSE_PREF) / (float)Cse.power_cycle;
Energy.active_power[0] = (float)(Settings->energy_power_calibration * CSE_PREF) / (float)Cse.power_cycle;
} else {
Energy.active_power[0] = 0;
}
}
} else {
if (Cse.power_invalid < Settings.param[P_CSE7766_INVALID_POWER]) { // Allow measurements down to about 1W
if (Cse.power_invalid < Settings->param[P_CSE7766_INVALID_POWER]) { // Allow measurements down to about 1W
Cse.power_invalid++;
} else {
Cse.power_cycle_first = 0;
@ -130,7 +130,7 @@ void CseReceived(void) {
if (0 == Energy.active_power[0]) {
Energy.current[0] = 0;
} else {
Energy.current[0] = (float)Settings.energy_current_calibration / (float)Cse.current_cycle;
Energy.current[0] = (float)Settings->energy_current_calibration / (float)Cse.current_cycle;
}
}
} else { // Powered off
@ -200,7 +200,7 @@ void CseEverySecond(void) {
cf_pulses = Cse.cf_pulses - Cse.cf_pulses_last_time;
}
if (cf_pulses && Energy.active_power[0]) {
uint32_t delta = (cf_pulses * Settings.energy_power_calibration) / 36;
uint32_t delta = (cf_pulses * Settings->energy_power_calibration) / 36;
// prevent invalid load delta steps even checksum is valid (issue #5789):
// prevent invalid load delta steps even checksum is valid but allow up to 4kW (issue #7155):
if (delta <= (4000 * 1000 / 36)) { // max load for S31/Pow R2: 4.00kW
@ -226,10 +226,10 @@ void CseSnsInit(void) {
SetSerial(4800, TS_SERIAL_8E1);
ClaimSerial();
}
if (0 == Settings.param[P_CSE7766_INVALID_POWER]) {
Settings.param[P_CSE7766_INVALID_POWER] = CSE_MAX_INVALID_POWER; // SetOption39 1..255
if (0 == Settings->param[P_CSE7766_INVALID_POWER]) {
Settings->param[P_CSE7766_INVALID_POWER] = CSE_MAX_INVALID_POWER; // SetOption39 1..255
}
Cse.power_invalid = Settings.param[P_CSE7766_INVALID_POWER];
Cse.power_invalid = Settings->param[P_CSE7766_INVALID_POWER];
Energy.use_overtemp = true; // Use global temperature for overtemp detection
} else {
TasmotaGlobal.energy_driver = ENERGY_NONE;
@ -251,17 +251,17 @@ bool CseCommand(void) {
if (CMND_POWERSET == Energy.command_code) {
if (XdrvMailbox.data_len && Cse.power_cycle) {
Settings.energy_power_calibration = (unsigned long)(CharToFloat(XdrvMailbox.data) * Cse.power_cycle) / CSE_PREF;
Settings->energy_power_calibration = (unsigned long)(CharToFloat(XdrvMailbox.data) * Cse.power_cycle) / CSE_PREF;
}
}
else if (CMND_VOLTAGESET == Energy.command_code) {
if (XdrvMailbox.data_len && Cse.voltage_cycle) {
Settings.energy_voltage_calibration = (unsigned long)(CharToFloat(XdrvMailbox.data) * Cse.voltage_cycle) / CSE_UREF;
Settings->energy_voltage_calibration = (unsigned long)(CharToFloat(XdrvMailbox.data) * Cse.voltage_cycle) / CSE_UREF;
}
}
else if (CMND_CURRENTSET == Energy.command_code) {
if (XdrvMailbox.data_len && Cse.current_cycle) {
Settings.energy_current_calibration = (unsigned long)(CharToFloat(XdrvMailbox.data) * Cse.current_cycle) / 1000;
Settings->energy_current_calibration = (unsigned long)(CharToFloat(XdrvMailbox.data) * Cse.current_cycle) / 1000;
}
}
else serviced = false; // Unknown command

View File

@ -214,15 +214,15 @@ void McpParseCalibration(void)
cal_registers.accumulation_interval = McpExtractInt(mcp_buffer, 52, 2);
if (mcp_calibrate & MCP_CALIBRATE_POWER) {
cal_registers.calibration_active_power = Settings.energy_power_calibration;
cal_registers.calibration_active_power = Settings->energy_power_calibration;
if (McpCalibrationCalc(&cal_registers, 16)) { action = true; }
}
if (mcp_calibrate & MCP_CALIBRATE_VOLTAGE) {
cal_registers.calibration_voltage = Settings.energy_voltage_calibration;
cal_registers.calibration_voltage = Settings->energy_voltage_calibration;
if (McpCalibrationCalc(&cal_registers, 0)) { action = true; }
}
if (mcp_calibrate & MCP_CALIBRATE_CURRENT) {
cal_registers.calibration_current = Settings.energy_current_calibration;
cal_registers.calibration_current = Settings->energy_current_calibration;
if (McpCalibrationCalc(&cal_registers, 8)) { action = true; }
}
mcp_timeout = 0;
@ -230,9 +230,9 @@ void McpParseCalibration(void)
mcp_calibrate = 0;
Settings.energy_power_calibration = cal_registers.calibration_active_power;
Settings.energy_voltage_calibration = cal_registers.calibration_voltage;
Settings.energy_current_calibration = cal_registers.calibration_current;
Settings->energy_power_calibration = cal_registers.calibration_active_power;
Settings->energy_voltage_calibration = cal_registers.calibration_voltage;
Settings->energy_current_calibration = cal_registers.calibration_current;
mcp_system_configuration = cal_registers.system_configuration;
@ -386,7 +386,7 @@ void McpParseFrequency(void)
uint16_t gain_line_frequency = mcp_buffer[4] * 256 + mcp_buffer[5];
if (mcp_calibrate & MCP_CALIBRATE_FREQUENCY) {
line_frequency_ref = Settings.energy_frequency_calibration;
line_frequency_ref = Settings->energy_frequency_calibration;
if ((0xFFFF == mcp_line_frequency) || (0 == gain_line_frequency)) { // Reset values to 50Hz
mcp_line_frequency = 50000;
@ -398,7 +398,7 @@ void McpParseFrequency(void)
McpSetFrequency(line_frequency_ref, gain_line_frequency);
}
Settings.energy_frequency_calibration = line_frequency_ref;
Settings->energy_frequency_calibration = line_frequency_ref;
mcp_calibrate = 0;
}
@ -602,7 +602,7 @@ bool McpCommand(void)
if (XdrvMailbox.data_len && mcp_active_power) {
value = (unsigned long)(CharToFloat(XdrvMailbox.data) * 100);
if ((value > 100) && (value < 200000)) { // Between 1W and 2000W
Settings.energy_power_calibration = value;
Settings->energy_power_calibration = value;
mcp_calibrate |= MCP_CALIBRATE_POWER;
McpGetCalibration();
}
@ -612,7 +612,7 @@ bool McpCommand(void)
if (XdrvMailbox.data_len && mcp_voltage_rms) {
value = (unsigned long)(CharToFloat(XdrvMailbox.data) * 10);
if ((value > 1000) && (value < 2600)) { // Between 100V and 260V
Settings.energy_voltage_calibration = value;
Settings->energy_voltage_calibration = value;
mcp_calibrate |= MCP_CALIBRATE_VOLTAGE;
McpGetCalibration();
}
@ -622,7 +622,7 @@ bool McpCommand(void)
if (XdrvMailbox.data_len && mcp_current_rms) {
value = (unsigned long)(CharToFloat(XdrvMailbox.data) * 10);
if ((value > 100) && (value < 80000)) { // Between 10mA and 8A
Settings.energy_current_calibration = value;
Settings->energy_current_calibration = value;
mcp_calibrate |= MCP_CALIBRATE_CURRENT;
McpGetCalibration();
}
@ -632,7 +632,7 @@ bool McpCommand(void)
if (XdrvMailbox.data_len && mcp_line_frequency) {
value = (unsigned long)(CharToFloat(XdrvMailbox.data) * 1000);
if ((value > 45000) && (value < 65000)) { // Between 45Hz and 65Hz
Settings.energy_frequency_calibration = value;
Settings->energy_frequency_calibration = value;
mcp_calibrate |= MCP_CALIBRATE_FREQUENCY;
McpGetFrequency();
}

View File

@ -160,18 +160,18 @@ void Ade7953GetData(void)
Ade7953.active_power[0], Ade7953.active_power[1], active_power_sum);
if (Energy.power_on) { // Powered on
Energy.voltage[0] = (float)Ade7953.voltage_rms / Settings.energy_voltage_calibration;
Energy.voltage[0] = (float)Ade7953.voltage_rms / Settings->energy_voltage_calibration;
Energy.frequency[0] = 223750.0f / ( (float)Ade7953.period + 1);
for (uint32_t channel = 0; channel < 2; channel++) {
Energy.data_valid[channel] = 0;
Energy.active_power[channel] = (float)Ade7953.active_power[channel] / (Settings.energy_power_calibration / 10);
Energy.reactive_power[channel] = (float)reactive_power[channel] / (Settings.energy_power_calibration / 10);
Energy.apparent_power[channel] = (float)apparent_power[channel] / (Settings.energy_power_calibration / 10);
Energy.active_power[channel] = (float)Ade7953.active_power[channel] / (Settings->energy_power_calibration / 10);
Energy.reactive_power[channel] = (float)reactive_power[channel] / (Settings->energy_power_calibration / 10);
Energy.apparent_power[channel] = (float)apparent_power[channel] / (Settings->energy_power_calibration / 10);
if (0 == Energy.active_power[channel]) {
Energy.current[channel] = 0;
} else {
Energy.current[channel] = (float)Ade7953.current_rms[channel] / (Settings.energy_current_calibration * 10);
Energy.current[channel] = (float)Ade7953.current_rms[channel] / (Settings->energy_current_calibration * 10);
}
}
/*
@ -182,7 +182,7 @@ void Ade7953GetData(void)
}
if (active_power_sum) {
Energy.kWhtoday_delta += ((active_power_sum * (100000 / (Settings.energy_power_calibration / 10))) / 3600);
Energy.kWhtoday_delta += ((active_power_sum * (100000 / (Settings->energy_power_calibration / 10))) / 3600);
EnergyUpdateToday();
}
}
@ -205,10 +205,10 @@ void Ade7953DrvInit(void)
pinMode(Pin(GPIO_ADE7953_IRQ), INPUT); // Related to resetPins() - Must be set to input
delay(100); // Need 100mS to init ADE7953
if (I2cSetDevice(ADE7953_ADDR)) {
if (HLW_PREF_PULSE == Settings.energy_power_calibration) {
Settings.energy_power_calibration = ADE7953_PREF;
Settings.energy_voltage_calibration = ADE7953_UREF;
Settings.energy_current_calibration = ADE7953_IREF;
if (HLW_PREF_PULSE == Settings->energy_power_calibration) {
Settings->energy_power_calibration = ADE7953_PREF;
Settings->energy_voltage_calibration = ADE7953_UREF;
Settings->energy_current_calibration = ADE7953_IREF;
}
I2cSetActiveFound(ADE7953_ADDR, "ADE7953");
Ade7953.init_step = 2;
@ -243,21 +243,21 @@ bool Ade7953Command(void)
else if (CMND_POWERSET == Energy.command_code) {
if (XdrvMailbox.data_len && Ade7953.active_power[channel]) {
if ((value > 100) && (value < 200000)) { // Between 1W and 2000W
Settings.energy_power_calibration = (Ade7953.active_power[channel] * 1000) / value; // 0.00 W
Settings->energy_power_calibration = (Ade7953.active_power[channel] * 1000) / value; // 0.00 W
}
}
}
else if (CMND_VOLTAGESET == Energy.command_code) {
if (XdrvMailbox.data_len && Ade7953.voltage_rms) {
if ((value > 10000) && (value < 26000)) { // Between 100V and 260V
Settings.energy_voltage_calibration = (Ade7953.voltage_rms * 100) / value; // 0.00 V
Settings->energy_voltage_calibration = (Ade7953.voltage_rms * 100) / value; // 0.00 V
}
}
}
else if (CMND_CURRENTSET == Energy.command_code) {
if (XdrvMailbox.data_len && Ade7953.current_rms[channel]) {
if ((value > 2000) && (value < 1000000)) { // Between 20mA and 10A
Settings.energy_current_calibration = ((Ade7953.current_rms[channel] * 100) / value) * 100; // 0.00 mA
Settings->energy_current_calibration = ((Ade7953.current_rms[channel] * 100) / value) * 100; // 0.00 mA
}
}
}

View File

@ -214,11 +214,11 @@ void Sdm220Show(bool json)
if (isnan(Sdm120.import_active)) { return; }
char import_active_chr[FLOATSZ];
dtostrfd(Sdm120.import_active, Settings.flag2.energy_resolution, import_active_chr);
dtostrfd(Sdm120.import_active, Settings->flag2.energy_resolution, import_active_chr);
char import_reactive_chr[FLOATSZ];
dtostrfd(Sdm120.import_reactive, Settings.flag2.energy_resolution, import_reactive_chr);
dtostrfd(Sdm120.import_reactive, Settings->flag2.energy_resolution, import_reactive_chr);
char export_reactive_chr[FLOATSZ];
dtostrfd(Sdm120.export_reactive, Settings.flag2.energy_resolution, export_reactive_chr);
dtostrfd(Sdm120.export_reactive, Settings->flag2.energy_resolution, export_reactive_chr);
char phase_angle_chr[FLOATSZ];
dtostrfd(Sdm120.phase_angle, 2, phase_angle_chr);

View File

@ -71,7 +71,7 @@ void Dds2382EverySecond(void)
Energy.power_factor[0] = (float)((buffer[35] << 8) + buffer[36]) / 1000.0; // 1.00
Energy.frequency[0] = (float)((buffer[37] << 8) + buffer[38]) / 100.0; // 50.0 Hz
uint8_t offset = 11;
if (Settings.flag3.dds2382_model) { // SetOption71 - Select different Modbus registers for Active Energy (#6531)
if (Settings->flag3.dds2382_model) { // SetOption71 - Select different Modbus registers for Active Energy (#6531)
offset = 19;
}
Energy.export_active[0] = (float)((buffer[offset] << 24) + (buffer[offset +1] << 16) + (buffer[offset +2] << 8) + buffer[offset +3]) / 100.0; // 429496.729 kW

Some files were not shown because too many files have changed in this diff Show More