martinarva / dynamic_energy_cost

35 stars 9 forks source link

Prices are a out by factor of 10x #18

Closed MilanAra88 closed 5 days ago

MilanAra88 commented 1 month ago

Hi there,

The pricing that is calculated incorrectly by a factor of 10.

For instance, when the elec rate is £0.17/kwh and the appliance has used 0.315 kwh - it should £0.059 but it is showing at £0.59 . See images. Any idea?

Many thanks,

Milan

image
martinarva commented 1 month ago

Please provide states of the sensors you used in the integration input.

Also check the cost sensor attributes, what do you have there.

martinarva commented 1 month ago

I don't know why it's off. Could you please send the picture of the power entity graph?

Does your device have also energy sensor (kWh) and could you test it with the energy sensor?

Calculation with energy sensor is more precise than using the integration left method with power sensor. However difference should be marginal not 10x

MilanAra88 commented 1 month ago

hi Marin,

This is strange - the real time costs seem to be calculating correctly by the daily, monthly, and year figures are way out.

Have you seen any other users with similar feedback?

martinarva commented 1 month ago

hi Marin,

This is strange - the real time costs seem to be calculating correctly by the daily, monthly, and year figures are way out.

Have you seen any other users with similar feedback?

No, i haven't. I have a few power based test sensors running and they are correct.

Does your device have energy sensor as well and did you try with it?

EDIT: I found one bug in the power based sensors code. Please try latest 0.4.1 version

martinarva commented 1 month ago

@MilanAra88 , i did some testing and compared it to the HA reiman sum + utility meter method and looks like its working properly.

I feed in my sensor.ss_load_power: state_class: measurement unit_of_measurement: W device_class: power friendly_name: SS Load power

and sensor.nordpool_import (price sensor) unit_of_measurement: EUR/kWh friendly_name: nordpool_import

About an hour and cost is 0.35€. Real time cost fluctuates, but average is about 0.35€/h, so it shpould be correct. It's not 10x off at least. Screenshot 2024-05-13 at 11 43 35

Comparison with my integration and reimann sum + utility meter method: Screenshot 2024-05-13 at 11 50 00

EDIT: Maybe you feed in sensor that gives kW not W?

andiukas commented 1 month ago

Same problem, consumption of the kettle after switching on twice image

MilanAra88 commented 1 month ago

The workaround i have used seems to work great! : https://community.home-assistant.io/t/solved-calculate-cost-for-individual-device-cost-kwh/523880/8?u=baljci333

I still use this nice work from Martin for the real time costs as this seems to be right!

martinarva commented 1 month ago

I'm still puzzled why this 10x error occurs.

Btw, @MilanAra88 , @andiukas do you have energy (kwh) sensor for your device?

MilanAra88 commented 1 month ago

Hi @martinarva, the monitor i use is the Tapo energy monitor. The "current consumption" is in W.

As i say, your live cost is spot on - but its the daily, monthly, yearly that seems to be off for me :(

See image:

image
martinarva commented 1 month ago

Maybe someone have any idea why this happens. Code that calculates the cost increment:

    @callback
    def _handle_real_time_cost_update(self, event):
        """Update cumulative cost based on the real-time cost sensor updates."""
        new_state = event.data.get('new_state')
        if new_state is None or new_state.state in ('unknown', 'unavailable'):
            _LOGGER.debug("Skipping update due to unavailable state")
            return

        try:
            current_cost = Decimal(new_state.state)
            _LOGGER.debug(f"Current cost retrieved from state: {current_cost}")  # Log current cost

            if current_cost <= 0:  # Skip updates if the new cost is not positive
                _LOGGER.debug(f"Skipping update as the calculated cost {current_cost} is not positive.")
                return

            time_difference = now() - self._last_update
            hours_passed = Decimal(time_difference.total_seconds()) / Decimal(3600)  # Convert time difference to hours as Decimal
            _LOGGER.debug(f"Time difference calculated as: {time_difference}, which is {hours_passed} hours.")  # Log time difference in hours

            self._state += (current_cost * hours_passed).quantize(Decimal('0.01'))
            self._last_update = now()
            self.async_write_ha_state()
            _LOGGER.debug(f"Updated state to: {self._state} using cost: {current_cost} over {hours_passed} hours")
        except (InvalidOperation, TypeError) as e:
            _LOGGER.error(f"Error updating cumulative cost: {e}")

Code Breakdown

  1. Method Decoration and Definition:

    • @callback: This decorator is used to tell Home Assistant that this function should be run in the event loop, optimizing it for fast execution. It's important in the context of asynchronous programming, ensuring that this method does not block other operations.
    • _handle_real_time_cost_update(self, event): This method is designed to handle updates triggered by a change in another sensor's state, with the event parameter carrying data related to this change.
  2. Handling of Event Data:

    • new_state = event.data.get('new_state'): This line extracts the new_state from the event data. The new_state typically contains the latest state information about the sensor that triggered the event.
  3. State Validity Check:

    • The method checks if new_state is None or its state is 'unknown' or 'unavailable'. If any of these conditions are true, the method logs a debug message and returns early without doing any further processing. This is crucial to ensure that the method only processes valid and available data.
  4. Cost Retrieval and Validation:

    • current_cost = Decimal(new_state.state): This line converts the state of the triggering sensor into a Decimal, which is a data type that provides precise fixed-point arithmetic. This step is necessary to handle financial calculations accurately.
    • The method then checks if current_cost is less than or equal to zero. If so, it logs this and returns early, as negative or zero costs do not contribute to cumulative calculations in this context.
  5. Time Difference Calculation:

    • time_difference = now() - self._last_update: Here, now() represents the current time, and self._last_update is the time when the last update occurred. This line calculates how much time has passed since the last update.
    • hours_passed = Decimal(time_difference.total_seconds()) / Decimal(3600): Converts the time_difference to the total number of seconds, and then divides by 3600 to convert this into hours. The result is stored as a Decimal for precision.
  6. State Update:

    • self._state += (current_cost * hours_passed).quantize(Decimal('0.01')): This line updates the sensor's state by adding the product of current_cost and hours_passed, quantized to two decimal places. This represents the accrued cost over the elapsed time, scaled to the cost rate per hour.
    • self._last_update = now(): Updates the last update timestamp to the current time.
    • self.async_write_ha_state(): Calls Home Assistant's method to write the updated state back to the system, ensuring that the state change is registered.
  7. Error Handling:

    • The entire cost update logic is wrapped in a try-except block to catch and log any errors that might occur during execution, such as InvalidOperation or TypeError. This is important for debugging and ensuring the component doesn't crash from unhandled exceptions.
DutchKillerbee commented 1 month ago

@martinarva I would increase the accuracy self._state += (current_cost * hours_passed).quantize(Decimal('0.01')) to self._state += (current_cost * hours_passed).quantize(Decimal('0.0001'))

If calculation is every 5 seconds, hours is a very small number. hours times a very little cost is 0.00 So add every 5 seconds 0.00 to the state makes sensor not accurate. Don't know if this will help in the factor 10 issue here but at least the state will become more accurate

martinarva commented 5 days ago

@DutchKillerbee , thanks for the insight. I increased accuracy and whis will be available in next release

martinarva commented 5 days ago

Version 0.5.0 released: https://github.com/martinarva/dynamic_energy_cost/releases/tag/v0.5.0

Please test and reopen, if still issues

andiukas commented 4 days ago

problem unsolved