D901 #2
5 changed files with 189 additions and 99 deletions
35
bumper.py
35
bumper.py
|
|
@ -30,12 +30,21 @@ def main():
|
||||||
xmpp_address = (listen_host, 5223)
|
xmpp_address = (listen_host, 5223)
|
||||||
mqtt_address = (listen_host, 8883)
|
mqtt_address = (listen_host, 8883)
|
||||||
|
|
||||||
xmpp_server = bumper.XMPPServer(xmpp_address)
|
xmpp_server = bumper.XMPPServer(xmpp_address, bumper_users=bumper.bumper_users_var, bumper_bots=bumper.bumper_bots_var,bumper_clients=bumper.bumper_clients_var)
|
||||||
mqtt_server = bumper.MQTTServer(mqtt_address,bumper_bots=bumper.bumper_bots_var,bumper_clients=bumper.bumper_clients_var,remove_clients=bumper.bumper_removeclients_var)
|
mqtt_server = bumper.MQTTServer(mqtt_address, bumper_bots=bumper.bumper_bots_var,bumper_clients=bumper.bumper_clients_var)
|
||||||
mqtt_helperbot = bumper.MQTTHelperBot(mqtt_address, bumper_bots=bumper.bumper_bots_var,bumper_clients=bumper.bumper_clients_var)
|
mqtt_helperbot = bumper.MQTTHelperBot(mqtt_address, bumper_bots=bumper.bumper_bots_var,bumper_clients=bumper.bumper_clients_var)
|
||||||
conf_server = bumper.ConfServer(conf_address_443, usessl=True, bumper_bots=bumper.bumper_bots_var,bumper_clients=bumper.bumper_clients_var, remove_clients=bumper.bumper_removeclients_var,helperbot=mqtt_helperbot)
|
conf_server = bumper.ConfServer(conf_address_443, usessl=True,bumper_users=bumper.bumper_users_var, bumper_bots=bumper.bumper_bots_var,bumper_clients=bumper.bumper_clients_var,helperbot=mqtt_helperbot)
|
||||||
conf_server_2 = bumper.ConfServer(conf_address_8007, usessl=False, bumper_bots=bumper.bumper_bots_var,bumper_clients=bumper.bumper_clients_var, helperbot=mqtt_helperbot,remove_clients=bumper.bumper_removeclients_var)
|
conf_server_2 = bumper.ConfServer(conf_address_8007, usessl=False,bumper_users=bumper.bumper_users_var, bumper_bots=bumper.bumper_bots_var,bumper_clients=bumper.bumper_clients_var, helperbot=mqtt_helperbot)
|
||||||
|
|
||||||
|
#add user
|
||||||
|
users = bumper.bumper_users_var.get()
|
||||||
|
user1 = bumper.BumperUser('user1')
|
||||||
|
user1.add_device('user_phone')
|
||||||
|
user1.add_bot('bot_id')
|
||||||
|
users.append(user1)
|
||||||
|
bumper.bumper_users_var.set(users)
|
||||||
|
|
||||||
|
|
||||||
# start xmpp server on port 5223 (sync)
|
# start xmpp server on port 5223 (sync)
|
||||||
xmpp_server.run(run_async=True) #Start in new thread
|
xmpp_server.run(run_async=True) #Start in new thread
|
||||||
|
|
||||||
|
|
@ -58,17 +67,19 @@ def main():
|
||||||
time.sleep(0.25)
|
time.sleep(0.25)
|
||||||
|
|
||||||
# WIP: Remove clients that have disconnected
|
# WIP: Remove clients that have disconnected
|
||||||
remove_clients = bumper.bumper_removeclients_var.get()
|
# remove_clients = bumper.bumper_removeclients_var.get()
|
||||||
if len(remove_clients) > 0:
|
# if len(remove_clients) > 0:
|
||||||
for uid in remove_clients:
|
# for uid in remove_clients:
|
||||||
if uid != "":
|
# if uid != "":
|
||||||
xmpp_server.remove_client_byuid(uid) #Remove clients from xmpp server
|
# xmpp_server.remove_client_byuid(uid) #Remove clients from xmpp server
|
||||||
remove_clients.remove(uid)
|
# remove_clients.remove(uid)
|
||||||
|
|
||||||
bumper.bumper_removeclients_var.set(remove_clients)
|
# bumper.bumper_removeclients_var.set(remove_clients)
|
||||||
|
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
|
bumper.bumperlog.info("Bumper Exiting - Keyboard Interrupt")
|
||||||
print("Bumper Exiting")
|
print("Bumper Exiting")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|
@ -8,10 +8,12 @@ import asyncio
|
||||||
import contextvars
|
import contextvars
|
||||||
import time
|
import time
|
||||||
import logging
|
import logging
|
||||||
|
from base64 import b64decode, b64encode
|
||||||
|
|
||||||
|
bumper_users_var = contextvars.ContextVar('bumper_users', default=[])
|
||||||
bumper_clients_var = contextvars.ContextVar('bumper_clients', default=[])
|
bumper_clients_var = contextvars.ContextVar('bumper_clients', default=[])
|
||||||
bumper_bots_var = contextvars.ContextVar('bumper_bots', default=[])
|
bumper_bots_var = contextvars.ContextVar('bumper_bots', default=[])
|
||||||
bumper_removeclients_var = contextvars.ContextVar('bumper_removeclients', default=[])
|
|
||||||
ca_cert = './certs/CA/cacert.pem'
|
ca_cert = './certs/CA/cacert.pem'
|
||||||
server_cert = './certs/cert.pem'
|
server_cert = './certs/cert.pem'
|
||||||
server_key = './certs/key.pem'
|
server_key = './certs/key.pem'
|
||||||
|
|
@ -35,6 +37,47 @@ def get_milli_time(timetoconvert):
|
||||||
return int(round(timetoconvert * 1000))
|
return int(round(timetoconvert * 1000))
|
||||||
|
|
||||||
|
|
||||||
|
class BumperUser(object):
|
||||||
|
def __init__(self,userid=""):
|
||||||
|
self.userid = userid
|
||||||
|
self.devices = []
|
||||||
|
self.tokens = []
|
||||||
|
self.authcodes = []
|
||||||
|
self.bots = []
|
||||||
|
|
||||||
|
def add_device(self, devid):
|
||||||
|
if not devid in self.devices:
|
||||||
|
self.devices.append(devid)
|
||||||
|
|
||||||
|
def remove_device(self, devid):
|
||||||
|
if devid in self.devices:
|
||||||
|
self.devices.remove(devid)
|
||||||
|
|
||||||
|
|
||||||
|
def add_token(self, token):
|
||||||
|
if not token in self.tokens:
|
||||||
|
self.tokens.append(token)
|
||||||
|
|
||||||
|
def revoke_token(self, token):
|
||||||
|
if token in self.tokens:
|
||||||
|
self.tokens.remove(token)
|
||||||
|
|
||||||
|
def add_authcode(self, authcode):
|
||||||
|
if not authcode in self.authcodes:
|
||||||
|
self.authcodes.append(authcode)
|
||||||
|
|
||||||
|
def revoke_authcode(self, authcode):
|
||||||
|
if authcode in self.authcodes:
|
||||||
|
self.authcodes.remove(authcode)
|
||||||
|
|
||||||
|
def add_bot(self, botdid):
|
||||||
|
if not botdid in self.bots:
|
||||||
|
self.bots.append(botdid)
|
||||||
|
|
||||||
|
def remove_bot(self, botdid):
|
||||||
|
if botdid in self.bots:
|
||||||
|
self.bots.remove(botdid)
|
||||||
|
|
||||||
class VacBotDevice(object):
|
class VacBotDevice(object):
|
||||||
def __init__(self,did="", vac_bot_device_class="",resource="" , name="", nick="", company="eco-ng"):
|
def __init__(self,did="", vac_bot_device_class="",resource="" , name="", nick="", company="eco-ng"):
|
||||||
self.vac_bot_device_class = vac_bot_device_class
|
self.vac_bot_device_class = vac_bot_device_class
|
||||||
|
|
@ -48,12 +91,11 @@ class VacBotDevice(object):
|
||||||
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):
|
class VacBotClient(object):
|
||||||
def __init__(self,userid="",realm="",token=""):
|
def __init__(self,userid="",realm="",token=""):
|
||||||
self.userid = userid
|
self.userid = userid
|
||||||
self.realm = realm
|
self.realm = realm
|
||||||
self.resource = token
|
self.resource = token
|
||||||
|
|
||||||
|
|
||||||
def asdict(self):
|
def asdict(self):
|
||||||
return {"userid": self.userid,"realm": self.realm,"resource": self.resource}
|
return {"userid": self.userid,"realm": self.realm,"resource": self.resource}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ from datetime import datetime, timedelta
|
||||||
import asyncio
|
import asyncio
|
||||||
import contextvars
|
import contextvars
|
||||||
from aiohttp import web
|
from aiohttp import web
|
||||||
|
import uuid
|
||||||
|
|
||||||
class aiohttp_filter(logging.Filter):
|
class aiohttp_filter(logging.Filter):
|
||||||
|
|
||||||
|
|
@ -32,10 +33,10 @@ class ConfServer():
|
||||||
bumper_clients = contextvars.ContextVar
|
bumper_clients = contextvars.ContextVar
|
||||||
bumper_bots = contextvars.ContextVar
|
bumper_bots = contextvars.ContextVar
|
||||||
|
|
||||||
def __init__(self, address, usessl=False, bumper_bots=contextvars.ContextVar, bumper_clients=contextvars.ContextVar, remove_clients=contextvars.ContextVar,helperbot=None):
|
def __init__(self, address, usessl=False, bumper_users=contextvars.ContextVar, bumper_bots=contextvars.ContextVar, bumper_clients=contextvars.ContextVar, helperbot=None):
|
||||||
|
self.bumper_users = bumper_users
|
||||||
self.bumper_bots = bumper_bots
|
self.bumper_bots = bumper_bots
|
||||||
self.bumper_clients = bumper_clients
|
self.bumper_clients = bumper_clients
|
||||||
self.remove_clients = remove_clients
|
|
||||||
self.helperbot = helperbot
|
self.helperbot = helperbot
|
||||||
self.usessl = usessl
|
self.usessl = usessl
|
||||||
self.address = address
|
self.address = address
|
||||||
|
|
@ -82,7 +83,7 @@ class ConfServer():
|
||||||
app.add_routes([
|
app.add_routes([
|
||||||
web.get('', self.handle_base),
|
web.get('', self.handle_base),
|
||||||
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/checkLogin', self.handle_checkLogin),
|
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/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),
|
||||||
|
|
@ -96,6 +97,9 @@ class ConfServer():
|
||||||
|
|
||||||
web.post('/lookup.do', self.handle_lookup),
|
web.post('/lookup.do', self.handle_lookup),
|
||||||
])
|
])
|
||||||
|
#Direct register from app:
|
||||||
|
#/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/directRegister
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
runner = web.AppRunner(app)
|
runner = web.AppRunner(app)
|
||||||
|
|
@ -130,61 +134,65 @@ class ConfServer():
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
confserverlog.exception('{}'.format(e))
|
confserverlog.exception('{}'.format(e))
|
||||||
|
|
||||||
async def handle_login(self, request):
|
async def handle_login(self, request):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
#Could implement basic auth if you wanted, or just accept anything
|
user_devid = request.match_info.get('devid', "")
|
||||||
countrycode = request.match_info.get('country', "us")
|
countrycode = request.match_info.get('country', "us")
|
||||||
|
if not user_devid == "": #Performing basic "auth" using devid, super insecure
|
||||||
|
users = bumper.bumper_users_var.get()
|
||||||
|
for user in users:
|
||||||
|
if user_devid in user.devices:
|
||||||
|
tmpaccesstoken = ''
|
||||||
|
if 'checkLogin' in request.path:
|
||||||
|
if request.query['accessToken'] in user.tokens and request.query['uid'] == "fuid_{}".format(user.userid):
|
||||||
|
tmpaccesstoken = request.query['accessToken']
|
||||||
|
else:
|
||||||
|
if tmpaccesstoken == '':
|
||||||
|
tmpaccesstoken = uuid.uuid4().hex
|
||||||
|
user.add_token(tmpaccesstoken)
|
||||||
|
|
||||||
|
body = {
|
||||||
|
"code": "0000",
|
||||||
|
"data": {
|
||||||
|
"accessToken": tmpaccesstoken, #Random chars 32 length
|
||||||
|
"country": countrycode,
|
||||||
|
"email": "null@null.com",
|
||||||
|
"uid": "fuid_{}".format(user.userid),
|
||||||
|
"username": "fusername_{}".format(user.userid),
|
||||||
|
},
|
||||||
|
"msg": "操作成功",
|
||||||
|
"time": bumper.get_milli_time(time.time())
|
||||||
|
}
|
||||||
|
bumper.bumper_users_var.set(users)
|
||||||
|
return web.json_response(body)
|
||||||
|
|
||||||
body = {
|
body = {
|
||||||
"code": "0000",
|
"code": "1005",
|
||||||
"data": {
|
"data": None,
|
||||||
"accessToken": "tempaccesstoken", #Random chars 32 length
|
"msg": "当前密码错误",
|
||||||
"country": countrycode,
|
|
||||||
"email": "null@null.com",
|
|
||||||
"uid": "fuid_{}".format(''.join(random.sample(string.ascii_letters,6))), #Date(14)_RandomChars(32)
|
|
||||||
"username": "fusername_{}".format(''.join(random.sample(string.ascii_letters,6))) #Random chars 8
|
|
||||||
},
|
|
||||||
"msg": "操作成功",
|
|
||||||
"time": bumper.get_milli_time(time.time())
|
"time": bumper.get_milli_time(time.time())
|
||||||
}
|
}
|
||||||
|
|
||||||
return web.json_response(body)
|
return web.json_response(body)
|
||||||
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
confserverlog.exception('{}'.format(e))
|
confserverlog.exception('{}'.format(e))
|
||||||
|
|
||||||
async def handle_checkLogin(self, request):
|
|
||||||
try:
|
|
||||||
# The app seems to remember it's last uid and accessToken
|
|
||||||
# If these don't match, it fails
|
|
||||||
countrycode = request.match_info.get('country', "us")
|
|
||||||
body = {
|
|
||||||
"code": "0000",
|
|
||||||
"data": {
|
|
||||||
"accessToken": "tempaccesstoken", #Random chars 32 length
|
|
||||||
"country": countrycode,
|
|
||||||
"email": "null@null.com",
|
|
||||||
"uid": "fuid_{}".format(''.join(random.sample(string.ascii_letters,6))), #Date(14)_RandomChars(32)
|
|
||||||
"username": "fusername_{}".format(''.join(random.sample(string.ascii_letters,6))) #Random chars 8
|
|
||||||
},
|
|
||||||
"msg": "操作成功",
|
|
||||||
"time": bumper.get_milli_time(time.time())
|
|
||||||
}
|
|
||||||
|
|
||||||
return web.json_response(body)
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
confserverlog.exception('{}'.format(e))
|
|
||||||
|
|
||||||
async def handle_logout(self, request):
|
async def handle_logout(self, request):
|
||||||
try:
|
try:
|
||||||
uid = request.query['uid']
|
user_devid = request.match_info.get('devid', "")
|
||||||
body = {"code": "0000","data": None,"msg": "操作成功", "time": bumper.get_milli_time(time.time())}
|
if not user_devid == "":
|
||||||
# QUERY String
|
users = bumper.bumper_users_var.get()
|
||||||
# 'uid=fuid_CUOVIn&accessToken=tempaccesstoken&requestId=e584de79f9cca854df6fb3352c6893b6&authTimespan=1550168440575&authTimeZone=GMT-5&authAppkey=eJUWrzRv34qFSaYk&authSign=14e38f95c7316e111c5815cf15f0f972'
|
for user in users:
|
||||||
if not uid == "":
|
if user_devid in user.devices:
|
||||||
remove_clients = self.remove_clients.get()
|
if request.query['uid'] == "fuid_{}".format(user.userid) and request.query['accessToken'] in user.tokens:
|
||||||
remove_clients.append(request.query['uid'])
|
user.revoke_token(request.query['accessToken'])
|
||||||
self.remove_clients.set(remove_clients)
|
bumper.bumper_users_var.set(users)
|
||||||
|
|
||||||
|
body = {"code": "0000","data": None,"msg": "操作成功", "time": bumper.get_milli_time(time.time())}
|
||||||
|
|
||||||
return web.json_response(body)
|
return web.json_response(body)
|
||||||
|
|
||||||
|
|
@ -193,19 +201,37 @@ class ConfServer():
|
||||||
|
|
||||||
async def handle_getAuthCode(self, request):
|
async def handle_getAuthCode(self, request):
|
||||||
try:
|
try:
|
||||||
countrycode = request.match_info.get('country', "us")
|
|
||||||
body = {
|
user_devid = request.match_info.get('devid', "")
|
||||||
"code": "0000",
|
if not user_devid == "":
|
||||||
"data": {
|
users = bumper.bumper_users_var.get()
|
||||||
"authCode": "{}_tempauthcode".format(countrycode), #countrycode_randomchars(32)
|
for user in users:
|
||||||
"ecovacsUid": "fuid_{}".format(''.join(random.sample(string.ascii_letters,6))) #Date(14)_RandomChars(32)
|
if user_devid in user.devices and request.query['accessToken'] in user.tokens:
|
||||||
},
|
countrycode = request.match_info.get('country', "us")
|
||||||
"msg": "操作成功",
|
tmpauthcode = "{}_{}".format(countrycode,uuid.uuid4().hex)
|
||||||
"time": bumper.get_milli_time(time.time())
|
user.add_authcode(tmpauthcode)
|
||||||
}
|
|
||||||
|
body = {
|
||||||
return web.json_response(body)
|
"code": "0000",
|
||||||
|
"data": {
|
||||||
|
"authCode": tmpauthcode,
|
||||||
|
"ecovacsUid": request.query['uid']
|
||||||
|
},
|
||||||
|
"msg": "操作成功",
|
||||||
|
"time": bumper.get_milli_time(time.time())
|
||||||
|
}
|
||||||
|
bumper.bumper_users_var.set(users)
|
||||||
|
return web.json_response(body)
|
||||||
|
|
||||||
|
body = {
|
||||||
|
"code": "1005",
|
||||||
|
"data": None,
|
||||||
|
"msg": "当前密码错误",
|
||||||
|
"time": bumper.get_milli_time(time.time())
|
||||||
|
}
|
||||||
|
|
||||||
|
return web.json_response(body)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
confserverlog.exception('{}'.format(e))
|
confserverlog.exception('{}'.format(e))
|
||||||
|
|
||||||
|
|
@ -271,7 +297,6 @@ class ConfServer():
|
||||||
|
|
||||||
async def handle_getProductIotMap(self, request):
|
async def handle_getProductIotMap(self, request):
|
||||||
try:
|
try:
|
||||||
#json_body = json.loads(await request.text())
|
|
||||||
body = {"code":0,"data":[{"classid":"dl8fht","product":{"_id":"5acb0fa87c295c0001876ecf","name":"DEEBOT 600 Series","icon":"5acc32067c295c0001876eea","UILogicId":"dl8fht","ota":False,"iconUrl":"https://portal-ww.ecouser.net/api/pim/file/get/5acc32067c295c0001876eea"}},{"classid":"02uwxm","product":{"_id":"5ae1481e7ccd1a0001e1f69e","name":"DEEBOT OZMO Slim10 Series","icon":"5b1dddc48bc45700014035a1","UILogicId":"02uwxm","ota":False,"iconUrl":"https://portal-ww.ecouser.net/api/pim/file/get/5b1dddc48bc45700014035a1"}},{"classid":"y79a7u","product":{"_id":"5b04c0227ccd1a0001e1f6a8","name":"DEEBOT OZMO 900","icon":"5b04c0217ccd1a0001e1f6a7","UILogicId":"y79a7u","ota":True,"iconUrl":"https://portal-ww.ecouser.net/api/pim/file/get/5b04c0217ccd1a0001e1f6a7"}},{"classid":"jr3pqa","product":{"_id":"5b43077b8bc457000140363e","name":"DEEBOT 711","icon":"5b5ac4cc8d5a56000111e769","UILogicId":"jr3pqa","ota":True,"iconUrl":"https://portal-ww.ecouser.net/api/pim/file/get/5b5ac4cc8d5a56000111e769"}},{"classid":"uv242z","product":{"_id":"5b5149b4ac0b87000148c128","name":"DEEBOT 710","icon":"5b5ac4e45f21100001882bb9","UILogicId":"uv242z","ota":True,"iconUrl":"https://portal-ww.ecouser.net/api/pim/file/get/5b5ac4e45f21100001882bb9"}},{"classid":"ls1ok3","product":{"_id":"5b6561060506b100015c8868","name":"DEEBOT 900 Series","icon":"5ba4a2cb6c2f120001c32839","UILogicId":"ls1ok3","ota":True,"iconUrl":"https://portal-ww.ecouser.net/api/pim/file/get/5ba4a2cb6c2f120001c32839"}}]}
|
body = {"code":0,"data":[{"classid":"dl8fht","product":{"_id":"5acb0fa87c295c0001876ecf","name":"DEEBOT 600 Series","icon":"5acc32067c295c0001876eea","UILogicId":"dl8fht","ota":False,"iconUrl":"https://portal-ww.ecouser.net/api/pim/file/get/5acc32067c295c0001876eea"}},{"classid":"02uwxm","product":{"_id":"5ae1481e7ccd1a0001e1f69e","name":"DEEBOT OZMO Slim10 Series","icon":"5b1dddc48bc45700014035a1","UILogicId":"02uwxm","ota":False,"iconUrl":"https://portal-ww.ecouser.net/api/pim/file/get/5b1dddc48bc45700014035a1"}},{"classid":"y79a7u","product":{"_id":"5b04c0227ccd1a0001e1f6a8","name":"DEEBOT OZMO 900","icon":"5b04c0217ccd1a0001e1f6a7","UILogicId":"y79a7u","ota":True,"iconUrl":"https://portal-ww.ecouser.net/api/pim/file/get/5b04c0217ccd1a0001e1f6a7"}},{"classid":"jr3pqa","product":{"_id":"5b43077b8bc457000140363e","name":"DEEBOT 711","icon":"5b5ac4cc8d5a56000111e769","UILogicId":"jr3pqa","ota":True,"iconUrl":"https://portal-ww.ecouser.net/api/pim/file/get/5b5ac4cc8d5a56000111e769"}},{"classid":"uv242z","product":{"_id":"5b5149b4ac0b87000148c128","name":"DEEBOT 710","icon":"5b5ac4e45f21100001882bb9","UILogicId":"uv242z","ota":True,"iconUrl":"https://portal-ww.ecouser.net/api/pim/file/get/5b5ac4e45f21100001882bb9"}},{"classid":"ls1ok3","product":{"_id":"5b6561060506b100015c8868","name":"DEEBOT 900 Series","icon":"5ba4a2cb6c2f120001c32839","UILogicId":"ls1ok3","ota":True,"iconUrl":"https://portal-ww.ecouser.net/api/pim/file/get/5ba4a2cb6c2f120001c32839"}}]}
|
||||||
return web.json_response(body)
|
return web.json_response(body)
|
||||||
|
|
||||||
|
|
@ -297,13 +322,18 @@ class ConfServer():
|
||||||
elif service == 'EcoUpdate':
|
elif service == 'EcoUpdate':
|
||||||
body = {"result":"ok","ip":"47.88.66.164","port":8005}
|
body = {"result":"ok","ip":"47.88.66.164","port":8005}
|
||||||
elif todo == 'loginByItToken':
|
elif todo == 'loginByItToken':
|
||||||
body = {
|
|
||||||
"resource": postbody["resource"],
|
users = bumper.bumper_users_var.get()
|
||||||
"result": "ok",
|
for user in users:
|
||||||
"todo": "result",
|
if postbody['userId'] == "fuid_{}".format(user.userid) and postbody['token'] in user.authcodes:
|
||||||
"token": postbody["token"], #RandomChar(32)
|
body = {
|
||||||
"userId": postbody["userId"] #RandomChar(16)
|
"resource": postbody["resource"],
|
||||||
}
|
"result": "ok",
|
||||||
|
"todo": "result",
|
||||||
|
"token": postbody["token"],
|
||||||
|
"userId": postbody["userId"]
|
||||||
|
}
|
||||||
|
|
||||||
elif todo == 'GetDeviceList':
|
elif todo == 'GetDeviceList':
|
||||||
active_bots = self.bumper_bots.get()
|
active_bots = self.bumper_bots.get()
|
||||||
body = {
|
body = {
|
||||||
|
|
|
||||||
|
|
@ -174,12 +174,11 @@ class MQTTServer():
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
mqttserverlog.exception('{}'.format(e))
|
mqttserverlog.exception('{}'.format(e))
|
||||||
|
|
||||||
def __init__(self, address, bumper_bots=contextvars.ContextVar, bumper_clients=contextvars.ContextVar,remove_clients=contextvars.ContextVar):
|
def __init__(self, address, bumper_bots=contextvars.ContextVar, bumper_clients=contextvars.ContextVar):
|
||||||
try:
|
try:
|
||||||
|
|
||||||
self.bumper_bots = bumper_bots
|
self.bumper_bots = bumper_bots
|
||||||
self.bumper_clients = bumper_clients
|
self.bumper_clients = bumper_clients
|
||||||
self.remove_clients = remove_clients
|
|
||||||
self.mqttserverthread = None
|
self.mqttserverthread = None
|
||||||
self.address = address
|
self.address = address
|
||||||
|
|
||||||
|
|
@ -216,7 +215,6 @@ class MQTTServer():
|
||||||
'clients':{
|
'clients':{
|
||||||
'connected_bots': self.bumper_bots,
|
'connected_bots': self.bumper_bots,
|
||||||
'connected_clients': self.bumper_clients,
|
'connected_clients': self.bumper_clients,
|
||||||
'remove_clients': self.remove_clients
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -285,7 +283,7 @@ class BumperMQTTServer_Plugin:
|
||||||
self.clients['connected_bots'].set(connected_bots)
|
self.clients['connected_bots'].set(connected_bots)
|
||||||
else:
|
else:
|
||||||
tmpuserdetail = str(didsplit[1]).split("/")
|
tmpuserdetail = str(didsplit[1]).split("/")
|
||||||
newuser = bumper.VacBotUser()
|
newuser = bumper.VacBotClient()
|
||||||
newuser.userid = didsplit[0]
|
newuser.userid = didsplit[0]
|
||||||
newuser.realm = tmpuserdetail[0]
|
newuser.realm = tmpuserdetail[0]
|
||||||
newuser.resource = tmpuserdetail[1]
|
newuser.resource = tmpuserdetail[1]
|
||||||
|
|
@ -314,7 +312,7 @@ class BumperMQTTServer_Plugin:
|
||||||
#mqttserverlog.debug('%s disconnected' % client_id)
|
#mqttserverlog.debug('%s disconnected' % client_id)
|
||||||
connected_bots = self.clients['connected_bots'].get()
|
connected_bots = self.clients['connected_bots'].get()
|
||||||
connected_clients = self.clients['connected_clients'].get()
|
connected_clients = self.clients['connected_clients'].get()
|
||||||
remove_clients = self.clients['remove_clients'].get()
|
#remove_clients = self.clients['remove_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:
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ from threading import Thread
|
||||||
import sys, socket, threading, re, time, logging, uuid, xml.etree.ElementTree as ET
|
import sys, socket, threading, re, time, logging, uuid, xml.etree.ElementTree as ET
|
||||||
import base64
|
import base64
|
||||||
import ssl
|
import ssl
|
||||||
|
import contextvars
|
||||||
import bumper
|
import bumper
|
||||||
|
|
||||||
xmppserverlog = logging.getLogger("xmppserver")
|
xmppserverlog = logging.getLogger("xmppserver")
|
||||||
|
|
@ -15,9 +16,12 @@ class XMPPServer():
|
||||||
clients = []
|
clients = []
|
||||||
exit_flag = False
|
exit_flag = False
|
||||||
|
|
||||||
def __init__(self, address):
|
def __init__(self, address, bumper_users=contextvars.ContextVar, bumper_bots=contextvars.ContextVar, bumper_clients=contextvars.ContextVar):
|
||||||
# Initialize bot server
|
# Initialize bot server
|
||||||
self.address = address
|
self.address = address
|
||||||
|
self.bumper_users = bumper_users
|
||||||
|
self.bumper_bots = bumper_bots
|
||||||
|
self.bumper_clients = bumper_clients
|
||||||
|
|
||||||
|
|
||||||
def run(self, run_async=False):
|
def run(self, run_async=False):
|
||||||
|
|
@ -86,9 +90,7 @@ class XMPPServer():
|
||||||
self.disconnect()
|
self.disconnect()
|
||||||
xmppserverlog.info('disconnecting')
|
xmppserverlog.info('disconnecting')
|
||||||
|
|
||||||
self.socket.close()
|
self.socket.close()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def disconnect(self):
|
def disconnect(self):
|
||||||
try:
|
try:
|
||||||
|
|
@ -339,8 +341,8 @@ class Client(threading.Thread):
|
||||||
|
|
||||||
elif 'resource' in aitem.tag:
|
elif 'resource' in aitem.tag:
|
||||||
self.clientresource = aitem.text
|
self.clientresource = aitem.text
|
||||||
|
|
||||||
if True:
|
if self.check_authcode(self.uid, password):
|
||||||
#Client authenticated, move to next state
|
#Client authenticated, move to next state
|
||||||
self._set_state('INIT')
|
self._set_state('INIT')
|
||||||
|
|
||||||
|
|
@ -364,6 +366,13 @@ class Client(threading.Thread):
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
xmppserverlog.exception('{}'.format(e))
|
xmppserverlog.exception('{}'.format(e))
|
||||||
|
|
||||||
|
def check_authcode(self, uid, authcode):
|
||||||
|
users = bumper.bumper_users_var.get()
|
||||||
|
for user in users:
|
||||||
|
if uid == "fuid_{}".format(user.userid) and authcode in user.authcodes:
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
def _handle_sasl_auth(self, data):
|
def _handle_sasl_auth(self, data):
|
||||||
try:
|
try:
|
||||||
|
|
@ -375,18 +384,18 @@ class Client(threading.Thread):
|
||||||
resource = saslauth[1]
|
resource = saslauth[1]
|
||||||
self.clientresource = resource
|
self.clientresource = resource
|
||||||
authcode = saslauth[2]
|
authcode = saslauth[2]
|
||||||
|
|
||||||
if authcode == "us_tempauthcode": #Handle auth
|
if self.check_authcode(self.uid, authcode):
|
||||||
#Send response
|
#Send response
|
||||||
self.send('<success xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/>') #Success
|
self.send('<success xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/>') #Success
|
||||||
|
|
||||||
#Client authenticated, move to next state
|
#Client authenticated, move to next state
|
||||||
self._set_state('INIT')
|
self._set_state('INIT')
|
||||||
|
|
||||||
else:
|
else:
|
||||||
#Failed to authenticate
|
#Failed to authenticate
|
||||||
self.send('<response xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/>') #Fail
|
self.send('<response xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/>') #Fail
|
||||||
|
|
||||||
except ET.ParseError as e:
|
except ET.ParseError as e:
|
||||||
if "no element found" in e.msg:
|
if "no element found" in e.msg:
|
||||||
xmppserverlog.debug('xml parse error - {} - {} - this is common with ecovac protocol'.format(data.decode('utf-8'), e))
|
xmppserverlog.debug('xml parse error - {} - {} - this is common with ecovac protocol'.format(data.decode('utf-8'), e))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue