class Orkiv(App): icon = 'customicon.png' def __init__(self, root_dir): super(Orkiv, self).__init__() self.root_dir = root_dir self.xmpp = None def connect_to_jabber(self, jabber_id, password): self.xmpp = ClientXMPP(jabber_id, password) self.xmpp.reconnect_max_attempts = 1 connected = self.xmpp.connect() if not connected: raise XMPPError("Vyanse kwikonecta") self.xmpp.process() self.xmpp.send_presence() self.xmpp.get_roster() self.xmpp.add_event_handler('message', self.root.handle_xmpp_message) def disconnect_xmpp(self): if self.xmpp and self.xmpp.state.ensure("connected"): self.xmpp.abort() self.xmpp = None def on_stop(self): self.disconnect_xmpp()
class Orkiv(App): def __init__(self): super(Orkiv, self).__init__() self.xmpp = None def connect_to_jabber(self, jabber_id, password): self.xmpp = ClientXMPP(jabber_id, password) #~ self.xmpp.connect() self.xmpp.reconnect_max_attempts = 1 connected = self.xmpp.connect() if not connected: raise XMPPError("unable to connect") self.xmpp.process() self.xmpp.send_presence() self.xmpp.get_roster() def disconnect_xmpp(self): if self.xmpp and self.xmpp.state.ensure("connected"): self.xmpp.abort() self.xmpp = None def on_stop(self): self.disconnect_xmpp()
class NefitCore(object): _accesskey_prefix = 'Ct7ZR03b_' _rrc_contact_prefix = 'rrccontact_' _rrc_gateway_prefix = 'rrcgateway_' _magic = bytearray.fromhex("58f18d70f667c9c79ef7de435bf0f9b1553bbb6e61816212ab80e5b0d351fbb1") serial_number = None access_key = None password = None use_ssl = False use_tls = False jid = None _from = None _to = None client = None encryption = None event = None container = {} def __init__(self, serial_number, access_key, password, host="wa2-mz36-qrmzh6.bosch.de", sasl_mech="SCRAM-SHA-1", use_ssl=False, use_tls=False): """ :param serial_number: :param access_key: :param password: :param host: :param sasl_mech: :param use_ssl: :param use_tls: """ serial_number = str(serial_number) self.serial_number = serial_number self.access_key = access_key self.password = password self.use_ssl = use_ssl self.use_tls = use_tls self.encryption = AESCipher(self._magic, access_key, password) identifier = serial_number + "@" + host self.jid = jid = self._from = self._rrc_contact_prefix + identifier self._to = self._rrc_gateway_prefix + identifier self.client = ClientXMPP( jid=jid, password=self._accesskey_prefix + access_key, sasl_mech=sasl_mech ) self.client.ssl_version = PROTOCOL_SSLv23 self.client.add_event_handler("session_start", self.session_start) self.client.register_plugin('xep_0199') @staticmethod def set_verbose(): import logging logging.basicConfig(filename="debug.log", level=logging.DEBUG) def message(self, msg): if msg['type'] in ('chat', 'normal'): headers = msg['body'].split("\n")[:-1] body = msg['body'].split("\n")[-1:][0] if 'HTTP/1.0 400 Bad Request' in headers: return response = self.decrypt(body) if 'Content-Type: application/json' in headers: _LOGGER.debug("response='{}'".format(response)) response = response.strip() if len(response) > 1: response = json.loads(response.strip()) self.container[id(self.event)] = response self.event.set() def connect(self, block=False, use_ssl=None, use_tls=None, **kwargs): self.client.connect( use_ssl=use_ssl if use_ssl is not None else self.use_ssl, use_tls=use_tls if use_tls is not None else self.use_tls, **kwargs ) self.client.process(block=block) def session_start(self, event): self.client.send_presence() self.client.get_roster() def disconnect(self, wait=None, send_close=False): self.client.disconnect(reconnect=False, wait=wait, send_close=send_close) def force_disconnect(self): self.disconnect(wait=False, send_close=False) self.client.abort() def get(self, uri, timeout=10): self.event = Event() self.client.add_event_handler("message", self.message) self.send("GET %s HTTP/1.1\rUser-Agent: NefitEasy\r\r" % uri) self.event.wait(timeout=timeout) self.client.del_event_handler("message", self.message) if id(self.event) not in self.container.keys(): raise NefitResponseException("Unable to get %s" % uri) return self.container[id(self.event)] def put(self, uri, data, timeout=10): data = data if isinstance(data, str) else json.dumps(data, separators=(',', ':')) encrypted_data = self.encrypt(data).decode("utf8") body = "\r".join([ 'PUT %s HTTP/1.1' % uri, 'Content-Type: application/json', 'Content-Length: %i' % len(encrypted_data), 'User-Agent: NefitEasy\r', encrypted_data ]) self.event = Event() self.client.add_event_handler("message", self.message) self.send(body) self.event.wait(timeout=timeout) self.client.del_event_handler("message", self.message) def send(self, body): # this horrible piece of code breaks xml syntax but does actually work... body = body.replace("\r", " \n") message = self.client.make_message(mto=self._to, mfrom=self._from, mbody=body) message['lang'] = None str_data = tostring(message.xml, xmlns=message.stream.default_ns, stream=message.stream, top_level=True) str_data = str_data.replace("
", " ") return message.stream.send_raw(str_data) def encrypt(self, data): return self.encryption.encrypt(data) def decrypt(self, data): return self.encryption.decrypt(data) def get_display_code(self): return self.get('/system/appliance/displaycode') def get_status(self): return self.get('/ecus/rrc/uiStatus') def get_location(self): return self.get('/system/location/latitude'), self.get('/system/location/longitude') def get_outdoor(self): return self.get('/system/sensors/temperatures/outdoor_t1') def get_pressure(self): return self.get('/system/appliance/systemPressure') def get_program(self): return ( self.get('/ecus/rrc/userprogram/activeprogram'), self.get('/ecus/rrc/userprogram/program1'), self.get('/ecus/rrc/userprogram/program2'), ) def get_year_total(self): return self.get('/ecus/rrc/recordings/yearTotal') def set_temperature(self, temperature): self.put('/heatingCircuits/hc1/temperatureRoomManual', {'value': float(temperature)}) self.put('/heatingCircuits/hc1/manualTempOverride/status', {'value': 'on'}) self.put('/heatingCircuits/hc1/manualTempOverride/temperature', {'value': float(temperature)}) def get_actualSupplyTemperature(self): return self.get('/heatingCircuits/hc1/actualSupplyTemperature')
class XmppBot: """ Interfaces with Jabber and identifies bosses by JID and resource. """ def __init__(self, connect_cfg): "Initialize XMPP bot" # (Sender JID, [local resource]) -> callback self.dispatch_map = {} self.jid = connect_cfg.jid self.connect(connect_cfg) def connect(self, config): "Connect to XMPP server" socks_cfg = config.get('socks_proxy', required=False) self.client = ClientXMPP(self.jid, config.password) proxy_cfg = config.get('http_proxy', required=False) if proxy_cfg is not None: self.client.use_proxy = True self.client.proxy_config = { 'host': proxy_cfg.host, 'port': proxy_cfg.get('port', assert_type=int), 'username': proxy_cfg.get('username', required=False), 'password': proxy_cfg.get('password', required=False), } print("Configured proxy", self.client.proxy_config) use_tls = config.get('tls', default=True) # Events self.client.add_event_handler("session_start", self._session_start) self.client.add_event_handler("message", self.message_dispatch) log.info("Initializing connection to XMPP") ip = config.get('ip', required=False) if ip is not None: print("port", config.port) port = config.get('port', default=5222, assert_type=int) self.client.connect((ip, port), use_tls=use_tls) else: self.client.connect(use_tls=use_tls) def _session_start(self, event): log.info('Starting XMPP session') self.client.send_presence() def add_dispatch(self, sender_jid, resource, callback): """ Register callback to handle incoming messages from sender_jid directed to a given resource (can be None to mean "any"). """ key = (sender_jid, resource) if key in self.dispatch_map: raise Exception("Sender JID duplicated: %s" % sender_jid) self.dispatch_map[key] = callback def message_dispatch(self, msg): "Dispatch incoming message depending on the sender" if msg['type'] not in ('chat', 'normal'): log.warning('Unknown message type: %r %r', msg, msg['type']) return to_jid = msg.get_to() from_jid = msg.get_from() resource = to_jid.resource def respond(response): "Closure to simplify responding" self.send_message(from_jid, response) log.debug("Got message:") log.debug("From: %s, to: %s", from_jid, to_jid) log.debug("Body: %r", msg) # Dispatch direct (to resource) or generic (to JID) callback = self.dispatch_map.get((from_jid.bare, resource), None) if callback is None: callback = self.dispatch_map.get((from_jid.bare, None), None) # If unknown - ignore if callback is None: respond(language.get('DONT_KNOW')) return # Construct a Message using bot-generic API message = Message(msg['body'], from_jid.full, respond) callback(message) message.finish() def send_message(self, jid, message): "Send a message" self.client.send_message(jid, message) def close(self): "Disconnect / close threads" self.client.abort()