Hi there,
I recently started to get errors with AppDaemon stating that HA has disconnected for a few seconds. This randomly occurs and disables callbacks from the listen_state function in the initialization. The rest still works fine. The only way to get it back to working again is restarting the Add On. Everything is running on a Pi 4.
Here’s the log:
-----------------------------------------------------------
Add-on: AppDaemon
Python Apps and Dashboard using AppDaemon 4.x for Home Assistant
-----------------------------------------------------------
Add-on version: 0.16.7
You are running the latest version of this add-on.
System: Home Assistant OS 13.2 (aarch64 / raspberrypi4-64)
Home Assistant Core: 2024.11.3
Home Assistant Supervisor: 2024.11.4
-----------------------------------------------------------
Please, share the above information when looking for help
or support in, e.g., GitHub, forums or the Discord chat.
-----------------------------------------------------------
s6-rc: info: service base-addon-banner successfully started
s6-rc: info: service fix-attrs: starting
s6-rc: info: service base-addon-log-level: starting
s6-rc: info: service fix-attrs successfully started
Log level is set to INFO
s6-rc: info: service base-addon-log-level successfully started
s6-rc: info: service legacy-cont-init: starting
s6-rc: info: service legacy-cont-init successfully started
s6-rc: info: service init-appdaemon: starting
s6-rc: info: service init-appdaemon successfully started
s6-rc: info: service appdaemon: starting
s6-rc: info: service appdaemon successfully started
s6-rc: info: service legacy-services: starting
[12:26:09] INFO: Starting AppDaemon...
s6-rc: info: service legacy-services successfully started
2024-11-24 12:26:14.863114 INFO AppDaemon: AppDaemon Version 4.4.2 starting
2024-11-24 12:26:14.863434 INFO AppDaemon: Python version is 3.11.10
2024-11-24 12:26:14.863606 INFO AppDaemon: Configuration read from: /config/appdaemon.yaml
2024-11-24 12:26:14.863765 INFO AppDaemon: Added log: AppDaemon
2024-11-24 12:26:14.863934 INFO AppDaemon: Added log: Error
2024-11-24 12:26:14.864078 INFO AppDaemon: Added log: Access
2024-11-24 12:26:14.864223 INFO AppDaemon: Added log: Diag
2024-11-24 12:26:15.163870 INFO AppDaemon: Loading Plugin HASS using class HassPlugin from module hassplugin
2024-11-24 12:26:15.511975 INFO HASS: HASS Plugin Initializing
2024-11-24 12:26:15.512291 INFO HASS: HASS Plugin initialization complete
2024-11-24 12:26:15.513154 INFO AppDaemon: Initializing HTTP
2024-11-24 12:26:15.513770 INFO AppDaemon: Using 'ws' for event stream
2024-11-24 12:26:15.518869 INFO AppDaemon: Starting API
2024-11-24 12:26:15.522131 INFO AppDaemon: Starting Admin Interface
2024-11-24 12:26:15.522893 INFO AppDaemon: Starting Dashboards
2024-11-24 12:26:15.545569 INFO HASS: Connected to Home Assistant 2024.11.3
2024-11-24 12:26:15.556635 INFO AppDaemon: App 'canbus_processor' added
2024-11-24 12:26:15.558595 INFO AppDaemon: Found 1 active apps
2024-11-24 12:26:15.559240 INFO AppDaemon: Found 0 inactive apps
2024-11-24 12:26:15.559708 INFO AppDaemon: Found 0 global libraries
2024-11-24 12:26:15.560222 INFO AppDaemon: Starting Apps with 1 workers and 1 pins
2024-11-24 12:26:15.561997 INFO AppDaemon: Running on port 5050
2024-11-24 12:26:15.624007 INFO HASS: Evaluating startup conditions
2024-11-24 12:26:15.628783 INFO HASS: Startup condition met: hass state=RUNNING
2024-11-24 12:26:15.629174 INFO HASS: All startup conditions met
2024-11-24 12:26:15.668198 INFO AppDaemon: Got initial state from namespace default
2024-11-24 12:26:17.572287 INFO AppDaemon: Scheduler running in realtime
2024-11-24 12:26:17.580791 INFO AppDaemon: Adding /config/apps to module import path
2024-11-24 12:26:17.584794 INFO AppDaemon: Loading App Module: /config/apps/canbus_processor.py
2024-11-24 12:26:17.644975 INFO AppDaemon: Loading app canbus_processor using class CANBusDataProcessor from module canbus_processor
2024-11-24 12:26:17.647252 INFO AppDaemon: Calling initialize() for canbus_processor
2024-11-24 12:26:17.739601 INFO canbus_processor: Launching CANBUS reader ...
2024-11-24 12:26:17.744376 INFO canbus_processor: Connecting to TCP socket ...
2024-11-24 12:26:17.856656 INFO canbus_processor: Connected to CANBUS source.
2024-11-24 12:28:22.839751 WARNING HASS: Disconnected from Home Assistant, retrying in 5 seconds
2024-11-24 12:28:22.848533 WARNING HASS: Attempt to call Home Assistant while disconnected: set_plugin_state
2024-11-24 12:28:24.034149 WARNING HASS: Attempt to call Home Assistant while disconnected: set_plugin_state
2024-11-24 12:28:24.038056 WARNING HASS: Attempt to call Home Assistant while disconnected: set_plugin_state
2024-11-24 12:28:24.042527 WARNING HASS: Attempt to call Home Assistant while disconnected: set_plugin_state
2024-11-24 12:28:32.911687 WARNING HASS: Attempt to call Home Assistant while disconnected: set_plugin_state
2024-11-24 12:28:32.914425 WARNING HASS: Attempt to call Home Assistant while disconnected: set_plugin_state
2024-11-24 12:28:32.916994 WARNING HASS: Attempt to call Home Assistant while disconnected: set_plugin_state
2024-11-24 12:28:33.808212 INFO HASS: Connected to Home Assistant 2024.11.3
2024-11-24 12:28:33.811216 WARNING HASS: Attempt to call Home Assistant while disconnected: set_plugin_state
2024-11-24 12:28:34.144559 WARNING HASS: Attempt to call Home Assistant while disconnected: set_plugin_state
2024-11-24 12:28:34.149903 WARNING HASS: Attempt to call Home Assistant while disconnected: set_plugin_state
2024-11-24 12:28:34.154324 WARNING HASS: Attempt to call Home Assistant while disconnected: set_plugin_state
2024-11-24 12:28:42.846107 WARNING HASS: Attempt to call Home Assistant while disconnected: set_plugin_state
2024-11-24 12:28:42.855810 WARNING HASS: Attempt to call Home Assistant while disconnected: set_plugin_state
2024-11-24 12:28:42.857769 WARNING HASS: Attempt to call Home Assistant while disconnected: set_plugin_state
2024-11-24 12:28:43.885881 INFO HASS: Evaluating startup conditions
2024-11-24 12:28:43.891534 WARNING HASS: Attempt to call Home Assistant while disconnected: set_plugin_state
2024-11-24 12:28:43.892852 INFO HASS: Startup condition met: hass state=RUNNING
2024-11-24 12:28:43.893228 INFO HASS: All startup conditions met
Here’s the code:
import appdaemon.plugins.hass.hassapi as hass
import socket
import time
from datetime import datetime
import asyncio
class CANBusDataProcessor(hass.Hass):
async def initialize(self):
self.data_buffer = "" # Initialize an empty data buffer as a string
self.tcp_host = "192.168.178.201" # CANBUS source IP address
self.tcp_port = 8881 # CANBUS source port
self.tcp_socket = None
self.process_interval = 30
# Define a parameter mapping dictionary
self.parameter_mapping = {
'0001': 'fehlermeldung',
'0004': 'heizkreistemperatur_soll',
'000c': 'aussentemperatur',
'000e': 'speichertemperatur',
'000f': 'heizkreistemperatur_ist',
'0011': 'raumtemperatur',
'0014': 'verdampfertemperatur',
'0075': 'raumfeuchte',
'001a': 'kollektortemperatur',
'0112': 'programm',
'0121': 'wochentag',
'0122': 'tag',
'0123': 'monat',
'0124': 'jahr',
'0125': 'stunde',
'0126': 'minute',
'0176': 'betriebsstatus',
'019a': 'softwareversion',
'0596': 'zuluft_soll',
'0597': 'zuluft_ist',
'0598': 'abluft_soll',
'0599': 'abluft_ist',
'059c': 'verfluessigertemperatur',
'05dd': 'lueftungsstufe',
'0571': 'lueftungszeit_ausserplan_stufe_0',
'0572': 'lueftungszeit_ausserplan_stufe_1',
'0573': 'lueftungszeit_ausserplan_stufe_2',
'0574': 'lueftungszeit_ausserplan_stufe_3',
'069e': 'motordrehzahl',
'06a0': 'motorleistung',
'0693': 'oelsumpftemperatur',
'0698': 'solarpumpe_pwm',
'091a': 'elekt_energie_ww_tag_wh',
'091b': 'elekt_energie_ww_tag_kwh',
'091c': 'elekt_energie_ww_summe_kwh',
'091d': 'elekt_energie_ww_summe_mwh',
'091e': 'elekt_energie_heizen_tag_wh',
'091f': 'elekt_energie_heizen_tag_kwh',
'0920': 'elekt_energie_heizen_summe_kwh',
'0921': 'elekt_energie_heizen_summe_mwh',
'092a': 'therm_energie_ww_tag_wh',
'092b': 'therm_energie_ww_tag_kwh',
'092c': 'therm_energie_ww_summe_kwh',
'092d': 'therm_energie_ww_summe_mwh',
'092e': 'therm_energie_heizen_tag_wh',
'092f': 'therm_energie_heizen_tag_kwh',
'0930': 'therm_energie_heizen_summe_kwh',
'0931': 'therm_energie_heizen_summe_mwh',
'c0ee': 'heiz_kuehlleistung',
'c355': 'solar_status'
}
# CANBUS request frames
self.data_to_send = [
b'\x07\xa2\x06\x00\x00\x61\x01\xfa\x00\x04\x00\x00\x00', #HK_temperatur_soll
b'\x07\xa2\x06\x00\x00\x31\x00\xfa\x05\x97\x00\x00\x00', #zuluft_ist
b'\x07\xa2\x06\x00\x00\x31\x00\xfa\x05\x99\x00\x00\x00', #abluft_ist
b'\x07\xa2\x06\x00\x00\x31\x00\xfa\x06\x9e\x00\x00\x00', #motordrehzahl
b'\x07\xa2\x06\x00\x00\x31\x00\xfa\x06\xa0\x00\x00\x00', #motorleistung
b'\x07\xa2\x06\x00\x00\x31\x00\xfa\x06\x98\x00\x00\x00', #solarpumpe_pwm
b'\x07\xa2\x06\x00\x00\x31\x00\xfa\xc0\xee\x00\x00\x00', #heiz_kuehlleistung
b'\x07\xa2\x06\x00\x00\x31\x00\xfa\x00\x14\x00\x00\x00', #verdampfertemperatur
b'\x07\xa2\x06\x00\x00\x31\x00\xfa\x05\x9c\x00\x00\x00', #verfluessigertemperatur
b'\x07\xa2\x06\x00\x00\x31\x00\xfa\x05\xdd\x00\x00\x00', #lueftungsstufe
b'\x07\xa2\x06\x00\x00\x31\x00\xfa\x09\x1a\x00\x00\x00', #elekt_energie_ww_tag_wh
b'\x07\xa2\x06\x00\x00\x31\x00\xfa\x09\x1b\x00\x00\x00', #elekt_energie_ww_tag_kwh
b'\x07\xa2\x06\x00\x00\x31\x00\xfa\x09\x1c\x00\x00\x00', #elekt_energie_ww_summe_kwh
b'\x07\xa2\x06\x00\x00\x31\x00\xfa\x09\x1d\x00\x00\x00', #elekt_energie_ww_summe_mwh
b'\x07\xa2\x06\x00\x00\x31\x00\xfa\x09\x1e\x00\x00\x00', #elekt_energie_heizen_tag_wh
b'\x07\xa2\x06\x00\x00\x31\x00\xfa\x09\x1f\x00\x00\x00', #elekt_energie_heizen_tag_kwh
b'\x07\xa2\x06\x00\x00\x31\x00\xfa\x09\x20\x00\x00\x00', #elekt_energie_heizen_summe_kwh
b'\x07\xa2\x06\x00\x00\x31\x00\xfa\x09\x21\x00\x00\x00', #elekt_energie_heizen_summe_mwh
b'\x07\xa2\x06\x00\x00\x31\x00\xfa\x09\x2a\x00\x00\x00', #therm_energie_ww_tag_wh
b'\x07\xa2\x06\x00\x00\x31\x00\xfa\x09\x2b\x00\x00\x00', #therm_energie_ww_tag_kwh
b'\x07\xa2\x06\x00\x00\x31\x00\xfa\x09\x2e\x00\x00\x00', #therm_energie_heizen_tag_wh
b'\x07\xa2\x06\x00\x00\x31\x00\xfa\x09\x2f\x00\x00\x00', #therm_energie_heizen_tag_kwh
b'\x07\xa2\x06\x00\x00\x31\x00\xfa\xc3\x55\x00\x00\x00' #solar_status
]
# Start CANBUS reader
await self.main()
# Start continuous CANBUS frame request
await self.run_every(self.send_multiple_frames, datetime.now(), self.process_interval)
# Listen for changes in ventilation level
await self.listen_state(self.ventilation_manual, "input_button.ventilation_manual_trigger")
async def connect_to_tcp(self):
try:
self.tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.tcp_socket.settimeout(30)
self.tcp_socket.connect((self.tcp_host, self.tcp_port))
self.log("Connected to CANBUS source.")
except Exception as e:
self.log(f"TCP connection error: {e}")
async def process_data(self):
data_buffer = ""
# Receive data from the TCP connection
data = self.tcp_socket.recv(1024)
if data:
# Append received data to the buffer
data_buffer += data.hex()
# Extract 26-character segment from the buffer
while len(data_buffer) >= 26:
segment = data_buffer[:26]
#self.log(f'Extracted CAN frame: {segment[0:2]} {segment[2:6]} {segment[6:10]} {segment[10:14]} {segment[14:16]} {segment[16:20]} {segment[20:24]} {segment[24:26]}')
# Remove the processed data from the buffer
data_buffer = data_buffer[26:]
# Extract data from segment
source = segment[2:6]
destination = segment[10:14]
id_hex = segment[16:20]
value_hex = segment[20:24]
if source == "0103" or source == "8001":
# Look up the parameter name in the mapping
parameter_name = self.parameter_mapping.get(id_hex, "unknown_parameter")
# Construct sensor names and set their states
sensor_name = f'sensor.{parameter_name}_can_value'
if parameter_name == "unknown_parameter":
await self.set_state('sensor.unknown_parameter_id', state=id_hex)
self.log(f'Set value {value_hex} for {sensor_name}')
await self.set_state(sensor_name, state=value_hex)
else:
self.tcp_socket.close()
self.log("No data. Closing TCP socket")
async def ventilation_manual(self, entity, attribute, old, new, kwargs):
try:
# Read the values for ventilation level and duration
level = int(float(await self.get_state("input_number.ventilation_level_wanted")))
duration = int(float(await self.get_state("input_number.ventilation_time_wanted")))
#Get level CAN ID
level_can_id_map = {
0: "0571",
1: "0572",
2: "0573",
3: "0574"
}
level_can_id = level_can_id_map.get(level)
# Convert level and duration to hexadecimal for CAN frame format
level_hex = f"{level:04x}" # Convert to 4-digit hex (e.g., '0003' for level 3)
duration_hex = f"{duration:04x}" # Convert to 4-digit hex (e.g., '0010' for 10)
# Construct the CAN frames
fan_speed_frame = bytes.fromhex(f"07a20600003000fa05dd{level_hex}00")
fan_duration_frame = bytes.fromhex(f"07a20600003000fa{level_can_id}{duration_hex}00")
# Send the frames
await self.send_single_frame(fan_speed_frame)
await self.send_single_frame(fan_duration_frame)
self.log(f"Sent fan speed frame: {fan_speed_frame.hex()}")
self.log(f"Sent fan duration frame: {fan_duration_frame.hex()}")
except Exception as e:
self.log(f"Error in on_ventilation_change: {e}")
async def send_multiple_frames(self,kwargs):
try:
# Send the data over the TCP socket
for frame in self.data_to_send:
self.tcp_socket.send(frame)
time.sleep(0.1)
except Exception as e:
self.log(f"Error sending data: {e}")
async def send_single_frame(self,frame,kwargs):
try:
# Send the frame over the TCP socket
self.tcp_socket.send(frame)
time.sleep(0.1)
except Exception as e:
self.log(f"Error sending data: {e}")
async def main(self):
self.log("Launching CANBUS reader ...")
while True:
self.log("Connecting to TCP socket ...")
await self.connect_to_tcp()
while self.tcp_socket:
await self.process_data()
self.log("TCP socket closed.")
def terminate(self):
self.tcp_socket.close()
self.log("Terminate. TCP socket closed.")