Hallo!
Sorry, dass ich wieder mit dem Thema anfange. Aber es bringt mich zum Verzweifeln.
Das Plugin verliert immer wieder die Verbindung zur Wärmepumpe.
Danach kommt immer dieser Fehler
Nach einem Neustart von sh klappt die Abfrage wieder ganz normal.
Im Plugin war der Abfrageintervall auf 5min.(cycle=300)
Mit diesem Wert kam der Fehler ca. 10mal am Tag. Nach Änderung auf cycle=60 nur mehr 2-3mal.
Die __init__.py
Kann mir jemand von euch Profis einen Tipp geben, woran das liegt, oder wie man den Fehler behebt?
LG Max
Sorry, dass ich wieder mit dem Thema anfange. Aber es bringt mich zum Verzweifeln.
Das Plugin verliert immer wieder die Verbindung zur Wärmepumpe.
Code:
2015-10-07 15:37:40,974 DEBUG Scheduler Luxtronic2 next time: 2015-10-07 15:38:40+02:00 -- scheduler.py:_next_time:289 2015-10-07 15:37:44,471 ERROR Luxtronic2 Method Luxtronic2 exception: error receiving answer: timeout -- scheduler.py:_task:348 Traceback (most recent call last): File "/usr/smarthome/plugins/luxtronic2/__init__.py", line 107, in _request answer = self._sock.recv(length) socket.timeout: timed out During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/usr/smarthome/lib/scheduler.py", line 344, in _task obj() File "/usr/smarthome/plugins/luxtronic2/__init__.py", line 254, in _refresh self.refresh_parameters() File "/usr/smarthome/plugins/luxtronic2/__init__.py", line 153, in refresh_parameters answer = self._request(request, 8) File "/usr/smarthome/plugins/luxtronic2/__init__.py", line 110, in _request raise luxex("error receiving answer: timeout") plugins.luxtronic2.luxex: error receiving answer: timeout
Code:
2015-10-07 15:39:40,476 WARNING Luxtronic2 Luxtronic2: failed to retrieve parameters -- __init__.py:refresh_parameters:173 2015-10-07 15:39:40,500 WARNING Luxtronic2 Luxtronic2: failed to retrieve calculated -- __init__.py:refresh_calculated:225 2015-10-07 15:39:40,531 DEBUG Luxtronic2 cycle takes 0.05545401573181152 seconds -- __init__.py:_refresh:276 2015-10-07 15:39:40,984 DEBUG Scheduler Luxtronic2 next time: 2015-10-07 15:40:40+02:00 -- scheduler.py:_next_time:289
Im Plugin war der Abfrageintervall auf 5min.(cycle=300)
Mit diesem Wert kam der Fehler ca. 10mal am Tag. Nach Änderung auf cycle=60 nur mehr 2-3mal.
Die __init__.py
Code:
#!/usr/bin/env python3 # vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab # # Copyright 2012-2013 KNX-User-Forum e.V. https://knx-user-forum.de/ # # This file is part of SmartHome.py. http://mknx.github.io/smarthome/ # # SmartHome.py is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # SmartHome.py is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with SmartHome.py. If not, see <http://www.gnu.org/licenses/>. # import sys import logging import socket import threading import struct import time import datetime logger = logging.getLogger('') class luxex(Exception): pass class LuxBase(): def __init__(self, host, port=8888): self.host = host self.port = int(port) self._sock = False self._lock = threading.Lock() self.is_connected = False self._connection_attempts = 0 self._connection_errorlog = 60 self._params = [] self._attrs = [] self._calc = [] def get_attribute(self, identifier): return self._attrs[identifier] if identifier < len(self._attrs) else None def get_parameter(self, identifier): return self._params[identifier] if identifier < len(self._params) else None def get_calculated(self, identifier): return self._calc[identifier] if identifier < len(self._calc) else None def get_attribute_count(self): return len(self._attrs) def get_parameter_count(self): return len(self._params) def get_calculated_count(self): return len(self._calc) def connect(self): self._lock.acquire() try: self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self._sock.settimeout(4) self._sock.connect((self.host, self.port)) except Exception as e: self._connection_attempts -= 1 if self._connection_attempts <= 0: logger.error( 'Luxtronic2: could not connect to {0}:{1}: {2}'.format(self.host, self.port, e)) self._connection_attempts = self._connection_errorlog return finally: self._lock.release() logger.info( 'Luxtronic2: connected to {0}:{1}'.format(self.host, self.port)) self.is_connected = True self._connection_attempts = 0 def close(self): self.is_connected = False try: self._sock.close() self._sock = False except: pass def _request(self, request, length): if not self.is_connected: raise luxex("no connection to luxtronic.") try: self._sock.send(request) except Exception as e: self._lock.release() self.close() raise luxex("error sending request: {0}".format(e)) try: answer = self._sock.recv(length) except socket.timeout: self._lock.release() raise luxex("error receiving answer: timeout") except Exception as e: self._lock.release() self.close() raise luxex("error receiving answer: {0}".format(e)) return answer def _request_more(self, length): try: return self._sock.recv(length) except socket.timeout: self._lock.release() raise luxex("error receiving payload: timeout") except Exception as e: self._lock.release() self.close() raise luxex("error receifing payload: {0}".format(e)) def set_param(self, param, value): param = int(param) # old = self._params[param] if param < len(self._params) else 0 payload = struct.pack('!iii', 3002, int(param), int(value)) self._lock.acquire() answer = self._request(payload, 8) self._lock.release() if len(answer) != 8: self.close() raise luxex("error receiving answer: no data") answer = struct.unpack('!ii', answer) fields = ['cmd', 'param'] answer = dict(list(zip(fields, answer))) if answer['cmd'] == 3002 and answer['param'] == param: logger.debug( "Luxtronic2: value {0} for parameter {1} stored".format(value, param)) return True else: logger.warning( "Luxtronic2: value {0} for parameter {1} not stored".format(value, param)) return False def refresh_parameters(self): request = struct.pack('!ii', 3003, 0) self._lock.acquire() answer = self._request(request, 8) if len(answer) != 8: self._lock.release() self.close() raise luxex("error receiving answer: no data") answer = struct.unpack('!ii', answer) fields = ['cmd', 'len'] answer = dict(list(zip(fields, answer))) if answer['cmd'] == 3003: params = [] for i in range(0, answer['len']): param = self._request_more(2) params.append(struct.unpack('!i', param)[0]) self._lock.release() if len(params) > 0: self._params = params return True return False else: self._lock.release() logger.warning("Luxtronic2: failed to retrieve parameters") return False def refresh_attributes(self): request = struct.pack('!ii', 3005, 0) self._lock.acquire() answer = self._request(request, 8) if len(answer) != 8: self._lock.release() self.close() raise luxex("error receiving answer: no data") answer = struct.unpack('!ii', answer) fields = ['cmd', 'len'] answer = dict(list(zip(fields, answer))) if answer['cmd'] == 3005: attrs = [] for i in range(0, answer['len']): attr = self._request_more(1) attrs.append(struct.unpack('!b', attr)[0]) self._lock.release() if len(attrs) > 0: self._attrs = attrs return True return False else: self._lock.release() logger.warning("Luxtronic2: failed to retrieve attributes") return False def refresh_calculated(self): request = struct.pack('!ii', 3004, 0) self._lock.acquire() answer = self._request(request, 12) if len(answer) != 12: self._lock.release() self.close() raise luxex("error receiving answer: no data") answer = struct.unpack('!iii', answer) fields = ['cmd', 'state', 'len'] answer = dict(list(zip(fields, answer))) if answer['cmd'] == 3004: calcs = [] for i in range(0, answer['len']): calc = self._request_more(4) calcs.append(struct.unpack('!i', calc)[0]) self._lock.release() if len(calcs) > 0: self._calc = calcs return answer['state'] return 0 else: self._lock.release() logger.warning("Luxtronic2: failed to retrieve calculated") return 0 class Luxtronic2(LuxBase): _parameter = {} _attribute = {} _calculated = {} _decoded = {} alive = True def __init__(self, smarthome, host, port=8888, cycle=60): LuxBase.__init__(self, host, port) self._sh = smarthome self._cycle = int(cycle) self.connect() def run(self): self.alive = True self._sh.scheduler.add('Luxtronic2', self._refresh, cycle=self._cycle) def stop(self): self.alive = False def _refresh(self): if not self.is_connected: return start = time.time() if len(self._parameter) > 0: self.refresh_parameters() for p in self._parameter: val = self.get_parameter(p) if val: self._parameter[p](val, 'Luxtronic2') if len(self._attribute) > 0: self.refresh_attributes() for a in self._attribute: val = self.get_attribute(a) if val: self._attribute[a](val, 'Luxtronic2') if len(self._calculated) > 0 or len(self._decoded) > 0: self.refresh_calculated() for c in self._calculated: val = self.get_calculated(c) if val: self._calculated[c](val, 'Luxtronic2') for d in self._decoded: val = self.get_calculated(d) if val: self._decoded[d](self._decode(d, val), 'Luxtronic2') cycletime = time.time() - start logger.debug("cycle takes {0} seconds".format(cycletime)) def _decode(self, identifier, value): if identifier == 95: return (datetime.datetime.fromtimestamp(value).strftime('%m.%d.%y %H:%M')) if identifier == 96: return (datetime.datetime.fromtimestamp(value).strftime('%m.%d.%y %H:%M')) if identifier == 97: return (datetime.datetime.fromtimestamp(value).strftime('%m.%d.%y %H:%M')) if identifier == 98: return (datetime.datetime.fromtimestamp(value).strftime('%m.%d.%y %H:%M')) if identifier == 99: return (datetime.datetime.fromtimestamp(value).strftime('%m.%d.%y %H:%M')) if identifier == 118: if value == 0: return 'Test' if value == 1: return 'Waermepumpe steht' if value == 2: return 'Test2' if value == 3: return 'Test3' return '???' if identifier == 120: if value == 0: return 'Heizbetrieb' if value == 1: return 'Keine Anforderung' if value == 2: return 'Netz- Einschaltverzoegerung' if value == 3: return 'SSP Zeit' if value == 4: return 'Sperrzeit' if value == 5: return 'Brauchwasser' if value == 6: return 'Estrich Programm' if value == 7: return 'Abtauen' if value == 8: return 'Pumpenvorlauf' if value == 9: return 'Thermische Desinfektion' if value == 10: return 'Kuehlbetrieb' if value == 12: return 'Schwimmbad' if value == 13: return 'Heizen Ext.' if value == 14: return 'Brauchwasser Ext.' if value == 16: return 'Durchflussueberwachung' if value == 17: return 'ZWE Betrieb' return '???' if identifier == 10: return float(value) / 10 if identifier == 11: return float(value) / 10 if identifier == 12: return float(value) / 10 if identifier == 15: return float(value) / 10 if identifier == 19: return float(value) / 10 if identifier == 20: return float(value) / 10 if identifier == 151: return float(value) / 10 if identifier == 152: return float(value) / 10 return value def parse_item(self, item): if 'lux2' in item.conf: d = item.conf['lux2'] d = int(d) self._decoded[d] = item if 'lux2_a' in item.conf: a = item.conf['lux2_a'] a = int(a) self._attribute[a] = item if 'lux2_c' in item.conf: c = item.conf['lux2_c'] c = int(c) self._calculated[c] = item if 'lux2_p' in item.conf: p = item.conf['lux2_p'] p = int(p) self._parameter[p] = item return self.update_item def update_item(self, item, caller=None, source=None, dest=None): if caller != 'Luxtronic2': self.set_param(item.conf['lux2_p'], item()) def main(): try: lux = LuxBase('192.168.1.11') lux.connect() if not lux.is_connected: return 1 start = time.time() lux.refresh_parameters() lux.refresh_attributes() lux.refresh_calculated() cycletime = time.time() - start print("{0} Parameters:".format(lux.get_parameter_count())) for i in range(0, lux.get_parameter_count()): print(" {0} = {1}".format(i + 1, lux.get_parameter(i))) print("{0} Attributes:".format(lux.get_attribute_count())) for i in range(0, lux.get_attribute_count()): print(" {0} = {1}".format(i + 1, lux.get_attribute(i))) print("{0} Calculated:".format(lux.get_calculated_count())) for i in range(0, lux.get_calculated_count()): print(" {0} = {1}".format(i + 1, lux.get_calculated(i))) print("cycle takes {0} seconds".format(cycletime)) except Exception as e: print("[EXCEPTION] error main: {0}".format(e)) return 1 finally: if lux: lux.close() if __name__ == "__main__": sys.exit(main())
LG Max
Kommentar