class Notifier: def __init__(self, protector): self.protector = protector self.db_model = Model() self.vendor_name = 'nasys' self.model_name = 'ul2011' self.initialize_notifier() def initialize_notifier(self): cnx = self.db_model.get_cnx_info(self.vendor_name, self.model_name) self.server = cnx['cnx_server'] port = cnx['cnx_port'] if port is not None and len(port) > 0: self.server += f':{port}' # this will be called when a new message is received def on_message(self, msg): print('Received: ', msg) json = json_loads(msg) data = str(json['payload']) fport = str(json['port']) dev_name = str(json['deveui']) # TODO: make sure the device is ours if fport == '24': status_info = decode_fp24_message(data) print(status_info) self.db_model.insert_log('feedback', json_dumps(status_info), 0) # TODO what if node error? # TODO profile_id == 255 ==> set individually # TODO current_level ===> update cmd_id? (hm...) elif fport == '25': usage_info = decode_fp25_message(data) print(usage_info) self.db_model.insert_sensor_data(dev_name, usage_info) elif fport == '60': reply_info = decode_fp60_message(data) print(reply_info) self.db_model.insert_log('feedback', json_dumps(reply_info), 0) # TODO also implement 01feXX message decoding elif fport == '99': sys_info = decode_fp99_message(data) print(sys_info) self.db_model.insert_log('feedback', json_dumps(sys_info), 0) # TODO # set active/inactive/error status depending on boot/shutdown/error # remember: change map icon as well def main_loop(self): while True: ws = websocket.WebSocket() ws.connect(self.server) if not ws.connected: raise KeyboardInterrupt() try: while True: msg = ws.recv() with self.protector: self.on_message(msg) except: # wait a bit, then reconnect # WARNING: we could possibly drop crucial messages # sleep(1) pass def clean_up(self): self.db_model.cleanup()
class Notifier: def __init__(self, protector): self.protector = protector self.client = mqtt.Client() self.db_model = Model() self.initialize_notifier() def initialize_notifier(self): cnx = self.db_model.get_cnx_info('iled', 'iled') # Called when the client receives a CONNACK response from the server def on_connect(client, userdata, flags, rc): # DEBUG print('Connected.') client.subscribe(cnx['cnx_mqtt_rx_topic']) # DEBUG print('Subscribed to {}'.format(cnx['cnx_mqtt_rx_topic'])) # Called when the client receives a message from the server def on_message(client, userdata, msg): with self.protector: try: topic = msg.topic msg = json_loads(str(msg.payload.decode())) dev_name = msg['devEUI'] command_hex = msg['dataHex'] except (ValueError, KeyError): # DEBUG print(datetime.now(), 'Ignoring bad message', topic, msg) return # DEBUG print(datetime.now(), topic, dev_name, command_hex) if command_hex == '312e303038': print(f'Received {command_hex} from {dev_name}') return info = self.db_model.get_dev_id_and_cmd_name(dev_name) if not info: print(f'Unknown device name {dev_name}') return try: dim_level_in_db = int( info['cmd_name'][len('set_dim_level_'):]) dim_level_reported = hex_to_dim_level(command_hex) has_problem = dim_level_in_db != dim_level_reported except: has_problem = True data = json_dumps({ 'received_message': json_dumps(msg), 'wanted_dim_level': dim_level_in_db, 'actual_dim_level': dim_level_reported, }) self.db_model.insert_log('feedback', data, has_problem) self.db_model.update_device_status( [info['dev_id']], dstat_name='error' if has_problem else 'active') self.client.on_connect = on_connect self.client.on_message = on_message password = aes_decrypt(cnx['cnx_password']) self.client.username_pw_set(cnx['cnx_username'], password) password = '' if cnx['cnx_port'] is not None: self.client.connect(cnx['cnx_server'], port=int(cnx['cnx_port']), keepalive=60) else: self.client.connect(cnx['cnx_server'], keepalive=60) def main_loop(self): self.client.loop_forever() def clean_up(self): try: self.client.disconnect() self.db_model.cleanup() except: pass