BUG ! Computed kWh device cannot be updated with initial svalue (workaround found)

Python and python framework

Moderator: leecollings

Post Reply
willemd
Posts: 738
Joined: Saturday 21 September 2019 17:55
Target OS: Raspberry Pi / ODroid
Domoticz version: 2024.1
Location: The Netherlands
Contact:

BUG ! Computed kWh device cannot be updated with initial svalue (workaround found)

Post by willemd »

Below is a small piece of code from a Python Plugin that I am developing using the DomoticzEx framework.
After each piece of code I have pasted the log output. It all seems to work fine except for the final update.
You can see the sValue is not updated onto the device. sValue remains ''" instead of "7;1". Why?
I do not understand why the last update does not work. Someone here does?

The device is a kWh device with the kWh value to be computed from the Watts input (not from device). I have checked the definition of the device and that shows up correctly. According to the Wiki the nValue should be zero and the sValue should be in the format "123;123456" and the second value will be ignored.

Code: Select all

Unit=DEVSLIST[Dev][0]
DeviceID="{:04x}{:04x}".format(self.Hwid,Unit)
Domoticz.Log(responseJson["stats"][Dev])
output is: 2025-06-25 09:22:28.900 Xtend: 7

fieldValue=responseJson["stats"][Dev]
Domoticz.Log(Devices[DeviceID].Units[Unit])
output is: 2025-06-25 09:22:28.900 Xtend: Unit: 43, Name: 'XTEND: HP energy usage', nValue: 7, sValue: '', LastUpdate: 2025-06-25 09:21:17

Devices[DeviceID].Units[Unit].nValue=0
Devices[DeviceID].Units[Unit].sValue=str(fieldValue)+";1" # watts are supplied, kwh are calculated by Domoticz.
Domoticz.Log(Devices[DeviceID].Units[Unit].sValue)
output is: 2025-06-25 09:22:28.900 Xtend: 7;1

Devices[DeviceID].Units[Unit].Update()
Domoticz.Log(Devices[DeviceID].Units[Unit])
output is: 2025-06-25 09:22:28.914 Xtend: Unit: 43, Name: 'XTEND: HP energy usage', nValue: 0, sValue: '', LastUpdate: 2025-06-25 09:22:28
Last edited by willemd on Wednesday 25 June 2025 11:47, edited 3 times in total.
willemd
Posts: 738
Joined: Saturday 21 September 2019 17:55
Target OS: Raspberry Pi / ODroid
Domoticz version: 2024.1
Location: The Netherlands
Contact:

Re: Python plugin does not update kWh device. Why?

Post by willemd »

I see an issue 6194 on Github which https://github.com/domoticz/domoticz/issues/6194 also describes the problem, although the description states that the device cannot be created. I can create the device I just cannot populate it with data.

There does not seem to be any action or solution to that issue?
willemd
Posts: 738
Joined: Saturday 21 September 2019 17:55
Target OS: Raspberry Pi / ODroid
Domoticz version: 2024.1
Location: The Netherlands
Contact:

Re: Python plugin does not update kWh device. Why?

Post by willemd »

I found that if you put an initial svalue on the device (with sqlite3, directly on the devicestatus table) then after that the update code works correctly.

So it is a bug when the device is created. It should initialize it with an initial svalue.

Or alternatively the update statement should work when there is no initial value.

But how to work around this in a Python plugin?
willemd
Posts: 738
Joined: Saturday 21 September 2019 17:55
Target OS: Raspberry Pi / ODroid
Domoticz version: 2024.1
Location: The Netherlands
Contact:

Re: Python plugin does not update kWh device. Why?

Post by willemd »

More info: also updating the device with a JSON statement does not work when there is no initial svalue present.
So the only workaround now is to add a svalue in the devicestatus table first directly in the dbase.

Note there is no problem updating other device types, only the computed kwh device.
willemd
Posts: 738
Joined: Saturday 21 September 2019 17:55
Target OS: Raspberry Pi / ODroid
Domoticz version: 2024.1
Location: The Netherlands
Contact:

Re: BUG ! Computed kWh device cannot be updated with initial svalue

Post by willemd »

I think I found where the problem is. It is in line 5371-5397 in the SQLhelper.cpp file.

If the initial svalue does not consists of two elements then it just restores the initial value. So if the initial value is empty (which it always is after the device is created) then the svalue remains empty. Here is the offending code.

Code: Select all

