D901 #2

Merged
bmartin5692 merged 34 commits from D901 into dev 2019-02-22 05:37:44 +01:00
5 changed files with 177 additions and 78 deletions
Showing only changes of commit f7d91aa650 - Show all commits

View file

@ -24,18 +24,18 @@ mqtt_address = ("0.0.0.0", 8883)
# A default bot could be set here to automatically add it as available # A default bot could be set here to automatically add it as available
# dbot = bumper.VacBotDevice("did", "class", "resource", "name","nick" ) # dbot = bumper.VacBotDevice("did", "class", "resource", "name","nick" )
# bclient = bumper.bumper_clients_var # bclient = bumper.bumper_bots_var
# bclienttemp = bclient.get() # bclienttemp = bclient.get()
# bclienttemp.append(dbot.asdict()) # bclienttemp.append(dbot.asdict())
# bclient.set(bclienttemp) # bclient.set(bclienttemp)
# start mqtt server (async) # start mqtt server (async)
mqtt_server = bumper.MQTTServer(mqtt_address, run_async=True,bumper_clients=bumper.bumper_clients_var) mqtt_server = bumper.MQTTServer(mqtt_address, run_async=True,bumper_bots=bumper.bumper_bots_var,bumper_clients=bumper.bumper_clients_var)
time.sleep(1.5) #Wait for broker startup time.sleep(1.5) #Wait for broker startup
# start mqtt server (async) # start mqtt server (async)
mqtt_helperbot = bumper.MQTTHelperBot(mqtt_address, run_async=True,bumper_clients=bumper.bumper_clients_var) mqtt_helperbot = bumper.MQTTHelperBot(mqtt_address, run_async=True,bumper_bots=bumper.bumper_bots_var,bumper_clients=bumper.bumper_clients_var)
# start conf server (async) # start conf server (async)
conf_server = bumper.ConfServer(conf_address, usessl=True, run_async=True, bumper_clients=bumper.bumper_clients_var, helperbot=mqtt_helperbot) conf_server = bumper.ConfServer(conf_address, usessl=True, run_async=True,bumper_bots=bumper.bumper_bots_var,bumper_clients=bumper.bumper_clients_var, helperbot=mqtt_helperbot)
# start xmpp server (sync) # start xmpp server (sync)
xmpp_server = bumper.XMPPServer(xmpp_address) xmpp_server = bumper.XMPPServer(xmpp_address)

View file

@ -9,6 +9,10 @@ import contextvars
import time import time
bumper_clients_var = contextvars.ContextVar('bumper_clients', default=[]) bumper_clients_var = contextvars.ContextVar('bumper_clients', default=[])
bumper_bots_var = contextvars.ContextVar('bumper_bots', default=[])
ca_cert = './certs/CA/cacert.pem'
server_cert = './certs/cert.pem'
server_key = './certs/key.pem'
def get_milli_time(timetoconvert): def get_milli_time(timetoconvert):
return int(round(timetoconvert * 1000)) return int(round(timetoconvert * 1000))
@ -26,3 +30,13 @@ class VacBotDevice(object):
def asdict(self): def asdict(self):
return {"class": self.vac_bot_device_class, "company": self.company, return {"class": self.vac_bot_device_class, "company": self.company,
"did": self.did, "name": self.name, "nick": self.nick, "resource": self.resource} "did": self.did, "name": self.name, "nick": self.nick, "resource": self.resource}
class VacBotUser(object):
def __init__(self,userid="",realm="",token=""):
self.userid = userid
self.realm = realm
self.resource = token
def asdict(self):
return {"userid": self.userid,"realm": self.realm,"resource": self.resource}

View file

