diff --git a/.github/workflows/Tasmota_build_development.yml b/.github/workflows/Tasmota_build_development.yml index de2417614..aaac05510 100644 --- a/.github/workflows/Tasmota_build_development.yml +++ b/.github/workflows/Tasmota_build_development.yml @@ -1361,7 +1361,7 @@ jobs: - name: Display files to transfer run: ls -R ./* - name: Push Firmware files to https://github.com/arendst/Tasmota-firmware - uses: dmnemec/copy_file_to_another_repo_action@main + uses: Jason2866/copy_file_to_another_repo_action@main env: API_TOKEN_GITHUB: ${{ secrets.API_TOKEN_GITHUB }} with: @@ -1374,7 +1374,7 @@ jobs: echo ${GITHUB_SHA} &> trigger.txt echo "$( trigger.txt echo "$(reg; } else if (var_isclass(b) && var_isstr(c)) { - class_attribute(vm, b, c, a); + class_attribute(vm, b, c, &a_temp); reg = vm->reg; } else if (var_ismodule(b) && var_isstr(c)) { - module_attribute(vm, b, c, a); + module_attribute(vm, b, c, &a_temp); reg = vm->reg; } else { attribute_error(vm, "attribute", b, c); } + bvalue *a = RA(); + *a = a_temp; /* assign the resul to the specified register on the updated stack */ dispatch(); } opcase(GETMET): { - bvalue *a = RA(), *b = RKB(), *c = RKC(); + bvalue a_temp; /* copy result to a temp variable because the stack may be relocated in virtual member calls */ + bvalue *b = RKB(), *c = RKC(); if (var_isinstance(b) && var_isstr(c)) { binstance *obj = var_toobj(b); - int type = obj_attribute(vm, b, var_tostr(c), a); + int type = obj_attribute(vm, b, var_tostr(c), &a_temp); reg = vm->reg; + bvalue *a = RA(); + *a = a_temp; if (basetype(type) == BE_FUNCTION) { /* check if the object is a superinstance, if so get the lowest possible subclass */ while (obj->sub) { @@ -819,7 +826,10 @@ newframe: /* a new call frame */ str(be_instance_name(obj)), str(var_tostr(c))); } } else if (var_ismodule(b) && var_isstr(c)) { - module_attribute(vm, b, c, &a[1]); + module_attribute(vm, b, c, &a_temp); + reg = vm->reg; + bvalue *a = RA(); + a[1] = a_temp; var_settype(a, NOT_METHOD); } else { attribute_error(vm, "method", b, c); diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 1edee92e2..967560e03 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -96,7 +96,11 @@ #define OTA_URL "http://ota.tasmota.com/tasmota/release/tasmota.bin.gz" // [OtaUrl] #endif // ESP8266 #ifdef ESP32 +#ifdef CONFIG_IDF_TARGET_ESP32C3 +#define OTA_URL "http://ota.tasmota.com/tasmota32/release/tasmota32c3.bin" // [OtaUrl] +#else // No CONFIG_IDF_TARGET_ESP32C3 #define OTA_URL "http://ota.tasmota.com/tasmota32/release/tasmota32.bin" // [OtaUrl] +#endif // CONFIG_IDF_TARGET_ESP32C3 #endif // ESP32 // -- MQTT ---------------------------------------- diff --git a/tasmota/settings.h b/tasmota/settings.h index 2a4ba3917..4e41c5916 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -483,9 +483,9 @@ typedef struct { int16_t toffset[2]; // 30E uint8_t display_font; // 312 DisplayOptions display_options; // 313 - uint32_t energy_kWhtoday_ph[3]; // 314 - uint32_t energy_kWhyesterday_ph[3]; // 320 - uint32_t energy_kWhtotal_ph[3]; // 32C + int32_t energy_kWhtoday_ph[3]; // 314 + int32_t energy_kWhyesterday_ph[3]; // 320 + int32_t energy_kWhtotal_ph[3]; // 32C uint8_t free_338[7]; // 338 @@ -786,8 +786,8 @@ typedef struct { uint8_t free_2d6[2]; // 2D6 - uint32_t energy_kWhtoday_ph[3]; // 2D8 - uint32_t energy_kWhtotal_ph[3]; // 2E4 + int32_t energy_kWhtoday_ph[3]; // 2D8 + int32_t energy_kWhtotal_ph[3]; // 2E4 // 2F0 - 2FF free locations } TRtcSettings; diff --git a/tasmota/settings.ino b/tasmota/settings.ino index 575621071..a3b6e1126 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -287,11 +287,11 @@ void UpdateQuickPowerCycle(bool update) { void EmergencyReset(void) { Serial.begin(115200); - Serial.write(0xAA); - Serial.write(0x55); + Serial.write(0xA5); + Serial.write(0x5A); delay(1); if (Serial.available() == 2) { - if ((Serial.read() == 0xAA) && (Serial.read() == 0x55)) { + if ((Serial.read() == 0xA5) && (Serial.read() == 0x5A)) { SettingsErase(3); // Reset all settings including QuickPowerCycle flag do { // Wait for user to remove Rx Tx jumper and power cycle @@ -302,7 +302,8 @@ void EmergencyReset(void) { ESP_Restart(); // Restart to init default settings } } - while (Serial.available()) { Serial.read(); } // Flush input buffer + Serial.println(); + Serial.flush(); #ifdef ESP32 delay(10); // Allow time to cleanup queues - if not used hangs ESP32 Serial.end(); diff --git a/tasmota/xdrv_03_energy.ino b/tasmota/xdrv_03_energy.ino index dbd1118aa..b35e39b6d 100644 --- a/tasmota/xdrv_03_energy.ino +++ b/tasmota/xdrv_03_energy.ino @@ -90,10 +90,10 @@ struct ENERGY { float total_sum; // 12345.12345 kWh total energy float yesterday_sum; // 123.123 kWh - uint32_t kWhtoday_delta[ENERGY_MAX_PHASES]; // 1212312345 Wh 10^-5 (deca micro Watt hours) - Overflows to Energy.kWhtoday (HLW and CSE only) - uint32_t kWhtoday_offset[ENERGY_MAX_PHASES]; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = Energy.daily - uint32_t kWhtoday[ENERGY_MAX_PHASES]; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = Energy.daily - uint32_t period[ENERGY_MAX_PHASES]; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = Energy.daily + int32_t kWhtoday_delta[ENERGY_MAX_PHASES]; // 1212312345 Wh 10^-5 (deca micro Watt hours) - Overflows to Energy.kWhtoday (HLW and CSE only) + int32_t kWhtoday_offset[ENERGY_MAX_PHASES]; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = Energy.daily + int32_t kWhtoday[ENERGY_MAX_PHASES]; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = Energy.daily + int32_t period[ENERGY_MAX_PHASES]; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = Energy.daily uint8_t fifth_second; uint8_t command_code; @@ -200,8 +200,8 @@ void EnergyUpdateToday(void) { Energy.daily_sum = 0.0; for (uint32_t i = 0; i < Energy.phase_count; i++) { - if (Energy.kWhtoday_delta[i] > 1000) { - uint32_t delta = Energy.kWhtoday_delta[i] / 1000; + if (abs(Energy.kWhtoday_delta[i]) > 1000) { + int32_t delta = Energy.kWhtoday_delta[i] / 1000; Energy.kWhtoday_delta[i] -= (delta * 1000); Energy.kWhtoday[i] += delta; } @@ -255,12 +255,12 @@ void EnergyUpdateTotal(void) { Energy.start_energy[i] = Energy.import_active[i]; // Init after restart and handle roll-over if any } else if (Energy.import_active[i] != Energy.start_energy[i]) { - Energy.kWhtoday[i] = (uint32_t)((Energy.import_active[i] - Energy.start_energy[i]) * 100000); + Energy.kWhtoday[i] = (int32_t)((Energy.import_active[i] - Energy.start_energy[i]) * 100000); } if ((Energy.total[i] < (Energy.import_active[i] - 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) - RtcSettings.energy_kWhtotal_ph[i] = (unsigned long)((Energy.import_active[i] * 100000) - Energy.kWhtoday_offset[i] - Energy.kWhtoday[i]); + RtcSettings.energy_kWhtotal_ph[i] = (int32_t)((Energy.import_active[i] * 100000) - Energy.kWhtoday_offset[i] - Energy.kWhtoday[i]); Settings->energy_kWhtotal_ph[i] = RtcSettings.energy_kWhtotal_ph[i]; Energy.total[i] = (float)(RtcSettings.energy_kWhtotal_ph[i] + Energy.kWhtoday_offset[i] + Energy.kWhtoday[i]) / 100000; Settings->energy_kWhtotal_time = (!Energy.kWhtoday_offset[i]) ? LocalTime() : Midnight(); diff --git a/tasmota/xdrv_52_9_berry.ino b/tasmota/xdrv_52_9_berry.ino index 8940b807e..091a1d608 100644 --- a/tasmota/xdrv_52_9_berry.ino +++ b/tasmota/xdrv_52_9_berry.ino @@ -120,6 +120,7 @@ void BerryDumpErrorAndClear(bvm *vm, bool berry_console) { top = be_top(vm); // update top after dump } else { AddLog(LOG_LEVEL_ERROR, PSTR(D_LOG_BERRY "Exception> '%s' - %s"), be_tostring(berry.vm, -2), be_tostring(berry.vm, -1)); + be_tracestack(vm); } } else { be_dumpstack(vm); diff --git a/tasmota/xsns_83_neopool.ino b/tasmota/xsns_83_neopool.ino index 50f0aac3d..18d7a7ee7 100644 --- a/tasmota/xsns_83_neopool.ino +++ b/tasmota/xsns_83_neopool.ino @@ -82,8 +82,12 @@ enum NeoPoolRegister { // addr Unit Description // ------ ------ ------------------------------------------------------------ // MODBUS page (0x0000 - 0x002E - unknown - for internal use only) - MBF_VOLT_24_36 = 0x0022, // 0x0022 Current 24-36V line in mV - MBF_VOLT_12 = 0x0023, // 0x0023 Current 12V line in mV + MBF_POWER_MODULE_VERSION = 0x0002, // 0x0002 undocumented - power module version + MBF_POWER_MODULE_NODEID = 0x0004, // 0x0004 undocumented - power module Node ID (6 register 0x0004 - 0x0009) + MBF_POWER_MODULE_REGISTER = 0x000C, // 0x000C undocumented - Writing an address in this register causes the power module register address to be read out into MBF_POWER_MODULE_DATA, see MBF_POWER_MODULE_REG_* + MBF_POWER_MODULE_DATA = 0x000D, // 0x000D undocumented - power module data as requested in MBF_POWER_MODULE_REGISTER + MBF_VOLT_24_36 = 0x0022, // 0x0022 undocumented - Current 24-36V line in mV + MBF_VOLT_12 = 0x0023, // 0x0023 undocumented - Current 12V line in mV // MEASURE page (0x01xx) MBF_ION_CURRENT = 0x0100, // 0x0100* Current measured in the ionization system @@ -108,6 +112,8 @@ enum NeoPoolRegister { MBF_CELL_RUNTIME_LOW = 0x0206, // 0x0206* undocumented - cell runtime (32 bit) - low word MBF_CELL_RUNTIME_HIGH = 0x0207, // 0x0207* undocumented - cell runtime (32 bit) - high word MBF_BOOST_CTRL = 0x020C, // 0x020C undocumented - 0x0000 = Boost Off, 0x05A0 = Boost with redox ctrl, 0x85A0 = Boost without redox ctrl + MBF_HIDRO_MODULE_VERSION = 0x0280, // 0x0280 undocumented - Hydrolysis module version + MBF_HIDRO_MODULE_CONNECTIVITY = 0x0281, // 0x0281 undocumented - Hydrolysis module connection quality (in myriad: 0..10000) MBF_SET_MANUAL_CTRL = 0x0289, // 0x0289 undocumented - write a 1 before manual control MBF_RELAY_STATE, after done write 0 and do MBF_EXEC MBF_ESCAPE = 0x0297, // 0x0297 undocumented - A write operation to this register is the same as using the ESC button on main screen - clears error MBF_SAVE_TO_EEPROM = 0x02F0, // 0x02F0 A write operation to this register starts a EEPROM storage operation immediately. During the EEPROM storage procedure, the system may be unresponsive to MODBUS requests. The operation will last always less than 1 second. @@ -211,7 +217,7 @@ enum NeoPoolRegister { MBF_PAR_PH2, // 0x0505 Lower limit of the pH regulation system. The value set in this register is multiplied by 100. This means that if we want to set a value of 7.0, the numerical content that we must write in this register is 700. This register must be always lower than MBF_PAR_PH1. MBF_PAR_RX1 = 0x0508, // 0x0508 Set point for the redox regulation system. This value must be in the range of 0 to 1000. MBF_PAR_CL1 = 0x050A, // 0x050A Set point for the chlorine regulation system. The value stored in this register is multiplied by 100. This mean that if we want to set a value of 1.5 ppm, we will have to write a numerical value of 150. This value stored in this register must be in the range of 0 to 1000. - MBF_PAR_FILTRATION_TYPE = 0x050F, // 0x050F undocumented - filtration type, see MBV_PAR_FILTRATION_TYPE_* 0 = Standard, 1 = Variable Hayward, 2 = Variable speed B + MBF_PAR_FILTRATION_CONF = 0x050F, // 0x050F mask undocumented - filtration type and speed, see MBMSK_PAR_FILTRATION_CONF_* MBF_PAR_FILTRATION_SPEED_FUNC = 0x0513, // 0x0513 undocumented - filtration speed function control MBF_PAR_FUNCTION_DEPENDENCY = 0x051B, // 0x051B mask Specification for the dependency of different functions, such as heating, from external events like FL1 (see MBMSK_FCTDEP_HEATING/MBMSK_DEPENDENCY_*) @@ -418,14 +424,23 @@ enum NeoPoolConstAndBitMask { MBV_PAR_RELAY_MODE_SHOW_ONLY = 1, // The system only shows the alarm on screen, but the dosing continues. MBV_PAR_RELAY_MODE_SHOW_AND_STOP = 2, // The system shows the alarm on screen and stops the dosing pump - // MBF_PAR_FILTRATION_TYPE - MBV_PAR_FILTRATION_TYPE_STANDARD = 0x00, // Standard (without speed control) - MBV_PAR_FILTRATION_TYPE_HAYWARD_SLOW = 0x01, // Variable Hayward Slow - MBV_PAR_FILTRATION_TYPE_HAYWARD_MEDIUM = 0x11, // Variable Hayward Medium - MBV_PAR_FILTRATION_TYPE_HAYWARD_FAST = 0x21, // Variable Hayward Fast - MBV_PAR_FILTRATION_TYPE_SPEED_B_SLOW = 0x02, // Variable speed B Slow - MBV_PAR_FILTRATION_TYPE_SPEED_B_MEDIUM = 0x12, // Variable speed B Medium - MBV_PAR_FILTRATION_TYPE_SPEED_B_FAST = 0x22, // Variable speed B Fast + // MBF_PAR_FILTRATION_CONF + MBMSK_PAR_FILTRATION_CONF_TYPE = 0x000F, // Filtration pump type, see MBV_PAR_FILTRATION_TYPE_* + MBMSK_PAR_FILTRATION_CONF_DEF_SPEED = 0x0070, // Filtration default speed, see MBV_PAR_FILTRATION_SPEED_* + MBMSK_PAR_FILTRATION_CONF_INT1_SPEED = 0x0380, // Filtration speed for timer interval 1, see MBV_PAR_FILTRATION_SPEED_* + MBMSK_PAR_FILTRATION_CONF_INT2_SPEED = 0x1C00, // Filtration speed for timer interval 2, see MBV_PAR_FILTRATION_SPEED_* + MBMSK_PAR_FILTRATION_CONF_INT3_SPEED = 0xE000, // Filtration speed for timer interval 3, see MBV_PAR_FILTRATION_SPEED_* + MBSHFT_PAR_FILTRATION_CONF_TYPE = 0, // Filtration pump type bit shift + MBSHFT_PAR_FILTRATION_CONF_DEF_SPEED = 4, // Filtration default speed bit shift + MBSHFT_PAR_FILTRATION_CONF_INT1_SPEED = 7, // Filtration speed for timer interval 1 bit shift + MBSHFT_PAR_FILTRATION_CONF_INT2_SPEED = 10, // Filtration speed for timer interval 2 bit shift + MBSHFT_PAR_FILTRATION_CONF_INT3_SPEED = 13, // Filtration speed for timer interval 3 bit shift + MBV_PAR_FILTRATION_TYPE_STANDARD = 0, // Standard (without speed control) + MBV_PAR_FILTRATION_TYPE_HAYWARD = 1, // Variable speed B + MBV_PAR_FILTRATION_TYPE_SPEED_B = 2, // Variable speed B + MBV_PAR_FILTRATION_SPEED_SLOW = 0, // Speed Slow + MBV_PAR_FILTRATION_SPEED_MEDIUM = 1, // Speed Medium + MBV_PAR_FILTRATION_SPEED_FAST = 2, // Speed Fast // MBF_PAR_FUNCTION_DEPENDENCY MBMSK_FCTDEP_HEATING = 0x0007, // Heating function dependency: @@ -529,6 +544,9 @@ enum NeoPoolConstAndBitMask { MBMSK_VS_FORCE_UNITS_GRH = 0x2000, // Display the hydrolysis/electrolysis in units of grams per hour (gr/h). MBMSK_VS_FORCE_UNITS_PERCENTAGE = 0x4000, // Display the hydrolysis/electrolysis in percentage units (%). MBMSK_ELECTROLISIS = 0x8000, // Display the word electrolysis instead of hydrolysis in generic mode. + + // MBF_POWER_MODULE_REG_* + MBV_POWER_MODULE_REG_INFO = 0, // undocumented - set of 26-byte power module register stores an ASCIIZ string containing the subversion and timestamp of the module, e. g. ".57\nMay 26 2020\n01:08:10\n\0" }; #include @@ -588,15 +606,10 @@ struct { {NEOPOOL_REG_TYPE_BLOCK, {MBF_CELL_RUNTIME_LOW, MBF_CELL_RUNTIME_HIGH - MBF_CELL_RUNTIME_LOW + 1, nullptr}}, {NEOPOOL_REG_TYPE_BLOCK, {MBF_PAR_VERSION, MBF_PAR_MODEL - MBF_PAR_VERSION + 1, nullptr}}, {NEOPOOL_REG_TYPE_BLOCK, {MBF_PAR_TIME_LOW, MBF_PAR_FILT_GPIO - MBF_PAR_TIME_LOW + 1, nullptr}}, - {NEOPOOL_REG_TYPE_BLOCK, {MBF_PAR_ION, MBF_PAR_FILTRATION_TYPE - MBF_PAR_ION + 1, nullptr}}, + {NEOPOOL_REG_TYPE_BLOCK, {MBF_PAR_ION, MBF_PAR_FILTRATION_CONF - MBF_PAR_ION + 1, nullptr}}, {NEOPOOL_REG_TYPE_BLOCK, {MBF_PAR_UICFG_MACHINE, MBF_PAR_UICFG_MACH_VISUAL_STYLE - MBF_PAR_UICFG_MACHINE + 1, nullptr}} }; -uint16_t filtration_types[2][3] = { - {MBV_PAR_FILTRATION_TYPE_HAYWARD_SLOW, MBV_PAR_FILTRATION_TYPE_HAYWARD_MEDIUM, MBV_PAR_FILTRATION_TYPE_HAYWARD_FAST}, - {MBV_PAR_FILTRATION_TYPE_SPEED_B_SLOW, MBV_PAR_FILTRATION_TYPE_SPEED_B_MEDIUM, MBV_PAR_FILTRATION_TYPE_SPEED_B_FAST} - }; - // NeoPool modbus function errors enum NeoPoolModbusCode { NEOPOOL_MODBUS_OK = 0, @@ -1823,24 +1836,25 @@ void CmndNeopoolFiltration(void) { uint16_t addr = MBF_PAR_FILT_MANUAL_STATE; uint16_t data; - uint16_t filtration_type; + uint16_t filtration_conf; uint32_t value[2] = { 0 }; uint32_t params_cnt = ParseParameters(nitems(value), value); if (XdrvMailbox.data_len) { - if (NEOPOOL_MODBUS_OK != NeoPoolReadRegister(MBF_PAR_FILTRATION_TYPE, &filtration_type, 1)) { + if (NEOPOOL_MODBUS_OK != NeoPoolReadRegister(MBF_PAR_FILTRATION_CONF, &filtration_conf, 1)) { NeopoolResponseError(); return; } - if (params_cnt > 2 || (MBV_PAR_FILTRATION_TYPE_STANDARD == filtration_type && params_cnt > 1)) { - // no speed control for standard types + if (params_cnt > 2 || (params_cnt > 1 && (MBV_PAR_FILTRATION_TYPE_STANDARD == (filtration_conf & MBMSK_PAR_FILTRATION_CONF_TYPE)))) { + // no speed control for standard filtration types NeopoolCmndError(); return; } if (params_cnt > 1) { if (value[1] >= 1 && value[1] <= 3) { // Set filtration speed first - NeoPoolWriteRegisterWord(MBF_PAR_FILTRATION_TYPE, (filtration_type & 0xFF00) | filtration_types[(filtration_type & 0x0F) - 1][value[1] - 1]); + NeoPoolWriteRegisterWord(MBF_PAR_FILTRATION_CONF, + (filtration_conf & ~MBMSK_PAR_FILTRATION_CONF_DEF_SPEED) | ((value[1] - 1) << MBSHFT_PAR_FILTRATION_CONF_DEF_SPEED)); NeoPoolWriteRegisterWord(MBF_EXEC, 1); } else { NeopoolCmndError();