class XMPPConnection(object): def __init__(self, jid, password, feature=None, keepalive=None, ca_cert=None, server=None, use_ipv6=None, bot=None): if feature is None: feature = {} self._bot = bot self.connected = False self.server = server self.client = ClientXMPP(jid, password, plugin_config={'feature_mechanisms': feature}) self.client.register_plugin('xep_0030') # Service Discovery self.client.register_plugin('xep_0045') # Multi-User Chat self.client.register_plugin('xep_0199') # XMPP Ping self.client.register_plugin('xep_0203') # XMPP Delayed messages self.client.register_plugin('xep_0249') # XMPP direct MUC invites if keepalive is not None: self.client.whitespace_keepalive = True # Just in case SleekXMPP's default changes to False in the future self.client.whitespace_keepalive_interval = keepalive if use_ipv6 is not None: self.client.use_ipv6 = use_ipv6 self.client.ca_certs = ca_cert # Used for TLS certificate validation self.client.add_event_handler("session_start", self.session_start) def session_start(self, _): self.client.send_presence() self.client.get_roster() def connect(self): if not self.connected: if self.server is not None: self.client.connect(self.server) else: self.client.connect() self.connected = True return self def disconnect(self): self.client.disconnect(wait=True) self.connected = False def serve_forever(self): self.client.process(block=True) def add_event_handler(self, name, cb): self.client.add_event_handler(name, cb) def del_event_handler(self, name, cb): self.client.del_event_handler(name, cb)
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 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="DIGEST-MD5"): """ :param serial_number: :param access_key: :param password: :param host: :param sasl_mech: """ serial_number = str(serial_number) self.serial_number = serial_number self.access_key = access_key self.password = password 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.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): self.client.connect() self.client.process(block=block) def session_start(self, event): self.client.send_presence() self.client.get_roster() def disconnect(self): self.client.disconnect() 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) return self.container[id(self.event)] if id(self.event) in self.container.keys() else None 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 XMPPConnection(object): def __init__(self, jid, password, feature=None, keepalive=None, ca_cert=None, server=None, bot=None): if feature is not None: feature = {} self._bot = bot self.connected = False self.server = server self.client = ClientXMPP(jid, password, plugin_config={'feature_mechanisms': feature}) self.client.register_plugin('xep_0030') # Service Discovery self.client.register_plugin('xep_0045') # Multi-User Chat self.client.register_plugin('xep_0199') # XMPP Ping self.client.register_plugin('xep_0203') # XMPP Delayed messages self.client.register_plugin('xep_0249') # XMPP direct MUC invites if keepalive is not None: self.client.whitespace_keepalive = True # Just in case SleekXMPP's default changes to False in the future self.client.whitespace_keepalive_interval = keepalive self.client.ca_certs = ca_cert # Used for TLS certificate validation self.client.add_event_handler("session_start", self.session_start) def session_start(self, _): self.client.send_presence() self.client.get_roster() def connect(self): if not self.connected: if self.server is not None: self.client.connect(self.server) else: self.client.connect() self.connected = True return self def disconnect(self): self.client.disconnect(wait=True) self.connected = False def serve_forever(self): self.client.process(block=True) def add_event_handler(self, name, cb): self.client.add_event_handler(name, cb) def del_event_handler(self, name, cb): self.client.del_event_handler(name, cb) def join_room(self, room, username, password): """ Attempt to join the given MUC .. deprecated:: 2.2.0 Use the methods on :class:`XMPPMUCRoom` instead. """ warnings.warn( "Using join_room is deprecated, use join from the " "MUCRoom class instead.", DeprecationWarning) self._bot.query_room(room).join(username=username, password=password) def configure_room(self, room): """ Configure the given MUC Currently this simply sets the default room configuration as received by the server. May be extended in the future to set a custom room configuration instead. .. deprecated:: 2.2.0 Use the methods on :class:`XMPPMUCRoom` instead. """ warnings.warn( "Using configure_room is deprecated, use configure from the " "MUCRoom class instead.", DeprecationWarning) self._bot.query_room(room).configure() def invite_in_room(self, room, jids_to_invite): """ .. deprecated:: 2.2.0 Use the methods on :class:`XMPPMUCRoom` instead. """ warnings.warn( "Using invite_in_room is deprecated, use invite from the " "MUCRoom class instead.", DeprecationWarning, ) self._bot.query_room(room).invite(jids_to_invite)
class XMPPConnection(Connection): def __init__(self, jid, password): self.connected = False self.client = ClientXMPP( jid, password, plugin_config={'feature_mechanisms': XMPP_FEATURE_MECHANISMS}) self.client.register_plugin('xep_0030') # Service Discovery self.client.register_plugin('xep_0045') # Multi-User Chat self.client.register_plugin( 'xep_0004' ) # Multi-User Chat backward compability (necessary for join room) self.client.register_plugin('xep_0199') # XMPP Ping self.client.register_plugin('xep_0203') # XMPP Delayed messages self.client.register_plugin('xep_0249') # XMPP direct MUC invites if XMPP_KEEPALIVE_INTERVAL is not None: self.client.whitespace_keepalive = True # Just in case SleekXMPP's default changes to False in the future self.client.whitespace_keepalive_interval = XMPP_KEEPALIVE_INTERVAL self.client.ca_certs = XMPP_CA_CERT_FILE # Used for TLS certificate validation self.client.add_event_handler("session_start", self.session_start) self.client.add_event_handler("ssl_invalid_cert", self.ssl_invalid_cert) def send_message(self, mess): self.client.send_message(mto=mess.getTo(), mbody=mess.getBody(), mtype=mess.getType(), mhtml=mess.getHTML()) def session_start(self, _): self.client.send_presence() self.client.get_roster() def ssl_invalid_cert(self, _): # Special quirk for google domains verify_gtalk_cert(self.client) def connect(self): if not self.connected: self.client.connect() self.connected = True return self def disconnect(self): self.client.disconnect(wait=True) self.connected = False def serve_forever(self): self.client.process(block=True) def add_event_handler(self, name, cb): self.client.add_event_handler(name, cb) def del_event_handler(self, name, cb): self.client.del_event_handler(name, cb) def join_room(self, room, username, password): """Attempt to join the given MUC""" muc = self.client.plugin['xep_0045'] muc.joinMUC(room, username, password=password, wait=True) # Room configuration can only be done once a MUC presence stanza # has been received from the server. This HAS to take place in a # separate thread because of how SleekXMPP processes these stanzas. t = Thread(target=self.configure_room, args=[room]) t.setDaemon(True) t.start() def configure_room(self, room): """ Configure the given MUC Currently this simply sets the default room configuration as received by the server. May be extended in the future to set a custom room configuration instead. """ muc = self.client.plugin['xep_0045'] affiliation = None while affiliation is None: sleep(0.5) affiliation = muc.getJidProperty(room=room, nick=muc.ourNicks[room], jidProperty='affiliation') if affiliation == "owner": logging.debug( "Configuring room {} because we have owner affiliation".format( room)) form = muc.getRoomConfig(room) muc.configureRoom(room, form) else: logging.debug( "Not configuring room {} because we don't have owner affiliation (affiliation={})" .format(room, affiliation)) def invite_in_room(self, room, jids_to_invite): muc = self.client.plugin['xep_0045'] for jid in jids_to_invite: logging.debug("Inviting %s to %s..." % (jid, room)) muc.invite(room, jid)
class XMPPConnection(object): def __init__(self, jid, password, feature=None, keepalive=None, ca_cert=None, server=None, bot=None): if feature is not None: feature = {} self._bot = bot self.connected = False self.server = server self.client = ClientXMPP(jid, password, plugin_config={'feature_mechanisms': feature}) self.client.register_plugin('xep_0030') # Service Discovery self.client.register_plugin('xep_0045') # Multi-User Chat self.client.register_plugin('xep_0004') # Multi-User Chat backward compability (necessary for join room) self.client.register_plugin('xep_0199') # XMPP Ping self.client.register_plugin('xep_0203') # XMPP Delayed messages self.client.register_plugin('xep_0249') # XMPP direct MUC invites if keepalive is not None: self.client.whitespace_keepalive = True # Just in case SleekXMPP's default changes to False in the future self.client.whitespace_keepalive_interval = keepalive self.client.ca_certs = ca_cert # Used for TLS certificate validation self.client.add_event_handler("session_start", self.session_start) self.client.add_event_handler("ssl_invalid_cert", self.ssl_invalid_cert) def session_start(self, _): self.client.send_presence() self.client.get_roster() def ssl_invalid_cert(self, _): # Special quirk for google domains verify_gtalk_cert(self.client) def connect(self): if not self.connected: if self.server is not None: self.client.connect(self.server) else: self.client.connect() self.connected = True return self def disconnect(self): self.client.disconnect(wait=True) self.connected = False def serve_forever(self): self.client.process(block=True) def add_event_handler(self, name, cb): self.client.add_event_handler(name, cb) def del_event_handler(self, name, cb): self.client.del_event_handler(name, cb) def join_room(self, room, username, password): """ Attempt to join the given MUC .. deprecated:: 2.2.0 Use the methods on :class:`XMPPMUCRoom` instead. """ warnings.warn( "Using join_room is deprecated, use join from the " "MUCRoom class instead.", DeprecationWarning ) self._bot.query_room(room).join(username=username, password=password) def configure_room(self, room): """ Configure the given MUC Currently this simply sets the default room configuration as received by the server. May be extended in the future to set a custom room configuration instead. .. deprecated:: 2.2.0 Use the methods on :class:`XMPPMUCRoom` instead. """ warnings.warn( "Using configure_room is deprecated, use configure from the " "MUCRoom class instead.", DeprecationWarning ) self._bot.query_room(room).configure() def invite_in_room(self, room, jids_to_invite): """ .. deprecated:: 2.2.0 Use the methods on :class:`XMPPMUCRoom` instead. """ warnings.warn( "Using invite_in_room is deprecated, use invite from the " "MUCRoom class instead.", DeprecationWarning, ) self._bot.query_room(room).invite(jids_to_invite)
class XMPPConnection(Connection): def __init__(self, jid, password): self.connected = False self.client = ClientXMPP(jid, password, plugin_config={'feature_mechanisms': XMPP_FEATURE_MECHANISMS}) self.client.register_plugin('xep_0030') # Service Discovery self.client.register_plugin('xep_0045') # Multi-User Chat self.client.register_plugin('xep_0004') # Multi-User Chat backward compability (necessary for join room) self.client.register_plugin('xep_0199') # XMPP Ping self.client.register_plugin('xep_0203') # XMPP Delayed messages self.client.register_plugin('xep_0249') # XMPP direct MUC invites if XMPP_KEEPALIVE_INTERVAL is not None: self.client.whitespace_keepalive = True # Just in case SleekXMPP's default changes to False in the future self.client.whitespace_keepalive_interval = XMPP_KEEPALIVE_INTERVAL self.client.ca_certs = XMPP_CA_CERT_FILE # Used for TLS certificate validation self.client.add_event_handler("session_start", self.session_start) self.client.add_event_handler("ssl_invalid_cert", self.ssl_invalid_cert) def send_message(self, mess): self.client.send_message(mto=mess.getTo(), mbody=mess.getBody(), mtype=mess.getType(), mhtml=mess.getHTML()) def session_start(self, _): self.client.send_presence() self.client.get_roster() def ssl_invalid_cert(self, _): # Special quirk for google domains verify_gtalk_cert(self.client) def connect(self): if not self.connected: self.client.connect() self.connected = True return self def disconnect(self): self.client.disconnect(wait=True) self.connected = False def serve_forever(self): self.client.process(block=True) def add_event_handler(self, name, cb): self.client.add_event_handler(name, cb) def del_event_handler(self, name, cb): self.client.del_event_handler(name, cb) def join_room(self, room, username, password): """Attempt to join the given MUC""" muc = self.client.plugin['xep_0045'] muc.joinMUC(room, username, password=password, wait=True) # Room configuration can only be done once a MUC presence stanza # has been received from the server. This HAS to take place in a # separate thread because of how SleekXMPP processes these stanzas. t = Thread(target=self.configure_room, args=[room]) t.setDaemon(True) t.start() def configure_room(self, room): """ Configure the given MUC Currently this simply sets the default room configuration as received by the server. May be extended in the future to set a custom room configuration instead. """ muc = self.client.plugin['xep_0045'] affiliation = None while affiliation is None: sleep(0.5) affiliation = muc.getJidProperty( room=room, nick=muc.ourNicks[room], jidProperty='affiliation' ) if affiliation == "owner": logging.debug("Configuring room {} because we have owner affiliation".format(room)) form = muc.getRoomConfig(room) muc.configureRoom(room, form) else: logging.debug("Not configuring room {} because we don't have owner affiliation (affiliation={})" .format(room, affiliation)) def invite_in_room(self, room, jids_to_invite): muc = self.client.plugin['xep_0045'] for jid in jids_to_invite: logging.debug("Inviting %s to %s..." % (jid, room)) muc.invite(room, jid)
class XMPPConnection(object): def __init__(self, jid, password): self.connected = False self.client = ClientXMPP( str(jid), password, plugin_config={'feature_mechanisms': XMPP_FEATURE_MECHANISMS}) self.client.register_plugin('xep_0030') # Service Discovery self.client.register_plugin('xep_0045') # Multi-User Chat self.client.register_plugin( 'xep_0004' ) # Multi-User Chat backward compability (necessary for join room) self.client.register_plugin('xep_0199') # XMPP Ping self.client.register_plugin('xep_0203') # XMPP Delayed messages self.client.register_plugin('xep_0249') # XMPP direct MUC invites if XMPP_KEEPALIVE_INTERVAL is not None: self.client.whitespace_keepalive = True # Just in case SleekXMPP's default changes to False in the future self.client.whitespace_keepalive_interval = XMPP_KEEPALIVE_INTERVAL self.client.ca_certs = XMPP_CA_CERT_FILE # Used for TLS certificate validation self.client.add_event_handler("session_start", self.session_start) self.client.add_event_handler("ssl_invalid_cert", self.ssl_invalid_cert) def session_start(self, _): self.client.send_presence() self.client.get_roster() def ssl_invalid_cert(self, _): # Special quirk for google domains verify_gtalk_cert(self.client) def connect(self): if not self.connected: self.client.connect() self.connected = True return self def disconnect(self): self.client.disconnect(wait=True) self.connected = False def serve_forever(self): self.client.process(block=True) def add_event_handler(self, name, cb): self.client.add_event_handler(name, cb) def del_event_handler(self, name, cb): self.client.del_event_handler(name, cb) def join_room(self, room, username, password): """ Attempt to join the given MUC .. deprecated:: 2.2.0 Use the methods on :class:`XMPPMUCRoom` instead. """ warnings.warn( "Using join_room is deprecated, use join from the " "MUCRoom class instead.", DeprecationWarning) holder.bot.query_room(room).join(username=username, password=password) def configure_room(self, room): """ Configure the given MUC Currently this simply sets the default room configuration as received by the server. May be extended in the future to set a custom room configuration instead. .. deprecated:: 2.2.0 Use the methods on :class:`XMPPMUCRoom` instead. """ warnings.warn( "Using configure_room is deprecated, use configure from the " "MUCRoom class instead.", DeprecationWarning) holder.bot.query_room(room).configure() def invite_in_room(self, room, jids_to_invite): """ .. deprecated:: 2.2.0 Use the methods on :class:`XMPPMUCRoom` instead. """ warnings.warn( "Using invite_in_room is deprecated, use invite from the " "MUCRoom class instead.", DeprecationWarning, ) holder.bot.query_room(room).invite(jids_to_invite)