std::vector<std::string> powerAndEnergyBeforeUpdate;
			StringSplit(sValueBeforeUpdate, ";", powerAndEnergyBeforeUpdate);
			if (powerAndEnergyBeforeUpdate.size() == 2)
			{
				//we need to use atof here because some users seem to have a illegal sValue in the database that causes std::stof to crash
				double powerDuringInterval = atof(powerAndEnergyBeforeUpdate[0].c_str());
				double energyUpToInterval = atof(powerAndEnergyBeforeUpdate[1].c_str());
				double energyDuringInterval = powerDuringInterval * intervalSeconds / 3600;
				double energyAfterInterval = energyUpToInterval + energyDuringInterval;
				std::vector<std::string> powerAndEnergyUpdate;
				StringSplit(sValue, ";", powerAndEnergyUpdate);
				if (!powerAndEnergyUpdate.empty())
				{
					const char* powerUpdate = powerAndEnergyUpdate[0].c_str();
                    char sValueUpdate[100];
                    sprintf(sValueUpdate, "%s;%.4f", powerUpdate, energyAfterInterval);
					sValue = sValueUpdate;
				}
				else
				{
                    sValue = sValueBeforeUpdate.c_str();
				}
			}
			else
            {
                sValue = sValueBeforeUpdate.c_str();
            }
willemd
Posts: 738
Joined: Saturday 21 September 2019 17:55
Target OS: Raspberry Pi / ODroid
Domoticz version: 2024.1
Location: The Netherlands
Contact:

Re: BUG ! Computed kWh device cannot be updated with initial svalue

Post by willemd »

I found a workaround

1) First I create the kWh device using the plugin with the default "from device" setting (leave the options field empty when creating the device).
2) Immediately after creation, I update the device svalue to "0;0" using the plugin.
3) and then immediately I update the options field to 'EnergyMeterMode': '1' which changes the device to "computed" instead of "from device".

Note in step 3 the update statement needs to be run with the UpdateOptions=True flag like this
Devices[DeviceID].Units[Unit].Update(UpdateOptions=True)

Now it has an initial value and future updates will work.
User avatar
lemassykoi
Posts: 37
Joined: Saturday 11 March 2017 23:51
Target OS: Raspberry Pi / ODroid
Domoticz version: 2025.1
Location: France
Contact:

Re: BUG ! Computed kWh device cannot be updated with initial svalue (workaround found)

Post by lemassykoi »

I had to deal with that same problem:

At first, I'm creating the device (lib Domoticz) with the options, using Typename (cause when using Type and Subtype, it was not working)
Then I init the device with svalue = "0;0"
then updates are ok

Code: Select all

