diff --git a/docs/fr_FR/changelog.md b/docs/fr_FR/changelog.md index 7a654ff..66dead0 100644 --- a/docs/fr_FR/changelog.md +++ b/docs/fr_FR/changelog.md @@ -4,6 +4,10 @@ > >S'il n'y a pas d'information sur la mise à jour, c'est que celle-ci concerne uniquement de la mise à jour de documentation, de traduction ou de texte. +# 18/12/2024 + +- Fix une fuite de mémoire sur le démon + # 25/11/2024 - Fix un soucis d'installation de dépendances qui pouvait se produire sur certaines installations diff --git a/resources/broadlinkd/broadlinkd.py b/resources/broadlinkd/broadlinkd.py index edacdd7..92efc94 100644 --- a/resources/broadlinkd/broadlinkd.py +++ b/resources/broadlinkd/broadlinkd.py @@ -23,174 +23,180 @@ import argparse import traceback import json -from broadlink import broadlink,rm2,a1,mp1,sp2,rm4 +from broadlink import broadlink, rm2, a1, mp1, sp2, rm4 import globals -from jeedom.jeedom import * +from jeedom.jeedom import jeedom_com, jeedom_socket, jeedom_utils, JEEDOM_SOCKET_MESSAGE # ---------------------------------------------------------------------------- + def listen(): - logging.debug("Start listening...") - jeedom_socket.open() - try: - while 1: - time.sleep(0.02) - read_socket() - read_broadlink() - except KeyboardInterrupt: - shutdown() + logging.debug("Start listening...") + jeedom_socket.open() + try: + while 1: + time.sleep(0.02) + read_socket() + read_broadlink() + except KeyboardInterrupt: + shutdown() + def read_socket(): - try: - global JEEDOM_SOCKET_MESSAGE - if not JEEDOM_SOCKET_MESSAGE.empty(): - logging.debug("Message received in socket JEEDOM_SOCKET_MESSAGE") - message = JEEDOM_SOCKET_MESSAGE.get().decode('utf-8') - message =json.loads(message) - if message['apikey'] != _apikey: - logging.error("Invalid apikey from socket: %s", message) - return - if message['cmd'] == 'add': - logging.debug('Add device : %s', message['device']) - if 'mac' in message['device']: - globals.KNOWN_DEVICES[message['device']['mac']] = message['device'] - elif message['cmd'] == 'remove': - logging.debug('Remove device : %s', message['device']) - if 'mac' in message['device']: - del globals.KNOWN_DEVICES[message['device']['mac']] - elif message['cmd'] == 'learnin': - logging.debug('Enter in learn mode') - globals.LEARN_MODE = True - globals.JEEDOMCOM.send_change_immediate({'learn_mode' : 1}) - devices = broadlink.discover(timeout=5) - logging.debug("found %s", devices) - globals.LEARN_MODE = False - globals.JEEDOMCOM.send_change_immediate({'learn_mode' : 0}) - for device in devices: - type = device.type - devtype = device.devtype - ip = device.host[0] - port = device.host[1] - mac = device.mac.hex() - reversemac = "".join(reversed([mac[i:i+2] for i in range(0, len(mac), 2)])) - globals.JEEDOMCOM.add_changes('devices::'+mac,{'type' : type, 'ip' : ip , 'mac': mac,'reversemac': reversemac, 'port' : port, 'learn' : 1 ,'devtype' :devtype}) - elif message['cmd'] == 'send': - if 'mac' in message['device']: - logging.debug('Send command') - send_broadlink(message) - except Exception as ex: - logging.error(ex) + try: + if not JEEDOM_SOCKET_MESSAGE.empty(): + logging.debug("Message received in socket JEEDOM_SOCKET_MESSAGE") + message = JEEDOM_SOCKET_MESSAGE.get().decode('utf-8') + message = json.loads(message) + if message['apikey'] != _apikey: + logging.error("Invalid apikey from socket: %s", message) + return + if message['cmd'] == 'add': + logging.debug('Add device : %s', message['device']) + if 'mac' in message['device']: + globals.KNOWN_DEVICES[message['device']['mac']] = message['device'] + elif message['cmd'] == 'remove': + logging.debug('Remove device : %s', message['device']) + if 'mac' in message['device']: + del globals.KNOWN_DEVICES[message['device']['mac']] + elif message['cmd'] == 'learnin': + logging.debug('Enter in learn mode') + globals.LEARN_MODE = True + globals.JEEDOMCOM.send_change_immediate({'learn_mode': 1}) + devices = broadlink.discover(timeout=5) + logging.debug("found %s", devices) + globals.LEARN_MODE = False + globals.JEEDOMCOM.send_change_immediate({'learn_mode': 0}) + for device in devices: + type = device.type + devtype = device.devtype + ip = device.host[0] + port = device.host[1] + mac = device.mac.hex() + reversemac = "".join(reversed([mac[i:i+2] for i in range(0, len(mac), 2)])) + globals.JEEDOMCOM.add_changes('devices::' + mac, {'type': type, 'ip': ip, 'mac': mac, 'reversemac': reversemac, 'port': port, 'learn': 1, 'devtype': devtype}) + elif message['cmd'] == 'send': + if 'mac' in message['device']: + logging.debug('Send command') + send_broadlink(message) + except Exception as ex: + logging.error(ex) # ---------------------------------------------------------------------------- + + def read_broadlink(): - now = datetime.datetime.now(datetime.timezone.utc) - result = {} - try: - for device in globals.KNOWN_DEVICES: - mac = globals.KNOWN_DEVICES[device]['mac'] - if mac in globals.LAST_TIME_READ and now < (globals.LAST_TIME_READ[mac]+datetime.timedelta(milliseconds=int(globals.KNOWN_DEVICES[device]['delay'])*1000)): - continue - if mac[-3:] == 'sub': - continue - else : - globals.LAST_TIME_READ[mac] = now - if globals.KNOWN_DEVICES[device]['type'] == 'rm2': - logging.debug('Handling RM2 for ' + globals.KNOWN_DEVICES[device]['name']) - result = rm2.read_rm2(globals.KNOWN_DEVICES[device]) - elif globals.KNOWN_DEVICES[device]['type'] == 'a1': - logging.debug('Handling A1 for ' + globals.KNOWN_DEVICES[device]['name']) - result = a1.read_a1(globals.KNOWN_DEVICES[device]) - elif globals.KNOWN_DEVICES[device]['type'] == 'sp2': - logging.debug('Handling SP2 for ' + globals.KNOWN_DEVICES[device]['name']) - result = sp2.read_sp2(globals.KNOWN_DEVICES[device]) - elif globals.KNOWN_DEVICES[device]['type'] == 'mp1': - logging.debug('Handling MP1 for ' + globals.KNOWN_DEVICES[device]['name']) - result = mp1.read_mp1(globals.KNOWN_DEVICES[device]) - elif globals.KNOWN_DEVICES[device]['type'] == 'rm4': - logging.debug('Handling RM4 for ' + globals.KNOWN_DEVICES[device]['name']) - result = rm4.read_rm4(globals.KNOWN_DEVICES[device]) - if result : - if mac in globals.LAST_STATE and result == globals.LAST_STATE[mac]: - continue - else: - globals.LAST_STATE[mac] = result - globals.JEEDOMCOM.add_changes('devices::'+mac,result) - except Exception as ex: - if str(ex) == 'timed out': - logging.debug('Device seems offline') - else: - logging.error(ex) + now = datetime.datetime.now(datetime.timezone.utc) + result = {} + try: + for device in globals.KNOWN_DEVICES: + mac = globals.KNOWN_DEVICES[device]['mac'] + if mac in globals.LAST_TIME_READ and now < (globals.LAST_TIME_READ[mac]+datetime.timedelta(milliseconds=int(globals.KNOWN_DEVICES[device]['delay'])*1000)): + continue + if mac[-3:] == 'sub': + continue + else: + globals.LAST_TIME_READ[mac] = now + if globals.KNOWN_DEVICES[device]['type'] == 'rm2': + logging.debug('Handling RM2 for ' + globals.KNOWN_DEVICES[device]['name']) + result = rm2.read_rm2(globals.KNOWN_DEVICES[device]) + elif globals.KNOWN_DEVICES[device]['type'] == 'a1': + logging.debug('Handling A1 for ' + globals.KNOWN_DEVICES[device]['name']) + result = a1.read_a1(globals.KNOWN_DEVICES[device]) + elif globals.KNOWN_DEVICES[device]['type'] == 'sp2': + logging.debug('Handling SP2 for ' + globals.KNOWN_DEVICES[device]['name']) + result = sp2.read_sp2(globals.KNOWN_DEVICES[device]) + elif globals.KNOWN_DEVICES[device]['type'] == 'mp1': + logging.debug('Handling MP1 for ' + globals.KNOWN_DEVICES[device]['name']) + result = mp1.read_mp1(globals.KNOWN_DEVICES[device]) + elif globals.KNOWN_DEVICES[device]['type'] == 'rm4': + logging.debug('Handling RM4 for ' + globals.KNOWN_DEVICES[device]['name']) + result = rm4.read_rm4(globals.KNOWN_DEVICES[device]) + if result: + if mac in globals.LAST_STATE and result == globals.LAST_STATE[mac]: + continue + else: + globals.LAST_STATE[mac] = result + globals.JEEDOMCOM.add_changes('devices::'+mac, result) + except Exception as ex: + if str(ex) == 'timed out': + logging.debug('Device seems offline') + else: + logging.error(ex) # ---------------------------------------------------------------------------- + def send_broadlink(message): - result = {} - if message['cmdType'] == 'refresh': - if message['device']['type'] == 'rm2': - result = rm2.read_rm2(message['device']) - elif message['device']['type'] == 'a1': - result = a1.read_a1(message['device']) - elif message['device']['type'] == 'mp1': - result = mp1.read_mp1(message['device']) - elif message['device']['type'] == 'sp2': - result = sp2.read_sp2(message['device']) - elif message['device']['type'] == 'rm4': - result = rm4.read_rm4(message['device']) - if result : - if message['device']['mac'] in globals.LAST_STATE and result == globals.LAST_STATE[message['device']['mac']]: - return - else: - globals.LAST_STATE[message['device']['mac']] = result - globals.JEEDOMCOM.add_changes('devices::'+message['device']['mac'],result) - return - elif message['device']['type'] == 'rm2': - if message['cmdType'] == 'learn': - result = rm2.learn_rm2(message['device']) - if result: - globals.JEEDOMCOM.add_changes('devices::'+message['device']['mac'],result) - else: - rm2.send_rm2(message['device']) - elif message['device']['type'] == 'rm4': - if message['cmdType'] == 'learn': - result = rm4.learn_rm4(message['device']) - if result: - globals.JEEDOMCOM.add_changes('devices::'+message['device']['mac'],result) - else: - rm4.send_rm4(message['device']) - elif message['device']['type'] == 'mp1': - result = mp1.send_mp1(message['device']) - if result: - globals.JEEDOMCOM.add_changes('devices::'+message['device']['mac'],result) - elif message['device']['type'] == 'sp2': - result = sp2.send_sp2(message['device']) - if result: - globals.JEEDOMCOM.add_changes('devices::'+message['device']['mac'],result) - return + result = {} + if message['cmdType'] == 'refresh': + if message['device']['type'] == 'rm2': + result = rm2.read_rm2(message['device']) + elif message['device']['type'] == 'a1': + result = a1.read_a1(message['device']) + elif message['device']['type'] == 'mp1': + result = mp1.read_mp1(message['device']) + elif message['device']['type'] == 'sp2': + result = sp2.read_sp2(message['device']) + elif message['device']['type'] == 'rm4': + result = rm4.read_rm4(message['device']) + if result: + if message['device']['mac'] in globals.LAST_STATE and result == globals.LAST_STATE[message['device']['mac']]: + return + else: + globals.LAST_STATE[message['device']['mac']] = result + globals.JEEDOMCOM.add_changes('devices::'+message['device']['mac'], result) + return + elif message['device']['type'] == 'rm2': + if message['cmdType'] == 'learn': + result = rm2.learn_rm2(message['device']) + if result: + globals.JEEDOMCOM.add_changes('devices::'+message['device']['mac'], result) + else: + rm2.send_rm2(message['device']) + elif message['device']['type'] == 'rm4': + if message['cmdType'] == 'learn': + result = rm4.learn_rm4(message['device']) + if result: + globals.JEEDOMCOM.add_changes('devices::'+message['device']['mac'], result) + else: + rm4.send_rm4(message['device']) + elif message['device']['type'] == 'mp1': + result = mp1.send_mp1(message['device']) + if result: + globals.JEEDOMCOM.add_changes('devices::'+message['device']['mac'], result) + elif message['device']['type'] == 'sp2': + result = sp2.send_sp2(message['device']) + if result: + globals.JEEDOMCOM.add_changes('devices::'+message['device']['mac'], result) + return # ---------------------------------------------------------------------------- def handler(signum=None, frame=None): - logging.debug("Signal %i caught, exiting...", signum) - shutdown() + logging.debug("Signal %i caught, exiting...", signum) + shutdown() + def shutdown(): - logging.debug("Shutdown") - logging.debug("Removing PID file %s", _pidfile) - try: - os.remove(_pidfile) - except: - pass - try: - jeedom_socket.close() - except: - pass - logging.debug("Exit 0") - sys.stdout.flush() - os._exit(0) + logging.debug("Shutdown") + logging.debug("Removing PID file %s", _pidfile) + try: + os.remove(_pidfile) + except Exception as ex: + logging.warning("Error while removing PID file: %s", ex) + try: + jeedom_socket.close() + except Exception as ex: + logging.warning("Error while closing socket: %s", ex) + logging.debug("Exit 0") + sys.stdout.flush() + os._exit(0) # ---------------------------------------------------------------------------- + _log_level = "error" _socket_port = 55013 _socket_host = '127.0.0.1' @@ -210,40 +216,40 @@ def shutdown(): args = parser.parse_args() if args.socketport: - _socket_port = int(args.socketport) + _socket_port = int(args.socketport) if args.loglevel: - _log_level = args.loglevel + _log_level = args.loglevel if args.callback: - _callback = args.callback + _callback = args.callback if args.apikey: - _apikey = args.apikey + _apikey = args.apikey if args.cycle: - _cycle = float(args.cycle) + _cycle = float(args.cycle) if args.pid: - _pidfile = args.pid + _pidfile = args.pid jeedom_utils.set_log_level(_log_level) logging.info('Start broadlinkd') logging.info('Log level: %s', _log_level) -logging.info('Socket port: %s', _socket_port) -logging.info('Socket host: %s', _socket_host) -logging.info('PID file: %s', _pidfile) -logging.info('Callback: %s', _callback) -logging.info('Cycle: %s', _cycle) +logging.debug('Socket port: %s', _socket_port) +logging.debug('Socket host: %s', _socket_host) +logging.debug('PID file: %s', _pidfile) +logging.debug('Callback: %s', _callback) +logging.debug('Cycle: %s', _cycle) signal.signal(signal.SIGINT, handler) signal.signal(signal.SIGTERM, handler) try: - jeedom_utils.write_pid(_pidfile) - globals.JEEDOMCOM = jeedom_com(apikey = _apikey,url = _callback,cycle=_cycle) - if not globals.JEEDOMCOM.test(): - logging.error('Network communication issues. Please fix your Jeedom network configuration.') - shutdown() - jeedom_socket = jeedom_socket(port=_socket_port,address=_socket_host) - listen() + jeedom_utils.write_pid(_pidfile) + globals.JEEDOMCOM = jeedom_com(apikey=_apikey, url=_callback, cycle=_cycle) + if not globals.JEEDOMCOM.test(): + logging.error('Network communication issues. Please fix your Jeedom network configuration.') + shutdown() + jeedom_socket = jeedom_socket(port=_socket_port, address=_socket_host) + listen() except Exception as ex: - logging.error('Fatal error : %s', ex) - logging.debug(traceback.format_exc()) - shutdown() + logging.error('Fatal error : %s', ex) + logging.debug(traceback.format_exc()) + shutdown() diff --git a/resources/broadlinkd/globals.py b/resources/broadlinkd/globals.py index b581d1d..dbf5d04 100644 --- a/resources/broadlinkd/globals.py +++ b/resources/broadlinkd/globals.py @@ -1,5 +1,5 @@ KNOWN_DEVICES = {} LEARN_MODE = False -LAST_STATE={} +LAST_STATE = {} LAST_TIME_READ = {} -JEEDOMCOM = '' \ No newline at end of file +JEEDOMCOM = None diff --git a/resources/broadlinkd/jeedom/jeedom.py b/resources/broadlinkd/jeedom/jeedom.py index 8310f7c..02aa03c 100644 --- a/resources/broadlinkd/jeedom/jeedom.py +++ b/resources/broadlinkd/jeedom/jeedom.py @@ -15,220 +15,197 @@ # import logging -import threading -import _thread as thread +from threading import Thread +import time import requests -import datetime from collections.abc import Mapping import os from queue import Queue import socketserver from socketserver import (TCPServer, StreamRequestHandler) -# ------------------------------------------------------------------------------ class jeedom_com(): - def __init__(self,apikey = '',url = '',cycle = 0.5,retry = 3): - self.apikey = apikey - self.url = url - self.cycle = cycle - self.retry = retry - self.changes = {} - if cycle > 0 : - self.send_changes_async() - logging.debug('Init request module v%s', requests.__version__) - - def send_changes_async(self): - try: - if len(self.changes) == 0: - resend_changes = threading.Timer(self.cycle, self.send_changes_async) - resend_changes.start() - return - start_time = datetime.datetime.now() - changes = self.changes - self.changes = {} - logging.debug('Send to jeedom : %s', changes) - i=0 - while i < self.retry: - try: - r = requests.post(self.url + '?apikey=' + self.apikey, json=changes, timeout=(0.5, 120), verify=False) - if r.status_code == requests.codes.ok: - break - except Exception as error: - logging.error('Error on send request to jeedom "%s" retry: %i/%i', error, i, self.retry) - i = i + 1 - if r.status_code != requests.codes.ok: - logging.error('Error on send request to jeedom, return code %s', r.status_code) - dt = datetime.datetime.now() - start_time - ms = (dt.days * 24 * 60 * 60 + dt.seconds) * 1000 + dt.microseconds / 1000.0 - timer_duration = self.cycle - ms - if timer_duration < 0.1: - timer_duration = 0.1 - if timer_duration > self.cycle: - timer_duration = self.cycle - resend_changes = threading.Timer(timer_duration, self.send_changes_async) - resend_changes.start() - except Exception as error: - logging.error('Critical error on send_changes_async %s', error) - resend_changes = threading.Timer(self.cycle, self.send_changes_async) - resend_changes.start() - - def add_changes(self,key,value): - if key.find('::') != -1: - tmp_changes = {} - changes = value - for k in reversed(key.split('::')): - if k not in tmp_changes: - tmp_changes[k] = {} - tmp_changes[k] = changes - changes = tmp_changes - tmp_changes = {} - if self.cycle <= 0: - self.send_change_immediate(changes) - else: - self.merge_dict(self.changes,changes) - else: - if self.cycle <= 0: - self.send_change_immediate({key:value}) - else: - self.changes[key] = value - - def send_change_immediate(self,change): - thread.start_new_thread(self.thread_change, (change,)) - - def thread_change(self,change): - logging.debug('Send to jeedom : %s', change) - i=0 - while i < self.retry: - try: - r = requests.post(self.url + '?apikey=' + self.apikey, json=change, timeout=(0.5, 120), verify=False) - if r.status_code == requests.codes.ok: - break - except Exception as error: - logging.error('Error on send request to jeedom "%s" retry: %i/%i', error, i, self.retry) - i = i + 1 - - def set_change(self,changes): - self.changes = changes - - def get_change(self): - return self.changes - - def merge_dict(self, d1, d2): - for k,v2 in d2.items(): - v1 = d1.get(k) # returns None if v1 has no value for this key - if ( isinstance(v1, Mapping) and - isinstance(v2, Mapping) ): - self.merge_dict(v1, v2) - else: - d1[k] = v2 - - def test(self): - try: - response = requests.get(self.url + '?apikey=' + self.apikey, verify=False) - if response.status_code != requests.codes.ok: - logging.error('Callback error: %s %s. Please check your network configuration page'% ( response.status_code, response.text,)) - return False - except Exception as ex: - logging.error('Callback result as a unknown error: %s. Please check your network configuration page', ex) - return False - return True - -# ------------------------------------------------------------------------------ + def __init__(self, apikey='', url='', cycle=0.5, retry=3): + self._apikey = apikey + self._url = url + self._cycle = cycle + self._retry = retry + self._changes = {} + if self._cycle > 0: + Thread(target=self.__thread_changes_async, daemon=True).start() + logging.debug('Init request module v%s', requests.__version__) + + def __thread_changes_async(self): + if self._cycle <= 0: + return + logging.info('Start changes async thread') + while True: + try: + time.sleep(self._cycle) + if len(self._changes) == 0: + continue + changes = self._changes + self._changes = {} + self.__post_change(changes) + except Exception as error: + logging.error('Critical error on send_changes_async %s', error) + + def add_changes(self, key: str, value): + if key.find('::') != -1: + tmp_changes = {} + changes = value + for k in reversed(key.split('::')): + if k not in tmp_changes: + tmp_changes[k] = {} + tmp_changes[k] = changes + changes = tmp_changes + tmp_changes = {} + if self._cycle <= 0: + self.send_change_immediate(changes) + else: + self.merge_dict(self._changes, changes) + else: + if self._cycle <= 0: + self.send_change_immediate({key: value}) + else: + self._changes[key] = value + + def send_change_immediate(self, change): + Thread(target=self.__post_change, args=(change,)).start() + + def __post_change(self, change): + logging.debug('Send to jeedom: %s', change) + for i in range(self._retry): + try: + r = requests.post(self._url + '?apikey=' + self._apikey, json=change, timeout=(0.5, 120), verify=False) + if r.status_code == requests.codes.ok: + return True + else: + logging.warning('Error on send request to jeedom, return code %s', r.status_code) + time.sleep(0.5) + except Exception as error: + logging.error('Error on send request to jeedom "%s" retry: %i/%i', error, i, self._retry) + return False + + def set_change(self, changes): + self._changes = changes + + def get_change(self): + return self._changes + + def merge_dict(self, d1, d2): + for k, v2 in d2.items(): + v1 = d1.get(k) # returns None if v1 has no value for this key + if (isinstance(v1, Mapping) and isinstance(v2, Mapping)): + self.merge_dict(v1, v2) + else: + d1[k] = v2 + + def test(self): + try: + response = requests.get(self._url + '?apikey=' + self._apikey, verify=False) + if response.status_code != requests.codes.ok: + logging.error('Callback error: %s %s. Please check your network configuration page', response.status_code, response.text) + return False + except Exception as ex: + logging.error('Callback result as a unknown error: %s. Please check your network configuration page', ex) + return False + return True + class jeedom_utils(): - @staticmethod - def convert_log_level(level = 'error'): - LEVELS = {'debug': logging.DEBUG, - 'info': logging.INFO, - 'notice': logging.WARNING, - 'warning': logging.WARNING, - 'error': logging.ERROR, - 'critical': logging.CRITICAL, - 'none': logging.NOTSET} - return LEVELS.get(level, logging.NOTSET) - - @staticmethod - def set_log_level(level = 'error'): - FORMAT = '[%(asctime)s.%(msecs)03d][%(levelname)s] : %(message)s' - logging.basicConfig(level=jeedom_utils.convert_log_level(level),format=FORMAT,datefmt='%Y-%m-%d %H:%M:%S') - - @staticmethod - def stripped(str): - return "".join([i for i in str if i in range(32, 127)]) - - @staticmethod - def ByteToHex( byteStr ): - return ''.join( [ "%02X " % ord( x ) for x in str(byteStr) ] ).strip() - - @staticmethod - def dec2hex(dec): - if dec is None: - return 0 - return hex(dec)[2:] - - @staticmethod - def testBit(int_type, offset): - mask = 1 << offset - return(int_type & mask) - - @staticmethod - def clearBit(int_type, offset): - mask = ~(1 << offset) - return(int_type & mask) - - @staticmethod - def split_len(seq, length): - return [seq[i:i+length] for i in range(0, len(seq), length)] - - @staticmethod - def write_pid(path): - pid = str(os.getpid()) - logging.debug("Writing PID %s to %s", pid, path) - open(path, 'w').write("%s\n" % pid) - -# ------------------------------------------------------------------------------ + @staticmethod + def convert_log_level(level='error'): + LEVELS = { + 'debug': logging.DEBUG, + 'info': logging.INFO, + 'notice': logging.WARNING, + 'warning': logging.WARNING, + 'error': logging.ERROR, + 'critical': logging.CRITICAL, + 'none': logging.NOTSET + } + return LEVELS.get(level, logging.NOTSET) + + @staticmethod + def set_log_level(level='error'): + FORMAT = '[%(asctime)s.%(msecs)03d][%(levelname)s] : %(message)s' + logging.basicConfig(level=jeedom_utils.convert_log_level(level), format=FORMAT, datefmt='%Y-%m-%d %H:%M:%S') + + @staticmethod + def stripped(str): + return "".join([i for i in str if i in range(32, 127)]) + + @staticmethod + def ByteToHex(byteStr): + return ''.join(["%02X " % ord(x) for x in str(byteStr)]).strip() + + @staticmethod + def dec2hex(dec): + if dec is None: + return 0 + return hex(dec)[2:] + + @staticmethod + def testBit(int_type, offset): + mask = 1 << offset + return (int_type & mask) + + @staticmethod + def clearBit(int_type, offset): + mask = ~(1 << offset) + return (int_type & mask) + + @staticmethod + def split_len(seq, length): + return [seq[i:i+length] for i in range(0, len(seq), length)] + + @staticmethod + def write_pid(path): + pid = str(os.getpid()) + logging.debug("Writing PID %s to %s", pid, path) + open(path, 'w').write("%s\n" % pid) + JEEDOM_SOCKET_MESSAGE = Queue() + class jeedom_socket_handler(StreamRequestHandler): - def handle(self): - global JEEDOM_SOCKET_MESSAGE - logging.debug("Client connected to [%s:%d]" % self.client_address) - lg = self.rfile.readline() - JEEDOM_SOCKET_MESSAGE.put(lg) - logging.debug("Message read from socket: %s", lg.strip()) - self.netAdapterClientConnected = False - logging.debug("Client disconnected from [%s:%d]" % self.client_address) + def handle(self): + global JEEDOM_SOCKET_MESSAGE + logging.debug("Client connected to [%s:%d]" % self.client_address) + lg = self.rfile.readline() + JEEDOM_SOCKET_MESSAGE.put(lg) + logging.debug("Message read from socket: %s", lg.strip()) + self.netAdapterClientConnected = False + logging.debug("Client disconnected from [%s:%d]" % self.client_address) + class jeedom_socket(): - def __init__(self,address='localhost', port=55000): - self.address = address - self.port = port - socketserver.TCPServer.allow_reuse_address = True - - def open(self): - self.netAdapter = TCPServer((self.address, self.port), jeedom_socket_handler) - if self.netAdapter: - logging.debug("Socket interface started") - threading.Thread(target=self.loopNetServer, args=()).start() - else: - logging.debug("Cannot start socket interface") - - def loopNetServer(self): - logging.debug("LoopNetServer Thread started") - logging.debug("Listening on: [%s:%d]" % (self.address, self.port)) - self.netAdapter.serve_forever() - logging.debug("LoopNetServer Thread stopped") - - def close(self): - self.netAdapter.shutdown() - - def getMessage(self): - return self.message - -# ------------------------------------------------------------------------------ -# END -# ------------------------------------------------------------------------------ + def __init__(self, address='localhost', port=55000): + self.address = address + self.port = port + socketserver.TCPServer.allow_reuse_address = True + + def open(self): + self.netAdapter = TCPServer((self.address, self.port), jeedom_socket_handler) + if self.netAdapter: + logging.debug("Socket interface started") + Thread(target=self.loopNetServer).start() + else: + logging.debug("Cannot start socket interface") + + def loopNetServer(self): + logging.debug("LoopNetServer Thread started") + logging.debug("Listening on: [%s:%d]" % (self.address, self.port)) + self.netAdapter.serve_forever() + logging.debug("LoopNetServer Thread stopped") + + def close(self): + self.netAdapter.shutdown() + + def getMessage(self): + return self.message