-
Notifications
You must be signed in to change notification settings - Fork 437
Open
Labels
Description
What happened?
I have some code that creates some energy sensors. This code worked fine for several years now, but after updating to AppDeamon version 0.17.12 I get an error when calling self.set_state()
The complete error logged after starting the code class below is as follows:
025-11-10 16:20:17.790386 INFO EnergyDailyUsage: Unexpected error setting sensor.delivered_low_day: argument of type 'ClientResponseError' is not iterable
My class is as follows:
import appdaemon.plugins.hass.hassapi as hass
import datetime
from pytz import timezone
from aiohttp import ClientResponseError
class EnergyDailyUsage(hass.Hass):
def initialize(self):
self.trace = False
self._trace("initialize", "started")
self.id_ch = self.args["consume_high"]
self.id_cl = self.args["consume_low"]
self.id_dh = self.args["deliver_high"]
self.id_dl = self.args["deliver_low"]
self.id_gas = self.args["gas"]
self.startDay = {}
self.startMonth = {}
self.startYear = {}
self.energyfilestore = self.get_app('EnergyFileStore')
self.run_daily(self.callback, datetime.time(0, 0, 0))
self.run_at(self.callback, datetime.datetime.now() + datetime.timedelta(seconds=2))
self.run_in(self._timertick, 60)
self.listen_state(self._tracemode, "input_boolean.trace_mode")
self.turn_off("input_boolean.trace_mode")
def _safe_float(self, value):
try:
return float(value)
except (TypeError, ValueError):
return 0.0
def _tracemode(self, entity, attribute, old, new, kwargs):
self.trace = new == 'on'
self._trace("_tracemode()", f"Trace mode {'on' if self.trace else 'off'}")
def callback(self, kwargs):
self._trace("callback", "started")
self._check_scope('day')
self._check_scope('month')
self._check_scope('year')
def _check_scope(self, scope):
data = self.energyfilestore.GetEnergyStart(scope == 'day', scope == 'month', scope == 'year')
now = datetime.datetime.now(timezone('Europe/Amsterdam'))
if "dt" in data:
if (
(scope == 'day' and data['dt'].date() != now.date()) or
(scope == 'month' and data['dt'].month != now.month) or
(scope == 'year' and data['dt'].year != now.year)
):
self._trace(f"_check_{scope}", f"Different {scope.capitalize()}")
self._store_startvalues(scope)
else:
self._trace(f"_check_{scope}", f"Same {scope.capitalize()}")
else:
self._store_startvalues(scope)
setattr(self, f"start{scope.capitalize()}", data)
def _store_startvalues(self, scope):
tz = timezone('Europe/Amsterdam')
now = datetime.datetime.now(tz=tz)
record = {
'dt': now,
'gas': self.get_state(self.id_gas),
'ch': self.get_state(self.id_ch),
'cl': self.get_state(self.id_cl),
'dh': self.get_state(self.id_dh),
'dl': self.get_state(self.id_dl),
}
self.energyfilestore.SetEnergyStart(
record,
scope == 'day',
scope == 'month',
scope == 'year'
)
setattr(self, f"start{scope.capitalize()}",
self.energyfilestore.GetEnergyStart(
scope == 'day',
scope == 'month',
scope == 'year'
))
def _timertick(self, args):
if self._check_if_values_ready():
self._create_and_save('day', self.startDay)
self._create_and_save('month', self.startMonth)
self._create_and_save('year', self.startYear)
self.run_in(self._timertick, 60)
def _check_if_values_ready(self):
for sensor in [self.id_ch, self.id_cl, self.id_dh, self.id_dl, self.id_gas]:
if self.get_state(sensor) == 'unknown':
return False
return True
def _create_and_save(self, scope, start_data):
suffix = f"_{scope}"
now_vals = {
'ch': self._safe_float(self.get_state(self.id_ch)),
'cl': self._safe_float(self.get_state(self.id_cl)),
'dh': self._safe_float(self.get_state(self.id_dh)),
'dl': self._safe_float(self.get_state(self.id_dl)),
'gas': self._safe_float(self.get_state(self.id_gas)),
}
deltas = {k: now_vals[k] - self._safe_float(start_data.get(k)) for k in now_vals}
if 'ch' in start_data:
self._set_energy_sensor(f"sensor.consumed_high{suffix}", deltas['ch'], f"{scope.capitalize()}s Consumed Electricity High", "kWh")
if 'cl' in start_data:
self._set_energy_sensor(f"sensor.consumed_low{suffix}", deltas['cl'], f"{scope.capitalize()}s Consumed Electricity Low", "kWh")
if 'dh' in start_data:
self._set_energy_sensor(f"sensor.delivered_high{suffix}", deltas['dh'], f"{scope.capitalize()}s Delivered Electricity High", "kWh")
if 'dl' in start_data:
self._set_energy_sensor(f"sensor.delivered_low{suffix}", deltas['dl'], f"{scope.capitalize()}s Delivered Electricity Low", "kWh")
if 'gas' in start_data:
self._set_energy_sensor(f"sensor.consumed_gas{suffix}", deltas['gas'], f"{scope.capitalize()}s Consumed Gas", "m3")
if 'ch' in start_data and 'cl' in start_data:
consumed = deltas['ch'] + deltas['cl']
self._set_energy_sensor(f"sensor.consumed{suffix}", consumed, f"{scope.capitalize()}s Consumed Electricity", "kWh")
if 'dh' in start_data and 'dl' in start_data:
delivered = deltas['dh'] + deltas['dl']
self._set_energy_sensor(f"sensor.delivered{suffix}", delivered, f"{scope.capitalize()}s Delivered Electricity", "kWh")
if all(k in start_data for k in ('ch', 'cl', 'dh', 'dl')):
netto = (deltas['ch'] + deltas['cl']) - (deltas['dh'] + deltas['dl'])
self._set_energy_sensor(f"sensor.netto{suffix}", netto, f"{scope.capitalize()}s Netto Electricity", "kWh")
def _set_energy_sensor(self, name, value, friendly_name, unit):
self._trace("_set_energy_sensor", f"Name = {name}")
try:
self.set_state(
entity_id=name,
state=round(value, 3),
attributes={
"friendly_name": friendly_name,
"unit_of_measurement": unit
}
)
except ClientResponseError as e:
self.error(f"Failed to set state for {name}: {e.status} {e.message}")
except Exception as e:
self.error(f"Unexpected error setting {name}: {e}")
def _trace(self, function, message):
if self.trace:
self.log(f"{function} -> {message}")Gr, Will
Version
4.5.12
Installation type
Home Assistant add-on
Relevant log output
Relevant code in the app or config file that caused the issue
Anything else?
No response