BLUETTI_DEVICE_DEFINITIONS = [
    # Name,                        UnitID, TypeName,        Type, Subtype, DevIDSfx, SwTypeCr, ImgCr, OptsSelector, OptsCreation, JSONKey, Used
    ("Bluetti Device Type",           1,  "Text",             243, 19, "devtype",        0, 0, {}, {}, "device_type",           0),
    ("Bluetti Serial Number",         2,  "Text",             243, 19, "serial",         0, 0, {}, {}, "serial_number",         0),
    ("Bluetti ARM Version",           3,  "Text",             243, 19, "arm",            0, 0, {}, {}, "arm_version",           0),
    ("Bluetti DSP Version",           4,  "Text",             243, 19, "dsp",            0, 0, {}, {}, "dsp_version",           0),
    ("Bluetti Total Battery",         5,  "Percentage",       243, 6,  "totalbatt",      0, 0, {}, {}, "total_battery_percent", 1),
    ("Bluetti DC Input Power",        6,  "kWh",              243, 29, "dcinpow",        0, 0, {}, {"EnergyMeterMode": "1"}, "dc_input_power",          0),
    ("Bluetti AC Input Power",        7,  "kWh",              243, 29, "acinpow",        0, 0, {}, {"EnergyMeterMode": "1"}, "ac_input_power",          1),
    ("Bluetti AC Output Power",       8,  "kWh",              243, 29, "acoutpow",       0, 0, {}, {"EnergyMeterMode": "1"}, "ac_output_power",         1),
    ("Bluetti DC Output Power",       9,  "kWh",              243, 29, "dcoutpow",       0, 0, {}, {"EnergyMeterMode": "1"}, "dc_output_power",         0),
    ("Bluetti Power Generation",      10, "kWh",              243, 29, "pwrgen",         4, 0, {}, {"EnergyMeterMode": "1"}, "power_generation",        0),
    ("Bluetti Internal DC Power",     25, "kWh",              243, 29, "intdcpower",     0, 0, {}, {"EnergyMeterMode": "1"}, "internal_dc_input_power", 0),
    ("Bluetti AC Charging Power",     27, "kWh",              243, 29, "acchargepow",    0, 0, {}, {"EnergyMeterMode": "1"}, "ac_charging_power",       0),
    ("Bluetti AC Output State",       11, "Switch",           244, 73, "acoutstate",     0, 9, {}, {}, "ac_output_on",              1),
    ("Bluetti DC Output State",       12, "Switch",           244, 73, "dcoutstate",     0, 9, {}, {}, "dc_output_on",              1),
    ("Bluetti Grid Charge",           28, "Switch",           244, 73, "gridcharge",     0, 9, {}, {}, "grid_charge_on",            1),
    ("Bluetti Time Control",          29, "Switch",           244, 73, "timecontrol",    0, 9, {}, {}, "time_control_on",           1),
    ("Bluetti Battery Range Start",   60, "Percentage",       243, 6,  "battrangestart", 0, 0, {}, {}, "battery_range_start",       0),
    ("Bluetti Battery Range End",     61, "Percentage",       243, 6,  "battrangeend",   0, 0, {}, {}, "battery_range_end",         0),
    ("Bluetti Time Schedule",         62, "Text",             243, 19, "timeschedule",   0, 0, {}, {}, "time_control_programming",  1),
    ("Bluetti Internal AC Voltage",   14, "Voltage",          243, 8,  "intacvolt",      0, 0, {}, {}, "internal_ac_voltage",       0),
    ("Bluetti Internal AC Frequency", 17, "Custom",           243, 31, "intacfreq",      0, 0, {}, {}, "internal_ac_frequency",     0),
    ("Bluetti AC Input Voltage",      20, "Voltage",          243, 8,  "acinvolt",       0, 0, {}, {}, "ac_input_voltage",          0),
    ("Bluetti Internal Current 3",    21, "Current (Single)", 243, 23, "intcurr3",       0, 0, {}, {}, "internal_current_three",    0),
    ("Bluetti AC Input Frequency",    23, "Custom",           243, 31, "acinfreq",       0, 0, {}, {}, "ac_input_frequency",        0),
    ("Bluetti Internal DC Voltage",   24, "Voltage",          243, 8,  "intdcvolt",      0, 0, {}, {}, "internal_dc_input_voltage", 0),
    ("Bluetti Internal DC Current",   26, "Current (Single)", 243, 23, "intdccurr",      0, 0, {}, {}, "internal_dc_input_current", 0),
    ("Bluetti AC Output Mode",        13, "Selector Switch",  244, 62, "acoutmode",     18, 0, {"LevelActions": "|||||", "LevelNames": "Off|Stop|Inverter Output|Bypass Output C|Bypass Output D|Load Matching", "LevelOffHidden": "false", "SelectorStyle": "1"}, {}, "ac_output_mode", 0),
    ("Bluetti UPS Mode",              30, "Selector Switch",  244, 62, "upsmode",       18, 0, {"LevelActions": "||||", "LevelNames": "Off|Customized|PV Priority|Standard|Time Control", "LevelOffHidden": "false", "SelectorStyle": "1"}, {}, "ups_mode", 1),
]
[...]

Code: Select all

    def create_domoticz_devices(self):
        """Create Domoticz devices"""
        Domoticz.Log("create_domoticz_devices: Starting device check/creation...")
        plugin_key = Parameters["Key"]

        for name, unit_id, type_name, d_type, d_subtype, device_id_suffix, d_switchtype, d_image, create_opts_selector, update_opts_general, json_key, used in BLUETTI_DEVICE_DEFINITIONS:
            full_device_id = f"{plugin_key}_{device_id_suffix}"

            if unit_id not in Devices:
                Domoticz.Log(f"Creating Unit {unit_id} ('{name}')...")
                Domoticz.Device(
                    Name       = str(name),
                    Unit       = int(unit_id),
                    TypeName   = str(type_name),
                    Switchtype = int(d_switchtype),
                    Image      = int(d_image),
                    Options    = dict(update_opts_general),
                    DeviceID   = full_device_id,
                    Used       = int(used)
                ).Create()

            # Apply update options if specified
            if unit_id in Devices and update_opts_general:
                try:
                    current_dev_options = Devices[unit_id].Options if hasattr(Devices[unit_id], 'Options') else {}
                    effective_options = current_dev_options.copy()

                    options_changed = False
                    for opt_key, opt_value in update_opts_general.items():
                        if str(effective_options.get(opt_key)) != str(opt_value):
                            effective_options[opt_key] = opt_value
                            options_changed = True
                    
                    if options_changed: 
                        Devices[unit_id].Update(nValue=Devices[unit_id].nValue, sValue="0;0", Options=effective_options)

                except Exception as e: 
                    Domoticz.Error(f"Error applying update options to {name}: {e}")

            elif unit_id in Devices and create_opts_selector:
                try:
                    Devices[unit_id].Update(nValue=0, sValue="0", Options=create_opts_selector)
                except Exception as e: 
                    Domoticz.Error(f"Error applying selector options to {name}: {e}")

            elif unit_id in Devices and type_name == 'Custom':  # Frequency in Hertz
                try:
                    Devices[unit_id].Update(nValue=0, sValue="50.0", Options={'Custom': '1;Hertz'})
                except Exception as e: 
                    Domoticz.Error(f"Error applying custom options to {name}: {e}")

            self.device_unit_map[json_key] = unit_id
