AppDaemon 4 - listen_state

Since upgrading to AD4, a number of my automation that use listen_state have been behaving erratically. did this method change?

one example is an automation i have looking at my temp sensors and using any change in Temp or Hum to calculate a feels like. The way I used the listen state is

self.listen_state(self.state_change_detected, self.args[“humsensor”])
self.listen_state(self.state_change_detected, self.args[“tempsensor”])

where the call back reads the values and calcs the feels like.
I am getting this error now

2020-03-15 00:43:40.236844 WARNING masterfeelsliketemp: ------------------------------------------------------------
2020-03-15 00:48:26.635880 WARNING studyfeelsliketemp: ------------------------------------------------------------
2020-03-15 00:48:30.010356 WARNING studyfeelsliketemp: Unexpected error in worker for App studyfeelsliketemp:
2020-03-15 00:48:30.012044 WARNING studyfeelsliketemp: Worker Ags: {‘id’: ‘61621241aac74f04ba14f2c6dc0e3ad0’, ‘name’: ‘studyfeelsliketemp’, ‘objectid’: ‘f5c8ec1faaa64708a0cf4936c6a1fe75’, ‘type’: ‘state’, ‘function’: <bound method FeelsLikeTempStateChange.state_change_detected of <set_feels_like_temp_state.FeelsLikeTempStateChange object at 0x7f5a8bc4f8e0>>, ‘attribute’: ‘state’, ‘entity’: ‘sensor.temperature_sensor_58’, ‘new_state’: ‘21.80’, ‘old_state’: ‘21.70’, ‘pin_app’: True, ‘pin_thread’: 10, ‘kwargs’: {‘__thread_id’: ‘thread-10’}}
2020-03-15 00:48:30.193852 WARNING studyfeelsliketemp: ------------------------------------------------------------
2020-03-15 00:48:30.195114 WARNING studyfeelsliketemp: Traceback (most recent call last):
File “/usr/local/lib/python3.8/site-packages/appdaemon/threading.py”, line 777, in worker
funcref(entity, attr, old_state, new_state,
File “/conf/apps/set_feels_like_temp_state.py”, line 39, in state_change_detected
self.get_sensor_values()
File “/conf/apps/set_feels_like_temp_state.py”, line 58, in get_sensor_values
self.set_state(self.args[“apparentsensor”], state = heatIndex, attributes = {“friendly_name”: self.args[“apperentfriendlyname”],“unit_of_measurement”: “°C”, “icon”: “mdi:thermometer” })
File “/usr/local/lib/python3.8/site-packages/appdaemon/utils.py”, line 191, in inner_sync_wrapper
f = run_coroutine_threadsafe(self, coro(self, *args, **kwargs))
File “/usr/local/lib/python3.8/site-packages/appdaemon/utils.py”, line 285, in run_coroutine_threadsafe
result = future.result(self.AD.internal_function_timeout)
File “/usr/local/lib/python3.8/concurrent/futures/_base.py”, line 441, in result
raise TimeoutError()
concurrent.futures._base.TimeoutError

and a lot of these in my info file

2020-03-17 10:55:15.953361 INFO AppDaemon: Adding thread 51
2020-03-17 10:55:16.990201 CRITICAL AppDaemon: Thread thread-10 has died
2020-03-17 10:55:16.991131 CRITICAL AppDaemon: Pinned apps were: [‘studyfeelsliketemp’]
2020-03-17 10:55:16.991752 CRITICAL AppDaemon: Thread will be restarted
2020-03-17 10:55:16.992358 INFO AppDaemon: Adding thread 10
2020-03-17 10:55:16.994937 CRITICAL AppDaemon: Thread thread-51 has died
2020-03-17 10:55:16.995575 CRITICAL AppDaemon: Pinned apps were:
2020-03-17 10:55:16.996107 CRITICAL AppDaemon: Thread will be restarted

This was working fine before I upgraded to AD4, any help much appreciated.

thanks

Please post the entire app code so we can have a look.

import appdaemon.plugins.hass.hassapi as hass
import datetime

# Args:
# tempsensor: 
# humsensor:
# apparentsensor:
# apperentfriendlyname:


class FeelsLikeTempStateChange(hass.Hass):

    def initialize(self):
        # Subscribe to sensors
        self.listen_state(self.state_change_detected, self.args["humsensor"])
        self.listen_state(self.state_change_detected, self.args["tempsensor"])
        runtime = datetime.datetime.now()
        addseconds = (round((runtime.minute*60 + runtime.second)/300)+1)*300
        runtime = runtime.replace(minute=0, second=0, microsecond=0) + datetime.timedelta(seconds=addseconds)
        self.run_every(self.checksensors,runtime,900)

    
        # add a run every to calcute feels like even if haven't changed

    def checksensors(self, kwargs):

            self.get_sensor_values()
 
    def state_change_detected(self, entity, attribute, old, new, kwargs):
        if new != "unavailable":
            self.get_sensor_values()
 
    
    def get_sensor_values (self):
        strTemp =  self.get_state(self.args["tempsensor"])
        strHum = self.get_state(self.args["humsensor"])

        if self.is_float(strHum):
           humVal = float(strHum)
        else:
           self.log(self.get_state(self.args["humsensor"])) 
           humVal = 0
        if self.is_float(strTemp):   
           tempVal = float(strTemp)
        else:
           self.log(self.get_state(self.args["tempsensor"])) 
           tempVal = 0

        heatIndex = self.heat_index(tempVal, humVal)
        self.set_state(self.args["apparentsensor"], state = heatIndex, attributes = {"friendly_name": self.args["apperentfriendlyname"],"unit_of_measurement": "°C", "icon": "mdi:thermometer"  })

    
    def celsius_to_fahrenheit(self,c):
       #Degrees Celsius (C) to degrees Fahrenheit (F)'
       return (c * 1.8) + 32.0

    def fahrenheit_to_celsius(self,f):
       #Degrees Fahrenheit (F) to degrees Celsius (C)'
       return (f - 32.0) * 0.555556 

    def is_float(self,str):
        try:
          float(str)
          return True
        except ValueError:
          return False 
        except TypeError:
          return False     

    def heat_index(self,tempVal, humVal):
  
        # Convert celius to fahrenheit (heat-index is only fahrenheit compatible)
        Tempfahrenheit = self.celsius_to_fahrenheit(tempVal)

        # Creating multiples of 'fahrenheit' & 'hum' values for the coefficients
        T2 = pow(Tempfahrenheit, 2)
        T3 = pow(Tempfahrenheit, 3)
        H2 = pow(humVal, 2)
        H3 = pow(humVal, 3)

        # Coefficients for the calculations
        C1 = [ -42.379, 2.04901523, 10.14333127, -0.22475541, -6.83783e-03, -5.481717e-02, 1.22874e-03, 8.5282e-04, -1.99e-06]
        C2 = [ 0.363445176, 0.988622465, 4.777114035, -0.114037667, -0.000850208, -0.020716198, 0.000687678, 0.000274954, 0]
        C3 = [ 16.923, 0.185212, 5.37941, -0.100254, 0.00941695, 0.00728898, 0.000345372, -0.000814971, 0.0000102102, -0.000038646, 0.0000291583, 0.00000142721, 0.000000197483, -0.0000000218429, 0.000000000843296, -0.0000000000481975]
       
        # Calculating heat-indexes with 3 different formula
        if Tempfahrenheit > 80 :
           heatindex1 = C1[0] + (C1[1] * Tempfahrenheit) + (C1[2] * humVal) + (C1[3] * Tempfahrenheit * humVal) + (C1[4] * T2) + (C1[5] * H2) + (C1[6] * T2 * humVal) + (C1[7] * Tempfahrenheit * H2) + (C1[8] * T2 * H2)
           #heatindex2 = C2[0] + (C2[1] * Tempfahrenheit) + (C2[2] * humVal) + (C2[3] * Tempfahrenheit * humVal) + (C2[4] * T2) + (C2[5] * H2) + (C2[6] * T2 * humVal) + (C2[7] * Tempfahrenheit * H2) + (C2[8] * T2 * H2)
           #heatindex3 = C3[0] + (C3[1] * Tempfahrenheit) + (C3[2] * humVal) + (C3[3] * Tempfahrenheit * humVal) + (C3[4] * T2) + (C3[5] * H2) + (C3[6] * T2 * humVal) + (C3[7] * Tempfahrenheit * H2) + (C3[8] * T2 * H2) + (C3[9] * T3) + (C3[10] * H3) + (C3[11] * T3 * humVal) + (C3[12] * Tempfahrenheit * H3) + (C3[13] * T3 * H2) + (C3[14] * T2 * H3) + (C3[15] * T3 * H3)
        else:
           heatindex1 = 0.5 * (Tempfahrenheit+ 61.0 +( (Tempfahrenheit-68.0) *1.2) + (humVal* 0.094))

        return  round(self.fahrenheit_to_celsius(heatindex1),1)

Are you sure that your runtime parameter does not evaluate to a time in the past?

Actually just looked at that, not sure what I was thinking when i wrote that, but the purpose was to ensure the run_every ran soon after the app was re-started. I have changes to
addseconds = 100

to see if that makes a difference