@ -13,8 +13,10 @@ from aiohttp import web
class ConfServer(): class ConfServer():
bumper_clients = contextvars.ContextVar bumper_clients = contextvars.ContextVar
bumper_bots = contextvars.ContextVar
def __init__(self, address, usessl=False, run_async=True, bumper_clients=contextvars.ContextVar, helperbot=None): def __init__(self, address, usessl=False, run_async=True, bumper_bots=contextvars.ContextVar, bumper_clients=contextvars.ContextVar, helperbot=None):
self.bumper_bots = bumper_bots
self.bumper_clients = bumper_clients self.bumper_clients = bumper_clients
self.helperbot = helperbot self.helperbot = helperbot
self.usessl = usessl self.usessl = usessl
@ -54,15 +56,16 @@ class ConfServer():
app.add_routes([ app.add_routes([
web.get('/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/login', self.handle_login), web.get('/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/login', self.handle_login),
web.get('/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/logout', self.handle_login), web.get('/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/checkLogin', self.handle_login),
web.get('/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/logout', self.handle_logout),
web.get('/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/getAuthCode', self.handle_getAuthCode), web.get('/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/getAuthCode', self.handle_getAuthCode),
web.get('/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/checkAgreement', self.handle_checkAgreement), web.get('/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/checkAgreement', self.handle_checkAgreement),
web.get('/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/common/getAuthCode', self.handle_checkVersion), web.get('/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/common/checkVersion', self.handle_checkVersion),
web.get('/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/campaign/homePageAlert', self.handle_homePageAlert), web.get('/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/campaign/homePageAlert', self.handle_homePageAlert),
web.post('/api/users/user.do', self.handle_usersapi), web.post('/api/users/user.do', self.handle_usersapi),
web.post('/api/pim/product/getProductIotMap', self.handle_getProductIotMap), web.post('/api/pim/product/getProductIotMap', self.handle_getProductIotMap),
web.post('/api/iot/devmanager.do', self.handle_devmanager) web.post('/api/iot/devmanager.do', self.handle_devmanager_botcommand)
]) ])
@ -71,7 +74,7 @@ class ConfServer():
if self.usessl: if self.usessl:
ssl_ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) ssl_ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
ssl_ctx.load_cert_chain('./certs/cert.pem', './certs/key.pem') ssl_ctx.load_cert_chain(bumper.server_cert,bumper.server_key)
site = web.TCPSite(runner, host=self.address[0], port=self.address[1],ssl_context=ssl_ctx) site = web.TCPSite(runner, host=self.address[0], port=self.address[1],ssl_context=ssl_ctx)
else: else:
@ -89,8 +92,8 @@ class ConfServer():
"accessToken": "tempaccesstoken", #Random chars 32 length "accessToken": "tempaccesstoken", #Random chars 32 length
"country": countrycode, "country": countrycode,
"email": "null@null.com", "email": "null@null.com",
"uid": "fuid_1", #Date(14)_RandomChars(32) "uid": "fuid_{}".format(''.join(random.sample(string.ascii_letters,6))), #Date(14)_RandomChars(32)
"username": "fusername_1" #Random chars 8 "username": "fusername_{}".format(''.join(random.sample(string.ascii_letters,6))) #Random chars 8
}, },
"msg": "操作成功", "msg": "操作成功",
"time": bumper.get_milli_time(time.time()) "time": bumper.get_milli_time(time.time())
@ -100,6 +103,7 @@ class ConfServer():
async def handle_logout(self, request): async def handle_logout(self, request):
body = {"code": "0000","data": None,"msg": "操作成功", "time": bumper.get_milli_time(time.time())} body = {"code": "0000","data": None,"msg": "操作成功", "time": bumper.get_milli_time(time.time())}
#TODO - when logging out close out any other connections MQTT/XMPP
return web.json_response(body) return web.json_response(body)
@ -109,7 +113,7 @@ class ConfServer():
"code": "0000", "code": "0000",
"data": { "data": {
"authCode": "{}_tempauthcode".format(countrycode), #countrycode_randomchars(32) "authCode": "{}_tempauthcode".format(countrycode), #countrycode_randomchars(32)
"ecovacsUid": "fuid_1" #Date(14)_RandomChars(32) "ecovacsUid": "fuid_{}".format(''.join(random.sample(string.ascii_letters,6))) #Date(14)_RandomChars(32)
}, },
"msg": "操作成功", "msg": "操作成功",
"time": bumper.get_milli_time(time.time()) "time": bumper.get_milli_time(time.time())
@ -171,6 +175,8 @@ class ConfServer():
return web.json_response(body) return web.json_response(body)
async def handle_usersapi(self, request): async def handle_usersapi(self, request):
body = {}
json_body = json.loads(await request.text()) json_body = json.loads(await request.text())
todo = json_body['todo'] todo = json_body['todo']
if todo == 'FindBest': if todo == 'FindBest':
@ -188,7 +194,7 @@ class ConfServer():
"userId": json_body["userId"] #RandomChar(16) "userId": json_body["userId"] #RandomChar(16)
} }
elif todo == 'GetDeviceList': elif todo == 'GetDeviceList':
active_bots = self.bumper_clients.get() active_bots = self.bumper_bots.get()
body = { body = {
"devices": active_bots, "devices": active_bots,
"result": "ok", "result": "ok",
@ -197,7 +203,7 @@ class ConfServer():
return web.json_response(body) return web.json_response(body)
async def handle_devmanager(self, request): async def handle_devmanager_botcommand(self, request):
json_body = json.loads(await request.text()) json_body = json.loads(await request.text())
randomid = ''.join(random.sample(string.ascii_letters,6)) randomid = ''.join(random.sample(string.ascii_letters,6))
retcmd = await self.helperbot.send_command(json_body, randomid) retcmd = await self.helperbot.send_command(json_body, randomid)

View file

@ -19,7 +19,7 @@ from datetime import datetime, timedelta
class MQTTHelperBot(): class MQTTHelperBot():
Client = MQTTClient() Client = MQTTClient()
def __init__(self, address, run_async=False, bumper_clients=contextvars.ContextVar): def __init__(self, address, run_async=False, bumper_bots=contextvars.ContextVar, bumper_clients=contextvars.ContextVar):
self.address = address self.address = address
self.client_id = "helper1@bumper/helper1" self.client_id = "helper1@bumper/helper1"
@ -51,7 +51,7 @@ class MQTTHelperBot():
async def start_helper_bot(self): async def start_helper_bot(self):
try: try:
await self.Client.connect('mqtts://{}:{}/'.format(self.address[0], self.address[1]), cafile='./certs/CA/cacert.pem') await self.Client.connect('mqtts://{}:{}/'.format(self.address[0], self.address[1]), cafile=bumper.ca_cert)
await self.Client.subscribe([ await self.Client.subscribe([
('iot/p2p/+/+/+/+/helper1/bumper/helper1/+/+/+',QOS_0), ('iot/p2p/+/+/+/+/helper1/bumper/helper1/+/+/+',QOS_0),
('iot/p2p/+',QOS_0) ('iot/p2p/+',QOS_0)
@ -125,6 +125,7 @@ class MQTTHelperBot():
class MQTTServer(): class MQTTServer():
default_config = {} default_config = {}
bumper_clients = [] bumper_clients = []
bumper_bots = []
async def broker_coro(self): async def broker_coro(self):
broker = hbmqtt.broker.Broker(config=self.default_config) broker = hbmqtt.broker.Broker(config=self.default_config)
@ -133,16 +134,16 @@ class MQTTServer():
async def active_bot_listing(self): async def active_bot_listing(self):
while True: while True:
await asyncio.sleep(5) await asyncio.sleep(5)
logging.debug('Connected bots: %s' % self.bumper_clients.get()) logging.debug('Connected bots: %s' % self.bumper_bots.get())
def __init__(self, address, run_async=False, bumper_clients=contextvars.ContextVar): def __init__(self, address, run_async=False, bumper_bots=contextvars.ContextVar, bumper_clients=contextvars.ContextVar):
#The below adds a plugin to the hbmqtt.broker.plugins without having to futz with setup.py #The below adds a plugin to the hbmqtt.broker.plugins without having to futz with setup.py
distribution = pkg_resources.Distribution("hbmqtt.broker.plugins") distribution = pkg_resources.Distribution("hbmqtt.broker.plugins")
bumper_plugin = pkg_resources.EntryPoint.parse('bumper = bumper.mqttserver:BumperMQTTServer_Plugin', dist=distribution) bumper_plugin = pkg_resources.EntryPoint.parse('bumper = bumper.mqttserver:BumperMQTTServer_Plugin', dist=distribution)
distribution._ep_map = {"hbmqtt.broker.plugins": {"bumper": bumper_plugin}} distribution._ep_map = {"hbmqtt.broker.plugins": {"bumper": bumper_plugin}}
pkg_resources.working_set.add(distribution) pkg_resources.working_set.add(distribution)
self.bumper_bots = bumper_bots
self.bumper_clients = bumper_clients self.bumper_clients = bumper_clients
try: try:
# Initialize bot server # Initialize bot server
@ -154,8 +155,8 @@ class MQTTServer():
'tls1': { 'tls1': {
'bind': "{}:{}".format(address[0], address[1]), 'bind': "{}:{}".format(address[0], address[1]),
'ssl': 'on', 'ssl': 'on',
'certfile': './certs/cert.pem', 'certfile': bumper.server_cert,
'keyfile': './certs/key.pem', 'keyfile': bumper.server_key,
}, },
}, },
'sys_interval': 10, 'sys_interval': 10,
@ -169,8 +170,10 @@ class MQTTServer():
'topic-check': { 'topic-check': {
'enabled': False 'enabled': False
}, },
'bots':{ 'clients':{
'connected_bots': bumper_clients 'connected_bots': bumper_bots,
'connected_clients': bumper_clients
} }
} }
if run_async: if run_async:
@ -198,14 +201,16 @@ class BumperMQTTServer_Plugin:
def __init__(self, context): def __init__(self, context):
self.context = context self.context = context
try: try:
self.bots = self.context.config['bots'] self.clients = self.context.config['clients']
except KeyError: except KeyError:
self.context.logger.warning("'bots' section not found in context configuration") self.context.logger.warning("'clients' section not found in context configuration")
async def on_broker_client_connected(self, client_id): async def on_broker_client_connected(self, client_id):
logging.debug('Bumper Connection: %s connected' % client_id) logging.debug('Bumper Connection: %s connected' % client_id)
connected_bots = self.bots['connected_bots'].get() connected_bots = self.clients['connected_bots'].get()
connected_clients = self.clients['connected_clients'].get()
didsplit = str(client_id).split("@") didsplit = str(client_id).split("@")
#If this isn't a fake user (fuid) then add as a bot #If this isn't a fake user (fuid) then add as a bot
if not (str(didsplit[0]).startswith("fuid") or str(didsplit[0]).startswith("helper")): if not (str(didsplit[0]).startswith("fuid") or str(didsplit[0]).startswith("helper")):
@ -221,20 +226,51 @@ class BumperMQTTServer_Plugin:
if botactive == False: if botactive == False:
connected_bots.append(newbot.asdict()) connected_bots.append(newbot.asdict())
logging.info("Adding bot to list: {}".format(newbot.asdict()))
self.clients['connected_bots'].set(connected_bots)
else:
tmpuserdetail = str(didsplit[1]).split("/")
newuser = bumper.VacBotUser()
newuser.userid = didsplit[0]
newuser.realm = tmpuserdetail[0]
newuser.resource = tmpuserdetail[1]
clientactive = False
for client in connected_clients:
if client['userid'] == newuser.userid:
clientactive = True
if clientactive == False:
connected_clients.append(newuser.asdict())
logging.info("Adding client to list: {}".format(newuser.asdict()))
self.clients['connected_clients'].set(connected_clients)
logging.debug('Connected Bots: %s' %self.clients['connected_bots'].get())
logging.debug('Connected Clients: %s' %self.clients['connected_clients'].get())
self.bots['connected_bots'].set(connected_bots)
logging.debug('Connected Bots: %s' %self.bots['connected_bots'].get())
async def on_broker_client_disconnected(self, client_id): async def on_broker_client_disconnected(self, client_id):
logging.debug('Bumper Connection: %s disconnected' % client_id) logging.debug('Bumper Connection: %s disconnected' % client_id)
connected_bots = self.bots['connected_bots'].get() connected_bots = self.clients['connected_bots'].get()
connected_clients = self.clients['connected_clients'].get()
didsplit = str(client_id).split("@") didsplit = str(client_id).split("@")
#If the did is in the list, remove it #If the did is in the list, remove it
for bot in connected_bots: for bot in connected_bots:
if didsplit[0] == bot['did']: if didsplit[0] == bot['did']:
logging.debug("Removing bot from list: {}".format(bot)) logging.info("Removing bot from list: {}".format(bot['did']))
connected_bots.remove(bot) connected_bots.remove(bot)
self.bots['connected_bots'].set(connected_bots) self.clients['connected_bots'].set(connected_bots)
logging.debug('Connected Bots: %s' %self.bots['connected_bots'].get()) logging.debug('Connected Bots: %s' %self.clients['connected_bots'].get())
for client in connected_clients:
if didsplit[0] == client['userid']:
logging.info("Removing client from list: {}".format(client['userid']))
connected_clients.remove(client)
self.clients['connected_clients'].set(connected_clients)
logging.debug('Connected Clients: %s' %self.clients['connected_clients'].get())

View file

@ -25,6 +25,7 @@ class XMPPServer():
for client in self.clients: for client in self.clients:
if client.address == client_address[0]: if client.address == client_address[0]:
client.disconnect() client.disconnect()
client.join()
thread_id = uuid.uuid4() thread_id = uuid.uuid4()
client = Client(thread_id, connection, client_address) client = Client(thread_id, connection, client_address)
@ -40,12 +41,15 @@ class XMPPServer():
logging.info('XMPPServer: bye') logging.info('XMPPServer: bye')
def disconnect(self): def disconnect(self):
logging.info('XMPPServer: waiting for all client threads to exit') try:
for client in self.clients: logging.info('XMPPServer: waiting for all client threads to exit')
client.disconnect() for client in self.clients:
client.join() client.disconnect()
self.exit_flag = True client.join()
logging.info('XMPPServer: shutting down...') self.exit_flag = True
logging.info('XMPPServer: shutting down...')
except Exception as e:
logging.exception("Exception: {}".format(e))
class Client(threading.Thread): class Client(threading.Thread):
@ -62,49 +66,72 @@ class Client(threading.Thread):
def __init__(self, thread_id, connection, client_address): def __init__(self, thread_id, connection, client_address):
threading.Thread.__init__(self) threading.Thread.__init__(self)
self.id = thread_id self.id = thread_id
self.name = "XMPP Thread {}".format(self.id) self.name = "XMPP Thread {}".format(client_address[0])
self.type = self.UNKNOWN self.type = self.UNKNOWN
self.state = self.IDLE self.state = self.IDLE
self.connection = connection self.connection = connection
self.address = client_address[0] self.address = client_address[0]
self.clientresource = ""
def send(self, command): def send(self, command):
logging.debug('to {}: {}'.format(self.address, command)) try:
self.connection.send(command.encode()) logging.debug('to {}: {}'.format(self.address, command))
self.connection.send(command.encode())
except OSError as e:
logging.error('XMPPServer: {}'.format(e))
except Exception as e:
logging.exception("Exception: {}".format(e))
def disconnect(self): def disconnect(self):
logging.info('{} disconnecting'.format(self.address)) try:
self.connection.close() logging.info('{} with resource {} disconnecting'.format(self.address, self.clientresource))
self._set_state('DISCONNECT') self.connection.close()
self._set_state('DISCONNECT')
except Exception as e:
logging.exception("Exception: {}".format(e))
def _tag_strip_uri(self, tag): def _tag_strip_uri(self, tag):
if tag[0] == '{': try:
uri, ignore, tag = tag[1:].partition('}') if tag[0] == '{':
return tag uri, ignore, tag = tag[1:].partition('}')
return tag
except Exception as e:
logging.exception("Exception: {}".format(e))
def _set_state(self, state): def _set_state(self, state):
new_state = getattr(Client, state) try:
if self.state > new_state: new_state = getattr(Client, state)
raise Exception('{} illegal state change {}->{}'.format(self.address, self.state, new_state)) if self.state > new_state:
logging.info('{} state: {}'.format(self.address, state)) raise Exception('{} illegal state change {}->{}'.format(self.address, self.state, new_state))
self.state = new_state logging.debug('{} state: {}'.format(self.address, state))
self.state = new_state
if new_state == '5':
self.join()
except Exception as e:
logging.exception("Exception: {}".format(e))
def _handle_ctl(self, xml, data): def _handle_ctl(self, xml, data):
ctl = xml[0][0] try:
if ctl.get('admin') and self.type == self.BOT: ctl = xml[0][0]
logging.info('admin username received from bot: {}'.format(ctl.get('admin'))) if ctl.get('admin') and self.type == self.BOT:
XMPPServer.client_id = ctl.get('admin') logging.debug('admin username received from bot: {}'.format(ctl.get('admin')))
return XMPPServer.client_id = ctl.get('admin')
# forward return
for client in XMPPServer.clients: # forward
if client.address != self.address and client.state == client.READY: for client in XMPPServer.clients:
if client.type == self.BOT: if client.address != self.address and client.state == client.READY:
data = data.decode('utf-8') if client.type == self.BOT:
id_index = data.find('id') data = data.decode('utf-8')
if id_index > -1: id_index = data.find('id')
data = data[:id_index] + 'from="' + XMPPServer.client_id + '" ' + data[id_index:] if id_index > -1:
data = data.encode() data = data[:id_index] + 'from="' + XMPPServer.client_id + '" ' + data[id_index:]
client.send(data.decode('utf-8')) data = data.encode()
client.send(data.decode('utf-8'))
except Exception as e:
logging.exception("Exception: {}".format(e))
def _handle_ping(self, xml, data): def _handle_ping(self, xml, data):
@ -118,14 +145,18 @@ class Client(threading.Thread):
def _handle_result(self, data): def _handle_result(self, data):
# forward # forward
for client in XMPPServer.clients: try:
if client.address != self.address and client.state == client.READY: for client in XMPPServer.clients:
client.send(data.decode('utf-8')) if client.address != self.address and client.state == client.READY:
client.send(data.decode('utf-8'))
except Exception as e:
logging.exception("Exception: {}".format(e))
def run(self): def run(self):
try: try:
logging.info('client connected: {}'.format(self.address)) logging.info('client connected: {}'.format(self.address))
self._set_state('CONNECT') self._set_state('CONNECT')
data = ""
while True: while True:
time.sleep(0.2) time.sleep(0.2)
if not self.connection._closed: if not self.connection._closed:
@ -143,6 +174,7 @@ class Client(threading.Thread):
self.send('<stream:features><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"/><session xmlns="urn:ietf:params:xml:ns:xmpp-session"/></stream:features>') self.send('<stream:features><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"/><session xmlns="urn:ietf:params:xml:ns:xmpp-session"/></stream:features>')
continue continue
xml = ET.fromstring(data) xml = ET.fromstring(data)
logging.debug("XMPPXML: {}".format(data))
if len(xml): if len(xml):
child = self._tag_strip_uri(xml[0].tag) child = self._tag_strip_uri(xml[0].tag)
else: else:
@ -150,6 +182,11 @@ class Client(threading.Thread):
if xml.tag == 'iq': if xml.tag == 'iq':
res = None res = None
if child == 'bind': if child == 'bind':
clientbindxml = xml.getchildren()
clientresourcexml = clientbindxml[0].getchildren()
self.clientresource = clientresourcexml[0].text
self.name = "XMPP Thread {}".format(self.clientresource)
logging.info("XMPP Client {} using resource {}".format(self.address, self.clientresource))
res = '<iq type="result" id="{}"><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"><jid>{}</jid></bind></iq>'.format(xml.get('id'), XMPPServer.bot_id) res = '<iq type="result" id="{}"><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"><jid>{}</jid></bind></iq>'.format(xml.get('id'), XMPPServer.bot_id)
self._set_state('BIND') self._set_state('BIND')
elif child == 'session': elif child == 'session':
@ -167,12 +204,12 @@ class Client(threading.Thread):
if len(xml) and xml[0].tag == 'status': if len(xml) and xml[0].tag == 'status':
# bot announcing arrival # bot announcing arrival
self.type = self.BOT self.type = self.BOT
logging.info('{} type set to BOT (based on presence tag)'.format(self.address)) logging.debug('{} type set to BOT (based on presence tag)'.format(self.address))
# send a command from an unknown user - the response will contain the correct admin username # send a command from an unknown user - the response will contain the correct admin username
self.send('<iq type="set" id="{}" from="{}" to="{}"><query xmlns="com:ctl"><ctl td="GetCleanState" /></query></iq>'.format(uuid.uuid4(), 'unknown@ecouser.net', XMPPServer.bot_id)) self.send('<iq type="set" id="{}" from="{}" to="{}"><query xmlns="com:ctl"><ctl td="GetCleanState" /></query></iq>'.format(uuid.uuid4(), 'unknown@ecouser.net', XMPPServer.bot_id))
elif xml.get('type') == 'available': elif xml.get('type') == 'available':
self.type = self.CONTROLLER self.type = self.CONTROLLER
logging.info('{} type set to CONTROLLER (based on presence tag)'.format(self.address)) logging.debug('{} type set to CONTROLLER (based on presence tag)'.format(self.address))
except ET.ParseError as e: except ET.ParseError as e:
logging.debug('error: {}'.format(e)) logging.debug('error: {}'.format(e))
except Exception as e: except Exception as e:
@ -181,8 +218,14 @@ class Client(threading.Thread):
except OSError as e: except OSError as e:
logging.error('XMPPServer: {}'.format(e)) logging.error('XMPPServer: {}'.format(e))
self._set_state('DISCONNECT') self._set_state('DISCONNECT')
except ConnectionResetError as e:
logging.error('XMPPServer: {}'.format(e))
self._set_state('DISCONNECT')
except Exception as e: except Exception as e:
logging.error('XMPPServer: {}'.format(e)) logging.error('XMPPServer: {}'.format(e))
self._set_state('DISCONNECT') self._set_state('DISCONNECT')
finally: finally:
self.disconnect() self.disconnect()