diff --git a/bumper/__init__.py b/bumper/__init__.py
index f9eb47a..f379e97 100644
--- a/bumper/__init__.py
+++ b/bumper/__init__.py
@@ -3,14 +3,12 @@
from bumper.confserver import ConfServer
from bumper.mqttserver import MQTTServer, MQTTHelperBot
from bumper.xmppserver import XMPPServer
+from bumper.models import *
+from bumper.db import *
import asyncio
-import json
-from datetime import datetime, timedelta
import os
import logging
from logging.handlers import RotatingFileHandler
-from tinydb import TinyDB, Query
-from tinydb.storages import MemoryStorage
import socket
import sys
@@ -100,6 +98,15 @@ helperbotlog.addHandler(helperbot_rotate)
# Override the logging level
# helperbotlog.setLevel(logging.INFO)
+boterrorlog = logging.getLogger("boterror")
+boterrorlog_rotate = RotatingFileHandler(
+ "logs/boterror.log", maxBytes=5000000, backupCount=5
+)
+boterrorlog_rotate.setFormatter(logformat)
+boterrorlog.addHandler(boterrorlog_rotate)
+# Override the logging level
+# boterrorlog.setLevel(logging.INFO)
+
xmppserverlog = logging.getLogger("xmppserver")
xmpp_rotate = RotatingFileHandler(
"logs/xmppserver.log", maxBytes=5000000, backupCount=5
@@ -156,23 +163,12 @@ async def start():
global mqtt_helperbot
mqtt_helperbot = MQTTHelperBot((bumper_listen, mqtt_listen_port))
global conf_server
- conf_server = ConfServer(
- (bumper_listen, conf1_listen_port), usessl=True, helperbot=mqtt_helperbot
- )
+ conf_server = ConfServer((bumper_listen, conf1_listen_port), usessl=True)
global conf_server_2
- conf_server_2 = ConfServer(
- (bumper_listen, conf2_listen_port), usessl=False, helperbot=mqtt_helperbot
- )
+ conf_server_2 = ConfServer((bumper_listen, conf2_listen_port), usessl=False)
global xmpp_server
xmpp_server = XMPPServer((bumper_listen, xmpp_listen_port))
- # Start web servers
- conf_server.confserver_app()
- asyncio.create_task(conf_server.start_server())
-
- conf_server_2.confserver_app()
- asyncio.create_task(conf_server_2.start_server())
-
# Start MQTT Server
asyncio.create_task(mqtt_server.broker_coro())
@@ -182,6 +178,20 @@ async def start():
# Start XMPP Server
asyncio.create_task(xmpp_server.start_async_server())
+ # Wait for helperbot to connect first
+ while mqtt_helperbot.Client is None:
+ await asyncio.sleep(0.1)
+
+ while not mqtt_helperbot.Client.session.transitions.state == "connected":
+ await asyncio.sleep(0.1)
+
+ # Start web servers
+ conf_server.confserver_app()
+ asyncio.create_task(conf_server.start_server())
+
+ conf_server_2.confserver_app()
+ asyncio.create_task(conf_server_2.start_server())
+
# Start maintenance
while not shutting_down:
asyncio.create_task(maintenance())
@@ -223,724 +233,6 @@ async def shutdown():
bumperlog.info("Shutdown complete")
-def get_milli_time(timetoconvert):
- return int(round(timetoconvert * 1000))
-
-
-def db_file():
- if db:
- return db
-
- return os_db_path()
-
-
-def os_db_path(): # createdir=True):
- return os.path.join(data_dir, "bumper.db")
-
-
-def db_get():
- try:
- # Will create the database if it doesn't exist
- db = TinyDB(db_file())
-
- # Will create the tables if they don't exist
- db.table("users", cache_size=0)
- db.table("clients", cache_size=0)
- db.table("bots", cache_size=0)
- db.table("tokens", cache_size=0)
-
- return db
-
- except json.decoder.JSONDecodeError as jerr:
- bumperlog.error("JsonErr: {} - Doc: {}".format(jerr.msg, jerr.doc))
-
- except Exception as ex:
- bumperlog.error(ex)
-
-
-class BumperUser(object):
- def __init__(self, userid=""):
- self.userid = userid
- self.devices = []
- self.bots = []
-
- def asdict(self):
- return {"userid": self.userid, "devices": self.devices, "bots": self.bots}
-
-
-def user_add(userid):
- newuser = BumperUser()
- newuser.userid = userid
-
- user = user_get(userid)
- if not user:
- bumperlog.info("Adding new user with userid: {}".format(newuser.userid))
- user_full_upsert(newuser.asdict())
-
-
-def user_get(userid):
- users = db_get().table("users")
- User = Query()
- return users.get(User.userid == userid)
-
-
-def user_by_deviceid(deviceid):
- users = db_get().table("users")
- User = Query()
- return users.get(User.devices.any([deviceid]))
-
-
-def user_full_upsert(user):
- users = db_get().table("users")
- User = Query()
- users.upsert(user, User.did == user["userid"])
-
-
-def user_add_device(userid, devid):
- users = db_get().table("users")
- User = Query()
- user = users.get(User.userid == userid)
- userdevices = list(user["devices"])
- if not devid in userdevices:
- userdevices.append(devid)
-
- users.upsert({"devices": userdevices}, User.userid == userid)
-
-
-def user_remove_device(userid, devid):
- users = db_get().table("users")
- User = Query()
- user = users.get(User.userid == userid)
- userdevices = list(user["devices"])
- if devid in userdevices:
- userdevices.remove(devid)
-
- users.upsert({"devices": userdevices}, User.userid == userid)
-
-
-def user_add_bot(userid, did):
- users = db_get().table("users")
- User = Query()
- user = users.get(User.userid == userid)
- userbots = list(user["bots"])
- if not did in userbots:
- userbots.append(did)
-
- users.upsert({"bots": userbots}, User.userid == userid)
-
-
-def user_remove_bot(userid, did):
- users = db_get().table("users")
- User = Query()
- user = users.get(User.userid == userid)
- userbots = list(user["bots"])
- if did in userbots:
- userbots.remove(did)
-
- users.upsert({"bots": userbots}, User.userid == userid)
-
-
-def user_get_tokens(userid):
- tokens = db_get().table("tokens")
- return tokens.search((Query().userid == userid))
-
-
-def user_get_token(userid, token):
- tokens = db_get().table("tokens")
- return tokens.get((Query().userid == userid) & (Query().token == token))
-
-
-def user_add_token(userid, token):
- tokens = db_get().table("tokens")
- tmptoken = tokens.get((Query().userid == userid) & (Query().token == token))
- if not tmptoken:
- bumperlog.debug("Adding token {} for userid {}".format(token, userid))
- tokens.insert(
- {
- "userid": userid,
- "token": token,
- "expiration": "{}".format(
- datetime.now() + timedelta(seconds=token_validity_seconds)
- ),
- }
- )
-
-
-def user_revoke_all_tokens(userid):
- tokens = db_get().table("tokens")
- tsearch = tokens.search(Query().userid == userid)
- for i in tsearch:
- tokens.remove(doc_ids=[i.doc_id])
-
-
-def user_revoke_expired_tokens(userid):
- tokens = db_get().table("tokens")
- tsearch = tokens.search(Query().userid == userid)
- for i in tsearch:
- if datetime.now() >= datetime.fromisoformat(i["expiration"]):
- bumperlog.debug("Removing token {} due to expiration".format(i["token"]))
- tokens.remove(doc_ids=[i.doc_id])
-
-
-def user_revoke_token(userid, token):
- tokens = db_get().table("tokens")
- tmptoken = tokens.get((Query().userid == userid) & (Query().token == token))
- if tmptoken:
- tokens.remove(doc_ids=[tmptoken.doc_id])
-
-
-def user_add_authcode(userid, token, authcode):
- tokens = db_get().table("tokens")
- tmptoken = tokens.get((Query().userid == userid) & (Query().token == token))
- if tmptoken:
- tokens.upsert(
- {"authcode": authcode},
- ((Query().userid == userid) & (Query().token == token)),
- )
-
-
-def user_revoke_authcode(userid, token, authcode):
- tokens = db_get().table("tokens")
- tmptoken = tokens.get((Query().userid == userid) & (Query().token == token))
- if tmptoken:
- tokens.upsert(
- {"authcode": ""}, ((Query().userid == userid) & (Query().token == token))
- )
-
-
-class VacBotDevice(object):
- def __init__(
- self, did="", vac_bot_device_class="", resource="", name="", nick="", company=""
- ):
- self.vac_bot_device_class = vac_bot_device_class
- self.company = company
- self.did = did
- self.name = name
- self.nick = nick
- self.resource = resource
- self.mqtt_connection = False
- self.xmpp_connection = False
-
- def asdict(self):
- return {
- "class": self.vac_bot_device_class,
- "company": self.company,
- "did": self.did,
- "name": self.name,
- "nick": self.nick,
- "resource": self.resource,
- "mqtt_connection": self.mqtt_connection,
- "xmpp_connection": self.xmpp_connection,
- }
-
-
-class GlobalVacBotDevice(VacBotDevice): # EcoVacs Home
- UILogicId = ""
- ota = True
- updateInfo = {"changeLog": "", "needUpdate": False}
- icon = ""
- deviceName = ""
-
-
-# EcoVacs Home Product IOT Map - 2019-05-20
-# https://portal-ww.ecouser.net/api/pim/product/getProductIotMap
-EcoVacsHomeProducts = [
- {
- "classid": "dl8fht",
- "product": {
- "UILogicId": "D_600",
- "_id": "5acb0fa87c295c0001876ecf",
- "icon": "5acc32067c295c0001876eea",
- "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5acc32067c295c0001876eea",
- "materialNo": "702-0000-0170",
- "name": "DEEBOT 600 Series",
- "ota": False,
- "supportType": {
- "alexa": True,
- "assistant": True,
- "share": True,
- "tmjl": False,
- },
- },
- },
- {
- "classid": "02uwxm",
- "product": {
- "UILogicId": "D_OZMO_SLIM10",
- "_id": "5ae1481e7ccd1a0001e1f69e",
- "icon": "5b1dddc48bc45700014035a1",
- "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5b1dddc48bc45700014035a1",
- "materialNo": "110-1715-0201",
- "name": "DEEBOT OZMO Slim10 Series",
- "ota": False,
- "supportType": {
- "alexa": True,
- "assistant": True,
- "share": True,
- "tmjl": False,
- },
- },
- },
- {
- "classid": "y79a7u",
- "product": {
- "UILogicId": "D_OZMO_900",
- "_id": "5b04c0227ccd1a0001e1f6a8",
- "icon": "5b04c0217ccd1a0001e1f6a7",
- "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5b04c0217ccd1a0001e1f6a7",
- "materialNo": "110-1810-0101",
- "name": "DEEBOT OZMO 900 Series",
- "ota": True,
- "supportType": {
- "alexa": True,
- "assistant": True,
- "share": True,
- "tmjl": False,
- },
- },
- },
- {
- "classid": "jr3pqa",
- "product": {
- "UILogicId": "D_700",
- "_id": "5b43077b8bc457000140363e",
- "icon": "5b5ac4cc8d5a56000111e769",
- "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5b5ac4cc8d5a56000111e769",
- "materialNo": "702-0000-0202",
- "name": "DEEBOT 711",
- "ota": True,
- "supportType": {
- "alexa": True,
- "assistant": True,
- "share": True,
- "tmjl": False,
- },
- },
- },
- {
- "classid": "uv242z",
- "product": {
- "UILogicId": "D_700",
- "_id": "5b5149b4ac0b87000148c128",
- "icon": "5b5ac4e45f21100001882bb9",
- "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5b5ac4e45f21100001882bb9",
- "materialNo": "702-0000-0205",
- "name": "DEEBOT 710",
- "ota": True,
- "supportType": {
- "alexa": True,
- "assistant": True,
- "share": True,
- "tmjl": False,
- },
- },
- },
- {
- "classid": "ls1ok3",
- "product": {
- "UILogicId": "D_900",
- "_id": "5b6561060506b100015c8868",
- "icon": "5ba4a2cb6c2f120001c32839",
- "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5ba4a2cb6c2f120001c32839",
- "materialNo": "110-1711-0201",
- "name": "DEEBOT 900 Series",
- "ota": True,
- "supportType": {
- "alexa": True,
- "assistant": True,
- "share": True,
- "tmjl": False,
- },
- },
- },
- {
- "classid": "eyi9jv",
- "product": {
- "UILogicId": "D_700",
- "_id": "5b7b65f364e1680001a08b54",
- "icon": "5b7b65f176f7f10001e9a0c2",
- "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5b7b65f176f7f10001e9a0c2",
- "materialNo": "715",
- "name": "DEEBOT 715",
- "ota": True,
- "supportType": {
- "alexa": True,
- "assistant": True,
- "share": True,
- "tmjl": False,
- },
- },
- },
- {
- "classid": "4zfacv",
- "product": {
- "UILogicId": "DN_2G",
- "_id": "5bf2596f23244a00013f2f13",
- "icon": "5c778731280fda0001770ba0",
- "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5c778731280fda0001770ba0",
- "materialNo": "910",
- "name": "DEEBOT 910",
- "ota": True,
- "supportType": {
- "alexa": True,
- "assistant": True,
- "share": True,
- "tmjl": False,
- },
- },
- },
- {
- "classid": "vi829v",
- "product": {
- "UILogicId": "DX_5G",
- "_id": "5c19a8f3a1e6ee0001782247",
- "icon": "5c9c7995e9e9270001354ab4",
- "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5c9c7995e9e9270001354ab4",
- "materialNo": "920",
- "name": "DEEBOT OZMO 920 Series",
- "ota": True,
- "supportType": {
- "alexa": True,
- "assistant": True,
- "share": True,
- "tmjl": False,
- },
- },
- },
- {
- "classid": "gd4uut",
- "product": {
- "UILogicId": "DR_935G",
- "_id": "5bc8189d68142800016a6937",
- "icon": "5c7384767b93c700013f12e7",
- "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5c7384767b93c700013f12e7",
- "materialNo": "960",
- "name": "DEEBOT OZMO 960",
- "ota": True,
- "supportType": {
- "alexa": True,
- "assistant": True,
- "share": False,
- "tmjl": False,
- },
- },
- },
- {
- "classid": "9akc61",
- "product": {
- "UILogicId": "D_500",
- "_id": "5c763f8263023c0001e7f855",
- "icon": "5c932067280fda0001770d7f",
- "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5c932067280fda0001770d7f",
- "materialNo": "D505",
- "name": "DEEBOT 505",
- "ota": False,
- "supportType": {
- "alexa": True,
- "assistant": True,
- "share": True,
- "tmjl": False,
- },
- },
- },
- {
- "classid": "r8ead0",
- "product": {
- "UILogicId": "D_500",
- "_id": "5c763f63280fda0001770b88",
- "icon": "5c93204b63023c0001e7faa7",
- "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5c93204b63023c0001e7faa7",
- "materialNo": "D502",
- "name": "DEEBOT 502",
- "ota": False,
- "supportType": {
- "alexa": True,
- "assistant": True,
- "share": True,
- "tmjl": False,
- },
- },
- },
- {
- "classid": "emzppx",
- "product": {
- "UILogicId": "D_500",
- "_id": "5c763f35280fda0001770b84",
- "icon": "5c931fef280fda0001770d7e",
- "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5c931fef280fda0001770d7e",
- "materialNo": "D501",
- "name": "DEEBOT 501",
- "ota": False,
- "supportType": {
- "alexa": True,
- "assistant": True,
- "share": True,
- "tmjl": False,
- },
- },
- },
- {
- "classid": "vsc5ia",
- "product": {
- "UILogicId": "D_500",
- "_id": "5c763eba280fda0001770b81",
- "icon": "5c874326280fda0001770d2a",
- "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5c874326280fda0001770d2a",
- "materialNo": "D500",
- "name": "DEEBOT 500",
- "ota": False,
- "supportType": {
- "alexa": True,
- "assistant": True,
- "share": True,
- "tmjl": False,
- },
- },
- },
- {
- "classid": "aqdd5p",
- "product": {
- "UILogicId": "D_900",
- "_id": "5cb7cfba179839000114d762",
- "icon": "5cb7cfbab72c4d00010e5fc7",
- "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5cb7cfbab72c4d00010e5fc7",
- "materialNo": "110-1711-0001",
- "name": "DEEBOT DE55",
- "ota": True,
- "supportType": {
- "alexa": False,
- "assistant": False,
- "share": False,
- "tmjl": False,
- },
- },
- },
-]
-
-
-class VacBotClient(object):
- def __init__(self, userid="", realm="", token=""):
- self.userid = userid
- self.realm = realm
- self.resource = token
- self.mqtt_connection = False
- self.xmpp_connection = False
-
- def asdict(self):
- return {
- "userid": self.userid,
- "realm": self.realm,
- "resource": self.resource,
- "mqtt_connection": self.mqtt_connection,
- "xmpp_connection": self.xmpp_connection,
- }
-
-
-def get_disconnected_xmpp_clients():
- clients = db_get().table("clients")
- Client = Query()
- return clients.search(Client.xmpp_connection == False)
-
-
-def check_authcode(uid, authcode):
- bumperlog.debug("Checking for authcode: {}".format(authcode))
- tokens = db_get().table("tokens")
- tmpauth = tokens.get(
- (Query().authcode == authcode)
- & ( # Match authcode
- (Query().userid == uid.replace("fuid_", ""))
- | (Query().userid == "fuid_{}".format(uid))
- ) # Userid with or without fuid_
- )
- if tmpauth:
- return True
-
- return False
-
-
-def loginByItToken(authcode):
- bumperlog.debug("Checking for authcode: {}".format(authcode))
- tokens = db_get().table("tokens")
- tmpauth = tokens.get(
- (Query().authcode == authcode)
- # & ( # Match authcode
- # (Query().userid == uid.replace("fuid_", ""))
- # | (Query().userid == "fuid_{}".format(uid))
- # ) # Userid with or without fuid_
- )
- if tmpauth:
- return {"token": tmpauth["token"], "userid": tmpauth["userid"]}
-
- return {}
-
-
-def check_token(uid, token):
- bumperlog.debug("Checking for token: {}".format(token))
- tokens = db_get().table("tokens")
- tmpauth = tokens.get(
- (Query().token == token)
- & ( # Match token
- (Query().userid == uid.replace("fuid_", ""))
- | (Query().userid == "fuid_{}".format(uid))
- ) # Userid with or without fuid_
- )
- if tmpauth:
- return True
-
- return False
-
-
-def revoke_expired_tokens():
- tokens = db_get().table("tokens").all()
- for i in tokens:
- if datetime.now() >= datetime.fromisoformat(i["expiration"]):
- bumperlog.debug("Removing token {} due to expiration".format(i["token"]))
- db_get().table("tokens").remove(doc_ids=[i.doc_id])
-
-
-def bot_add(sn, did, devclass, resource, company):
- newbot = VacBotDevice()
- newbot.did = did
- newbot.name = sn
- newbot.vac_bot_device_class = devclass
- newbot.resource = resource
- newbot.company = company
-
- bot = bot_get(did)
- 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
- bumperlog.info(
- "Adding new bot with SN: {} DID: {}".format(newbot.name, newbot.did)
- )
- bot_full_upsert(newbot.asdict())
-
-
-def bot_remove(did):
- bots = db_get().table("bots")
- bot = bot_get(did)
- bots.remove(doc_ids=[bot.doc_id])
-
-
-def bot_get(did):
- bots = db_get().table("bots")
- Bot = Query()
- return bots.get(Bot.did == did)
-
-
-def bot_toEcoVacsHome_JSON(bot): # EcoVacs Home
- for botprod in EcoVacsHomeProducts:
- if botprod["classid"] == bot["class"]:
- bot["UILogicId"] = botprod["product"]["UILogicId"]
- bot["ota"] = botprod["product"]["ota"]
- bot["icon"] = botprod["product"]["iconUrl"]
- return json.dumps(
- bot, default=lambda o: o.__dict__, sort_keys=False
- ) # , indent=4)
-
-
-def bot_full_upsert(vacbot):
- bots = db_get().table("bots")
- Bot = Query()
- bots.upsert(vacbot, Bot.did == vacbot["did"])
-
-
-def bot_set_nick(did, nick):
- bots = db_get().table("bots")
- Bot = Query()
- bots.upsert({"nick": nick}, Bot.did == did)
-
-
-def bot_set_mqtt(did, mqtt):
- bots = db_get().table("bots")
- Bot = Query()
- bots.upsert({"mqtt_connection": mqtt}, Bot.did == did)
-
-
-def bot_set_xmpp(did, xmpp):
- bots = db_get().table("bots")
- Bot = Query()
- bots.upsert({"xmpp_connection": xmpp}, Bot.did == did)
-
-
-def client_add(userid, realm, resource):
- newclient = VacBotClient()
- newclient.userid = userid
- newclient.realm = realm
- newclient.resource = resource
-
- client = client_get(resource)
- if not client:
- bumperlog.info("Adding new client with resource {}".format(newclient.resource))
- client_full_upsert(newclient.asdict())
-
-
-def client_get(resource):
- clients = db_get().table("clients")
- Client = Query()
- return clients.get(Client.resource == resource)
-
-
-def client_full_upsert(client):
- clients = db_get().table("clients")
- Client = Query()
- clients.upsert(client, Client.resource == client["resource"])
-
-
-def client_set_mqtt(resource, mqtt):
- clients = db_get().table("clients")
- Client = Query()
- clients.upsert({"mqtt_connection": mqtt}, Client.resource == resource)
-
-
-def client_set_xmpp(resource, xmpp):
- clients = db_get().table("clients")
- Client = Query()
- clients.upsert({"xmpp_connection": xmpp}, Client.resource == resource)
-
-
-RETURN_API_SUCCESS = "0000"
-ERR_ACTIVATE_TOKEN_TIMEOUT = "1006"
-ERR_COMMON = "0001"
-ERR_DEFAULT = "9000"
-ERR_EMAIL_NON_EXIST = "1002"
-ERR_EMAIL_SEND_TIME_LIMIT = "1011"
-ERR_EMAIL_USED = "1001"
-ERR_INTERFACE_AUTH = "0002"
-ERR_PARAM_INVALID = "0003"
-ERR_PWD_WRONG = "1005"
-ERR_RESET_PWD_TOKEN_TIMEOUT = "1007"
-ERR_TIMESTAMP_INVALID = "0005"
-ERR_TOKEN_INVALID = "0004"
-ERR_USER_DISABLE = "1004"
-ERR_USER_NOT_ACTIVATED = "1003"
-ERR_WRONG_COMFIRM_PWD = "10010"
-ERR_WRONG_EMAIL_ADDRESS = "1008"
-ERR_WRONG_PWD_FROMATE = "1009"
-
-API_ERRORS = {
- RETURN_API_SUCCESS: "0000",
- ERR_ACTIVATE_TOKEN_TIMEOUT: "1006",
- ERR_COMMON: "0001",
- ERR_DEFAULT: "9000",
- ERR_EMAIL_NON_EXIST: "1002",
- ERR_EMAIL_SEND_TIME_LIMIT: "1011",
- ERR_EMAIL_USED: "1001",
- ERR_INTERFACE_AUTH: "0002",
- ERR_PARAM_INVALID: "0003",
- ERR_PWD_WRONG: "1005",
- ERR_RESET_PWD_TOKEN_TIMEOUT: "1007",
- ERR_TIMESTAMP_INVALID: "0005",
- ERR_TOKEN_INVALID: "0004",
- ERR_USER_DISABLE: "1004",
- ERR_USER_NOT_ACTIVATED: "1003",
- ERR_WRONG_COMFIRM_PWD: "10010",
- ERR_WRONG_EMAIL_ADDRESS: "1008",
- ERR_WRONG_PWD_FROMATE: "1009",
-}
-
-
def create_certs():
import platform
import os
@@ -978,7 +270,7 @@ def create_certs():
print("Certificates created")
os.chdir(odir)
-
+
if "__main__.py" in sys.argv[0]:
os.execv(
sys.executable, ["python", "-m", "bumper"] + sys.argv[1:]
@@ -991,6 +283,7 @@ def create_certs():
def first_run():
create_certs()
+
def main(argv=None):
import argparse
diff --git a/bumper/confserver.py b/bumper/confserver.py
index afc9fe1..be64d59 100644
--- a/bumper/confserver.py
+++ b/bumper/confserver.py
@@ -6,6 +6,7 @@ import ssl
import string
import random
import bumper
+from bumper.models import *
from datetime import datetime, timedelta
import asyncio
from aiohttp import web
@@ -36,42 +37,24 @@ logging.getLogger("aiohttp.access").addFilter(
) # Add logging filter above to aiohttp.access
-class EcoVacs_Login:
- accessToken = ""
- country = ""
- email = ""
- uid = ""
- username = ""
-
- def toJSON(self):
- return json.dumps(
- self, default=lambda o: o.__dict__, sort_keys=False
- ) # , indent=4)
-
-
-class EcoVacsHome_Login(EcoVacs_Login):
- loginName = ""
- mobile = ""
- ucUid = ""
-
-
class ConfServer:
- def __init__(self, address, usessl=False, helperbot=None):
- self.helperbot = helperbot
+ def __init__(self, address, usessl=False):
self.usessl = usessl
self.address = address
- self.confthread = None
- self.run_async = False
self.app = None
self.site = None
self.runner = None
+ def get_milli_time(self, timetoconvert):
+ return int(round(timetoconvert * 1000))
+
def confserver_app(self):
self.app = web.Application(loop=asyncio.get_event_loop())
self.app.add_routes(
[
web.get("", self.handle_base),
+ web.get("/restart_{service}", self.handle_RestartService),
web.get(
"/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/login",
self.handle_login,
@@ -190,9 +173,9 @@ class ConfServer:
await self.site.start()
except PermissionError as e:
- confserverlog.error(e.strerror)
+ confserverlog.error(e.strerror)
asyncio.create_task(bumper.shutdown())
-
+
except asyncio.CancelledError:
pass
@@ -202,7 +185,7 @@ class ConfServer:
async def stop_server(self):
try:
- await self.runner.shutdown()
+ await self.runner.shutdown()
except Exception as e:
confserverlog.exception("{}".format(e))
@@ -210,9 +193,82 @@ class ConfServer:
async def handle_base(self, request):
try:
# TODO - API Options here for viewing clients, tokens, restarting the server, etc.
- text = "Bumper!"
+ # text = "Bumper!"
+ bots = bumper.db_get().table("bots").all()
+ clients = bumper.db_get().table("clients").all()
+ helperbot = bumper.mqtt_helperbot.Client.session.transitions.state
+ mqttserver = bumper.mqtt_server.broker
+ mq_sessions = []
+ for sess in mqttserver._sessions:
+ tmpsess = []
+ tmpsess.append({"client_id": mqttserver._sessions[sess][0].client_id})
+ tmpsess.append(
+ {"state": mqttserver._sessions[sess][0].transitions.state}
+ )
+ mq_sessions.append(tmpsess)
+ all = {
+ "bots": bots,
+ "clients": clients,
+ "helperbot": [{"state": helperbot}],
+ "mqtt_server": [
+ {"state": mqttserver.transitions.state},
+ {
+ "sessions": [
+ {"count": len(mqttserver._sessions)},
+ {"clients": mq_sessions},
+ ]
+ },
+ ],
+ }
- return web.json_response(text)
+ return web.json_response(all)
+
+ except Exception as e:
+ confserverlog.exception("{}".format(e))
+
+ async def restart_Helper(self):
+
+ await bumper.mqtt_helperbot.Client.disconnect()
+ await bumper.mqtt_helperbot.start_helper_bot()
+
+ async def restart_MQTT(self):
+ mqttserver = bumper.mqtt_server.broker
+
+ for sess in list(mqttserver._sessions):
+ sessobj = mqttserver._sessions[sess][1]
+ await sessobj.writer.close()
+ mqttserver.delete_session(sess)
+
+ await bumper.mqtt_server.broker.shutdown()
+ while not bumper.mqtt_server.broker.transitions.state == "stopped":
+ await asyncio.sleep(0.1)
+
+ await bumper.mqtt_server.broker_coro()
+ while not bumper.mqtt_server.broker.transitions.state == "started":
+ await asyncio.sleep(0.1)
+
+ async def restart_XMPP(self):
+ bumper.xmpp_server.disconnect()
+ await bumper.xmpp_server.start_async_server()
+
+ async def handle_RestartService(self, request):
+ try:
+ service = request.match_info.get("service", "")
+ if service == "Helperbot":
+ await self.restart_Helper()
+ return web.json_response({"status": "complete"})
+ elif service == "MQTTServer":
+ await self.restart_MQTT()
+ aloop = asyncio.get_event_loop()
+ aloop.call_later(
+ 2, lambda: asyncio.create_task(self.restart_Helper())
+ ) # In 2 seconds restart Helperbot
+ return web.json_response({"status": "complete"})
+ elif service == "XMPPServer":
+ await self.restart_XMPP()
+ return web.json_response({"status": "complete"})
+ else:
+ return web.json_response({"status": "invalid service"})
except Exception as e:
confserverlog.exception("{}".format(e))
@@ -256,7 +312,7 @@ class ConfServer:
login_details.email = "null@null.com"
body = {
- "code": bumper.RETURN_API_SUCCESS,
+ "code": API_ERRORS[RETURN_API_SUCCESS],
"data": json.loads(login_details.toJSON()),
# {
# "accessToken": self.generate_token(tmpuser), # Generate a token
@@ -266,9 +322,7 @@ class ConfServer:
# "username": "fusername_{}".format(tmpuser["userid"]),
# },
"msg": "操作成功",
- "time": bumper.get_milli_time(
- datetime.utcnow().timestamp()
- ),
+ "time": self.get_milli_time(datetime.utcnow().timestamp()),
}
return web.json_response(body)
@@ -277,7 +331,7 @@ class ConfServer:
"code": bumper.ERR_USER_NOT_ACTIVATED,
"data": None,
"msg": "当前密码错误",
- "time": bumper.get_milli_time(datetime.utcnow().timestamp()),
+ "time": self.get_milli_time(datetime.utcnow().timestamp()),
}
return web.json_response(body)
@@ -323,7 +377,7 @@ class ConfServer:
"loginName": login_details.loginName,
},
"msg": "操作成功",
- "time": bumper.get_milli_time(datetime.utcnow().timestamp()),
+ "time": self.get_milli_time(datetime.utcnow().timestamp()),
}
return web.json_response(body)
@@ -359,7 +413,7 @@ class ConfServer:
# "username": "fusername_{}".format(tmpuser["userid"]),
# },
"msg": "操作成功",
- "time": bumper.get_milli_time(datetime.utcnow().timestamp()),
+ "time": self.get_milli_time(datetime.utcnow().timestamp()),
}
return web.json_response(body)
@@ -368,7 +422,7 @@ class ConfServer:
"code": bumper.ERR_TOKEN_INVALID,
"data": None,
"msg": "当前密码错误",
- "time": bumper.get_milli_time(datetime.utcnow().timestamp()),
+ "time": self.get_milli_time(datetime.utcnow().timestamp()),
}
return web.json_response(body)
@@ -459,7 +513,7 @@ class ConfServer:
# "username": "fusername_{}".format(tmpuser["userid"]),
# },
"msg": "操作成功",
- "time": bumper.get_milli_time(datetime.utcnow().timestamp()),
+ "time": self.get_milli_time(datetime.utcnow().timestamp()),
}
return body
@@ -483,7 +537,7 @@ class ConfServer:
"code": bumper.RETURN_API_SUCCESS,
"data": None,
"msg": "操作成功",
- "time": bumper.get_milli_time(datetime.utcnow().timestamp()),
+ "time": self.get_milli_time(datetime.utcnow().timestamp()),
}
return web.json_response(body)
@@ -525,7 +579,7 @@ class ConfServer:
},
"msg": "操作成功",
"success": True,
- "time": bumper.get_milli_time(
+ "time": self.get_milli_time(
datetime.utcnow().timestamp()
),
}
@@ -537,7 +591,7 @@ class ConfServer:
"ecovacsUid": request.query["uid"],
},
"msg": "操作成功",
- "time": bumper.get_milli_time(
+ "time": self.get_milli_time(
datetime.utcnow().timestamp()
),
}
@@ -547,7 +601,7 @@ class ConfServer:
"code": bumper.ERR_TOKEN_INVALID,
"data": None,
"msg": "当前密码错误",
- "time": bumper.get_milli_time(datetime.utcnow().timestamp()),
+ "time": self.get_milli_time(datetime.utcnow().timestamp()),
}
return web.json_response(body)
@@ -569,7 +623,7 @@ class ConfServer:
"v": None,
},
"msg": "操作成功",
- "time": bumper.get_milli_time(datetime.utcnow().timestamp()),
+ "time": self.get_milli_time(datetime.utcnow().timestamp()),
}
return web.json_response(body)
@@ -594,7 +648,7 @@ class ConfServer:
},
"msg": "操作成功",
"success": True,
- "time": bumper.get_milli_time(datetime.utcnow().timestamp()),
+ "time": self.get_milli_time(datetime.utcnow().timestamp()),
}
return web.json_response(body)
@@ -609,7 +663,7 @@ class ConfServer:
"data": None,
"msg": "操作成功",
"success": True,
- "time": bumper.get_milli_time(datetime.utcnow().timestamp()),
+ "time": self.get_milli_time(datetime.utcnow().timestamp()),
}
return web.json_response(body)
@@ -624,7 +678,7 @@ class ConfServer:
"data": None,
"msg": "操作成功",
"success": True,
- "time": bumper.get_milli_time(datetime.utcnow().timestamp()),
+ "time": self.get_milli_time(datetime.utcnow().timestamp()),
}
return web.json_response(body)
@@ -639,7 +693,7 @@ class ConfServer:
"data": None,
"msg": "操作成功",
"success": True,
- "time": bumper.get_milli_time(datetime.utcnow().timestamp()),
+ "time": self.get_milli_time(datetime.utcnow().timestamp()),
}
return web.json_response(body)
@@ -654,7 +708,7 @@ class ConfServer:
"data": "N",
"msg": "操作成功",
"success": True,
- "time": bumper.get_milli_time(datetime.utcnow().timestamp()),
+ "time": self.get_milli_time(datetime.utcnow().timestamp()),
}
return web.json_response(body)
@@ -678,7 +732,7 @@ class ConfServer:
"data": {"hasNextPage": 0, "items": []},
"msg": "操作成功",
"success": True,
- "time": bumper.get_milli_time(datetime.utcnow().timestamp()),
+ "time": self.get_milli_time(datetime.utcnow().timestamp()),
}
return web.json_response(body)
@@ -698,7 +752,7 @@ class ConfServer:
},
"msg": "操作成功",
"success": True,
- "time": bumper.get_milli_time(datetime.utcnow().timestamp()),
+ "time": self.get_milli_time(datetime.utcnow().timestamp()),
}
return web.json_response(body)
@@ -720,7 +774,7 @@ class ConfServer:
},
"msg": "操作成功",
"success": True,
- "time": bumper.get_milli_time(datetime.utcnow().timestamp()),
+ "time": self.get_milli_time(datetime.utcnow().timestamp()),
}
return web.json_response(body)
@@ -752,14 +806,14 @@ class ConfServer:
],
"msg": "操作成功",
"success": True,
- "time": bumper.get_milli_time(datetime.utcnow().timestamp()),
+ "time": self.get_milli_time(datetime.utcnow().timestamp()),
}
else:
body = {
"code": bumper.RETURN_API_SUCCESS,
"data": [],
"msg": "操作成功",
- "time": bumper.get_milli_time(datetime.utcnow().timestamp()),
+ "time": self.get_milli_time(datetime.utcnow().timestamp()),
}
return web.json_response(body)
@@ -769,7 +823,7 @@ class ConfServer:
async def handle_homePageAlert(self, request):
try:
- nextAlert = bumper.get_milli_time(
+ nextAlert = self.get_milli_time(
(datetime.now() + timedelta(hours=12)).timestamp()
)
@@ -781,10 +835,10 @@ class ConfServer:
"hasCampaign": "N",
"imageUrl": None,
"nextAlertTime": nextAlert,
- "serverTime": bumper.get_milli_time(datetime.utcnow().timestamp()),
+ "serverTime": self.get_milli_time(datetime.utcnow().timestamp()),
},
"msg": "操作成功",
- "time": bumper.get_milli_time(datetime.utcnow().timestamp()),
+ "time": self.get_milli_time(datetime.utcnow().timestamp()),
}
return web.json_response(body)
@@ -1088,9 +1142,11 @@ class ConfServer:
if did != "":
bot = bumper.bot_get(did)
- if bot["company"] == "eco-ng" and bot["mqtt_connection"] == True:
+ if bot["company"] == "eco-ng":
body = ""
- retcmd = await self.helperbot.send_command(json_body, randomid)
+ retcmd = await bumper.mqtt_helperbot.send_command(
+ json_body, randomid
+ )
confserverlog.debug("Send Bot - {}".format(json_body))
confserverlog.debug("Bot Response - {}".format(body))
logs = []
@@ -1138,8 +1194,10 @@ class ConfServer:
if did != "":
bot = bumper.bot_get(did)
- if bot["company"] == "eco-ng" and bot["mqtt_connection"] == True:
- retcmd = await self.helperbot.send_command(json_body, randomid)
+ if bot["company"] == "eco-ng":
+ retcmd = await bumper.mqtt_helperbot.send_command(
+ json_body, randomid
+ )
body = retcmd
confserverlog.debug("Send Bot - {}".format(json_body))
confserverlog.debug("Bot Response - {}".format(body))
@@ -1184,7 +1242,9 @@ class ConfServer:
if did != "":
bot = bumper.bot_get(did)
if bot["company"] == "eco-ng" and bot["mqtt_connection"] == True:
- retcmd = await self.helperbot.send_command(json_body, randomid)
+ retcmd = await bumper.mqtt_helperbot.send_command(
+ json_body, randomid
+ )
body = retcmd
confserverlog.debug("Send Bot - {}".format(json_body))
confserverlog.debug("Bot Response - {}".format(body))
@@ -1215,10 +1275,7 @@ class ConfServer:
async def disconnect(self):
try:
confserverlog.info("shutting down")
- if self.run_async:
- self.confthread.join()
- else:
- await self.app.shutdown()
+ await self.app.shutdown()
except Exception as e:
confserverlog.exception("{}".format(e))
diff --git a/bumper/db.py b/bumper/db.py
new file mode 100644
index 0000000..20181f9
--- /dev/null
+++ b/bumper/db.py
@@ -0,0 +1,366 @@
+#!/usr/bin/env python3
+import bumper
+from bumper.models import VacBotClient, VacBotDevice, BumperUser, EcoVacsHomeProducts
+from tinydb import TinyDB, Query
+from tinydb.storages import MemoryStorage
+from datetime import datetime, timedelta
+import os
+import json
+import logging
+
+
+bumperlog = logging.getLogger("bumper")
+
+
+def db_file():
+ if bumper.db:
+ return bumper.db
+
+ return os_db_path()
+
+
+def os_db_path(): # createdir=True):
+ return os.path.join(bumper.data_dir, "bumper.db")
+
+
+def db_get():
+ # Will create the database if it doesn't exist
+ db = TinyDB(db_file())
+
+ # Will create the tables if they don't exist
+ db.table("users", cache_size=0)
+ db.table("clients", cache_size=0)
+ db.table("bots", cache_size=0)
+ db.table("tokens", cache_size=0)
+
+ return db
+
+
+def user_add(userid):
+ newuser = BumperUser()
+ newuser.userid = userid
+
+ user = user_get(userid)
+ if not user:
+ bumperlog.info("Adding new user with userid: {}".format(newuser.userid))
+ user_full_upsert(newuser.asdict())
+
+
+def user_get(userid):
+ users = db_get().table("users")
+ User = Query()
+ return users.get(User.userid == userid)
+
+
+def user_by_deviceid(deviceid):
+ users = db_get().table("users")
+ User = Query()
+ return users.get(User.devices.any([deviceid]))
+
+
+def user_full_upsert(user):
+ opendb = db_get()
+ with opendb:
+ users = opendb.table("users")
+ User = Query()
+ users.upsert(user, User.did == user["userid"])
+
+
+def user_add_device(userid, devid):
+ opendb = db_get()
+ with opendb:
+ users = opendb.table("users")
+ User = Query()
+ user = users.get(User.userid == userid)
+ userdevices = list(user["devices"])
+ if not devid in userdevices:
+ userdevices.append(devid)
+
+ users.upsert({"devices": userdevices}, User.userid == userid)
+
+
+def user_remove_device(userid, devid):
+ opendb = db_get()
+ with opendb:
+ users = opendb.table("users")
+ User = Query()
+ user = users.get(User.userid == userid)
+ userdevices = list(user["devices"])
+ if devid in userdevices:
+ userdevices.remove(devid)
+
+ users.upsert({"devices": userdevices}, User.userid == userid)
+
+
+def user_add_bot(userid, did):
+ opendb = db_get()
+ with opendb:
+ users = opendb.table("users")
+ User = Query()
+ user = users.get(User.userid == userid)
+ userbots = list(user["bots"])
+ if not did in userbots:
+ userbots.append(did)
+
+ users.upsert({"bots": userbots}, User.userid == userid)
+
+
+def user_remove_bot(userid, did):
+ opendb = db_get()
+ with opendb:
+ users = opendb.table("users")
+ User = Query()
+ user = users.get(User.userid == userid)
+ userbots = list(user["bots"])
+ if did in userbots:
+ userbots.remove(did)
+
+ users.upsert({"bots": userbots}, User.userid == userid)
+
+
+def user_get_tokens(userid):
+ tokens = db_get().table("tokens")
+ return tokens.search((Query().userid == userid))
+
+
+def user_get_token(userid, token):
+ tokens = db_get().table("tokens")
+ return tokens.get((Query().userid == userid) & (Query().token == token))
+
+
+def user_add_token(userid, token):
+ opendb = db_get()
+ with opendb:
+ tokens = opendb.table("tokens")
+ tmptoken = tokens.get((Query().userid == userid) & (Query().token == token))
+ if not tmptoken:
+ bumperlog.debug("Adding token {} for userid {}".format(token, userid))
+ tokens.insert(
+ {
+ "userid": userid,
+ "token": token,
+ "expiration": "{}".format(
+ datetime.now()
+ + timedelta(seconds=bumper.token_validity_seconds)
+ ),
+ }
+ )
+
+
+def user_revoke_all_tokens(userid):
+ opendb = db_get()
+ with opendb:
+ tokens = opendb.table("tokens")
+ tsearch = tokens.search(Query().userid == userid)
+ for i in tsearch:
+ tokens.remove(doc_ids=[i.doc_id])
+
+
+def user_revoke_expired_tokens(userid):
+ opendb = db_get()
+ with opendb:
+ tokens = opendb.table("tokens")
+ tsearch = tokens.search(Query().userid == userid)
+ for i in tsearch:
+ if datetime.now() >= datetime.fromisoformat(i["expiration"]):
+ bumperlog.debug(
+ "Removing token {} due to expiration".format(i["token"])
+ )
+ tokens.remove(doc_ids=[i.doc_id])
+
+
+def user_revoke_token(userid, token):
+ opendb = db_get()
+ with opendb:
+ tokens = opendb.table("tokens")
+ tmptoken = tokens.get((Query().userid == userid) & (Query().token == token))
+ if tmptoken:
+ tokens.remove(doc_ids=[tmptoken.doc_id])
+
+
+def user_add_authcode(userid, token, authcode):
+ opendb = db_get()
+ with opendb:
+ tokens = opendb.table("tokens")
+ tmptoken = tokens.get((Query().userid == userid) & (Query().token == token))
+ if tmptoken:
+ tokens.upsert(
+ {"authcode": authcode},
+ ((Query().userid == userid) & (Query().token == token)),
+ )
+
+
+def user_revoke_authcode(userid, token, authcode):
+ opendb = db_get()
+ with opendb:
+ tokens = opendb.table("tokens")
+ tmptoken = tokens.get((Query().userid == userid) & (Query().token == token))
+ if tmptoken:
+ tokens.upsert(
+ {"authcode": ""},
+ ((Query().userid == userid) & (Query().token == token)),
+ )
+
+
+def get_disconnected_xmpp_clients():
+ clients = db_get().table("clients")
+ Client = Query()
+ return clients.search(Client.xmpp_connection == False)
+
+
+def check_authcode(uid, authcode):
+ bumperlog.debug("Checking for authcode: {}".format(authcode))
+ tokens = db_get().table("tokens")
+ tmpauth = tokens.get(
+ (Query().authcode == authcode)
+ & ( # Match authcode
+ (Query().userid == uid.replace("fuid_", ""))
+ | (Query().userid == "fuid_{}".format(uid))
+ ) # Userid with or without fuid_
+ )
+ if tmpauth:
+ return True
+
+ return False
+
+
+def loginByItToken(authcode):
+ bumperlog.debug("Checking for authcode: {}".format(authcode))
+ tokens = db_get().table("tokens")
+ tmpauth = tokens.get(
+ (Query().authcode == authcode)
+ # & ( # Match authcode
+ # (Query().userid == uid.replace("fuid_", ""))
+ # | (Query().userid == "fuid_{}".format(uid))
+ # ) # Userid with or without fuid_
+ )
+ if tmpauth:
+ return {"token": tmpauth["token"], "userid": tmpauth["userid"]}
+
+ return {}
+
+
+def check_token(uid, token):
+ bumperlog.debug("Checking for token: {}".format(token))
+ tokens = db_get().table("tokens")
+ tmpauth = tokens.get(
+ (Query().token == token)
+ & ( # Match token
+ (Query().userid == uid.replace("fuid_", ""))
+ | (Query().userid == "fuid_{}".format(uid))
+ ) # Userid with or without fuid_
+ )
+ if tmpauth:
+ return True
+
+ return False
+
+
+def revoke_expired_tokens():
+ tokens = db_get().table("tokens").all()
+ for i in tokens:
+ if datetime.now() >= datetime.fromisoformat(i["expiration"]):
+ bumperlog.debug("Removing token {} due to expiration".format(i["token"]))
+ db_get().table("tokens").remove(doc_ids=[i.doc_id])
+
+
+def bot_add(sn, did, devclass, resource, company):
+ newbot = VacBotDevice()
+ newbot.did = did
+ newbot.name = sn
+ newbot.vac_bot_device_class = devclass
+ newbot.resource = resource
+ newbot.company = company
+
+ bot = bot_get(did)
+ 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
+ bumperlog.info(
+ "Adding new bot with SN: {} DID: {}".format(newbot.name, newbot.did)
+ )
+ bot_full_upsert(newbot.asdict())
+
+
+def bot_remove(did):
+ bots = db_get().table("bots")
+ bot = bot_get(did)
+ bots.remove(doc_ids=[bot.doc_id])
+
+
+def bot_get(did):
+ bots = db_get().table("bots")
+ Bot = Query()
+ return bots.get(Bot.did == did)
+
+
+def bot_toEcoVacsHome_JSON(bot): # EcoVacs Home
+ for botprod in EcoVacsHomeProducts:
+ if botprod["classid"] == bot["class"]:
+ bot["UILogicId"] = botprod["product"]["UILogicId"]
+ bot["ota"] = botprod["product"]["ota"]
+ bot["icon"] = botprod["product"]["iconUrl"]
+ return json.dumps(
+ bot, default=lambda o: o.__dict__, sort_keys=False
+ ) # , indent=4)
+
+
+def bot_full_upsert(vacbot):
+ bots = db_get().table("bots")
+ Bot = Query()
+ bots.upsert(vacbot, Bot.did == vacbot["did"])
+
+
+def bot_set_nick(did, nick):
+ bots = db_get().table("bots")
+ Bot = Query()
+ bots.upsert({"nick": nick}, Bot.did == did)
+
+
+def bot_set_mqtt(did, mqtt):
+ bots = db_get().table("bots")
+ Bot = Query()
+ bots.upsert({"mqtt_connection": mqtt}, Bot.did == did)
+
+
+def bot_set_xmpp(did, xmpp):
+ bots = db_get().table("bots")
+ Bot = Query()
+ bots.upsert({"xmpp_connection": xmpp}, Bot.did == did)
+
+
+def client_add(userid, realm, resource):
+ newclient = VacBotClient()
+ newclient.userid = userid
+ newclient.realm = realm
+ newclient.resource = resource
+
+ client = client_get(resource)
+ if not client:
+ bumperlog.info("Adding new client with resource {}".format(newclient.resource))
+ client_full_upsert(newclient.asdict())
+
+
+def client_get(resource):
+ clients = db_get().table("clients")
+ Client = Query()
+ return clients.get(Client.resource == resource)
+
+
+def client_full_upsert(client):
+ clients = db_get().table("clients")
+ Client = Query()
+ clients.upsert(client, Client.resource == client["resource"])
+
+
+def client_set_mqtt(resource, mqtt):
+ clients = db_get().table("clients")
+ Client = Query()
+ clients.upsert({"mqtt_connection": mqtt}, Client.resource == resource)
+
+
+def client_set_xmpp(resource, xmpp):
+ clients = db_get().table("clients")
+ Client = Query()
+ clients.upsert({"xmpp_connection": xmpp}, Client.resource == resource)
diff --git a/bumper/models.py b/bumper/models.py
new file mode 100644
index 0000000..25e091b
--- /dev/null
+++ b/bumper/models.py
@@ -0,0 +1,401 @@
+#!/usr/bin/env python3
+import json
+
+
+class VacBotDevice(object):
+ def __init__(
+ self, did="", vac_bot_device_class="", resource="", name="", nick="", company=""
+ ):
+ self.vac_bot_device_class = vac_bot_device_class
+ self.company = company
+ self.did = did
+ self.name = name
+ self.nick = nick
+ self.resource = resource
+ self.mqtt_connection = False
+ self.xmpp_connection = False
+
+ def asdict(self):
+ return {
+ "class": self.vac_bot_device_class,
+ "company": self.company,
+ "did": self.did,
+ "name": self.name,
+ "nick": self.nick,
+ "resource": self.resource,
+ "mqtt_connection": self.mqtt_connection,
+ "xmpp_connection": self.xmpp_connection,
+ }
+
+
+class BumperUser(object):
+ def __init__(self, userid=""):
+ self.userid = userid
+ self.devices = []
+ self.bots = []
+
+ def asdict(self):
+ return {"userid": self.userid, "devices": self.devices, "bots": self.bots}
+
+
+class GlobalVacBotDevice(VacBotDevice): # EcoVacs Home
+ UILogicId = ""
+ ota = True
+ updateInfo = {"changeLog": "", "needUpdate": False}
+ icon = ""
+ deviceName = ""
+
+
+class VacBotClient(object):
+ def __init__(self, userid="", realm="", token=""):
+ self.userid = userid
+ self.realm = realm
+ self.resource = token
+ self.mqtt_connection = False
+ self.xmpp_connection = False
+
+ def asdict(self):
+ return {
+ "userid": self.userid,
+ "realm": self.realm,
+ "resource": self.resource,
+ "mqtt_connection": self.mqtt_connection,
+ "xmpp_connection": self.xmpp_connection,
+ }
+
+
+class EcoVacs_Login:
+ accessToken = ""
+ country = ""
+ email = ""
+ uid = ""
+ username = ""
+
+ def toJSON(self):
+ return json.dumps(
+ self, default=lambda o: o.__dict__, sort_keys=False
+ ) # , indent=4)
+
+
+class EcoVacsHome_Login(EcoVacs_Login):
+ loginName = ""
+ mobile = ""
+ ucUid = ""
+
+
+# EcoVacs Home Product IOT Map - 2019-05-20
+# https://portal-ww.ecouser.net/api/pim/product/getProductIotMap
+EcoVacsHomeProducts = [
+ {
+ "classid": "dl8fht",
+ "product": {
+ "UILogicId": "D_600",
+ "_id": "5acb0fa87c295c0001876ecf",
+ "icon": "5acc32067c295c0001876eea",
+ "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5acc32067c295c0001876eea",
+ "materialNo": "702-0000-0170",
+ "name": "DEEBOT 600 Series",
+ "ota": False,
+ "supportType": {
+ "alexa": True,
+ "assistant": True,
+ "share": True,
+ "tmjl": False,
+ },
+ },
+ },
+ {
+ "classid": "02uwxm",
+ "product": {
+ "UILogicId": "D_OZMO_SLIM10",
+ "_id": "5ae1481e7ccd1a0001e1f69e",
+ "icon": "5b1dddc48bc45700014035a1",
+ "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5b1dddc48bc45700014035a1",
+ "materialNo": "110-1715-0201",
+ "name": "DEEBOT OZMO Slim10 Series",
+ "ota": False,
+ "supportType": {
+ "alexa": True,
+ "assistant": True,
+ "share": True,
+ "tmjl": False,
+ },
+ },
+ },
+ {
+ "classid": "y79a7u",
+ "product": {
+ "UILogicId": "D_OZMO_900",
+ "_id": "5b04c0227ccd1a0001e1f6a8",
+ "icon": "5b04c0217ccd1a0001e1f6a7",
+ "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5b04c0217ccd1a0001e1f6a7",
+ "materialNo": "110-1810-0101",
+ "name": "DEEBOT OZMO 900 Series",
+ "ota": True,
+ "supportType": {
+ "alexa": True,
+ "assistant": True,
+ "share": True,
+ "tmjl": False,
+ },
+ },
+ },
+ {
+ "classid": "jr3pqa",
+ "product": {
+ "UILogicId": "D_700",
+ "_id": "5b43077b8bc457000140363e",
+ "icon": "5b5ac4cc8d5a56000111e769",
+ "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5b5ac4cc8d5a56000111e769",
+ "materialNo": "702-0000-0202",
+ "name": "DEEBOT 711",
+ "ota": True,
+ "supportType": {
+ "alexa": True,
+ "assistant": True,
+ "share": True,
+ "tmjl": False,
+ },
+ },
+ },
+ {
+ "classid": "uv242z",
+ "product": {
+ "UILogicId": "D_700",
+ "_id": "5b5149b4ac0b87000148c128",
+ "icon": "5b5ac4e45f21100001882bb9",
+ "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5b5ac4e45f21100001882bb9",
+ "materialNo": "702-0000-0205",
+ "name": "DEEBOT 710",
+ "ota": True,
+ "supportType": {
+ "alexa": True,
+ "assistant": True,
+ "share": True,
+ "tmjl": False,
+ },
+ },
+ },
+ {
+ "classid": "ls1ok3",
+ "product": {
+ "UILogicId": "D_900",
+ "_id": "5b6561060506b100015c8868",
+ "icon": "5ba4a2cb6c2f120001c32839",
+ "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5ba4a2cb6c2f120001c32839",
+ "materialNo": "110-1711-0201",
+ "name": "DEEBOT 900 Series",
+ "ota": True,
+ "supportType": {
+ "alexa": True,
+ "assistant": True,
+ "share": True,
+ "tmjl": False,
+ },
+ },
+ },
+ {
+ "classid": "eyi9jv",
+ "product": {
+ "UILogicId": "D_700",
+ "_id": "5b7b65f364e1680001a08b54",
+ "icon": "5b7b65f176f7f10001e9a0c2",
+ "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5b7b65f176f7f10001e9a0c2",
+ "materialNo": "715",
+ "name": "DEEBOT 715",
+ "ota": True,
+ "supportType": {
+ "alexa": True,
+ "assistant": True,
+ "share": True,
+ "tmjl": False,
+ },
+ },
+ },
+ {
+ "classid": "4zfacv",
+ "product": {
+ "UILogicId": "DN_2G",
+ "_id": "5bf2596f23244a00013f2f13",
+ "icon": "5c778731280fda0001770ba0",
+ "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5c778731280fda0001770ba0",
+ "materialNo": "910",
+ "name": "DEEBOT 910",
+ "ota": True,
+ "supportType": {
+ "alexa": True,
+ "assistant": True,
+ "share": True,
+ "tmjl": False,
+ },
+ },
+ },
+ {
+ "classid": "vi829v",
+ "product": {
+ "UILogicId": "DX_5G",
+ "_id": "5c19a8f3a1e6ee0001782247",
+ "icon": "5c9c7995e9e9270001354ab4",
+ "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5c9c7995e9e9270001354ab4",
+ "materialNo": "920",
+ "name": "DEEBOT OZMO 920 Series",
+ "ota": True,
+ "supportType": {
+ "alexa": True,
+ "assistant": True,
+ "share": True,
+ "tmjl": False,
+ },
+ },
+ },
+ {
+ "classid": "gd4uut",
+ "product": {
+ "UILogicId": "DR_935G",
+ "_id": "5bc8189d68142800016a6937",
+ "icon": "5c7384767b93c700013f12e7",
+ "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5c7384767b93c700013f12e7",
+ "materialNo": "960",
+ "name": "DEEBOT OZMO 960",
+ "ota": True,
+ "supportType": {
+ "alexa": True,
+ "assistant": True,
+ "share": False,
+ "tmjl": False,
+ },
+ },
+ },
+ {
+ "classid": "9akc61",
+ "product": {
+ "UILogicId": "D_500",
+ "_id": "5c763f8263023c0001e7f855",
+ "icon": "5c932067280fda0001770d7f",
+ "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5c932067280fda0001770d7f",
+ "materialNo": "D505",
+ "name": "DEEBOT 505",
+ "ota": False,
+ "supportType": {
+ "alexa": True,
+ "assistant": True,
+ "share": True,
+ "tmjl": False,
+ },
+ },
+ },
+ {
+ "classid": "r8ead0",
+ "product": {
+ "UILogicId": "D_500",
+ "_id": "5c763f63280fda0001770b88",
+ "icon": "5c93204b63023c0001e7faa7",
+ "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5c93204b63023c0001e7faa7",
+ "materialNo": "D502",
+ "name": "DEEBOT 502",
+ "ota": False,
+ "supportType": {
+ "alexa": True,
+ "assistant": True,
+ "share": True,
+ "tmjl": False,
+ },
+ },
+ },
+ {
+ "classid": "emzppx",
+ "product": {
+ "UILogicId": "D_500",
+ "_id": "5c763f35280fda0001770b84",
+ "icon": "5c931fef280fda0001770d7e",
+ "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5c931fef280fda0001770d7e",
+ "materialNo": "D501",
+ "name": "DEEBOT 501",
+ "ota": False,
+ "supportType": {
+ "alexa": True,
+ "assistant": True,
+ "share": True,
+ "tmjl": False,
+ },
+ },
+ },
+ {
+ "classid": "vsc5ia",
+ "product": {
+ "UILogicId": "D_500",
+ "_id": "5c763eba280fda0001770b81",
+ "icon": "5c874326280fda0001770d2a",
+ "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5c874326280fda0001770d2a",
+ "materialNo": "D500",
+ "name": "DEEBOT 500",
+ "ota": False,
+ "supportType": {
+ "alexa": True,
+ "assistant": True,
+ "share": True,
+ "tmjl": False,
+ },
+ },
+ },
+ {
+ "classid": "aqdd5p",
+ "product": {
+ "UILogicId": "D_900",
+ "_id": "5cb7cfba179839000114d762",
+ "icon": "5cb7cfbab72c4d00010e5fc7",
+ "iconUrl": "https://portal-ww.ecouser.net/api/pim/file/get/5cb7cfbab72c4d00010e5fc7",
+ "materialNo": "110-1711-0001",
+ "name": "DEEBOT DE55",
+ "ota": True,
+ "supportType": {
+ "alexa": False,
+ "assistant": False,
+ "share": False,
+ "tmjl": False,
+ },
+ },
+ },
+]
+
+
+RETURN_API_SUCCESS = "0000"
+ERR_ACTIVATE_TOKEN_TIMEOUT = "1006"
+ERR_COMMON = "0001"
+ERR_DEFAULT = "9000"
+ERR_EMAIL_NON_EXIST = "1002"
+ERR_EMAIL_SEND_TIME_LIMIT = "1011"
+ERR_EMAIL_USED = "1001"
+ERR_INTERFACE_AUTH = "0002"
+ERR_PARAM_INVALID = "0003"
+ERR_PWD_WRONG = "1005"
+ERR_RESET_PWD_TOKEN_TIMEOUT = "1007"
+ERR_TIMESTAMP_INVALID = "0005"
+ERR_TOKEN_INVALID = "0004"
+ERR_USER_DISABLE = "1004"
+ERR_USER_NOT_ACTIVATED = "1003"
+ERR_WRONG_COMFIRM_PWD = "10010"
+ERR_WRONG_EMAIL_ADDRESS = "1008"
+ERR_WRONG_PWD_FROMATE = "1009"
+
+API_ERRORS = {
+ RETURN_API_SUCCESS: "0000",
+ ERR_ACTIVATE_TOKEN_TIMEOUT: "1006",
+ ERR_COMMON: "0001",
+ ERR_DEFAULT: "9000",
+ ERR_EMAIL_NON_EXIST: "1002",
+ ERR_EMAIL_SEND_TIME_LIMIT: "1011",
+ ERR_EMAIL_USED: "1001",
+ ERR_INTERFACE_AUTH: "0002",
+ ERR_PARAM_INVALID: "0003",
+ ERR_PWD_WRONG: "1005",
+ ERR_RESET_PWD_TOKEN_TIMEOUT: "1007",
+ ERR_TIMESTAMP_INVALID: "0005",
+ ERR_TOKEN_INVALID: "0004",
+ ERR_USER_DISABLE: "1004",
+ ERR_USER_NOT_ACTIVATED: "1003",
+ ERR_WRONG_COMFIRM_PWD: "10010",
+ ERR_WRONG_EMAIL_ADDRESS: "1008",
+ ERR_WRONG_PWD_FROMATE: "1009",
+}
+
diff --git a/bumper/mqttserver.py b/bumper/mqttserver.py
index 5e247a4..72b1feb 100644
--- a/bumper/mqttserver.py
+++ b/bumper/mqttserver.py
@@ -15,6 +15,7 @@ from datetime import datetime, timedelta
import bumper
helperbotlog = logging.getLogger("helperbot")
+boterrorlog = logging.getLogger("boterror")
mqttserverlog = logging.getLogger("mqttserver")
logging.getLogger("transitions").setLevel(logging.CRITICAL + 1) # Ignore this logger
@@ -30,7 +31,7 @@ logging.getLogger("hbmqtt.client").setLevel(logging.CRITICAL + 1) # Ignore this
class MQTTHelperBot:
- Client = MQTTClient()
+ Client = None
wait_resp_timeout_seconds = 10
expire_msg_seconds = 10
@@ -38,14 +39,14 @@ class MQTTHelperBot:
self.address = address
self.client_id = "helper1@bumper/helper1"
self.command_responses = []
- self.helperthread = None
async def start_helper_bot(self):
try:
- self.Client = MQTTClient(
- client_id=self.client_id, config={"check_hostname": False}
- )
+ if self.Client is None:
+ self.Client = MQTTClient(
+ client_id=self.client_id, config={"check_hostname": False}
+ )
await self.Client.connect(
"mqtts://{}:{}/".format(self.address[0], self.address[1]),
@@ -102,11 +103,19 @@ class MQTTHelperBot:
)
elif str(message.topic).split("/")[1] == "atr":
# Broadcast message received on atr
- helperbotlog.debug(
- "Received Broadcast - Topic: {} - Message: {}".format(
- message.topic, str(message.data.decode("utf-8"))
+ if str(message.topic).split("/")[2] == "errors":
+ boterrorlog.error(
+ "Received Error - Topic: {} - Message: {}".format(
+ message.topic, str(message.data.decode("utf-8"))
+ )
)
- )
+ else:
+ helperbotlog.debug(
+ "Received Broadcast - Topic: {} - Message: {}".format(
+ message.topic, str(message.data.decode("utf-8"))
+ )
+ )
+
else:
helperbotlog.debug(
"Received Message - Topic: {} - Message: {}".format(
@@ -174,29 +183,30 @@ class MQTTHelperBot:
}
async def send_command(self, cmdjson, requestid):
- try:
- ttopic = "iot/p2p/{}/helper1/bumper/helper1/{}/{}/{}/q/{}/{}".format(
- cmdjson["cmdName"],
- cmdjson["toId"],
- cmdjson["toType"],
- cmdjson["toRes"],
- requestid,
- cmdjson["payloadType"],
- )
+ if not self.Client._handler.writer is None:
try:
- await self.Client.publish(
- ttopic, str(cmdjson["payload"]).encode(), QOS_0
+ ttopic = "iot/p2p/{}/helper1/bumper/helper1/{}/{}/{}/q/{}/{}".format(
+ cmdjson["cmdName"],
+ cmdjson["toId"],
+ cmdjson["toType"],
+ cmdjson["toRes"],
+ requestid,
+ cmdjson["payloadType"],
)
+ try:
+ await self.Client.publish(
+ ttopic, str(cmdjson["payload"]).encode(), QOS_0
+ )
+ except Exception as e:
+ helperbotlog.exception("{}".format(e))
+
+ resp = await self.wait_for_resp(requestid)
+
+ return resp
+
except Exception as e:
helperbotlog.exception("{}".format(e))
-
- resp = await self.wait_for_resp(requestid)
-
- return resp
-
- except Exception as e:
- helperbotlog.exception("{}".format(e))
- return {}
+ return {}
class MQTTServer:
@@ -224,7 +234,6 @@ class MQTTServer:
def __init__(self, address):
try:
- self.mqttserverthread = None
self.address = address
# The below adds a plugin to the hbmqtt.broker.plugins without having to futz with setup.py
@@ -345,40 +354,33 @@ class BumperMQTTServer_Plugin:
return authenticated
async def on_broker_client_connected(self, client_id):
- try:
- didsplit = str(client_id).split("@")
- bot = bumper.bot_get(didsplit[0])
- if bot:
- bumper.bot_set_mqtt(bot["did"], True)
- return
+ didsplit = str(client_id).split("@")
- # clientuserid = didsplit[0]
- clientresource = didsplit[1].split("/")[1]
- client = bumper.client_get(clientresource)
- if client:
- bumper.client_set_mqtt(client["resource"], True)
- return
+ bot = bumper.bot_get(didsplit[0])
+ if bot:
+ bumper.bot_set_mqtt(bot["did"], True)
+ return
- except Exception as e:
- mqttserverlog.exception("{}".format(e))
+ # clientuserid = didsplit[0]
+ clientresource = didsplit[1].split("/")[1]
+ client = bumper.client_get(clientresource)
+ if client:
+ bumper.client_set_mqtt(client["resource"], True)
+ return
async def on_broker_client_disconnected(self, client_id):
- try:
- didsplit = str(client_id).split("@")
- bot = bumper.bot_get(didsplit[0])
- if bot:
- bumper.bot_set_mqtt(bot["did"], False)
- return
+ didsplit = str(client_id).split("@")
- # clientuserid = didsplit[0]
- clientresource = didsplit[1].split("/")[1]
- client = bumper.client_get(clientresource)
- if client:
- bumper.client_set_mqtt(client["resource"], False)
- return
-
- except Exception as e:
- mqttserverlog.exception("{}".format(e))
+ bot = bumper.bot_get(didsplit[0])
+ if bot:
+ bumper.bot_set_mqtt(bot["did"], False)
+ return
+ # clientuserid = didsplit[0]
+ clientresource = didsplit[1].split("/")[1]
+ client = bumper.client_get(clientresource)
+ if client:
+ bumper.client_set_mqtt(client["resource"], False)
+ return
diff --git a/bumper/xmppserver.py b/bumper/xmppserver.py
index ef43a58..be932a9 100644
--- a/bumper/xmppserver.py
+++ b/bumper/xmppserver.py
@@ -10,6 +10,7 @@ import bumper
import asyncio
xmppserverlog = logging.getLogger("xmppserver")
+boterrorlog = logging.getLogger("boterror")
class XMPPServer:
@@ -50,17 +51,14 @@ class XMPPServer:
asyncio.create_task(bumper.shutdown())
def disconnect(self):
- try:
- xmppserverlog.debug("waiting for all client threads to exit")
- for client in self.clients:
- client._disconnect()
- self.exit_flag = True
- xmppserverlog.debug("shutting down")
- self.server_coro.cancel()
+ xmppserverlog.debug("waiting for all clients to disconnect")
+ for client in self.clients:
+ client._disconnect()
- except Exception as e:
- xmppserverlog.error("{}".format(e))
+ self.exit_flag = True
+ xmppserverlog.debug("shutting down")
+ self.server_coro.cancel()
class XMPPServer_Protocol(asyncio.Protocol):
@@ -614,80 +612,70 @@ class XMPPAsyncClient:
xmppserverlog.exception("{}".format(e))
def _handle_session(self, xml):
- try:
- res = ''.format(xml.get("id"))
- self._set_state("READY")
- self.send(res)
- asyncio.Task(self.schedule_ping(30))
-
- except Exception as e:
- xmppserverlog.exception("{}".format(e))
+ res = ''.format(xml.get("id"))
+ self._set_state("READY")
+ self.send(res)
+ asyncio.Task(self.schedule_ping(30))
def _handle_presence(self, xml):
- try:
- if len(xml) and xml[0].tag == "status":
+ if len(xml) and xml[0].tag == "status":
+ xmppserverlog.debug(
+ "bot presence {} ".format(
+ ET.tostring(xml, encoding="utf-8").decode("utf-8")
+ )
+ )
+ # Most likely a bot, possibly hello world in text
+
+ # Send dummy return
+ self.send(' dummy '.format(self.bumper_jid))
+
+ # If it is a BOT, send extras
+ if self.type == self.BOT:
+ # get device info
+ self.send(
+ ''.format(
+ self.bumper_jid, XMPPServer.server_id
+ )
+ )
+
+ else:
+ xmppserverlog.debug(
+ "client presence - {} ".format(
+ ET.tostring(xml, encoding="utf-8").decode("utf-8")
+ )
+ )
+
+ if xml.get("type") == "available":
xmppserverlog.debug(
- "bot presence {} ".format(
+ "client presence available - {} ".format(
ET.tostring(xml, encoding="utf-8").decode("utf-8")
)
)
- # Most likely a bot, possibly hello world in text
# Send dummy return
self.send(
' dummy '.format(self.bumper_jid)
)
-
- # If it is a BOT, send extras
- if self.type == self.BOT:
- # get device info
- self.send(
- ''.format(
- self.bumper_jid, XMPPServer.server_id
- )
- )
-
- else:
+ elif xml.get("type") == "unavailable":
xmppserverlog.debug(
- "client presence - {} ".format(
+ "client presence unavailable (DISCONNECT) - {} ".format(
ET.tostring(xml, encoding="utf-8").decode("utf-8")
)
)
- if xml.get("type") == "available":
- xmppserverlog.debug(
- "client presence available - {} ".format(
- ET.tostring(xml, encoding="utf-8").decode("utf-8")
- )
+ self._set_state("DISCONNECT")
+ else:
+ # Sometimes the android app sends these
+ xmppserverlog.debug(
+ "client presence (UNKNOWN) - {} ".format(
+ ET.tostring(xml, encoding="utf-8")
)
-
- # Send dummy return
- self.send(
- ' dummy '.format(self.bumper_jid)
- )
- elif xml.get("type") == "unavailable":
- xmppserverlog.debug(
- "client presence unavailable (DISCONNECT) - {} ".format(
- ET.tostring(xml, encoding="utf-8").decode("utf-8")
- )
- )
-
- self._set_state("DISCONNECT")
- else:
- # Sometimes the android app sends these
- xmppserverlog.debug(
- "client presence (UNKNOWN) - {} ".format(
- ET.tostring(xml, encoding="utf-8")
- )
- )
- # Send dummy return
- self.send(
- ' dummy '.format(self.bumper_jid)
- )
-
- except Exception as e:
- xmppserverlog.exception("{}".format(e))
+ )
+ # Send dummy return
+ self.send(
+ ' dummy '.format(self.bumper_jid)
+ )
def _parse_data(self, data):
@@ -721,6 +709,19 @@ class XMPPAsyncClient:
).replace("ns0:", ""),
)
)
+ if (
+ 'td="error"' in newdata
+ or "errs=" in newdata
+ or 'k="DeviceAlert' in newdata
+ ):
+ boterrorlog.error(
+ "Received Error from ({}:{} | {}) - {}".format(
+ self.address[0],
+ self.address[1],
+ self.bumper_jid,
+ newdata,
+ )
+ )
self._handle_iq(item, newdata)
item.clear()
@@ -790,34 +791,31 @@ class XMPPAsyncClient:
xmppserverlog.exception("{}".format(e))
def _handle_iq(self, xml, data):
- try:
- if len(xml):
- child = self._tag_strip_uri(xml[0].tag)
- else:
- child = None
- if xml.tag == "iq":
- if child == "bind":
- self._handle_bind(xml)
- elif child == "session":
- self._handle_session(xml)
- elif child == "ping":
- self._handle_ping(xml, data)
- elif child == "query":
- if self.type == self.BOT:
- self._handle_result(xml, data)
- else:
- self._handle_ctl(xml, data)
- elif xml.get("type") == "result":
- if self.type == self.BOT:
- self._handle_result(xml, data)
- else:
- self._handle_result(xml, data)
- elif xml.get("type") == "set":
- if self.type == self.BOT:
- self._handle_result(xml, data)
- else:
- self._handle_result(xml, data)
+ if len(xml):
+ child = self._tag_strip_uri(xml[0].tag)
+ else:
+ child = None
- except Exception as e:
- xmppserverlog.exception("{}".format(e))
+ if xml.tag == "iq":
+ if child == "bind":
+ self._handle_bind(xml)
+ elif child == "session":
+ self._handle_session(xml)
+ elif child == "ping":
+ self._handle_ping(xml, data)
+ elif child == "query":
+ if self.type == self.BOT:
+ self._handle_result(xml, data)
+ else:
+ self._handle_ctl(xml, data)
+ elif xml.get("type") == "result":
+ if self.type == self.BOT:
+ self._handle_result(xml, data)
+ else:
+ self._handle_result(xml, data)
+ elif xml.get("type") == "set":
+ if self.type == self.BOT:
+ self._handle_result(xml, data)
+ else:
+ self._handle_result(xml, data)
diff --git a/tests/test_confserver.py b/tests/test_confserver.py
index 15fdac7..2d0a70b 100644
--- a/tests/test_confserver.py
+++ b/tests/test_confserver.py
@@ -7,15 +7,16 @@ import json
import tinydb
import pytest_aiohttp
import pytest_asyncio
+import datetime, time
from aiohttp import web
def create_confserver():
- return bumper.ConfServer("127.0.0.1:11111", False, mock.MagicMock)
+ return bumper.ConfServer("127.0.0.1:11111", False)
def create_app(loop):
- confserver = bumper.ConfServer("127.0.0.1:11111", False, mock.MagicMock)
+ confserver = bumper.ConfServer("127.0.0.1:11111", False)
confserver.confserver_app()
return confserver.app
@@ -32,18 +33,31 @@ def remove_existing_db():
async def test_confserver_ssl():
- conf_server = bumper.ConfServer(("127.0.0.1", 111111), usessl=True, helperbot=None)
+ conf_server = bumper.ConfServer(("127.0.0.1", 111111), usessl=True)
conf_server.confserver_app()
asyncio.create_task(conf_server.start_server())
async def test_confserver_no_ssl():
- conf_server = bumper.ConfServer(("127.0.0.1", 111111), usessl=False, helperbot=None)
+ conf_server = bumper.ConfServer(("127.0.0.1", 111111), usessl=False)
conf_server.confserver_app()
asyncio.create_task(conf_server.start_server())
-async def test_base(aiohttp_client):
+def test_get_milli_time():
+ cserv = create_confserver()
+ assert (
+ cserv.get_milli_time(
+ datetime.datetime(
+ 2018, 1, 1, 1, 0, 0, 0, tzinfo=datetime.timezone.utc
+ ).timestamp()
+ )
+ == 1514768400000
+ )
+
+
+# Comment out test_base until api changes are complete
+""" async def test_base(aiohttp_client):
remove_existing_db()
bumper.db = "tests/tmp.db" # Set db location for testing
client = await aiohttp_client(create_app)
@@ -51,7 +65,7 @@ async def test_base(aiohttp_client):
resp = await client.get("/")
assert resp.status == 200
text = await resp.text()
- assert "Bumper!" in text
+ assert "Bumper!" in text """
async def test_login(aiohttp_client):
@@ -696,6 +710,7 @@ async def test_lg_logs(aiohttp_client):
bumper.bot_set_mqtt("did_1234", True)
confserver = create_confserver()
client = await aiohttp_client(create_app)
+ bumper.mqtt_helperbot = bumper.mqttserver.MQTTHelperBot("127.0.0.1")
# Test return get status
command_getstatus_resp = {
@@ -703,7 +718,7 @@ async def test_lg_logs(aiohttp_client):
"resp": "",
"ret": "ok",
}
- confserver.helperbot.send_command = mock.MagicMock(
+ bumper.mqtt_helperbot.send_command = mock.MagicMock(
return_value=async_return(command_getstatus_resp)
)
@@ -726,14 +741,6 @@ async def test_lg_logs(aiohttp_client):
jsonresp = json.loads(text)
assert jsonresp["ret"] == "ok"
- # Not bot online
- bumper.bot_set_mqtt("did_1234", False)
- resp = await client.post("/api/lg/log.do", json=postbody)
- assert resp.status == 200
- text = await resp.text()
- jsonresp = json.loads(text)
- assert jsonresp["ret"] == "fail"
-
async def test_postLookup(aiohttp_client):
remove_existing_db()
@@ -762,6 +769,7 @@ async def test_devmgr(aiohttp_client):
bumper.db = "tests/tmp.db" # Set db location for testing
confserver = create_confserver()
client = await aiohttp_client(create_app)
+ bumper.mqtt_helperbot = bumper.mqttserver.MQTTHelperBot("127.0.0.1")
# Test PollSCResult
postbody = {"td": "PollSCResult"}
@@ -791,7 +799,7 @@ async def test_devmgr(aiohttp_client):
"resp": "",
"ret": "ok",
}
- confserver.helperbot.send_command = mock.MagicMock(
+ bumper.mqtt_helperbot.send_command = mock.MagicMock(
return_value=async_return(command_getstatus_resp)
)
resp = await client.post("/api/iot/devmanager.do", json=postbody)
@@ -802,7 +810,7 @@ async def test_devmgr(aiohttp_client):
# Test return fail timeout
command_timeout_resp = {"id": "resp_1234", "errno": "timeout", "ret": "fail"}
- confserver.helperbot.send_command = mock.MagicMock(
+ bumper.mqtt_helperbot.send_command = mock.MagicMock(
return_value=async_return(command_timeout_resp)
)
resp = await client.post("/api/iot/devmanager.do", json=postbody)
@@ -811,23 +819,13 @@ async def test_devmgr(aiohttp_client):
test_resp = json.loads(text)
assert test_resp["ret"] == "fail"
- # Set bot not on mqtt
- bumper.bot_set_mqtt("did_1234", False)
- confserver.helperbot.send_command = mock.MagicMock(
- return_value=async_return(command_getstatus_resp)
- )
- resp = await client.post("/api/iot/devmanager.do", json=postbody)
- assert resp.status == 200
- text = await resp.text()
- test_resp = json.loads(text)
- assert test_resp["ret"] == "fail"
-
async def test_dim_devmanager(aiohttp_client):
remove_existing_db()
bumper.db = "tests/tmp.db" # Set db location for testing
confserver = create_confserver()
client = await aiohttp_client(create_app)
+ bumper.mqtt_helperbot = bumper.mqttserver.MQTTHelperBot("127.0.0.1")
# Test PollSCResult
postbody = {"td": "PollSCResult"}
@@ -857,7 +855,7 @@ async def test_dim_devmanager(aiohttp_client):
"resp": "",
"ret": "ok",
}
- confserver.helperbot.send_command = mock.MagicMock(
+ bumper.mqtt_helperbot.send_command = mock.MagicMock(
return_value=async_return(command_getstatus_resp)
)
resp = await client.post("/api/dim/devmanager.do", json=postbody)
@@ -868,7 +866,7 @@ async def test_dim_devmanager(aiohttp_client):
# Test return fail timeout
command_timeout_resp = {"id": "resp_1234", "errno": "timeout", "ret": "fail"}
- confserver.helperbot.send_command = mock.MagicMock(
+ bumper.mqtt_helperbot.send_command = mock.MagicMock(
return_value=async_return(command_timeout_resp)
)
resp = await client.post("/api/dim/devmanager.do", json=postbody)
@@ -880,7 +878,7 @@ async def test_dim_devmanager(aiohttp_client):
# Set bot not on mqtt
bumper.bot_set_mqtt("did_1234", False)
- confserver.helperbot.send_command = mock.MagicMock(
+ bumper.mqtt_helperbot.send_command = mock.MagicMock(
return_value=async_return(command_getstatus_resp)
)
resp = await client.post("/api/dim/devmanager.do", json=postbody)
diff --git a/tests/test_db.py b/tests/test_db.py
new file mode 100644
index 0000000..52c49a4
--- /dev/null
+++ b/tests/test_db.py
@@ -0,0 +1,145 @@
+#!/usr/bin/env python3
+import bumper
+from bumper.models import VacBotClient, VacBotDevice, BumperUser, EcoVacsHomeProducts
+from tinydb import TinyDB, Query
+from tinydb.storages import MemoryStorage
+from datetime import datetime, timedelta
+import os
+import json
+import logging
+
+
+def test_db_path():
+ bumper.db = None
+ assert bumper.db_file() == os.path.join(bumper.data_dir, "bumper.db")
+
+
+def test_user_db():
+
+ bumper.db = "tests/tmp.db" # Set db location for testing
+ bumper.user_add("testuser") # Add testuser
+
+ assert (
+ bumper.user_get("testuser")["userid"] == "testuser"
+ ) # Test that testuser was created and returned
+
+ bumper.user_add_device("testuser", "dev_1234") # Add device to testuser
+
+ assert (
+ bumper.user_by_deviceid("dev_1234")["userid"] == "testuser"
+ ) # Test that testuser was found by deviceid
+
+ bumper.user_remove_device("testuser", "dev_1234") # Remove device from testuser
+
+ assert "dev_1234" not in bumper.user_get("testuser")["devices"]
+ # Test that dev_1234 was not found in testuser devices
+
+ bumper.user_add_bot("testuser", "bot_1234") # Add bot did to testuser
+
+ assert "bot_1234" in bumper.user_get("testuser")["bots"]
+ # Test that bot was found in testuser's bot list
+
+ bumper.user_remove_bot("testuser", "bot_1234") # Remove bot did from testuser
+
+ assert "bot_1234" not in bumper.user_get("testuser")["bots"]
+ # Test that bot was not found in testuser's bot list
+
+ bumper.user_add_token("testuser", "token_1234") # Add token to testuser
+
+ assert bumper.check_token("testuser", "token_1234")
+ # Test that token was found for testuser
+
+ assert bumper.user_get_token("testuser", "token_1234")
+ # Test that token was returned for testuser
+
+ bumper.user_add_authcode(
+ "testuser", "token_1234", "auth_1234"
+ ) # Add authcode to token_1234 for testuser
+ assert bumper.check_authcode("testuser", "auth_1234")
+ # Test that authcode was found for testuser
+
+ bumper.user_revoke_authcode(
+ "testuser", "token_1234", "auth_1234"
+ ) # Remove authcode from testuser
+ assert bumper.check_authcode("testuser", "auth_1234") == False
+ # Test that authcode was not found for testuser
+ bumper.user_revoke_token("testuser", "token_1234") # Remove token from testuser
+ assert (
+ bumper.check_token("testuser", "token_1234") == False
+ ) # Test that token was not found for testuser
+ bumper.user_add_token("testuser", "token_1234") # Add token_1234
+ bumper.user_add_token("testuser", "token_4321") # Add token_4321
+ assert len(bumper.user_get_tokens("testuser")) == 2 # Test 2 tokens are available
+ bumper.user_revoke_all_tokens("testuser") # Revoke all tokens
+ assert len(bumper.user_get_tokens("testuser")) == 0 # Test 0 tokens are available
+
+ db = TinyDB("tests/tmp.db")
+ tokens = db.table("tokens")
+ tokens.insert(
+ {
+ "userid": "testuser",
+ "token": "token_1234",
+ "expiration": "{}".format(datetime.now() + timedelta(seconds=-10)),
+ }
+ ) # Add expired token
+ db.close()
+ assert len(bumper.user_get_tokens("testuser")) == 1 # Test 1 tokens are available
+ bumper.user_revoke_expired_tokens("testuser") # Revoke expired tokens
+ assert len(bumper.user_get_tokens("testuser")) == 0 # Test 0 tokens are available
+
+ db = TinyDB("tests/tmp.db")
+ tokens = db.table("tokens")
+ tokens.insert(
+ {
+ "userid": "testuser",
+ "token": "token_1234",
+ "expiration": "{}".format(datetime.now() + timedelta(seconds=-10)),
+ }
+ ) # Add expired token
+ db.close()
+ assert len(bumper.user_get_tokens("testuser")) == 1 # Test 1 tokens are available
+ bumper.revoke_expired_tokens() # Revoke expired tokens
+ assert len(bumper.user_get_tokens("testuser")) == 0 # Test 0 tokens are available
+
+
+def test_bot_db():
+ bumper.db = "tests/tmp.db" # Set db location for testing
+ bumper.bot_add("sn_123", "did_123", "dev_123", "res_123", "co_123")
+ assert bumper.bot_get("did_123") # Test that bot was added to db
+
+ bumper.bot_set_nick("did_123", "nick_123")
+ assert (
+ bumper.bot_get("did_123")["nick"] == "nick_123"
+ ) # Test that nick was added to bot
+
+ bumper.bot_set_mqtt("did_123", True)
+ assert bumper.bot_get("did_123")[
+ "mqtt_connection"
+ ] # Test that mqtt was set True for bot
+
+ bumper.bot_set_xmpp("did_123", True)
+ assert bumper.bot_get("did_123")[
+ "xmpp_connection"
+ ] # Test that xmpp was set True for bot
+
+ bumper.bot_remove("did_123")
+ assert bumper.bot_get("did_123") == None # Test that bot is no longer in db
+
+
+def test_client_db():
+ bumper.db = "tests/tmp.db" # Set db location for testing
+ bumper.client_add("user_123", "realm_123", "resource_123")
+ assert bumper.client_get("resource_123") # Test client was added
+
+ bumper.client_set_mqtt("resource_123", True)
+ assert bumper.client_get("resource_123")[
+ "mqtt_connection"
+ ] # Test that mqtt was set True for client
+
+ bumper.client_set_xmpp("resource_123", False)
+ assert (
+ bumper.client_get("resource_123")["xmpp_connection"] == False
+ ) # Test that xmpp was set False for client
+ assert (
+ len(bumper.get_disconnected_xmpp_clients()) == 1
+ ) # Test len of connected xmpp clients is 1
diff --git a/tests/test_init.py b/tests/test_init.py
index 7c1218e..67779e0 100644
--- a/tests/test_init.py
+++ b/tests/test_init.py
@@ -5,29 +5,18 @@ from tinydb.storages import MemoryStorage
from tinydb import TinyDB, Query
import bumper
import os
-import datetime, time
import platform
import json
import asyncio
from testfixtures import LogCapture
-def test_get_milli_time():
- assert (
- bumper.get_milli_time(
- datetime.datetime(
- 2018, 1, 1, 1, 0, 0, 0, tzinfo=datetime.timezone.utc
- ).timestamp()
- )
- == 1514768400000
- )
-
-
def test_strtobool():
assert bumper.strtobool("t") == True
assert bumper.strtobool("f") == False
assert bumper.strtobool(0) == False
+
async def test_start_stop():
with LogCapture() as l:
if os.path.exists("tests/tmp.db"):
@@ -36,12 +25,12 @@ async def test_start_stop():
b = bumper
b.db = "tests/tmp.db" # Set db location for testing
b.conf1_listen_address = "127.0.0.1"
- b.conf1_listen_port = 444
+ b.conf1_listen_port = 444
asyncio.create_task(b.start())
await asyncio.sleep(0.1)
l.check_present(("bumper", "INFO", "Starting Bumper"))
l.clear()
-
+
asyncio.create_task(b.shutdown())
await asyncio.sleep(0.1)
l.check_present(
@@ -71,142 +60,3 @@ async def test_start_stop_debug():
)
assert b.shutting_down == True
-
-def test_db_path():
- bumper.db = None
- assert bumper.db_file() == os.path.join(bumper.data_dir, "bumper.db")
-
-
-def test_user_db():
-
- bumper.db = "tests/tmp.db" # Set db location for testing
- bumper.user_add("testuser") # Add testuser
-
- assert (
- bumper.user_get("testuser")["userid"] == "testuser"
- ) # Test that testuser was created and returned
-
- bumper.user_add_device("testuser", "dev_1234") # Add device to testuser
-
- assert (
- bumper.user_by_deviceid("dev_1234")["userid"] == "testuser"
- ) # Test that testuser was found by deviceid
-
- bumper.user_remove_device("testuser", "dev_1234") # Remove device from testuser
-
- assert "dev_1234" not in bumper.user_get("testuser")["devices"]
- # Test that dev_1234 was not found in testuser devices
-
- bumper.user_add_bot("testuser", "bot_1234") # Add bot did to testuser
-
- assert "bot_1234" in bumper.user_get("testuser")["bots"]
- # Test that bot was found in testuser's bot list
-
- bumper.user_remove_bot("testuser", "bot_1234") # Remove bot did from testuser
-
- assert "bot_1234" not in bumper.user_get("testuser")["bots"]
- # Test that bot was not found in testuser's bot list
-
- bumper.user_add_token("testuser", "token_1234") # Add token to testuser
-
- assert bumper.check_token("testuser", "token_1234")
- # Test that token was found for testuser
-
- assert bumper.user_get_token("testuser", "token_1234")
- # Test that token was returned for testuser
-
- bumper.user_add_authcode(
- "testuser", "token_1234", "auth_1234"
- ) # Add authcode to token_1234 for testuser
- assert bumper.check_authcode("testuser", "auth_1234")
- # Test that authcode was found for testuser
-
- bumper.user_revoke_authcode(
- "testuser", "token_1234", "auth_1234"
- ) # Remove authcode from testuser
- assert bumper.check_authcode("testuser", "auth_1234") == False
- # Test that authcode was not found for testuser
- bumper.user_revoke_token("testuser", "token_1234") # Remove token from testuser
- assert (
- bumper.check_token("testuser", "token_1234") == False
- ) # Test that token was not found for testuser
- bumper.user_add_token("testuser", "token_1234") # Add token_1234
- bumper.user_add_token("testuser", "token_4321") # Add token_4321
- assert len(bumper.user_get_tokens("testuser")) == 2 # Test 2 tokens are available
- bumper.user_revoke_all_tokens("testuser") # Revoke all tokens
- assert len(bumper.user_get_tokens("testuser")) == 0 # Test 0 tokens are available
-
- db = TinyDB("tests/tmp.db")
- tokens = db.table("tokens")
- tokens.insert(
- {
- "userid": "testuser",
- "token": "token_1234",
- "expiration": "{}".format(
- datetime.datetime.now() + datetime.timedelta(seconds=-10)
- ),
- }
- ) # Add expired token
- db.close()
- assert len(bumper.user_get_tokens("testuser")) == 1 # Test 1 tokens are available
- bumper.user_revoke_expired_tokens("testuser") # Revoke expired tokens
- assert len(bumper.user_get_tokens("testuser")) == 0 # Test 0 tokens are available
-
- db = TinyDB("tests/tmp.db")
- tokens = db.table("tokens")
- tokens.insert(
- {
- "userid": "testuser",
- "token": "token_1234",
- "expiration": "{}".format(
- datetime.datetime.now() + datetime.timedelta(seconds=-10)
- ),
- }
- ) # Add expired token
- db.close()
- assert len(bumper.user_get_tokens("testuser")) == 1 # Test 1 tokens are available
- bumper.revoke_expired_tokens() # Revoke expired tokens
- assert len(bumper.user_get_tokens("testuser")) == 0 # Test 0 tokens are available
-
-
-def test_bot_db():
- bumper.db = "tests/tmp.db" # Set db location for testing
- bumper.bot_add("sn_123", "did_123", "dev_123", "res_123", "co_123")
- assert bumper.bot_get("did_123") # Test that bot was added to db
-
- bumper.bot_set_nick("did_123", "nick_123")
- assert (
- bumper.bot_get("did_123")["nick"] == "nick_123"
- ) # Test that nick was added to bot
-
- bumper.bot_set_mqtt("did_123", True)
- assert bumper.bot_get("did_123")[
- "mqtt_connection"
- ] # Test that mqtt was set True for bot
-
- bumper.bot_set_xmpp("did_123", True)
- assert bumper.bot_get("did_123")[
- "xmpp_connection"
- ] # Test that xmpp was set True for bot
-
- bumper.bot_remove("did_123")
- assert bumper.bot_get("did_123") == None # Test that bot is no longer in db
-
-
-def test_client_db():
- bumper.db = "tests/tmp.db" # Set db location for testing
- bumper.client_add("user_123", "realm_123", "resource_123")
- assert bumper.client_get("resource_123") # Test client was added
-
- bumper.client_set_mqtt("resource_123", True)
- assert bumper.client_get("resource_123")[
- "mqtt_connection"
- ] # Test that mqtt was set True for client
-
- bumper.client_set_xmpp("resource_123", False)
- assert (
- bumper.client_get("resource_123")["xmpp_connection"] == False
- ) # Test that xmpp was set False for client
- assert (
- len(bumper.get_disconnected_xmpp_clients()) == 1
- ) # Test len of connected xmpp clients is 1
diff --git a/tests/test_mqttserver.py b/tests/test_mqttserver.py
index cf2232b..0f0ccb2 100644
--- a/tests/test_mqttserver.py
+++ b/tests/test_mqttserver.py
@@ -14,10 +14,11 @@ import time
async def test_helperbot_message():
- with LogCapture("helperbot") as l:
- mqtt_address = ("127.0.0.1", 8883)
- mqtt_server = bumper.MQTTServer(mqtt_address)
- await mqtt_server.broker_coro()
+ mqtt_address = ("127.0.0.1", 8883)
+ mqtt_server = bumper.MQTTServer(mqtt_address)
+ await mqtt_server.broker_coro()
+
+ with LogCapture() as l:
# Test broadcast message
mqtt_helperbot = bumper.MQTTHelperBot(mqtt_address)
@@ -125,20 +126,42 @@ async def test_helperbot_message():
) # Check received message was logged
l.clear()
mqtt_helperbot.Client.disconnect()
- await mqtt_server.broker.shutdown()
+
+ # Received error message
+ mqtt_helperbot = bumper.MQTTHelperBot(mqtt_address)
+ await mqtt_helperbot.start_helper_bot()
+ assert (
+ mqtt_helperbot.Client._connected_state._value == True
+ ) # Check helperbot is connected
+ msg_payload = ""
+ msg_topic_name = "iot/atr/errors/bot_serial/ls1ok3/wC3g/x"
+ await mqtt_helperbot.Client.publish(
+ msg_topic_name, msg_payload.encode(), hbmqtt.client.QOS_0
+ )
+ try:
+ await asyncio.wait_for(mqtt_helperbot.Client.deliver_message(), timeout=0.1)
+ except asyncio.TimeoutError:
+ pass
+
+ l.check_present(
+ (
+ "boterror",
+ "ERROR",
+ "Received Error - Topic: iot/atr/errors/bot_serial/ls1ok3/wC3g/x - Message: ",
+ )
+ ) # Check received message was logged
+ l.clear()
+ mqtt_helperbot.Client.disconnect()
+
+ await mqtt_server.broker.shutdown()
async def test_helperbot_expire_message():
+ mqtt_address = ("127.0.0.1", 8883)
+ mqtt_server = bumper.MQTTServer(mqtt_address)
+ await mqtt_server.broker_coro()
+
with LogCapture("helperbot") as l:
- mqtt_address = ("127.0.0.1", 8883)
- mqtt_server = bumper.MQTTServer(mqtt_address)
- await mqtt_server.broker_coro()
- # mqtt_address = ("127.0.0.1", 8883)
- # mqtt_server = bumper.MQTTServer(mqtt_address)
- # broker = hbmqtt.broker.Broker(
- # mqtt_server.default_config, plugin_namespace="hbmqtt.test.plugins"
- # )
- # await broker.start()
# Test broadcast message
mqtt_helperbot = bumper.MQTTHelperBot(mqtt_address)
@@ -195,19 +218,14 @@ async def test_helperbot_expire_message():
)
) # Check received message was logged
mqtt_helperbot.Client.disconnect()
- await mqtt_server.broker.shutdown()
+
+ await mqtt_server.broker.shutdown()
async def test_helperbot_sendcommand():
mqtt_address = ("127.0.0.1", 8883)
mqtt_server = bumper.MQTTServer(mqtt_address)
await mqtt_server.broker_coro()
- # mqtt_address = ("127.0.0.1", 8883)
- # mqtt_server = bumper.MQTTServer(mqtt_address)
- # broker = hbmqtt.broker.Broker(
- # mqtt_server.default_config, plugin_namespace="hbmqtt.test.plugins"
- # )
- # await broker.start()
mqtt_helperbot = bumper.MQTTHelperBot(mqtt_address)
await mqtt_helperbot.start_helper_bot()
diff --git a/tests/test_xmppserver.py b/tests/test_xmppserver.py
index 74d2a0c..ef48025 100644
--- a/tests/test_xmppserver.py
+++ b/tests/test_xmppserver.py
@@ -21,10 +21,11 @@ def mock_transport_extra_info(*args, **kwargs):
async def test_xmpp_server():
+ xmpp_address = ("127.0.0.1", 5223)
+ xmpp_server = bumper.XMPPServer(xmpp_address)
+ await xmpp_server.start_async_server()
+
with LogCapture("xmppserver") as l:
- xmpp_address = ("127.0.0.1", 5223)
- xmpp_server = bumper.XMPPServer(xmpp_address)
- await xmpp_server.start_async_server()
reader, writer = await asyncio.open_connection("127.0.0.1", 5223)
@@ -52,10 +53,8 @@ async def test_xmpp_server():
await writer.drain()
await asyncio.sleep(0.1)
- xmpp_server.disconnect()
- await asyncio.sleep(0.1)
- assert len(xmpp_server.clients) == 0 # Client count decreased
- print(l)
+
+ xmpp_server.disconnect()
async def test_client_connect_no_starttls(*args, **kwargs):
@@ -209,6 +208,11 @@ async def test_client_connect_starttls_called(*args, **kwargs):
async def test_xmpp_server_client_tls():
+
+ xmpp_address = ("127.0.0.1", 5223)
+ xmpp_server = bumper.XMPPServer(xmpp_address)
+ await xmpp_server.start_async_server()
+
with LogCapture("xmppserver") as l:
async def do_stuff_after_start_tls(
@@ -227,10 +231,6 @@ async def test_xmpp_server_client_tls():
await writer.drain()
- xmpp_address = ("127.0.0.1", 5223)
- xmpp_server = bumper.XMPPServer(xmpp_address)
- await xmpp_server.start_async_server()
-
reader, writer = await asyncio.open_connection("127.0.0.1", 5223)
writer.write(
@@ -616,3 +616,30 @@ async def test_client_send_iq(*args, **kwargs):
# Reset mock calls
mock_send.reset_mock()
+ # Bot error report
+ test_data = "".encode(
+ "utf-8"
+ )
+ xmppclient2._parse_data(test_data)
+
+ assert (
+ mock_send.mock_calls[0].args[0]
+ == ''
+ ) # result sent to ecouser.net
+
+ # Reset mock calls
+ mock_send.reset_mock()
+
+ # Bot "DorpError" to all
+ test_data = "".encode(
+ "utf-8"
+ )
+ xmppclient2._parse_data(test_data)
+ assert (
+ mock_send.mock_calls[0].args[0]
+ == ''
+ ) # result sent to ecouser.net
+
+ # Reset mock calls
+ mock_send.reset_mock()
+
diff --git a/tests/test_z_problem.py b/tests/test_z_problem.py
index f3f00f2..3bd2ca5 100644
--- a/tests/test_z_problem.py
+++ b/tests/test_z_problem.py
@@ -100,4 +100,3 @@ def test_main(mock_firstrun):
bumper.main()
assert mock_firstrun.called == True
bumper.ca_cert = "tests/test_certs/ca.crt"
-