Format with black

Formatting code with black
- pipenv update
This commit is contained in:
Brian Martin 2019-05-30 06:55:15 -04:00
parent 401af5652f
commit c3098e03e4
8 changed files with 741 additions and 663 deletions

6
Pipfile.lock generated
View file

@ -333,11 +333,11 @@
}, },
"pbr": { "pbr": {
"hashes": [ "hashes": [
"sha256:6901995b9b686cb90cceba67a0f6d4d14ae003cd59bc12beb61549bdfbe3bc89", "sha256:0ce920b865091450bbcd452b35cf6d6eb8a6d9ce13ad2210d6e77557f85cf32b",
"sha256:d950c64aeea5456bbd147468382a5bb77fe692c13c9f00f0219814ce5b642755" "sha256:93d2dc6ee0c9af4dbc70bc1251d0e545a9910ca8863774761f92716dece400b6"
], ],
"index": "pypi", "index": "pypi",
"version": "==5.2.0" "version": "==5.2.1"
}, },
"pylint": { "pylint": {
"hashes": [ "hashes": [

View file

@ -25,9 +25,11 @@ token_validity_seconds = 3600 # 1 hour
db = None db = None
# Logs # Logs
os.makedirs("logs", exist_ok=True) #Ensure logs directory exists or create os.makedirs("logs", exist_ok=True) # Ensure logs directory exists or create
# Set format for all logs # Set format for all logs
logformat = logging.Formatter("[%(asctime)s] :: %(levelname)s :: %(name)s :: %(module)s :: %(funcName)s :: %(lineno)d :: %(message)s") logformat = logging.Formatter(
"[%(asctime)s] :: %(levelname)s :: %(name)s :: %(module)s :: %(funcName)s :: %(lineno)d :: %(message)s"
)
bumperlog = logging.getLogger("bumper") bumperlog = logging.getLogger("bumper")
bumper_rotate = RotatingFileHandler("logs/bumper.log", maxBytes=5000000, backupCount=5) bumper_rotate = RotatingFileHandler("logs/bumper.log", maxBytes=5000000, backupCount=5)
@ -37,28 +39,36 @@ bumperlog.addHandler(bumper_rotate)
# bumperlog.setLevel(logging.INFO) # bumperlog.setLevel(logging.INFO)
confserverlog = logging.getLogger("confserver") confserverlog = logging.getLogger("confserver")
conf_rotate = RotatingFileHandler("logs/confserver.log", maxBytes=5000000, backupCount=5) conf_rotate = RotatingFileHandler(
"logs/confserver.log", maxBytes=5000000, backupCount=5
)
conf_rotate.setFormatter(logformat) conf_rotate.setFormatter(logformat)
confserverlog.addHandler(conf_rotate) confserverlog.addHandler(conf_rotate)
# Override the logging level # Override the logging level
# confserverlog.setLevel(logging.INFO) # confserverlog.setLevel(logging.INFO)
mqttserverlog = logging.getLogger("mqttserver") mqttserverlog = logging.getLogger("mqttserver")
mqtt_rotate = RotatingFileHandler("logs/mqttserver.log", maxBytes=5000000, backupCount=5) mqtt_rotate = RotatingFileHandler(
"logs/mqttserver.log", maxBytes=5000000, backupCount=5
)
mqtt_rotate.setFormatter(logformat) mqtt_rotate.setFormatter(logformat)
mqttserverlog.addHandler(mqtt_rotate) mqttserverlog.addHandler(mqtt_rotate)
# Override the logging level # Override the logging level
# mqttserverlog.setLevel(logging.INFO) # mqttserverlog.setLevel(logging.INFO)
helperbotlog = logging.getLogger("helperbot") helperbotlog = logging.getLogger("helperbot")
helperbot_rotate = RotatingFileHandler("logs/helperbot.log", maxBytes=5000000, backupCount=5) helperbot_rotate = RotatingFileHandler(
"logs/helperbot.log", maxBytes=5000000, backupCount=5
)
helperbot_rotate.setFormatter(logformat) helperbot_rotate.setFormatter(logformat)
helperbotlog.addHandler(helperbot_rotate) helperbotlog.addHandler(helperbot_rotate)
# Override the logging level # Override the logging level
# helperbotlog.setLevel(logging.INFO) # helperbotlog.setLevel(logging.INFO)
xmppserverlog = logging.getLogger("xmppserver") xmppserverlog = logging.getLogger("xmppserver")
xmpp_rotate = RotatingFileHandler("logs/xmppserver.log", maxBytes=5000000, backupCount=5) xmpp_rotate = RotatingFileHandler(
"logs/xmppserver.log", maxBytes=5000000, backupCount=5
)
xmpp_rotate.setFormatter(logformat) xmpp_rotate.setFormatter(logformat)
xmppserverlog.addHandler(xmpp_rotate) xmppserverlog.addHandler(xmpp_rotate)
# Override the logging level # Override the logging level
@ -81,12 +91,17 @@ def db_file():
def os_db_path(): def os_db_path():
if platform.system() == "Windows": if platform.system() == "Windows":
os.makedirs(os.getenv("APPDATA"), exist_ok=True) #Ensure db_path directory exists or create os.makedirs(
os.getenv("APPDATA"), exist_ok=True
) # Ensure db_path directory exists or create
return os.path.join(os.getenv("APPDATA"), "bumper.db") return os.path.join(os.getenv("APPDATA"), "bumper.db")
else: else:
os.makedirs(os.path.expanduser("~/.config"), exist_ok=True) #Ensure db_path directory exists or create os.makedirs(
os.path.expanduser("~/.config"), exist_ok=True
) # Ensure db_path directory exists or create
return os.path.expanduser("~/.config/bumper.db") return os.path.expanduser("~/.config/bumper.db")
def db_get(): def db_get():
try: try:
# Will create the database if it doesn't exist # Will create the database if it doesn't exist
@ -100,7 +115,6 @@ def db_get():
return db return db
except json.decoder.JSONDecodeError as jerr: except json.decoder.JSONDecodeError as jerr:
bumperlog.error("JsonErr: {} - Doc: {}".format(jerr.msg, jerr.doc)) bumperlog.error("JsonErr: {} - Doc: {}".format(jerr.msg, jerr.doc))
@ -284,297 +298,293 @@ class VacBotDevice(object):
} }
def toJSON(self): def toJSON(self):
return json.dumps(self, default=lambda o: o.__dict__, return json.dumps(
sort_keys=False)#, indent=4) self, default=lambda o: o.__dict__, sort_keys=False
) # , indent=4)
class GlobalVacBotDevice(VacBotDevice): #EcoVacs Home
class GlobalVacBotDevice(VacBotDevice): # EcoVacs Home
UILogicId = "" UILogicId = ""
ota = True ota = True
updateInfo = { updateInfo = {"changeLog": "", "needUpdate": False}
"changeLog": "",
"needUpdate": False
}
icon = "" icon = ""
deviceName = "" deviceName = ""
#EcoVacs Home Product IOT Map - 2019-05-20 # EcoVacs Home Product IOT Map - 2019-05-20
#https://portal-ww.ecouser.net/api/pim/product/getProductIotMap # https://portal-ww.ecouser.net/api/pim/product/getProductIotMap
EcoVacsHomeProducts = [ EcoVacsHomeProducts = [
{ {
"classid": "dl8fht", "classid": "dl8fht",
"product": { "product": {
"UILogicId": "D_600", "UILogicId": "D_600",
"_id": "5acb0fa87c295c0001876ecf", "_id": "5acb0fa87c295c0001876ecf",
"icon": "5acc32067c295c0001876eea", "icon": "5acc32067c295c0001876eea",
"iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5acc32067c295c0001876eea", "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5acc32067c295c0001876eea",
"materialNo": "702-0000-0170", "materialNo": "702-0000-0170",
"name": "DEEBOT 600 Series", "name": "DEEBOT 600 Series",
"ota": False, "ota": False,
"supportType": { "supportType": {
"alexa": True, "alexa": True,
"assistant": True, "assistant": True,
"share": True, "share": True,
"tmjl": False "tmjl": False,
} },
}
}, },
{ },
"classid": "02uwxm", {
"product": { "classid": "02uwxm",
"UILogicId": "D_OZMO_SLIM10", "product": {
"_id": "5ae1481e7ccd1a0001e1f69e", "UILogicId": "D_OZMO_SLIM10",
"icon": "5b1dddc48bc45700014035a1", "_id": "5ae1481e7ccd1a0001e1f69e",
"iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5b1dddc48bc45700014035a1", "icon": "5b1dddc48bc45700014035a1",
"materialNo": "110-1715-0201", "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5b1dddc48bc45700014035a1",
"name": "DEEBOT OZMO Slim10 Series", "materialNo": "110-1715-0201",
"ota": False, "name": "DEEBOT OZMO Slim10 Series",
"supportType": { "ota": False,
"alexa": True, "supportType": {
"assistant": True, "alexa": True,
"share": True, "assistant": True,
"tmjl": False "share": True,
} "tmjl": False,
} },
}, },
{ },
"classid": "y79a7u", {
"product": { "classid": "y79a7u",
"UILogicId": "D_OZMO_900", "product": {
"_id": "5b04c0227ccd1a0001e1f6a8", "UILogicId": "D_OZMO_900",
"icon": "5b04c0217ccd1a0001e1f6a7", "_id": "5b04c0227ccd1a0001e1f6a8",
"iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5b04c0217ccd1a0001e1f6a7", "icon": "5b04c0217ccd1a0001e1f6a7",
"materialNo": "110-1810-0101", "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5b04c0217ccd1a0001e1f6a7",
"name": "DEEBOT OZMO 900 Series", "materialNo": "110-1810-0101",
"ota": True, "name": "DEEBOT OZMO 900 Series",
"supportType": { "ota": True,
"alexa": True, "supportType": {
"assistant": True, "alexa": True,
"share": True, "assistant": True,
"tmjl": False "share": True,
} "tmjl": False,
} },
}, },
{ },
"classid": "jr3pqa", {
"product": { "classid": "jr3pqa",
"UILogicId": "D_700", "product": {
"_id": "5b43077b8bc457000140363e", "UILogicId": "D_700",
"icon": "5b5ac4cc8d5a56000111e769", "_id": "5b43077b8bc457000140363e",
"iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5b5ac4cc8d5a56000111e769", "icon": "5b5ac4cc8d5a56000111e769",
"materialNo": "702-0000-0202", "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5b5ac4cc8d5a56000111e769",
"name": "DEEBOT 711", "materialNo": "702-0000-0202",
"ota": True, "name": "DEEBOT 711",
"supportType": { "ota": True,
"alexa": True, "supportType": {
"assistant": True, "alexa": True,
"share": True, "assistant": True,
"tmjl": False "share": True,
} "tmjl": False,
} },
}, },
{ },
"classid": "uv242z", {
"product": { "classid": "uv242z",
"UILogicId": "D_700", "product": {
"_id": "5b5149b4ac0b87000148c128", "UILogicId": "D_700",
"icon": "5b5ac4e45f21100001882bb9", "_id": "5b5149b4ac0b87000148c128",
"iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5b5ac4e45f21100001882bb9", "icon": "5b5ac4e45f21100001882bb9",
"materialNo": "702-0000-0205", "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5b5ac4e45f21100001882bb9",
"name": "DEEBOT 710", "materialNo": "702-0000-0205",
"ota": True, "name": "DEEBOT 710",
"supportType": { "ota": True,
"alexa": True, "supportType": {
"assistant": True, "alexa": True,
"share": True, "assistant": True,
"tmjl": False "share": True,
} "tmjl": False,
} },
}, },
{ },
"classid": "ls1ok3", {
"product": { "classid": "ls1ok3",
"UILogicId": "D_900", "product": {
"_id": "5b6561060506b100015c8868", "UILogicId": "D_900",
"icon": "5ba4a2cb6c2f120001c32839", "_id": "5b6561060506b100015c8868",
"iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5ba4a2cb6c2f120001c32839", "icon": "5ba4a2cb6c2f120001c32839",
"materialNo": "110-1711-0201", "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5ba4a2cb6c2f120001c32839",
"name": "DEEBOT 900 Series", "materialNo": "110-1711-0201",
"ota": True, "name": "DEEBOT 900 Series",
"supportType": { "ota": True,
"alexa": True, "supportType": {
"assistant": True, "alexa": True,
"share": True, "assistant": True,
"tmjl": False "share": True,
} "tmjl": False,
} },
}, },
{ },
"classid": "eyi9jv", {
"product": { "classid": "eyi9jv",
"UILogicId": "D_700", "product": {
"_id": "5b7b65f364e1680001a08b54", "UILogicId": "D_700",
"icon": "5b7b65f176f7f10001e9a0c2", "_id": "5b7b65f364e1680001a08b54",
"iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5b7b65f176f7f10001e9a0c2", "icon": "5b7b65f176f7f10001e9a0c2",
"materialNo": "715", "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5b7b65f176f7f10001e9a0c2",
"name": "DEEBOT 715", "materialNo": "715",
"ota": True, "name": "DEEBOT 715",
"supportType": { "ota": True,
"alexa": True, "supportType": {
"assistant": True, "alexa": True,
"share": True, "assistant": True,
"tmjl": False "share": True,
} "tmjl": False,
} },
}, },
{ },
"classid": "4zfacv", {
"product": { "classid": "4zfacv",
"UILogicId": "DN_2G", "product": {
"_id": "5bf2596f23244a00013f2f13", "UILogicId": "DN_2G",
"icon": "5c778731280fda0001770ba0", "_id": "5bf2596f23244a00013f2f13",
"iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5c778731280fda0001770ba0", "icon": "5c778731280fda0001770ba0",
"materialNo": "910", "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5c778731280fda0001770ba0",
"name": "DEEBOT 910", "materialNo": "910",
"ota": True, "name": "DEEBOT 910",
"supportType": { "ota": True,
"alexa": True, "supportType": {
"assistant": True, "alexa": True,
"share": True, "assistant": True,
"tmjl": False "share": True,
} "tmjl": False,
} },
}, },
{ },
"classid": "vi829v", {
"product": { "classid": "vi829v",
"UILogicId": "DX_5G", "product": {
"_id": "5c19a8f3a1e6ee0001782247", "UILogicId": "DX_5G",
"icon": "5c9c7995e9e9270001354ab4", "_id": "5c19a8f3a1e6ee0001782247",
"iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5c9c7995e9e9270001354ab4", "icon": "5c9c7995e9e9270001354ab4",
"materialNo": "920", "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5c9c7995e9e9270001354ab4",
"name": "DEEBOT OZMO 920 Series", "materialNo": "920",
"ota": True, "name": "DEEBOT OZMO 920 Series",
"supportType": { "ota": True,
"alexa": True, "supportType": {
"assistant": True, "alexa": True,
"share": True, "assistant": True,
"tmjl": False "share": True,
} "tmjl": False,
} },
}, },
{ },
"classid": "gd4uut", {
"product": { "classid": "gd4uut",
"UILogicId": "DR_935G", "product": {
"_id": "5bc8189d68142800016a6937", "UILogicId": "DR_935G",
"icon": "5c7384767b93c700013f12e7", "_id": "5bc8189d68142800016a6937",
"iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5c7384767b93c700013f12e7", "icon": "5c7384767b93c700013f12e7",
"materialNo": "960", "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5c7384767b93c700013f12e7",
"name": "DEEBOT OZMO 960", "materialNo": "960",
"ota": True, "name": "DEEBOT OZMO 960",
"supportType": { "ota": True,
"alexa": True, "supportType": {
"assistant": True, "alexa": True,
"share": False, "assistant": True,
"tmjl": False "share": False,
} "tmjl": False,
} },
}, },
{ },
"classid": "9akc61", {
"product": { "classid": "9akc61",
"UILogicId": "D_500", "product": {
"_id": "5c763f8263023c0001e7f855", "UILogicId": "D_500",
"icon": "5c932067280fda0001770d7f", "_id": "5c763f8263023c0001e7f855",
"iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5c932067280fda0001770d7f", "icon": "5c932067280fda0001770d7f",
"materialNo": "D505", "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5c932067280fda0001770d7f",
"name": "DEEBOT 505", "materialNo": "D505",
"ota": False, "name": "DEEBOT 505",
"supportType": { "ota": False,
"alexa": True, "supportType": {
"assistant": True, "alexa": True,
"share": True, "assistant": True,
"tmjl": False "share": True,
} "tmjl": False,
} },
}, },
{ },
"classid": "r8ead0", {
"product": { "classid": "r8ead0",
"UILogicId": "D_500", "product": {
"_id": "5c763f63280fda0001770b88", "UILogicId": "D_500",
"icon": "5c93204b63023c0001e7faa7", "_id": "5c763f63280fda0001770b88",
"iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5c93204b63023c0001e7faa7", "icon": "5c93204b63023c0001e7faa7",
"materialNo": "D502", "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5c93204b63023c0001e7faa7",
"name": "DEEBOT 502", "materialNo": "D502",
"ota": False, "name": "DEEBOT 502",
"supportType": { "ota": False,
"alexa": True, "supportType": {
"assistant": True, "alexa": True,
"share": True, "assistant": True,
"tmjl": False "share": True,
} "tmjl": False,
} },
}, },
{ },
"classid": "emzppx", {
"product": { "classid": "emzppx",
"UILogicId": "D_500", "product": {
"_id": "5c763f35280fda0001770b84", "UILogicId": "D_500",
"icon": "5c931fef280fda0001770d7e", "_id": "5c763f35280fda0001770b84",
"iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5c931fef280fda0001770d7e", "icon": "5c931fef280fda0001770d7e",
"materialNo": "D501", "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5c931fef280fda0001770d7e",
"name": "DEEBOT 501", "materialNo": "D501",
"ota": False, "name": "DEEBOT 501",
"supportType": { "ota": False,
"alexa": True, "supportType": {
"assistant": True, "alexa": True,
"share": True, "assistant": True,
"tmjl": False "share": True,
} "tmjl": False,
} },
}, },
{ },
"classid": "vsc5ia", {
"product": { "classid": "vsc5ia",
"UILogicId": "D_500", "product": {
"_id": "5c763eba280fda0001770b81", "UILogicId": "D_500",
"icon": "5c874326280fda0001770d2a", "_id": "5c763eba280fda0001770b81",
"iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5c874326280fda0001770d2a", "icon": "5c874326280fda0001770d2a",
"materialNo": "D500", "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5c874326280fda0001770d2a",
"name": "DEEBOT 500", "materialNo": "D500",
"ota": False, "name": "DEEBOT 500",
"supportType": { "ota": False,
"alexa": True, "supportType": {
"assistant": True, "alexa": True,
"share": True, "assistant": True,
"tmjl": False "share": True,
} "tmjl": False,
} },
}, },
{ },
"classid": "aqdd5p", {
"product": { "classid": "aqdd5p",
"UILogicId": "D_900", "product": {
"_id": "5cb7cfba179839000114d762", "UILogicId": "D_900",
"icon": "5cb7cfbab72c4d00010e5fc7", "_id": "5cb7cfba179839000114d762",
"iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5cb7cfbab72c4d00010e5fc7", "icon": "5cb7cfbab72c4d00010e5fc7",
"materialNo": "110-1711-0001", "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5cb7cfbab72c4d00010e5fc7",
"name": "DEEBOT DE55", "materialNo": "110-1711-0001",
"ota": True, "name": "DEEBOT DE55",
"supportType": { "ota": True,
"alexa": False, "supportType": {
"assistant": False, "alexa": False,
"share": False, "assistant": False,
"tmjl": False "share": False,
} "tmjl": False,
} },
} },
] },
]
class VacBotClient(object): class VacBotClient(object):
@ -616,18 +626,19 @@ def check_authcode(uid, authcode):
return False return False
def loginByItToken(authcode): def loginByItToken(authcode):
bumperlog.debug("Checking for authcode: {}".format(authcode)) bumperlog.debug("Checking for authcode: {}".format(authcode))
tokens = db_get().table("tokens") tokens = db_get().table("tokens")
tmpauth = tokens.get( tmpauth = tokens.get(
(Query().authcode == authcode) (Query().authcode == authcode)
#& ( # Match authcode # & ( # Match authcode
# (Query().userid == uid.replace("fuid_", "")) # (Query().userid == uid.replace("fuid_", ""))
# | (Query().userid == "fuid_{}".format(uid)) # | (Query().userid == "fuid_{}".format(uid))
#) # Userid with or without fuid_ # ) # Userid with or without fuid_
) )
if tmpauth: if tmpauth:
return {"token":tmpauth["token"], "userid":tmpauth["userid"]} return {"token": tmpauth["token"], "userid": tmpauth["userid"]}
return {} return {}
@ -665,10 +676,12 @@ def bot_add(sn, did, devclass, resource, company):
newbot.company = company newbot.company = company
bot = bot_get(did) bot = bot_get(did)
if not bot: # Not existing bot in database if not bot: # Not existing bot in database
if not devclass == "" or "@" not in sn or "tmp" not in sn: # try to prevent bad additions to the bot list if (
not devclass == "" or "@" not in sn or "tmp" not in sn
): # try to prevent bad additions to the bot list
bumperlog.info( bumperlog.info(
"Adding new bot with SN: {} DID: {}".format(newbot.name, newbot.did) "Adding new bot with SN: {} DID: {}".format(newbot.name, newbot.did)
) )
bot_full_upsert(newbot.asdict()) bot_full_upsert(newbot.asdict())
@ -685,14 +698,15 @@ def bot_get(did):
return bots.get(Bot.did == did) return bots.get(Bot.did == did)
def bot_toEcoVacsHome_JSON(bot): #EcoVacs Home def bot_toEcoVacsHome_JSON(bot): # EcoVacs Home
for botprod in EcoVacsHomeProducts: for botprod in EcoVacsHomeProducts:
if botprod["classid"] == bot["class"]: if botprod["classid"] == bot["class"]:
bot["UILogicId"] = botprod["product"]["UILogicId"] bot["UILogicId"] = botprod["product"]["UILogicId"]
bot["ota"] = botprod["product"]["ota"] bot["ota"] = botprod["product"]["ota"]
bot["icon"] = botprod["product"]["iconUrl"] bot["icon"] = botprod["product"]["iconUrl"]
return json.dumps(bot, default=lambda o: o.__dict__, return json.dumps(
sort_keys=False)#, indent=4) bot, default=lambda o: o.__dict__, sort_keys=False
) # , indent=4)
def bot_full_upsert(vacbot): def bot_full_upsert(vacbot):

View file

@ -31,7 +31,10 @@ class aiohttp_filter(logging.Filter):
confserverlog = logging.getLogger("confserver") confserverlog = logging.getLogger("confserver")
logging.getLogger("aiohttp.access").addFilter(aiohttp_filter()) #Add logging filter above to aiohttp.access logging.getLogger("aiohttp.access").addFilter(
aiohttp_filter()
) # Add logging filter above to aiohttp.access
class EcoVacs_Login: class EcoVacs_Login:
accessToken = "" accessToken = ""
@ -41,14 +44,17 @@ class EcoVacs_Login:
username = "" username = ""
def toJSON(self): def toJSON(self):
return json.dumps(self, default=lambda o: o.__dict__, return json.dumps(
sort_keys=False)#, indent=4) self, default=lambda o: o.__dict__, sort_keys=False
) # , indent=4)
class EcoVacsHome_Login(EcoVacs_Login): class EcoVacsHome_Login(EcoVacs_Login):
loginName = "" loginName = ""
mobile = "" mobile = ""
ucUid = "" ucUid = ""
class ConfServer: class ConfServer:
def __init__(self, address, usessl=False, helperbot=None): def __init__(self, address, usessl=False, helperbot=None):
self.helperbot = helperbot self.helperbot = helperbot
@ -72,7 +78,7 @@ class ConfServer:
"/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/checkLogin", "/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/checkLogin",
self.handle_login, self.handle_login,
), ),
web.get( #EcoVacs Home GetUserAccountInfo web.get( # EcoVacs Home GetUserAccountInfo
"/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/getUserAccountInfo", "/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/getUserAccountInfo",
self.handle_getUserAccountInfo, self.handle_getUserAccountInfo,
), ),
@ -84,15 +90,14 @@ class ConfServer:
"/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/getAuthCode", "/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/getAuthCode",
self.handle_getAuthCode, self.handle_getAuthCode,
), ),
web.get( #EcoVacs Home GetAuthCode web.get( # EcoVacs Home GetAuthCode
"/{apiversion}/{apptype}/auth/getAuthCode", "/{apiversion}/{apptype}/auth/getAuthCode", self.handle_getAuthCode
self.handle_getAuthCode
), ),
web.get( web.get(
"/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/checkAgreement", "/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/checkAgreement",
self.handle_checkAgreement, self.handle_checkAgreement,
), ),
web.get( #EcoVacs Home CheckAgreement web.get( # EcoVacs Home CheckAgreement
"/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/checkAgreementBatch", "/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/checkAgreementBatch",
self.handle_checkAgreement, self.handle_checkAgreement,
), ),
@ -100,39 +105,38 @@ class ConfServer:
"/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/common/checkVersion", "/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/common/checkVersion",
self.handle_checkVersion, self.handle_checkVersion,
), ),
web.get( #EcoVacs Home CheckAPPVersion web.get( # EcoVacs Home CheckAPPVersion
"/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/common/checkAPPVersion", "/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/common/checkAPPVersion",
self.handle_checkAPPVersion, self.handle_checkAPPVersion,
), ),
web.get( #EcoVacs Home Upload Device Info web.get( # EcoVacs Home Upload Device Info
"/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/common/uploadDeviceInfo", "/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/common/uploadDeviceInfo",
self.handle_uploadDeviceInfo, self.handle_uploadDeviceInfo,
), ),
web.get( #EcoVacs Home GetAdByPositionType web.get( # EcoVacs Home GetAdByPositionType
"/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/ad/getAdByPositionType", "/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/ad/getAdByPositionType",
self.handle_getAdByPositionType, self.handle_getAdByPositionType,
), ),
web.get( #EcoVacs Home Get Boot Screen web.get( # EcoVacs Home Get Boot Screen
"/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/ad/getBootScreen", "/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/ad/getBootScreen",
self.handle_getBootScreen, self.handle_getBootScreen,
), ),
web.get( #EcoVacs Home message hasUnreadMsg web.get( # EcoVacs Home message hasUnreadMsg
"/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/message/hasUnreadMsg", "/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/message/hasUnreadMsg",
self.handle_hasUnreadMessage, self.handle_hasUnreadMessage,
), ),
web.get( #EcoVacs Home neng message hasUnreadMsg web.get( # EcoVacs Home neng message hasUnreadMsg
"/api/neng/message/hasUnreadMsg", "/api/neng/message/hasUnreadMsg", self.handle_neng_hasUnreadMessage
self.handle_neng_hasUnreadMessage,
), ),
web.get( #EcoVacs Home message getMsgList web.get( # EcoVacs Home message getMsgList
"/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/message/getMsgList", "/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/message/getMsgList",
self.handle_getMsgList, self.handle_getMsgList,
), ),
web.get( #EcoVacs Home common getSystemReminder web.get( # EcoVacs Home common getSystemReminder
"/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/common/getSystemReminder", "/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/common/getSystemReminder",
self.handle_getSystemReminder, self.handle_getSystemReminder,
), ),
web.get( #EcoVacs Home shop getCnWapShopConfig web.get( # EcoVacs Home shop getCnWapShopConfig
"/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/shop/getCnWapShopConfig", "/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/shop/getCnWapShopConfig",
self.handle_getCnWapShopConfig, self.handle_getCnWapShopConfig,
), ),
@ -142,14 +146,16 @@ class ConfServer:
), ),
web.post("/api/users/user.do", self.handle_usersapi), web.post("/api/users/user.do", self.handle_usersapi),
web.get("/api/users/user.do", self.handle_usersapi), web.get("/api/users/user.do", self.handle_usersapi),
web.post("/api/appsvr/app.do", self.handle_appsvr_api), #EcoVacs Home web.post("/api/appsvr/app.do", self.handle_appsvr_api), # EcoVacs Home
web.get("/api/appsvr/app.do", self.handle_appsvr_api), #EcoVacs Home web.get("/api/appsvr/app.do", self.handle_appsvr_api), # EcoVacs Home
web.post( web.post(
"/api/pim/product/getProductIotMap", self.handle_getProductIotMap "/api/pim/product/getProductIotMap", self.handle_getProductIotMap
), ),
web.post("/api/lg/log.do", self.handle_lg_log), #EcoVacs Home web.post("/api/lg/log.do", self.handle_lg_log), # EcoVacs Home
web.post("/api/iot/devmanager.do", self.handle_devmanager_botcommand), web.post("/api/iot/devmanager.do", self.handle_devmanager_botcommand),
web.post("/api/dim/devmanager.do", self.handle_dim_devmanager), #EcoVacs Home web.post(
"/api/dim/devmanager.do", self.handle_dim_devmanager
), # EcoVacs Home
web.post("/lookup.do", self.handle_lookup), web.post("/lookup.do", self.handle_lookup),
] ]
) )
@ -158,7 +164,9 @@ class ConfServer:
async def start_server(self): async def start_server(self):
try: try:
confserverlog.info("Starting ConfServer at {}:{}".format(self.address[0], self.address[1])) confserverlog.info(
"Starting ConfServer at {}:{}".format(self.address[0], self.address[1])
)
runner = web.AppRunner(self.app) runner = web.AppRunner(self.app)
await runner.setup() await runner.setup()
@ -218,10 +226,12 @@ class ConfServer:
apptype, countrycode, user, request.query["accessToken"] apptype, countrycode, user, request.query["accessToken"]
) )
else: else:
if "global_" in apptype: #EcoVacs Home if "global_" in apptype: # EcoVacs Home
login_details = EcoVacsHome_Login() login_details = EcoVacsHome_Login()
login_details.ucUid = "fuid_{}".format(user["userid"]) login_details.ucUid = "fuid_{}".format(user["userid"])
login_details.loginName = "fusername_{}".format(user["userid"]) login_details.loginName = "fusername_{}".format(
user["userid"]
)
login_details.mobile = None login_details.mobile = None
else: else:
@ -239,13 +249,13 @@ class ConfServer:
body = { body = {
"code": bumper.RETURN_API_SUCCESS, "code": bumper.RETURN_API_SUCCESS,
"data": json.loads(login_details.toJSON()), "data": json.loads(login_details.toJSON()),
#{ # {
# "accessToken": self.generate_token(tmpuser), # Generate a token # "accessToken": self.generate_token(tmpuser), # Generate a token
# "country": countrycode, # "country": countrycode,
# "email": "null@null.com", # "email": "null@null.com",
# "uid": "fuid_{}".format(tmpuser["userid"]), # "uid": "fuid_{}".format(tmpuser["userid"]),
# "username": "fusername_{}".format(tmpuser["userid"]), # "username": "fusername_{}".format(tmpuser["userid"]),
#}, # },
"msg": "操作成功", "msg": "操作成功",
"time": bumper.get_milli_time( "time": bumper.get_milli_time(
datetime.utcnow().timestamp() datetime.utcnow().timestamp()
@ -278,7 +288,7 @@ class ConfServer:
apptype = request.match_info.get("apptype", "") apptype = request.match_info.get("apptype", "")
user = bumper.user_by_deviceid(user_devid) user = bumper.user_by_deviceid(user_devid)
if "global_" in apptype: #EcoVacs Home if "global_" in apptype: # EcoVacs Home
login_details = EcoVacsHome_Login() login_details = EcoVacsHome_Login()
login_details.ucUid = "fuid_{}".format(user["userid"]) login_details.ucUid = "fuid_{}".format(user["userid"])
login_details.loginName = "fusername_{}".format(user["userid"]) login_details.loginName = "fusername_{}".format(user["userid"])
@ -293,17 +303,16 @@ class ConfServer:
body = { body = {
"code": bumper.RETURN_API_SUCCESS, "code": bumper.RETURN_API_SUCCESS,
"data": "data": {
{ "email": login_details.email,
"email": login_details.email, "hasMobile": "N",
"hasMobile": "N", "hasPassword": "Y",
"hasPassword": "Y", "uid": login_details.uid,
"uid": login_details.uid, "userName": login_details.username,
"userName": login_details.username, "obfuscatedMobile": None,
"obfuscatedMobile": None, "mobile": None,
"mobile": None, "loginName": login_details.loginName,
"loginName": login_details.loginName },
},
"msg": "操作成功", "msg": "操作成功",
"time": bumper.get_milli_time(datetime.utcnow().timestamp()), "time": bumper.get_milli_time(datetime.utcnow().timestamp()),
} }
@ -312,12 +321,11 @@ class ConfServer:
except Exception as e: except Exception as e:
confserverlog.exception("{}".format(e)) confserverlog.exception("{}".format(e))
def check_token(self, apptype, countrycode, user, token): def check_token(self, apptype, countrycode, user, token):
try: try:
if bumper.check_token(user["userid"], token): if bumper.check_token(user["userid"], token):
if "global_" in apptype: #EcoVacs Home if "global_" in apptype: # EcoVacs Home
login_details = EcoVacsHome_Login() login_details = EcoVacsHome_Login()
login_details.ucUid = "fuid_{}".format(user["userid"]) login_details.ucUid = "fuid_{}".format(user["userid"])
login_details.loginName = "fusername_{}".format(user["userid"]) login_details.loginName = "fusername_{}".format(user["userid"])
@ -334,13 +342,13 @@ class ConfServer:
body = { body = {
"code": bumper.RETURN_API_SUCCESS, "code": bumper.RETURN_API_SUCCESS,
"data": json.loads(login_details.toJSON()), "data": json.loads(login_details.toJSON()),
#{ # {
# "accessToken": self.generate_token(tmpuser), # Generate a token # "accessToken": self.generate_token(tmpuser), # Generate a token
# "country": countrycode, # "country": countrycode,
# "email": "null@null.com", # "email": "null@null.com",
# "uid": "fuid_{}".format(tmpuser["userid"]), # "uid": "fuid_{}".format(tmpuser["userid"]),
# "username": "fusername_{}".format(tmpuser["userid"]), # "username": "fusername_{}".format(tmpuser["userid"]),
#}, # },
"msg": "操作成功", "msg": "操作成功",
"time": bumper.get_milli_time(datetime.utcnow().timestamp()), "time": bumper.get_milli_time(datetime.utcnow().timestamp()),
} }
@ -385,7 +393,7 @@ class ConfServer:
if user: # Default to user 0 if user: # Default to user 0
tmpuser = user tmpuser = user
if "global_" in apptype: #EcoVacs Home if "global_" in apptype: # EcoVacs Home
login_details = EcoVacsHome_Login() login_details = EcoVacsHome_Login()
login_details.ucUid = "fuid_{}".format(tmpuser["userid"]) login_details.ucUid = "fuid_{}".format(tmpuser["userid"])
login_details.loginName = "fusername_{}".format(tmpuser["userid"]) login_details.loginName = "fusername_{}".format(tmpuser["userid"])
@ -402,7 +410,7 @@ class ConfServer:
else: else:
bumper.user_add("tmpuser") # Add a new user bumper.user_add("tmpuser") # Add a new user
tmpuser = bumper.user_get("tmpuser") tmpuser = bumper.user_get("tmpuser")
if "global_" in apptype: #EcoVacs Home if "global_" in apptype: # EcoVacs Home
login_details = EcoVacsHome_Login() login_details = EcoVacsHome_Login()
login_details.ucUid = "fuid_{}".format(tmpuser["userid"]) login_details.ucUid = "fuid_{}".format(tmpuser["userid"])
login_details.loginName = "fusername_{}".format(tmpuser["userid"]) login_details.loginName = "fusername_{}".format(tmpuser["userid"])
@ -431,17 +439,16 @@ class ConfServer:
# Deactivate old tokens and authcodes # Deactivate old tokens and authcodes
bumper.user_revoke_expired_tokens(tmpuser["userid"]) bumper.user_revoke_expired_tokens(tmpuser["userid"])
body = { body = {
"code": bumper.RETURN_API_SUCCESS, "code": bumper.RETURN_API_SUCCESS,
"data": json.loads(login_details.toJSON()), "data": json.loads(login_details.toJSON()),
#{ # {
# "accessToken": self.generate_token(tmpuser), # Generate a token # "accessToken": self.generate_token(tmpuser), # Generate a token
# "country": countrycode, # "country": countrycode,
# "email": "null@null.com", # "email": "null@null.com",
# "uid": "fuid_{}".format(tmpuser["userid"]), # "uid": "fuid_{}".format(tmpuser["userid"]),
# "username": "fusername_{}".format(tmpuser["userid"]), # "username": "fusername_{}".format(tmpuser["userid"]),
#}, # },
"msg": "操作成功", "msg": "操作成功",
"time": bumper.get_milli_time(datetime.utcnow().timestamp()), "time": bumper.get_milli_time(datetime.utcnow().timestamp()),
} }
@ -478,9 +485,9 @@ class ConfServer:
async def handle_getAuthCode(self, request): async def handle_getAuthCode(self, request):
try: try:
apptype = request.match_info.get("apptype", "") apptype = request.match_info.get("apptype", "")
user_devid = request.match_info.get("devid", "") #Ecovacs user_devid = request.match_info.get("devid", "") # Ecovacs
if user_devid == "": if user_devid == "":
user_devid = request.query["deviceId"] #Ecovacs Home user_devid = request.query["deviceId"] # Ecovacs Home
if not user_devid == "": if not user_devid == "":
user = bumper.user_by_deviceid(user_devid) user = bumper.user_by_deviceid(user_devid)
@ -502,17 +509,17 @@ class ConfServer:
authcode = token["authcode"] authcode = token["authcode"]
if "global" in apptype: if "global" in apptype:
body = { body = {
"code": bumper.RETURN_API_SUCCESS, "code": bumper.RETURN_API_SUCCESS,
"data": { "data": {
"authCode": authcode, "authCode": authcode,
"ecovacsUid": request.query["uid"], "ecovacsUid": request.query["uid"],
}, },
"msg": "操作成功", "msg": "操作成功",
"success": True, "success": True,
"time": bumper.get_milli_time( "time": bumper.get_milli_time(
datetime.utcnow().timestamp() datetime.utcnow().timestamp()
), ),
} }
else: else:
body = { body = {
"code": bumper.RETURN_API_SUCCESS, "code": bumper.RETURN_API_SUCCESS,
@ -561,7 +568,7 @@ class ConfServer:
except Exception as e: except Exception as e:
confserverlog.exception("{}".format(e)) confserverlog.exception("{}".format(e))
async def handle_checkAPPVersion(self, request): #EcoVacs Home async def handle_checkAPPVersion(self, request): # EcoVacs Home
try: try:
body = { body = {
"code": bumper.RETURN_API_SUCCESS, "code": bumper.RETURN_API_SUCCESS,
@ -586,7 +593,7 @@ class ConfServer:
except Exception as e: except Exception as e:
confserverlog.exception("{}".format(e)) confserverlog.exception("{}".format(e))
async def handle_uploadDeviceInfo(self, request): #EcoVacs Home async def handle_uploadDeviceInfo(self, request): # EcoVacs Home
try: try:
body = { body = {
"code": bumper.RETURN_API_SUCCESS, "code": bumper.RETURN_API_SUCCESS,
@ -601,7 +608,7 @@ class ConfServer:
except Exception as e: except Exception as e:
confserverlog.exception("{}".format(e)) confserverlog.exception("{}".format(e))
async def handle_getAdByPositionType(self, request): #EcoVacs Home async def handle_getAdByPositionType(self, request): # EcoVacs Home
try: try:
body = { body = {
"code": bumper.RETURN_API_SUCCESS, "code": bumper.RETURN_API_SUCCESS,
@ -616,7 +623,7 @@ class ConfServer:
except Exception as e: except Exception as e:
confserverlog.exception("{}".format(e)) confserverlog.exception("{}".format(e))
async def handle_getBootScreen(self, request): #EcoVacs Home async def handle_getBootScreen(self, request): # EcoVacs Home
try: try:
body = { body = {
"code": bumper.RETURN_API_SUCCESS, "code": bumper.RETURN_API_SUCCESS,
@ -631,7 +638,7 @@ class ConfServer:
except Exception as e: except Exception as e:
confserverlog.exception("{}".format(e)) confserverlog.exception("{}".format(e))
async def handle_hasUnreadMessage(self, request): #EcoVacs Home async def handle_hasUnreadMessage(self, request): # EcoVacs Home
try: try:
body = { body = {
"code": bumper.RETURN_API_SUCCESS, "code": bumper.RETURN_API_SUCCESS,
@ -646,30 +653,20 @@ class ConfServer:
except Exception as e: except Exception as e:
confserverlog.exception("{}".format(e)) confserverlog.exception("{}".format(e))
async def handle_neng_hasUnreadMessage(self, request): # EcoVacs Home
async def handle_neng_hasUnreadMessage(self, request): #EcoVacs Home
try: try:
body = { body = {"code": 0, "data": {"hasUnRead": True}}
"code": 0,
"data": {
"hasUnRead": True
},
}
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_getMsgList(self, request): # EcoVacs Home
async def handle_getMsgList(self, request): #EcoVacs Home
try: try:
body = { body = {
"code": bumper.RETURN_API_SUCCESS, "code": bumper.RETURN_API_SUCCESS,
"data": { "data": {"hasNextPage": 0, "items": []},
"hasNextPage": 0,
"items": []
},
"msg": "操作成功", "msg": "操作成功",
"success": True, "success": True,
"time": bumper.get_milli_time(datetime.utcnow().timestamp()), "time": bumper.get_milli_time(datetime.utcnow().timestamp()),
@ -680,7 +677,7 @@ class ConfServer:
except Exception as e: except Exception as e:
confserverlog.exception("{}".format(e)) confserverlog.exception("{}".format(e))
async def handle_getCnWapShopConfig(self, request): #EcoVacs Home async def handle_getCnWapShopConfig(self, request): # EcoVacs Home
try: try:
body = { body = {
"code": bumper.RETURN_API_SUCCESS, "code": bumper.RETURN_API_SUCCESS,
@ -688,8 +685,8 @@ class ConfServer:
"myShopShowFlag": "N", "myShopShowFlag": "N",
"myShopUrl": "", "myShopUrl": "",
"shopIndexShowFlag": "N", "shopIndexShowFlag": "N",
"shopIndexUrl": "" "shopIndexUrl": "",
}, },
"msg": "操作成功", "msg": "操作成功",
"success": True, "success": True,
"time": bumper.get_milli_time(datetime.utcnow().timestamp()), "time": bumper.get_milli_time(datetime.utcnow().timestamp()),
@ -700,20 +697,17 @@ class ConfServer:
except Exception as e: except Exception as e:
confserverlog.exception("{}".format(e)) confserverlog.exception("{}".format(e))
async def handle_getSystemReminder(self, request): #EcoVacs Home async def handle_getSystemReminder(self, request): # EcoVacs Home
try: try:
body = { body = {
"code": bumper.RETURN_API_SUCCESS, "code": bumper.RETURN_API_SUCCESS,
"data": "data": {
{ "iosGradeTime": {"iodGradeFlag": "N"},
"iosGradeTime": {
"iodGradeFlag": "N"
},
"openNotification": { "openNotification": {
"openNotificationContent": None, "openNotificationContent": None,
"openNotificationFlag": "N", "openNotificationFlag": "N",
"openNotificationTitle": None "openNotificationTitle": None,
} },
}, },
"msg": "操作成功", "msg": "操作成功",
"success": True, "success": True,
@ -736,16 +730,16 @@ class ConfServer:
"force": "N", "force": "N",
"id": "20180804040641_7d746faf18b8cb22a50d145598fe4c90", "id": "20180804040641_7d746faf18b8cb22a50d145598fe4c90",
"type": "USER", "type": "USER",
"url": "https://bumper.ecovacs.com/content/agreement?id=20180804040641_7d746faf18b8cb22a50d145598fe4c90&language=EN", #"https://gl-us-wap.ecovacs.com/content/agreement?id=20180804040641_7d746faf18b8cb22a50d145598fe4c90&language=EN "url": "https://bumper.ecovacs.com/content/agreement?id=20180804040641_7d746faf18b8cb22a50d145598fe4c90&language=EN", # "https://gl-us-wap.ecovacs.com/content/agreement?id=20180804040641_7d746faf18b8cb22a50d145598fe4c90&language=EN
"version": "1.01" "version": "1.01",
}, },
{ {
"force": "N", "force": "N",
"id": "20180804040245_4e7c56dfb7ebd3b81b1f2747d0859fac", "id": "20180804040245_4e7c56dfb7ebd3b81b1f2747d0859fac",
"type": "PRIVACY", "type": "PRIVACY",
"url": "https://bumper.ecovacs.com/content/agreement?id=20180804040245_4e7c56dfb7ebd3b81b1f2747d0859fac&language=EN", #"https://gl-us-wap.ecovacs.com/content/agreement?id=20180804040245_4e7c56dfb7ebd3b81b1f2747d0859fac&language=EN" "url": "https://bumper.ecovacs.com/content/agreement?id=20180804040245_4e7c56dfb7ebd3b81b1f2747d0859fac&language=EN", # "https://gl-us-wap.ecovacs.com/content/agreement?id=20180804040245_4e7c56dfb7ebd3b81b1f2747d0859fac&language=EN"
"version": "1.01" "version": "1.01",
} },
], ],
"msg": "操作成功", "msg": "操作成功",
"success": True, "success": True,
@ -886,18 +880,18 @@ class ConfServer:
srvip = socket.gethostbyname(socket.gethostname()) srvip = socket.gethostbyname(socket.gethostname())
srvport = 5223 srvport = 5223
confserverlog.info( confserverlog.info(
"Reporting FindBest-EcoMsgNew Server to Bot as: {}:{}".format(srvip, srvport) "Reporting FindBest-EcoMsgNew Server to Bot as: {}:{}".format(
srvip, srvport
)
) )
body = { body = {"result": "ok", "ip": srvip, "port": srvport}
"result": "ok",
"ip": srvip,
"port": srvport,
}
elif service == "EcoUpdate": elif service == "EcoUpdate":
srvip = "47.88.66.164" #EcoVacs Server srvip = "47.88.66.164" # EcoVacs Server
srvport = 8005 srvport = 8005
confserverlog.info( confserverlog.info(
"Reporting FindBest-EcoUpdate Server to Bot as: {}:{}".format(srvip, srvport) "Reporting FindBest-EcoUpdate Server to Bot as: {}:{}".format(
srvip, srvport
)
) )
body = {"result": "ok", "ip": srvip, "port": srvport} body = {"result": "ok", "ip": srvip, "port": srvport}
@ -911,7 +905,7 @@ class ConfServer:
"token": postbody["token"], "token": postbody["token"],
"userId": postbody["userId"], "userId": postbody["userId"],
} }
else: #EcoVacs Home LoginByITToken else: # EcoVacs Home LoginByITToken
loginToken = bumper.loginByItToken(postbody["token"]) loginToken = bumper.loginByItToken(postbody["token"])
if not loginToken == {}: if not loginToken == {}:
body = { body = {
@ -924,7 +918,6 @@ class ConfServer:
else: else:
body = {"result": "fail", "todo": "result"} body = {"result": "fail", "todo": "result"}
elif todo == "GetDeviceList": elif todo == "GetDeviceList":
body = { body = {
"devices": bumper.db_get().table("bots").all(), "devices": bumper.db_get().table("bots").all(),
@ -957,8 +950,6 @@ class ConfServer:
body = {"result": "fail", "todo": "result"} body = {"result": "fail", "todo": "result"}
return web.json_response(body) return web.json_response(body)
async def handle_appsvr_api(self, request): async def handle_appsvr_api(self, request):
if not request.method == "GET": # Skip GET for now if not request.method == "GET": # Skip GET for now
try: try:
@ -973,13 +964,15 @@ class ConfServer:
todo = postbody["todo"] todo = postbody["todo"]
if todo == "GetGlobalDeviceList": #EcoVacs Home if todo == "GetGlobalDeviceList": # EcoVacs Home
bots = bumper.db_get().table("bots").all() bots = bumper.db_get().table("bots").all()
botlist = [] botlist = []
for bot in bots: for bot in bots:
if bot["class"] != "": if bot["class"] != "":
b = bumper.bot_toEcoVacsHome_JSON(bot) b = bumper.bot_toEcoVacsHome_JSON(bot)
if not b is None: #Happens if the bot isn't on the EcoVacs Home list if (
not b is None
): # Happens if the bot isn't on the EcoVacs Home list
botlist.append(json.loads(b)) botlist.append(json.loads(b))
body = { body = {
@ -1002,7 +995,6 @@ class ConfServer:
body = {"result": "fail", "todo": "result"} body = {"result": "fail", "todo": "result"}
return web.json_response(body) return web.json_response(body)
async def handle_lookup(self, request): async def handle_lookup(self, request):
try: try:
@ -1023,7 +1015,9 @@ class ConfServer:
srvip = socket.gethostbyname(socket.gethostname()) srvip = socket.gethostbyname(socket.gethostname())
srvport = 5223 srvport = 5223
confserverlog.info( confserverlog.info(
"Reporting FindBest-EcoMsgNew Server to Bot as: {}:{}".format(srvip, srvport) "Reporting FindBest-EcoMsgNew Server to Bot as: {}:{}".format(
srvip, srvport
)
) )
msgserver = {"ip": srvip, "port": srvport, "result": "ok"} msgserver = {"ip": srvip, "port": srvport, "result": "ok"}
msgserver = json.dumps(msgserver) msgserver = json.dumps(msgserver)
@ -1047,8 +1041,7 @@ class ConfServer:
except Exception as e: except Exception as e:
confserverlog.exception("{}".format(e)) confserverlog.exception("{}".format(e))
async def handle_lg_log(self, request): # EcoVacs Home
async def handle_lg_log(self, request): #EcoVacs Home
try: try:
json_body = json.loads(await request.text()) json_body = json.loads(await request.text())
@ -1060,7 +1053,7 @@ class ConfServer:
if not "cmdName" in json_body: if not "cmdName" in json_body:
if "td" in json_body: if "td" in json_body:
json_body["cmdName"] = json_body["td"] json_body["cmdName"] = json_body["td"]
#json_body["td"] = "q" # json_body["td"] = "q"
if not "toId" in json_body: if not "toId" in json_body:
json_body["toId"] = did json_body["toId"] = did
@ -1078,20 +1071,15 @@ class ConfServer:
json_body["payload"] = "" json_body["payload"] = ""
if json_body["td"] == "GetCleanLogs": if json_body["td"] == "GetCleanLogs":
json_body["td"] = "q" json_body["td"] = "q"
json_body["payload"] = '<ctl count=\"30\"/>' #<ctl />" json_body["payload"] = '<ctl count="30"/>' # <ctl />"
if did != "": if did != "":
bot = bumper.bot_get(did) bot = bumper.bot_get(did)
if bot["company"] == "eco-ng" and bot["mqtt_connection"] == True: if bot["company"] == "eco-ng" and bot["mqtt_connection"] == True:
body = "" body = ""
retcmd = await self.helperbot.send_command(json_body, randomid) retcmd = await self.helperbot.send_command(json_body, randomid)
confserverlog.debug( confserverlog.debug("Send Bot - {}".format(json_body))
"Send Bot - {}".format(json_body) confserverlog.debug("Bot Response - {}".format(body))
)
confserverlog.debug(
"Bot Response - {}".format(body)
)
logs = [] logs = []
logsroot = ET.fromstring(retcmd["resp"]) logsroot = ET.fromstring(retcmd["resp"])
if logsroot.attrib["ret"] == "ok": if logsroot.attrib["ret"] == "ok":
@ -1100,16 +1088,13 @@ class ConfServer:
logs.append(l.attrib) logs.append(l.attrib)
body = { body = {
"ret": "ok", "ret": "ok",
#"logs": logs, #TODO: Doesn't parse correctly, new protocol & server side processing # "logs": logs, #TODO: Doesn't parse correctly, new protocol & server side processing
"logs": [] "logs": [],
} }
else: else:
body = { body = {"ret": "ok", "logs": []}
"ret": "ok",
"logs": [],
}
confserverlog.debug( confserverlog.debug(
"\r\n POST: {} \r\n Response: {}".format(json_body, body) "\r\n POST: {} \r\n Response: {}".format(json_body, body)
@ -1126,7 +1111,6 @@ class ConfServer:
body = {"id": randomid, "errno": bumper.ERR_COMMON, "ret": "fail"} body = {"id": randomid, "errno": bumper.ERR_COMMON, "ret": "fail"}
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))
@ -1136,7 +1120,7 @@ class ConfServer:
randomid = "".join(random.sample(string.ascii_letters, 6)) randomid = "".join(random.sample(string.ascii_letters, 6))
did = "" did = ""
if "toId" in json_body: # Its a command if "toId" in json_body: # Its a command
did = json_body["toId"] did = json_body["toId"]
if did != "": if did != "":
@ -1144,12 +1128,8 @@ class ConfServer:
if bot["company"] == "eco-ng" and bot["mqtt_connection"] == True: if bot["company"] == "eco-ng" and bot["mqtt_connection"] == True:
retcmd = await self.helperbot.send_command(json_body, randomid) retcmd = await self.helperbot.send_command(json_body, randomid)
body = retcmd body = retcmd
confserverlog.debug( confserverlog.debug("Send Bot - {}".format(json_body))
"Send Bot - {}".format(json_body) confserverlog.debug("Bot Response - {}".format(body))
)
confserverlog.debug(
"Bot Response - {}".format(body)
)
return web.json_response(body) return web.json_response(body)
else: else:
# No response, send error back # No response, send error back
@ -1158,7 +1138,12 @@ class ConfServer:
json_body["toId"] json_body["toId"]
) )
) )
body = {"id": randomid, "errno": 500, "ret": "fail", "debug": "wait for response timed out"} body = {
"id": randomid,
"errno": 500,
"ret": "fail",
"debug": "wait for response timed out",
}
return web.json_response(body) return web.json_response(body)
else: else:
@ -1167,21 +1152,20 @@ class ConfServer:
body = {"ret": "ok"} body = {"ret": "ok"}
return web.json_response(body) return web.json_response(body)
if json_body["td"] == "HasUnreadMsg": #EcoVacs Home if json_body["td"] == "HasUnreadMsg": # EcoVacs Home
body = {"ret":"ok","unRead":False} body = {"ret": "ok", "unRead": False}
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_dim_devmanager(self, request): # Used in EcoVacs Home App
async def handle_dim_devmanager(self, request): #Used in EcoVacs Home App
try: try:
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))
did = "" did = ""
if "toId" in json_body: # Its a command if "toId" in json_body: # Its a command
did = json_body["toId"] did = json_body["toId"]
if did != "": if did != "":
@ -1189,12 +1173,8 @@ class ConfServer:
if bot["company"] == "eco-ng" and bot["mqtt_connection"] == True: if bot["company"] == "eco-ng" and bot["mqtt_connection"] == True:
retcmd = await self.helperbot.send_command(json_body, randomid) retcmd = await self.helperbot.send_command(json_body, randomid)
body = retcmd body = retcmd
confserverlog.debug( confserverlog.debug("Send Bot - {}".format(json_body))
"Send Bot - {}".format(json_body) confserverlog.debug("Bot Response - {}".format(body))
)
confserverlog.debug(
"Bot Response - {}".format(body)
)
return web.json_response(body) return web.json_response(body)
else: else:
# No response, send error back # No response, send error back
@ -1212,8 +1192,8 @@ class ConfServer:
body = {"ret": "ok"} body = {"ret": "ok"}
return web.json_response(body) return web.json_response(body)
if json_body["td"] == "HasUnreadMsg": #EcoVacs Home if json_body["td"] == "HasUnreadMsg": # EcoVacs Home
body = {"ret":"ok","unRead":False} body = {"ret": "ok", "unRead": False}
return web.json_response(body) return web.json_response(body)
except Exception as e: except Exception as e:

View file

@ -34,10 +34,7 @@ class MQTTHelperBot:
Client = MQTTClient() Client = MQTTClient()
def __init__( def __init__(self, address):
self,
address
):
self.address = address self.address = address
self.client_id = "helper1@bumper/helper1" self.client_id = "helper1@bumper/helper1"
self.command_responses = [] self.command_responses = []
@ -71,8 +68,12 @@ class MQTTHelperBot:
message = await self.Client.deliver_message() message = await self.Client.deliver_message()
if str(message.topic).split("/")[6] == "helper1": if str(message.topic).split("/")[6] == "helper1":
#Response to command # Response to command
helperbotlog.debug("Received Response - Topic: {} - Message: {}".format(message.topic, str(message.data.decode("utf-8")))) helperbotlog.debug(
"Received Response - Topic: {} - Message: {}".format(
message.topic, str(message.data.decode("utf-8"))
)
)
self.command_responses.append( self.command_responses.append(
{ {
"time": time.time(), "time": time.time(),
@ -81,13 +82,25 @@ class MQTTHelperBot:
} }
) )
elif str(message.topic).split("/")[3] == "helper1": elif str(message.topic).split("/")[3] == "helper1":
#Helperbot sending command # Helperbot sending command
helperbotlog.debug("Send Command - Topic: {} - Message: {}".format(message.topic, str(message.data.decode("utf-8")))) helperbotlog.debug(
"Send Command - Topic: {} - Message: {}".format(
message.topic, str(message.data.decode("utf-8"))
)
)
elif str(message.topic).split("/")[1] == "atr": elif str(message.topic).split("/")[1] == "atr":
#Broadcast message received on atr # Broadcast message received on atr
helperbotlog.debug("Received Broadcast - Topic: {} - Message: {}".format(message.topic, str(message.data.decode("utf-8")))) helperbotlog.debug(
"Received Broadcast - Topic: {} - Message: {}".format(
message.topic, str(message.data.decode("utf-8"))
)
)
else: else:
helperbotlog.debug("Received Message - Topic: {} - Message: {}".format(message.topic, str(message.data.decode("utf-8")))) helperbotlog.debug(
"Received Message - Topic: {} - Message: {}".format(
message.topic, str(message.data.decode("utf-8"))
)
)
# Cleanup "expired messages" > 60 seconds from time # Cleanup "expired messages" > 60 seconds from time
for msg in self.command_responses: for msg in self.command_responses:
@ -95,10 +108,13 @@ class MQTTHelperBot:
datetime.fromtimestamp(msg["time"]) + timedelta(seconds=10) datetime.fromtimestamp(msg["time"]) + timedelta(seconds=10)
).timestamp() ).timestamp()
if time.time() > expire_time: if time.time() > expire_time:
helperbotlog.debug("Pruning Message Time: {}, MsgTime: {}, MsgTime+60: {}".format(time.time(), msg['time'], expire_time)) helperbotlog.debug(
"Pruning Message Time: {}, MsgTime: {}, MsgTime+60: {}".format(
time.time(), msg["time"], expire_time
)
)
self.command_responses.remove(msg) self.command_responses.remove(msg)
async def wait_for_resp(self, requestid): async def wait_for_resp(self, requestid):
try: try:
@ -119,13 +135,28 @@ class MQTTHelperBot:
self.command_responses.remove(msg) self.command_responses.remove(msg)
return resp return resp
return {"id": requestid, "errno": 500, "ret": "fail", "debug": "wait for response timed out"} return {
"id": requestid,
"errno": 500,
"ret": "fail",
"debug": "wait for response timed out",
}
except asyncio.CancelledError as e: except asyncio.CancelledError as e:
helperbotlog.debug("wait_for_resp cancelled by asyncio") helperbotlog.debug("wait_for_resp cancelled by asyncio")
return {"id": requestid, "errno": 500, "ret": "fail", "debug": "wait for response timed out"} return {
"id": requestid,
"errno": 500,
"ret": "fail",
"debug": "wait for response timed out",
}
except Exception as e: except Exception as e:
helperbotlog.exception("{}".format(e)) helperbotlog.exception("{}".format(e))
return {"id": requestid, "errno": 500, "ret": "fail", "debug": "wait for response timed out"} return {
"id": requestid,
"errno": 500,
"ret": "fail",
"debug": "wait for response timed out",
}
async def send_command(self, cmdjson, requestid): async def send_command(self, cmdjson, requestid):
try: try:
@ -158,7 +189,9 @@ class MQTTServer:
async def broker_coro(self): async def broker_coro(self):
try: try:
mqttserverlog.info("Starting MQTT Server at {}:{}".format(self.address[0], self.address[1])) mqttserverlog.info(
"Starting MQTT Server at {}:{}".format(self.address[0], self.address[1])
)
broker = hbmqtt.broker.Broker(config=self.default_config) broker = hbmqtt.broker.Broker(config=self.default_config)
await broker.start() await broker.start()
@ -175,11 +208,7 @@ class MQTTServer:
mqttserverlog.exception("{}".format(e)) mqttserverlog.exception("{}".format(e))
exit(1) exit(1)
def __init__(self, address):
def __init__(
self,
address
):
try: try:
self.mqttserverthread = None self.mqttserverthread = None
self.address = address self.address = address
@ -253,9 +282,9 @@ class BumperMQTTServer_Plugin:
client_id = session.client_id client_id = session.client_id
didsplit = str(client_id).split("@") didsplit = str(client_id).split("@")
if not ( # if ecouser or bumper aren't in details it is a bot if not ( # if ecouser or bumper aren't in details it is a bot
"ecouser" in didsplit[1] "ecouser" in didsplit[1] or "bumper" in didsplit[1]
or "bumper" in didsplit[1]): ):
tmpbotdetail = str(didsplit[1]).split("/") tmpbotdetail = str(didsplit[1]).split("/")
bumper.bot_add( bumper.bot_add(
username, username,
@ -298,7 +327,9 @@ class BumperMQTTServer_Plugin:
authenticated = False authenticated = False
except Exception as e: except Exception as e:
mqttserverlog.exception("Session: {} - {}".format((kwargs.get("session", None)),e)) mqttserverlog.exception(
"Session: {} - {}".format((kwargs.get("session", None)), e)
)
authenticated = False authenticated = False
return authenticated return authenticated
@ -312,7 +343,7 @@ class BumperMQTTServer_Plugin:
bumper.bot_set_mqtt(bot["did"], True) bumper.bot_set_mqtt(bot["did"], True)
return return
#clientuserid = didsplit[0] # clientuserid = didsplit[0]
clientresource = didsplit[1].split("/")[1] clientresource = didsplit[1].split("/")[1]
client = bumper.client_get(clientresource) client = bumper.client_get(clientresource)
if client: if client:
@ -330,7 +361,7 @@ class BumperMQTTServer_Plugin:
if bot: if bot:
bumper.bot_set_mqtt(bot["did"], False) bumper.bot_set_mqtt(bot["did"], False)
#clientuserid = didsplit[0] # clientuserid = didsplit[0]
clientresource = didsplit[1].split("/")[1] clientresource = didsplit[1].split("/")[1]
client = bumper.client_get(clientresource) client = bumper.client_get(clientresource)
if client: if client:

View file

@ -9,7 +9,8 @@ import asyncio, functools
xmppserverlog = logging.getLogger("xmppserver") xmppserverlog = logging.getLogger("xmppserver")
class XMPPServer():
class XMPPServer:
server_id = "ecouser.net" server_id = "ecouser.net"
clients = [] clients = []
exit_flag = False exit_flag = False
@ -45,6 +46,7 @@ class XMPPServer():
except Exception as e: except Exception as e:
xmppserverlog.error("{}".format(e)) xmppserverlog.error("{}".format(e))
class XMPPServer_Protocol(asyncio.Protocol): class XMPPServer_Protocol(asyncio.Protocol):
client_id = None client_id = None
exit_flag = False exit_flag = False
@ -55,8 +57,10 @@ class XMPPServer_Protocol(asyncio.Protocol):
aclient = None aclient = None
def connection_made(self, transport): def connection_made(self, transport):
if self.aclient: #Existing client... upgrading to TLS if self.aclient: # Existing client... upgrading to TLS
xmppserverlog.debug("Upgraded connection for {}".format(self.aclient.address)) xmppserverlog.debug(
"Upgraded connection for {}".format(self.aclient.address)
)
self.aclient.transport = transport self.aclient.transport = transport
else: else:
aclient = XMPPAsyncClient(transport) aclient = XMPPAsyncClient(transport)
@ -65,11 +69,16 @@ class XMPPServer_Protocol(asyncio.Protocol):
self.aclient.state = getattr(aclient, "CONNECT") self.aclient.state = getattr(aclient, "CONNECT")
xmppserverlog.debug("New Connection from {}".format(aclient.address)) xmppserverlog.debug("New Connection from {}".format(aclient.address))
def connection_lost(self, error): def connection_lost(self, error):
XMPPServer.clients.remove(self.aclient) XMPPServer.clients.remove(self.aclient)
self.aclient._set_state("DISCONNECT") self.aclient._set_state("DISCONNECT")
xmppserverlog.debug("End Connection for ({}:{} | {})".format(self.aclient.address[0], self.aclient.address[1], self.aclient.bumper_jid)) xmppserverlog.debug(
"End Connection for ({}:{} | {})".format(
self.aclient.address[0],
self.aclient.address[1],
self.aclient.bumper_jid,
)
)
def data_received(self, data): def data_received(self, data):
self.aclient._parse_data(data) self.aclient._parse_data(data)
@ -103,7 +112,11 @@ class XMPPAsyncClient:
def send(self, command): def send(self, command):
try: try:
if self.log_sent_message: if self.log_sent_message:
xmppserverlog.debug("send to ({}:{} | {}) - {}".format(self.address[0], self.address[1], self.bumper_jid, command)) xmppserverlog.debug(
"send to ({}:{} | {}) - {}".format(
self.address[0], self.address[1], self.bumper_jid, command
)
)
self.transport.write(command.encode()) self.transport.write(command.encode())
@ -145,7 +158,11 @@ class XMPPAsyncClient:
) )
) )
xmppserverlog.debug("({}:{} | {}) state: {}".format(self.address[0],self.address[1],self.bumper_jid, state)) xmppserverlog.debug(
"({}:{} | {}) state: {}".format(
self.address[0], self.address[1], self.bumper_jid, state
)
)
self.state = new_state self.state = new_state
@ -172,18 +189,18 @@ class XMPPAsyncClient:
self.send( self.send(
'<iq type="error" id="{}"><error type="cancel" code="501"><feature-not-implemented xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/></error></iq>'.format( '<iq type="error" id="{}"><error type="cancel" code="501"><feature-not-implemented xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/></error></iq>'.format(
xml.get("id") xml.get("id")
)) )
)
return return
if "disco#info" in data: if "disco#info" in data:
# Return not-implemented for disco#info # Return not-implemented for disco#info
self.send( self.send(
'<iq type="error" id="{}"><error type="cancel" code="501"><feature-not-implemented xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/></error></iq>'.format( '<iq type="error" id="{}"><error type="cancel" code="501"><feature-not-implemented xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/></error></iq>'.format(
xml.get("id") xml.get("id")
) )
) )
return return
if xml.get("type") == "set": if xml.get("type") == "set":
if ( if (
@ -255,7 +272,6 @@ class XMPPAsyncClient:
pingstring = pingstring.replace('iq xmlns="urn:xmpp:ping"', "iq") pingstring = pingstring.replace('iq xmlns="urn:xmpp:ping"', "iq")
pingstring = pingstring.replace("<ping", '<ping xmlns="urn:xmpp:ping"') pingstring = pingstring.replace("<ping", '<ping xmlns="urn:xmpp:ping"')
for client in XMPPServer.clients: for client in XMPPServer.clients:
if ( if (
client.bumper_jid != self.bumper_jid client.bumper_jid != self.bumper_jid
@ -267,10 +283,11 @@ class XMPPAsyncClient:
except Exception as e: except Exception as e:
xmppserverlog.exception("{}".format(e)) xmppserverlog.exception("{}".format(e))
async def schedule_ping(self, time): async def schedule_ping(self, time):
if not self.state == 5: #disconnected if not self.state == 5: # disconnected
pingstring = "<iq from='{}' to='{}' id='s2c1' type='get'><ping xmlns='urn:xmpp:ping'/></iq>".format(XMPPServer.server_id, self.bumper_jid) pingstring = "<iq from='{}' to='{}' id='s2c1' type='get'><ping xmlns='urn:xmpp:ping'/></iq>".format(
XMPPServer.server_id, self.bumper_jid
)
self.send(pingstring) self.send(pingstring)
await asyncio.sleep(time) await asyncio.sleep(time)
asyncio.Task(self.schedule_ping(time)) asyncio.Task(self.schedule_ping(time))
@ -290,7 +307,9 @@ class XMPPAsyncClient:
adminuser = ctlerr.replace("permission denied, please contact ", "") adminuser = ctlerr.replace("permission denied, please contact ", "")
adminuser = adminuser.replace(" ", "") adminuser = adminuser.replace(" ", "")
if not ( if not (
adminuser.startswith("fuid_") or adminuser.startswith("fusername_") or bumper.use_auth adminuser.startswith("fuid_")
or adminuser.startswith("fusername_")
or bumper.use_auth
): # if not fuid_ then its ecovacs OR ignore bumper auth ): # if not fuid_ then its ecovacs OR ignore bumper auth
# TODO: Implement auth later, should this user have access to bot? # TODO: Implement auth later, should this user have access to bot?
@ -345,7 +364,7 @@ class XMPPAsyncClient:
): ):
if not "@" in ctl_to: # No user@, send to all clients? if not "@" in ctl_to: # No user@, send to all clients?
# TODO: Revisit later, this may be wrong # TODO: Revisit later, this may be wrong
client.send(rxmlstring) client.send(rxmlstring)
elif ( elif (
client.uid.lower() in ctl_to.lower() client.uid.lower() in ctl_to.lower()
@ -381,15 +400,15 @@ class XMPPAsyncClient:
# Send STARTTLS to client with auth mechanisms # Send STARTTLS to client with auth mechanisms
if self.TLSUpgraded == False: if self.TLSUpgraded == False:
#With STARTTLS #https://xmpp.org/rfcs/rfc3920.html # With STARTTLS #https://xmpp.org/rfcs/rfc3920.html
self.send( self.send(
'<stream:features><starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls"><required/></starttls><auth xmlns="http://jabber.org/features/iq-auth"/><mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><mechanism>PLAIN</mechanism></mechanisms></stream:features>' '<stream:features><starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls"><required/></starttls><auth xmlns="http://jabber.org/features/iq-auth"/><mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><mechanism>PLAIN</mechanism></mechanisms></stream:features>'
) )
else: else:
# Already using TLS send authentication support for iq-auth (fallback) and SASL # Already using TLS send authentication support for iq-auth (fallback) and SASL
self.send( self.send(
'<stream:features><auth xmlns="http://jabber.org/features/iq-auth"/><mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><mechanism>PLAIN</mechanism></mechanisms></stream:features>' '<stream:features><auth xmlns="http://jabber.org/features/iq-auth"/><mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><mechanism>PLAIN</mechanism></mechanisms></stream:features>'
) )
else: else:
@ -435,13 +454,20 @@ class XMPPAsyncClient:
except Exception as e: except Exception as e:
xmppserverlog.exception("{}".format(e)) xmppserverlog.exception("{}".format(e))
async def _handle_starttls(self, data): async def _handle_starttls(self, data):
try: try:
if self.TLSUpgraded == False: if self.TLSUpgraded == False:
self.TLSUpgraded = True #Set TLSUpgraded true to prevent further attempts to upgrade connection self.TLSUpgraded = (
xmppserverlog.debug("Upgrading connection with STARTTLS for {}:{}".format(self.address[0],self.address[1])) True
self.send("<proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>") #send process to client ) # Set TLSUpgraded true to prevent further attempts to upgrade connection
xmppserverlog.debug(
"Upgrading connection with STARTTLS for {}:{}".format(
self.address[0], self.address[1]
)
)
self.send(
"<proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>"
) # send process to client
# After proceed the connection should be upgraded to TLS # After proceed the connection should be upgraded to TLS
loop = asyncio.get_event_loop() loop = asyncio.get_event_loop()
@ -452,14 +478,14 @@ class XMPPAsyncClient:
ssl_ctx.load_cert_chain(bumper.server_cert, bumper.server_key) ssl_ctx.load_cert_chain(bumper.server_cert, bumper.server_key)
ssl_ctx.load_verify_locations(cafile=bumper.ca_cert) ssl_ctx.load_verify_locations(cafile=bumper.ca_cert)
new_transport = await loop.start_tls(transport , protocol, ssl_ctx, server_side=True) new_transport = await loop.start_tls(
transport, protocol, ssl_ctx, server_side=True
)
protocol.connection_made(new_transport) protocol.connection_made(new_transport)
except Exception as e: except Exception as e:
xmppserverlog.exception("{}".format(e)) xmppserverlog.exception("{}".format(e))
def _handle_iq_auth(self, data): def _handle_iq_auth(self, data):
try: try:
xml = ET.fromstring(data.decode("utf-8")) xml = ET.fromstring(data.decode("utf-8"))
@ -500,7 +526,7 @@ class XMPPAsyncClient:
self.clientresource = aitem.text self.clientresource = aitem.text
resource = self.clientresource resource = self.clientresource
if self.devclass: # if there is a devclass it is a bot if self.devclass: # if there is a devclass it is a bot
bumper.bot_add("", self.uid, "", resource, "eco-legacy") bumper.bot_add("", self.uid, "", resource, "eco-legacy")
xmppserverlog.debug("bot authenticated {}".format(self.uid)) xmppserverlog.debug("bot authenticated {}".format(self.uid))
@ -525,9 +551,7 @@ class XMPPAsyncClient:
self._set_state("INIT") self._set_state("INIT")
# Successful auth # Successful auth
self.send( self.send('<iq type="result" id="{}"/>'.format(xml.get("id")))
'<iq type="result" id="{}"/>'.format(xml.get("id"))
)
else: else:
# Failed auth # Failed auth
@ -572,7 +596,7 @@ class XMPPAsyncClient:
if len(saslauth) > 2: if len(saslauth) > 2:
authcode = saslauth[2] authcode = saslauth[2]
if self.devclass: # if there is a devclass it is a bot if self.devclass: # if there is a devclass it is a bot
bumper.bot_add(self.uid, self.uid, self.devclass, "atom", "eco-legacy") bumper.bot_add(self.uid, self.uid, self.devclass, "atom", "eco-legacy")
self.type = self.BOT self.type = self.BOT
xmppserverlog.debug("bot authenticated {}".format(self.uid)) xmppserverlog.debug("bot authenticated {}".format(self.uid))
@ -631,7 +655,11 @@ class XMPPAsyncClient:
self.bumper_jid = "{}@{}.ecorobot.net/atom".format( self.bumper_jid = "{}@{}.ecorobot.net/atom".format(
self.uid, self.devclass self.uid, self.devclass
) )
xmppserverlog.debug("new bot ({}:{} | {})".format(self.address[0],self.address[1], self.bumper_jid)) xmppserverlog.debug(
"new bot ({}:{} | {})".format(
self.address[0], self.address[1], self.bumper_jid
)
)
res = '<iq type="result" id="{}"><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"><jid>{}</jid></bind></iq>'.format( res = '<iq type="result" id="{}"><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"><jid>{}</jid></bind></iq>'.format(
xml.get("id"), self.bumper_jid xml.get("id"), self.bumper_jid
) )
@ -641,14 +669,22 @@ class XMPPAsyncClient:
self.bumper_jid = "{}@{}/{}".format( self.bumper_jid = "{}@{}/{}".format(
self.uid, XMPPServer.server_id, self.clientresource self.uid, XMPPServer.server_id, self.clientresource
) )
xmppserverlog.debug("new client ({}:{} | {})".format(self.address[0],self.address[1], self.bumper_jid)) xmppserverlog.debug(
"new client ({}:{} | {})".format(
self.address[0], self.address[1], self.bumper_jid
)
)
res = '<iq type="result" id="{}"><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"><jid>{}</jid></bind></iq>'.format( res = '<iq type="result" id="{}"><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"><jid>{}</jid></bind></iq>'.format(
xml.get("id"), self.bumper_jid xml.get("id"), self.bumper_jid
) )
else: else:
self.name = "XMPP_Client_{}_{}".format(self.uid, self.address) self.name = "XMPP_Client_{}_{}".format(self.uid, self.address)
self.bumper_jid = "{}@{}".format(self.uid, XMPPServer.server_id) self.bumper_jid = "{}@{}".format(self.uid, XMPPServer.server_id)
xmppserverlog.debug("new client ({}:{} | {})".format(self.address[0],self.address[1], self.bumper_jid)) xmppserverlog.debug(
"new client ({}:{} | {})".format(
self.address[0], self.address[1], self.bumper_jid
)
)
res = '<iq type="result" id="{}"><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"><jid>{}</jid></bind></iq>'.format( res = '<iq type="result" id="{}"><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"><jid>{}</jid></bind></iq>'.format(
xml.get("id"), self.bumper_jid xml.get("id"), self.bumper_jid
) )
@ -666,7 +702,6 @@ class XMPPAsyncClient:
self.send(res) self.send(res)
asyncio.Task(self.schedule_ping(30)) asyncio.Task(self.schedule_ping(30))
except Exception as e: except Exception as e:
xmppserverlog.exception("{}".format(e)) xmppserverlog.exception("{}".format(e))
@ -675,7 +710,9 @@ class XMPPAsyncClient:
if len(xml) and xml[0].tag == "status": if len(xml) and xml[0].tag == "status":
xmppserverlog.debug( xmppserverlog.debug(
"bot presence {} ".format(ET.tostring(xml, encoding="utf-8").decode("utf-8")) "bot presence {} ".format(
ET.tostring(xml, encoding="utf-8").decode("utf-8")
)
) )
# Most likely a bot, possibly hello world in text # Most likely a bot, possibly hello world in text
@ -684,8 +721,6 @@ class XMPPAsyncClient:
'<presence to="{}"> dummy </presence>'.format(self.bumper_jid) '<presence to="{}"> dummy </presence>'.format(self.bumper_jid)
) )
# If it is a BOT, send extras # If it is a BOT, send extras
if self.type == self.BOT: if self.type == self.BOT:
# get device info # get device info
@ -695,17 +730,18 @@ class XMPPAsyncClient:
) )
) )
else: else:
xmppserverlog.debug( xmppserverlog.debug(
"client presence - {} ".format(ET.tostring(xml, encoding="utf-8").decode("utf-8")) "client presence - {} ".format(
ET.tostring(xml, encoding="utf-8").decode("utf-8")
)
) )
if xml.get("type") == "available": if xml.get("type") == "available":
xmppserverlog.debug( xmppserverlog.debug(
"client presence available - {} ".format( "client presence available - {} ".format(
ET.tostring(xml, encoding="utf-8").decode("utf-8")) ET.tostring(xml, encoding="utf-8").decode("utf-8")
)
) )
# Send dummy return # Send dummy return
@ -715,7 +751,8 @@ class XMPPAsyncClient:
elif xml.get("type") == "unavailable": elif xml.get("type") == "unavailable":
xmppserverlog.debug( xmppserverlog.debug(
"client presence unavailable (DISCONNECT) - {} ".format( "client presence unavailable (DISCONNECT) - {} ".format(
ET.tostring(xml, encoding="utf-8").decode("utf-8")) ET.tostring(xml, encoding="utf-8").decode("utf-8")
)
) )
self._set_state("DISCONNECT") self._set_state("DISCONNECT")
@ -756,7 +793,9 @@ class XMPPAsyncClient:
if self.log_incoming_data: if self.log_incoming_data:
xmppserverlog.debug( xmppserverlog.debug(
"from ({}:{} | {}) - {}".format( "from ({}:{} | {}) - {}".format(
self.address[0],self.address[1],self.bumper_jid, self.address[0],
self.address[1],
self.bumper_jid,
str( str(
ET.tostring(item, encoding="utf-8").decode( ET.tostring(item, encoding="utf-8").decode(
"utf-8" "utf-8"

View file

@ -6,7 +6,8 @@ import sys, socket
import time import time
import platform import platform
import os import os
#os.environ['PYTHONASYNCIODEBUG'] = '1' # Uncomment to enable ASYNCIODEBUG
# os.environ['PYTHONASYNCIODEBUG'] = '1' # Uncomment to enable ASYNCIODEBUG
import asyncio import asyncio
@ -25,8 +26,8 @@ async def main():
level=logging.DEBUG, level=logging.DEBUG,
format="[%(asctime)s] :: %(levelname)s :: %(name)s :: %(module)s :: %(funcName)s :: %(lineno)d :: %(message)s", format="[%(asctime)s] :: %(levelname)s :: %(name)s :: %(module)s :: %(funcName)s :: %(lineno)d :: %(message)s",
) )
loop.set_debug(True) # Set asyncio loop to debug loop.set_debug(True) # Set asyncio loop to debug
#logging.getLogger("asyncio").setLevel(logging.DEBUG) # Show debug asyncio logs (disabled in init, uncomment for debugging asyncio) # logging.getLogger("asyncio").setLevel(logging.DEBUG) # Show debug asyncio logs (disabled in init, uncomment for debugging asyncio)
else: else:
logging.basicConfig( logging.basicConfig(
level=logging.INFO, level=logging.INFO,
@ -47,9 +48,7 @@ async 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_server = bumper.XMPPServer(xmpp_address)
xmpp_address
)
mqtt_server = bumper.MQTTServer(mqtt_address) mqtt_server = bumper.MQTTServer(mqtt_address)
mqtt_helperbot = bumper.MQTTHelperBot(mqtt_address) mqtt_helperbot = bumper.MQTTHelperBot(mqtt_address)
conf_server = bumper.ConfServer( conf_server = bumper.ConfServer(
@ -78,7 +77,7 @@ async def main():
asyncio.create_task(xmpp_server.start_async_server()) asyncio.create_task(xmpp_server.start_async_server())
maintain = asyncio.create_task(maintenance_tasks()) maintain = asyncio.create_task(maintenance_tasks())
await maintain #Keeps the loop running until this exits await maintain # Keeps the loop running until this exits
finally: finally:
# Cleanup and close tasks/loop # Cleanup and close tasks/loop
@ -86,9 +85,10 @@ async def main():
task.cancel() task.cancel()
loop.close() loop.close()
async def maintenance_tasks(): async def maintenance_tasks():
while True: while True:
await asyncio.sleep(30) # Sleep 30 seconds await asyncio.sleep(30) # Sleep 30 seconds
bumper.revoke_expired_tokens() bumper.revoke_expired_tokens()
@ -101,4 +101,3 @@ if __name__ == "__main__":
pass pass
finally: finally:
bumper.bumperlog.info("Bumper Exiting!") bumper.bumperlog.info("Bumper Exiting!")

View file

@ -181,4 +181,7 @@ def test_client_db():
assert_false( assert_false(
bumper.client_get("resource_123")["xmpp_connection"] bumper.client_get("resource_123")["xmpp_connection"]
) # Test that xmpp was set False for client ) # Test that xmpp was set False for client
assert_equals(len(bumper.get_disconnected_xmpp_clients()), 1) # Test len of connected xmpp clients is 1 assert_equals(
len(bumper.get_disconnected_xmpp_clients()), 1
) # Test len of connected xmpp clients is 1

View file

@ -12,13 +12,14 @@ confserver = bumper.ConfServer("127.0.0.1:11111", False, mock.MagicMock)
confserver.confserver_app() confserver.confserver_app()
app = confserver.app app = confserver.app
def async_return(result): def async_return(result):
f = asyncio.Future() f = asyncio.Future()
f.set_result(result) f.set_result(result)
return f return f
def test_disconnect():
def test_disconnect():
async def test_disconnect_async(): async def test_disconnect_async():
await confserver.disconnect() await confserver.disconnect()
@ -513,6 +514,7 @@ def test_postLookup():
client.close() client.close()
) # Close test server after all tests are done ) # Close test server after all tests are done
def test_devmgr(): def test_devmgr():
if os.path.exists("tests/tmp.db"): if os.path.exists("tests/tmp.db"):
os.remove("tests/tmp.db") # Remove existing db os.remove("tests/tmp.db") # Remove existing db
@ -551,20 +553,30 @@ def test_devmgr():
postbody = {"toId": "did_1234"} postbody = {"toId": "did_1234"}
# Test return get status # Test return get status
command_getstatus_resp = { "id": "resp_1234", "resp": "<ctl ret='ok' status='idle'/>", "ret": "ok" } command_getstatus_resp = {
confserver.helperbot.send_command = mock.MagicMock(return_value=async_return(command_getstatus_resp)) "id": "resp_1234",
"resp": "<ctl ret='ok' status='idle'/>",
"ret": "ok",
}
confserver.helperbot.send_command = mock.MagicMock(
return_value=async_return(command_getstatus_resp)
)
# Test # Test
loop.run_until_complete(test_devmanager(postbody, command=True)) loop.run_until_complete(test_devmanager(postbody, command=True))
# Test return fail timeout # Test return fail timeout
command_timeout_resp = {"id": "resp_1234", "errno": "timeout", "ret": "fail"} command_timeout_resp = {"id": "resp_1234", "errno": "timeout", "ret": "fail"}
confserver.helperbot.send_command = mock.MagicMock(return_value=async_return(command_timeout_resp)) confserver.helperbot.send_command = mock.MagicMock(
return_value=async_return(command_timeout_resp)
)
# Test # Test
loop.run_until_complete(test_devmanager(postbody, command=True)) loop.run_until_complete(test_devmanager(postbody, command=True))
# Set bot not on mqtt # Set bot not on mqtt
bumper.bot_set_mqtt("did_1234", False) bumper.bot_set_mqtt("did_1234", False)
confserver.helperbot.send_command = mock.MagicMock(return_value=async_return(command_getstatus_resp)) confserver.helperbot.send_command = mock.MagicMock(
return_value=async_return(command_getstatus_resp)
)
# Test # Test
loop.run_until_complete(test_devmanager(postbody, command=True)) loop.run_until_complete(test_devmanager(postbody, command=True))