User avatar
waltervl
Posts: 6685
Joined: Monday 28 January 2019 18:48
Target OS: Linux
Domoticz version: 2025.1
Location: NL
Contact:

Re: BUG ! Computed kWh device cannot be updated with initial svalue (workaround found)

Post by waltervl »

just for the record, the bug or behavior is also discussed in this github issue https://github.com/domoticz/domoticz/issues/6194

And just a quote from @pipiche, plugin author of the Zigbee4Domoticz plugin
I'm wondering if the error is not in the (python plugin) code

device1 = Domoticz.Device(Name="EnergyMeterMode1", Unit=1, Type=243, Subtype=29, Switchtype=0, DeviceID="EnergyMeterMode1", Options = {"EnergyMeterMode": 1})

My understanding is that 'EnergyMeterMode' should be a string and not an int, as for the zigbee4domoticz plugin we are doing

Options = {'EnergyMeterMode': '0'} for (from Device) or Options = {'EnergyMeterMode': '1'} for from Compute

and we do not have any issue to report when creating the wdiget
Domoticz running on Udoo X86 (on Ubuntu)
Devices/plugins: ZigbeeforDomoticz (with Xiaomi, Ikea, Tuya devices), Nefit Easy, Midea Airco, Omnik Solar, Goodwe Solar
willemd
Posts: 738
Joined: Saturday 21 September 2019 17:55
Target OS: Raspberry Pi / ODroid
Domoticz version: 2024.1
Location: The Netherlands
Contact:

Re: BUG ! Computed kWh device cannot be updated with initial svalue (workaround found)

Post by willemd »

I already used {'EnergyMeterMode': '1'} or {'EnergyMeterMode': '0'} so already defined it as string and still encountered the problem.

As already mentioned, the problem is not in creating the device. Creation works and also the device looks exactly like other "computed" kWh devices (created via the GUI).

The problem is that it cannot be given a new svalue if the initial svalue is empty. Whether you are using a plugin or a JSON, the problem is the same, you cannot assign a svalue if the current svalue is empty.

So therefore, as a workaround, you first have to create the devices as a "from device" kWh meter and make sure svalue is not empty. If then you change the device to "computed" the svalue retains its value, is not empty, and therefore it can be given new values.
User avatar
lemassykoi
Posts: 37
Joined: Saturday 11 March 2017 23:51
Target OS: Raspberry Pi / ODroid
Domoticz version: 2025.1
Location: France
Contact:

Re: BUG ! Computed kWh device cannot be updated with initial svalue (workaround found)

Post by lemassykoi »

I tried some tests:

Creating a device with Typename or Type and Subtype, with EnergyMeterMode set to 1 at device creation will always fail the sensor

The only way to create a working sensor is to omit EnergyMeterMode during creation and specify it only for value updates:

Code: Select all

devices_to_create = {
    15: {"Name": f"{vehicle_name} Charging Power", "Type": 243, "Subtype": 29},
}
for unit, params in devices_to_create.items():
    if unit not in Devices: 
        device_params = params.copy()
        device_params.setdefault("Used", 1)
        Domoticz.Device(Unit=unit, **device_params).Create()

Devices[15].Update(nValue=0, sValue=f"{power_w};0", Options={'EnergyMeterMode': '1'})
this way I don't need to update fake values "0;0" first.
willemd
Posts: 738
Joined: Saturday 21 September 2019 17:55
Target OS: Raspberry Pi / ODroid
Domoticz version: 2024.1
Location: The Netherlands
Contact:

Re: BUG ! Computed kWh device cannot be updated with initial svalue (workaround found)

Post by willemd »

lemassykoi wrote: Thursday 04 September 2025 15:29 I tried some tests:

Creating a device with Typename or Type and Subtype, with EnergyMeterMode set to 1 at device creation will always fail the sensor

The only way to create a working sensor is to omit EnergyMeterMode during creation and specify it only for value updates:

Code: Select all

devices_to_create = {
    15: {"Name": f"{vehicle_name} Charging Power", "Type": 243, "Subtype": 29},
}
for unit, params in devices_to_create.items():
    if unit not in Devices: 
        device_params = params.copy()
        device_params.setdefault("Used", 1)
        Domoticz.Device(Unit=unit, **device_params).Create()

Devices[15].Update(nValue=0, sValue=f"{power_w};0", Options={'EnergyMeterMode': '1'})
this way I don't need to update fake values "0;0" first.
Is that not the same problem as described before? Did you just want to reconfirm that or are you adding new info?

Problem as described was that you cannot create a device with EnergyMeterMode equal to 1 first and then in a separate statement assign a value. The value field which was created as empty field during creation remains empty.

Workaround was to first create with EnergyMeterMode equal to 0, then assign a value (so the field is no longer empty) and then switch to EnergyMeterMode 1. Any further updates to the field are then processed correctly.
User avatar
lemassykoi
Posts: 37
Joined: Saturday 11 March 2017 23:51
Target OS: Raspberry Pi / ODroid
Domoticz version: 2025.1
Location: France
Contact:

Re: BUG ! Computed kWh device cannot be updated with initial svalue (workaround found)

Post by lemassykoi »

willemd wrote: Friday 05 September 2025 12:55 Workaround was to first create with EnergyMeterMode equal to 0, then assign a value (so the field is no longer empty) and then switch to EnergyMeterMode 1. Any further updates to the field are then processed correctly.
This is not correct.

No need to assign a value, and no need to "switch" energymetermode to 1

Options can be set at device creation, or at device update
I now set option during update process
willemd
Posts: 738
Joined: Saturday 21 September 2019 17:55
Target OS: Raspberry Pi / ODroid
Domoticz version: 2024.1
Location: The Netherlands
Contact:

Re: BUG ! Computed kWh device cannot be updated with initial svalue (workaround found)

Post by willemd »

I know options can be set during device creation.

But the problem was not in setting the options, the problem was to assign an s-value after a device was created with energymetermode 1. Assigning the svalue did not work.

Maybe we are just misunderstanding each other so let's leave it at that. As far as know. the problem still exists, but also the workaround is still avaiable, so no big deal.
User avatar
lemassykoi
Posts: 37
Joined: Saturday 11 March 2017 23:51
Target OS: Raspberry Pi / ODroid
Domoticz version: 2025.1
Location: France
Contact:

Re: BUG ! Computed kWh device cannot be updated with initial svalue (workaround found)

Post by lemassykoi »

I'm not 100% sure that the Option for EnergyMeterMode is made to be set during device creation

Capture d’écran du 2025-09-06 17-19-08.png
Capture d’écran du 2025-09-06 17-19-08.png (43.33 KiB) Viewed 138 times
source: https://wiki.domoticz.com/Developing_a_ ... vice_Types

I don't understand why you absolutely want to set options at device creation.
Try this : don't create the device with options, only use options for update process. You should not need to add fake value, and the update will work.
willemd
Posts: 738
Joined: Saturday 21 September 2019 17:55
Target OS: Raspberry Pi / ODroid
Domoticz version: 2024.1
Location: The Netherlands
Contact:

Re: BUG ! Computed kWh device cannot be updated with initial svalue (workaround found)

Post by willemd »

If you don't set options then it will behave like energymetermode is 0.

If you need mode 1 you have to set it.
User avatar
lemassykoi
Posts: 37
Joined: Saturday 11 March 2017 23:51
Target OS: Raspberry Pi / ODroid
Domoticz version: 2025.1
Location: France
Contact:

Re: BUG ! Computed kWh device cannot be updated with initial svalue (workaround found)

Post by lemassykoi »

I'm sorry, but, again, this is not true

you can create a device without options. It will indeed be created with energymetermode set to 0

THEN when you update your sensor with real first value, you pass value AND options to update method, like I wrote earlier, and from now, energymetermode is set to 1 and never go back to 0
willemd
Posts: 738
Joined: Saturday 21 September 2019 17:55
Target OS: Raspberry Pi / ODroid
Domoticz version: 2024.1
Location: The Netherlands
Contact:

Re: BUG ! Computed kWh device cannot be updated with initial svalue (workaround found)

Post by willemd »

Correct, we are stating the same thing.

But if you first create the device with energymetermode=1 and then try to assign a svalue....
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest