Re-org and start of API #47
12 changed files with 1323 additions and 1169 deletions
|
|
@ -3,14 +3,12 @@
|
||||||
from bumper.confserver import ConfServer
|
from bumper.confserver import ConfServer
|
||||||
from bumper.mqttserver import MQTTServer, MQTTHelperBot
|
from bumper.mqttserver import MQTTServer, MQTTHelperBot
|
||||||
from bumper.xmppserver import XMPPServer
|
from bumper.xmppserver import XMPPServer
|
||||||
|
from bumper.models import *
|
||||||
|
from bumper.db import *
|
||||||
import asyncio
|
import asyncio
|
||||||
import json
|
|
||||||
from datetime import datetime, timedelta
|
|
||||||
import os
|
import os
|
||||||
import logging
|
import logging
|
||||||
from logging.handlers import RotatingFileHandler
|
from logging.handlers import RotatingFileHandler
|
||||||
from tinydb import TinyDB, Query
|
|
||||||
from tinydb.storages import MemoryStorage
|
|
||||||
import socket
|
import socket
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
@ -100,6 +98,15 @@ helperbotlog.addHandler(helperbot_rotate)
|
||||||
# Override the logging level
|
# Override the logging level
|
||||||
# helperbotlog.setLevel(logging.INFO)
|
# 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")
|
xmppserverlog = logging.getLogger("xmppserver")
|
||||||
xmpp_rotate = RotatingFileHandler(
|
xmpp_rotate = RotatingFileHandler(
|
||||||
"logs/xmppserver.log", maxBytes=5000000, backupCount=5
|
"logs/xmppserver.log", maxBytes=5000000, backupCount=5
|
||||||
|
|
@ -156,23 +163,12 @@ async def start():
|
||||||
global mqtt_helperbot
|
global mqtt_helperbot
|
||||||
mqtt_helperbot = MQTTHelperBot((bumper_listen, mqtt_listen_port))
|
mqtt_helperbot = MQTTHelperBot((bumper_listen, mqtt_listen_port))
|
||||||
global conf_server
|
global conf_server
|
||||||
conf_server = ConfServer(
|
conf_server = ConfServer((bumper_listen, conf1_listen_port), usessl=True)
|
||||||
(bumper_listen, conf1_listen_port), usessl=True, helperbot=mqtt_helperbot
|
|
||||||
)
|
|
||||||
global conf_server_2
|
global conf_server_2
|
||||||
conf_server_2 = ConfServer(
|
conf_server_2 = ConfServer((bumper_listen, conf2_listen_port), usessl=False)
|
||||||
(bumper_listen, conf2_listen_port), usessl=False, helperbot=mqtt_helperbot
|
|
||||||
)
|
|
||||||
global xmpp_server
|
global xmpp_server
|
||||||
xmpp_server = XMPPServer((bumper_listen, xmpp_listen_port))
|
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
|
# Start MQTT Server
|
||||||
asyncio.create_task(mqtt_server.broker_coro())
|
asyncio.create_task(mqtt_server.broker_coro())
|
||||||
|
|
||||||
|
|
@ -182,6 +178,20 @@ async def start():
|
||||||
# Start XMPP Server
|
# Start XMPP Server
|
||||||
asyncio.create_task(xmpp_server.start_async_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
|
# Start maintenance
|
||||||
while not shutting_down:
|
while not shutting_down:
|
||||||
asyncio.create_task(maintenance())
|
asyncio.create_task(maintenance())
|
||||||
|
|
@ -223,724 +233,6 @@ async def shutdown():
|
||||||
bumperlog.info("Shutdown complete")
|
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():
|
def create_certs():
|
||||||
import platform
|
import platform
|
||||||
import os
|
import os
|
||||||
|
|
@ -991,6 +283,7 @@ def create_certs():
|
||||||
def first_run():
|
def first_run():
|
||||||
create_certs()
|
create_certs()
|
||||||
|
|
||||||
|
|
||||||
def main(argv=None):
|
def main(argv=None):
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import ssl
|
||||||
import string
|
import string
|
||||||
import random
|
import random
|
||||||
import bumper
|
import bumper
|
||||||
|
from bumper.models import *
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
import asyncio
|
import asyncio
|
||||||
from aiohttp import web
|
from aiohttp import web
|
||||||
|
|
@ -36,42 +37,24 @@ logging.getLogger("aiohttp.access").addFilter(
|
||||||
) # Add logging filter above to aiohttp.access
|
) # 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:
|
class ConfServer:
|
||||||
def __init__(self, address, usessl=False, helperbot=None):
|
def __init__(self, address, usessl=False):
|
||||||
self.helperbot = helperbot
|
|
||||||
self.usessl = usessl
|
self.usessl = usessl
|
||||||
self.address = address
|
self.address = address
|
||||||
self.confthread = None
|
|
||||||
self.run_async = False
|
|
||||||
self.app = None
|
self.app = None
|
||||||
self.site = None
|
self.site = None
|
||||||
self.runner = None
|
self.runner = None
|
||||||
|
|
||||||
|
def get_milli_time(self, timetoconvert):
|
||||||
|
return int(round(timetoconvert * 1000))
|
||||||
|
|
||||||
def confserver_app(self):
|
def confserver_app(self):
|
||||||
self.app = web.Application(loop=asyncio.get_event_loop())
|
self.app = web.Application(loop=asyncio.get_event_loop())
|
||||||
|
|
||||||
self.app.add_routes(
|
self.app.add_routes(
|
||||||
[
|
[
|
||||||
web.get("", self.handle_base),
|
web.get("", self.handle_base),
|
||||||
|
web.get("/restart_{service}", self.handle_RestartService),
|
||||||
web.get(
|
web.get(
|
||||||
"/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/login",
|
"/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/login",
|
||||||
self.handle_login,
|
self.handle_login,
|
||||||
|
|
@ -210,9 +193,82 @@ class ConfServer:
|
||||||
async def handle_base(self, request):
|
async def handle_base(self, request):
|
||||||
try:
|
try:
|
||||||
# TODO - API Options here for viewing clients, tokens, restarting the server, etc.
|
# 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:
|
except Exception as e:
|
||||||
confserverlog.exception("{}".format(e))
|
confserverlog.exception("{}".format(e))
|
||||||
|
|
@ -256,7 +312,7 @@ class ConfServer:
|
||||||
login_details.email = "null@null.com"
|
login_details.email = "null@null.com"
|
||||||
|
|
||||||
body = {
|
body = {
|
||||||
"code": bumper.RETURN_API_SUCCESS,
|
"code": API_ERRORS[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
|
||||||
|
|
@ -266,9 +322,7 @@ class ConfServer:
|
||||||
# "username": "fusername_{}".format(tmpuser["userid"]),
|
# "username": "fusername_{}".format(tmpuser["userid"]),
|
||||||
# },
|
# },
|
||||||
"msg": "操作成功",
|
"msg": "操作成功",
|
||||||
"time": bumper.get_milli_time(
|
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||||
datetime.utcnow().timestamp()
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return web.json_response(body)
|
return web.json_response(body)
|
||||||
|
|
@ -277,7 +331,7 @@ class ConfServer:
|
||||||
"code": bumper.ERR_USER_NOT_ACTIVATED,
|
"code": bumper.ERR_USER_NOT_ACTIVATED,
|
||||||
"data": None,
|
"data": None,
|
||||||
"msg": "当前密码错误",
|
"msg": "当前密码错误",
|
||||||
"time": bumper.get_milli_time(datetime.utcnow().timestamp()),
|
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||||
}
|
}
|
||||||
|
|
||||||
return web.json_response(body)
|
return web.json_response(body)
|
||||||
|
|
@ -323,7 +377,7 @@ class ConfServer:
|
||||||
"loginName": login_details.loginName,
|
"loginName": login_details.loginName,
|
||||||
},
|
},
|
||||||
"msg": "操作成功",
|
"msg": "操作成功",
|
||||||
"time": bumper.get_milli_time(datetime.utcnow().timestamp()),
|
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||||
}
|
}
|
||||||
return web.json_response(body)
|
return web.json_response(body)
|
||||||
|
|
||||||
|
|
@ -359,7 +413,7 @@ class ConfServer:
|
||||||
# "username": "fusername_{}".format(tmpuser["userid"]),
|
# "username": "fusername_{}".format(tmpuser["userid"]),
|
||||||
# },
|
# },
|
||||||
"msg": "操作成功",
|
"msg": "操作成功",
|
||||||
"time": bumper.get_milli_time(datetime.utcnow().timestamp()),
|
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||||
}
|
}
|
||||||
return web.json_response(body)
|
return web.json_response(body)
|
||||||
|
|
||||||
|
|
@ -368,7 +422,7 @@ class ConfServer:
|
||||||
"code": bumper.ERR_TOKEN_INVALID,
|
"code": bumper.ERR_TOKEN_INVALID,
|
||||||
"data": None,
|
"data": None,
|
||||||
"msg": "当前密码错误",
|
"msg": "当前密码错误",
|
||||||
"time": bumper.get_milli_time(datetime.utcnow().timestamp()),
|
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||||
}
|
}
|
||||||
return web.json_response(body)
|
return web.json_response(body)
|
||||||
|
|
||||||
|
|
@ -459,7 +513,7 @@ class ConfServer:
|
||||||
# "username": "fusername_{}".format(tmpuser["userid"]),
|
# "username": "fusername_{}".format(tmpuser["userid"]),
|
||||||
# },
|
# },
|
||||||
"msg": "操作成功",
|
"msg": "操作成功",
|
||||||
"time": bumper.get_milli_time(datetime.utcnow().timestamp()),
|
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||||
}
|
}
|
||||||
|
|
||||||
return body
|
return body
|
||||||
|
|
@ -483,7 +537,7 @@ class ConfServer:
|
||||||
"code": bumper.RETURN_API_SUCCESS,
|
"code": bumper.RETURN_API_SUCCESS,
|
||||||
"data": None,
|
"data": None,
|
||||||
"msg": "操作成功",
|
"msg": "操作成功",
|
||||||
"time": bumper.get_milli_time(datetime.utcnow().timestamp()),
|
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||||
}
|
}
|
||||||
|
|
||||||
return web.json_response(body)
|
return web.json_response(body)
|
||||||
|
|
@ -525,7 +579,7 @@ class ConfServer:
|
||||||
},
|
},
|
||||||
"msg": "操作成功",
|
"msg": "操作成功",
|
||||||
"success": True,
|
"success": True,
|
||||||
"time": bumper.get_milli_time(
|
"time": self.get_milli_time(
|
||||||
datetime.utcnow().timestamp()
|
datetime.utcnow().timestamp()
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
@ -537,7 +591,7 @@ class ConfServer:
|
||||||
"ecovacsUid": request.query["uid"],
|
"ecovacsUid": request.query["uid"],
|
||||||
},
|
},
|
||||||
"msg": "操作成功",
|
"msg": "操作成功",
|
||||||
"time": bumper.get_milli_time(
|
"time": self.get_milli_time(
|
||||||
datetime.utcnow().timestamp()
|
datetime.utcnow().timestamp()
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
@ -547,7 +601,7 @@ class ConfServer:
|
||||||
"code": bumper.ERR_TOKEN_INVALID,
|
"code": bumper.ERR_TOKEN_INVALID,
|
||||||
"data": None,
|
"data": None,
|
||||||
"msg": "当前密码错误",
|
"msg": "当前密码错误",
|
||||||
"time": bumper.get_milli_time(datetime.utcnow().timestamp()),
|
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||||
}
|
}
|
||||||
|
|
||||||
return web.json_response(body)
|
return web.json_response(body)
|
||||||
|
|
@ -569,7 +623,7 @@ class ConfServer:
|
||||||
"v": None,
|
"v": None,
|
||||||
},
|
},
|
||||||
"msg": "操作成功",
|
"msg": "操作成功",
|
||||||
"time": bumper.get_milli_time(datetime.utcnow().timestamp()),
|
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||||
}
|
}
|
||||||
|
|
||||||
return web.json_response(body)
|
return web.json_response(body)
|
||||||
|
|
@ -594,7 +648,7 @@ class ConfServer:
|
||||||
},
|
},
|
||||||
"msg": "操作成功",
|
"msg": "操作成功",
|
||||||
"success": True,
|
"success": True,
|
||||||
"time": bumper.get_milli_time(datetime.utcnow().timestamp()),
|
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||||
}
|
}
|
||||||
|
|
||||||
return web.json_response(body)
|
return web.json_response(body)
|
||||||
|
|
@ -609,7 +663,7 @@ class ConfServer:
|
||||||
"data": None,
|
"data": None,
|
||||||
"msg": "操作成功",
|
"msg": "操作成功",
|
||||||
"success": True,
|
"success": True,
|
||||||
"time": bumper.get_milli_time(datetime.utcnow().timestamp()),
|
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||||
}
|
}
|
||||||
|
|
||||||
return web.json_response(body)
|
return web.json_response(body)
|
||||||
|
|
@ -624,7 +678,7 @@ class ConfServer:
|
||||||
"data": None,
|
"data": None,
|
||||||
"msg": "操作成功",
|
"msg": "操作成功",
|
||||||
"success": True,
|
"success": True,
|
||||||
"time": bumper.get_milli_time(datetime.utcnow().timestamp()),
|
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||||
}
|
}
|
||||||
|
|
||||||
return web.json_response(body)
|
return web.json_response(body)
|
||||||
|
|
@ -639,7 +693,7 @@ class ConfServer:
|
||||||
"data": None,
|
"data": None,
|
||||||
"msg": "操作成功",
|
"msg": "操作成功",
|
||||||
"success": True,
|
"success": True,
|
||||||
"time": bumper.get_milli_time(datetime.utcnow().timestamp()),
|
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||||
}
|
}
|
||||||
|
|
||||||
return web.json_response(body)
|
return web.json_response(body)
|
||||||
|
|
@ -654,7 +708,7 @@ class ConfServer:
|
||||||
"data": "N",
|
"data": "N",
|
||||||
"msg": "操作成功",
|
"msg": "操作成功",
|
||||||
"success": True,
|
"success": True,
|
||||||
"time": bumper.get_milli_time(datetime.utcnow().timestamp()),
|
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||||
}
|
}
|
||||||
|
|
||||||
return web.json_response(body)
|
return web.json_response(body)
|
||||||
|
|
@ -678,7 +732,7 @@ class ConfServer:
|
||||||
"data": {"hasNextPage": 0, "items": []},
|
"data": {"hasNextPage": 0, "items": []},
|
||||||
"msg": "操作成功",
|
"msg": "操作成功",
|
||||||
"success": True,
|
"success": True,
|
||||||
"time": bumper.get_milli_time(datetime.utcnow().timestamp()),
|
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||||
}
|
}
|
||||||
|
|
||||||
return web.json_response(body)
|
return web.json_response(body)
|
||||||
|
|
@ -698,7 +752,7 @@ class ConfServer:
|
||||||
},
|
},
|
||||||
"msg": "操作成功",
|
"msg": "操作成功",
|
||||||
"success": True,
|
"success": True,
|
||||||
"time": bumper.get_milli_time(datetime.utcnow().timestamp()),
|
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||||
}
|
}
|
||||||
|
|
||||||
return web.json_response(body)
|
return web.json_response(body)
|
||||||
|
|
@ -720,7 +774,7 @@ class ConfServer:
|
||||||
},
|
},
|
||||||
"msg": "操作成功",
|
"msg": "操作成功",
|
||||||
"success": True,
|
"success": True,
|
||||||
"time": bumper.get_milli_time(datetime.utcnow().timestamp()),
|
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||||
}
|
}
|
||||||
|
|
||||||
return web.json_response(body)
|
return web.json_response(body)
|
||||||
|
|
@ -752,14 +806,14 @@ class ConfServer:
|
||||||
],
|
],
|
||||||
"msg": "操作成功",
|
"msg": "操作成功",
|
||||||
"success": True,
|
"success": True,
|
||||||
"time": bumper.get_milli_time(datetime.utcnow().timestamp()),
|
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
body = {
|
body = {
|
||||||
"code": bumper.RETURN_API_SUCCESS,
|
"code": bumper.RETURN_API_SUCCESS,
|
||||||
"data": [],
|
"data": [],
|
||||||
"msg": "操作成功",
|
"msg": "操作成功",
|
||||||
"time": bumper.get_milli_time(datetime.utcnow().timestamp()),
|
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||||
}
|
}
|
||||||
|
|
||||||
return web.json_response(body)
|
return web.json_response(body)
|
||||||
|
|
@ -769,7 +823,7 @@ class ConfServer:
|
||||||
|
|
||||||
async def handle_homePageAlert(self, request):
|
async def handle_homePageAlert(self, request):
|
||||||
try:
|
try:
|
||||||
nextAlert = bumper.get_milli_time(
|
nextAlert = self.get_milli_time(
|
||||||
(datetime.now() + timedelta(hours=12)).timestamp()
|
(datetime.now() + timedelta(hours=12)).timestamp()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -781,10 +835,10 @@ class ConfServer:
|
||||||
"hasCampaign": "N",
|
"hasCampaign": "N",
|
||||||
"imageUrl": None,
|
"imageUrl": None,
|
||||||
"nextAlertTime": nextAlert,
|
"nextAlertTime": nextAlert,
|
||||||
"serverTime": bumper.get_milli_time(datetime.utcnow().timestamp()),
|
"serverTime": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||||
},
|
},
|
||||||
"msg": "操作成功",
|
"msg": "操作成功",
|
||||||
"time": bumper.get_milli_time(datetime.utcnow().timestamp()),
|
"time": self.get_milli_time(datetime.utcnow().timestamp()),
|
||||||
}
|
}
|
||||||
|
|
||||||
return web.json_response(body)
|
return web.json_response(body)
|
||||||
|
|
@ -1088,9 +1142,11 @@ class ConfServer:
|
||||||
|
|
||||||
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":
|
||||||
body = ""
|
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("Send Bot - {}".format(json_body))
|
||||||
confserverlog.debug("Bot Response - {}".format(body))
|
confserverlog.debug("Bot Response - {}".format(body))
|
||||||
logs = []
|
logs = []
|
||||||
|
|
@ -1138,8 +1194,10 @@ class ConfServer:
|
||||||
|
|
||||||
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":
|
||||||
retcmd = await self.helperbot.send_command(json_body, randomid)
|
retcmd = await bumper.mqtt_helperbot.send_command(
|
||||||
|
json_body, randomid
|
||||||
|
)
|
||||||
body = retcmd
|
body = retcmd
|
||||||
confserverlog.debug("Send Bot - {}".format(json_body))
|
confserverlog.debug("Send Bot - {}".format(json_body))
|
||||||
confserverlog.debug("Bot Response - {}".format(body))
|
confserverlog.debug("Bot Response - {}".format(body))
|
||||||
|
|
@ -1184,7 +1242,9 @@ class ConfServer:
|
||||||
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:
|
||||||
retcmd = await self.helperbot.send_command(json_body, randomid)
|
retcmd = await bumper.mqtt_helperbot.send_command(
|
||||||
|
json_body, randomid
|
||||||
|
)
|
||||||
body = retcmd
|
body = retcmd
|
||||||
confserverlog.debug("Send Bot - {}".format(json_body))
|
confserverlog.debug("Send Bot - {}".format(json_body))
|
||||||
confserverlog.debug("Bot Response - {}".format(body))
|
confserverlog.debug("Bot Response - {}".format(body))
|
||||||
|
|
@ -1215,9 +1275,6 @@ class ConfServer:
|
||||||
async def disconnect(self):
|
async def disconnect(self):
|
||||||
try:
|
try:
|
||||||
confserverlog.info("shutting down")
|
confserverlog.info("shutting down")
|
||||||
if self.run_async:
|
|
||||||
self.confthread.join()
|
|
||||||
else:
|
|
||||||
await self.app.shutdown()
|
await self.app.shutdown()
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
|
||||||
366
bumper/db.py
Normal file
366
bumper/db.py
Normal file
|
|
@ -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)
|
||||||
401
bumper/models.py
Normal file
401
bumper/models.py
Normal file
|
|
@ -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",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -15,6 +15,7 @@ from datetime import datetime, timedelta
|
||||||
import bumper
|
import bumper
|
||||||
|
|
||||||
helperbotlog = logging.getLogger("helperbot")
|
helperbotlog = logging.getLogger("helperbot")
|
||||||
|
boterrorlog = logging.getLogger("boterror")
|
||||||
mqttserverlog = logging.getLogger("mqttserver")
|
mqttserverlog = logging.getLogger("mqttserver")
|
||||||
|
|
||||||
logging.getLogger("transitions").setLevel(logging.CRITICAL + 1) # Ignore this logger
|
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:
|
class MQTTHelperBot:
|
||||||
|
|
||||||
Client = MQTTClient()
|
Client = None
|
||||||
wait_resp_timeout_seconds = 10
|
wait_resp_timeout_seconds = 10
|
||||||
expire_msg_seconds = 10
|
expire_msg_seconds = 10
|
||||||
|
|
||||||
|
|
@ -38,11 +39,11 @@ class MQTTHelperBot:
|
||||||
self.address = address
|
self.address = address
|
||||||
self.client_id = "helper1@bumper/helper1"
|
self.client_id = "helper1@bumper/helper1"
|
||||||
self.command_responses = []
|
self.command_responses = []
|
||||||
self.helperthread = None
|
|
||||||
|
|
||||||
async def start_helper_bot(self):
|
async def start_helper_bot(self):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
if self.Client is None:
|
||||||
self.Client = MQTTClient(
|
self.Client = MQTTClient(
|
||||||
client_id=self.client_id, config={"check_hostname": False}
|
client_id=self.client_id, config={"check_hostname": False}
|
||||||
)
|
)
|
||||||
|
|
@ -102,11 +103,19 @@ class MQTTHelperBot:
|
||||||
)
|
)
|
||||||
elif str(message.topic).split("/")[1] == "atr":
|
elif str(message.topic).split("/")[1] == "atr":
|
||||||
# Broadcast message received on atr
|
# Broadcast message received on atr
|
||||||
|
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(
|
helperbotlog.debug(
|
||||||
"Received Broadcast - Topic: {} - Message: {}".format(
|
"Received Broadcast - Topic: {} - Message: {}".format(
|
||||||
message.topic, str(message.data.decode("utf-8"))
|
message.topic, str(message.data.decode("utf-8"))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
helperbotlog.debug(
|
helperbotlog.debug(
|
||||||
"Received Message - Topic: {} - Message: {}".format(
|
"Received Message - Topic: {} - Message: {}".format(
|
||||||
|
|
@ -174,6 +183,7 @@ class MQTTHelperBot:
|
||||||
}
|
}
|
||||||
|
|
||||||
async def send_command(self, cmdjson, requestid):
|
async def send_command(self, cmdjson, requestid):
|
||||||
|
if not self.Client._handler.writer is None:
|
||||||
try:
|
try:
|
||||||
ttopic = "iot/p2p/{}/helper1/bumper/helper1/{}/{}/{}/q/{}/{}".format(
|
ttopic = "iot/p2p/{}/helper1/bumper/helper1/{}/{}/{}/q/{}/{}".format(
|
||||||
cmdjson["cmdName"],
|
cmdjson["cmdName"],
|
||||||
|
|
@ -224,7 +234,6 @@ class MQTTServer:
|
||||||
|
|
||||||
def __init__(self, address):
|
def __init__(self, address):
|
||||||
try:
|
try:
|
||||||
self.mqttserverthread = None
|
|
||||||
self.address = address
|
self.address = address
|
||||||
|
|
||||||
# The below adds a plugin to the hbmqtt.broker.plugins without having to futz with setup.py
|
# The below adds a plugin to the hbmqtt.broker.plugins without having to futz with setup.py
|
||||||
|
|
@ -345,7 +354,7 @@ class BumperMQTTServer_Plugin:
|
||||||
return authenticated
|
return authenticated
|
||||||
|
|
||||||
async def on_broker_client_connected(self, client_id):
|
async def on_broker_client_connected(self, client_id):
|
||||||
try:
|
|
||||||
didsplit = str(client_id).split("@")
|
didsplit = str(client_id).split("@")
|
||||||
|
|
||||||
bot = bumper.bot_get(didsplit[0])
|
bot = bumper.bot_get(didsplit[0])
|
||||||
|
|
@ -360,11 +369,8 @@ class BumperMQTTServer_Plugin:
|
||||||
bumper.client_set_mqtt(client["resource"], True)
|
bumper.client_set_mqtt(client["resource"], True)
|
||||||
return
|
return
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
mqttserverlog.exception("{}".format(e))
|
|
||||||
|
|
||||||
async def on_broker_client_disconnected(self, client_id):
|
async def on_broker_client_disconnected(self, client_id):
|
||||||
try:
|
|
||||||
didsplit = str(client_id).split("@")
|
didsplit = str(client_id).split("@")
|
||||||
|
|
||||||
bot = bumper.bot_get(didsplit[0])
|
bot = bumper.bot_get(didsplit[0])
|
||||||
|
|
@ -378,7 +384,3 @@ class BumperMQTTServer_Plugin:
|
||||||
if client:
|
if client:
|
||||||
bumper.client_set_mqtt(client["resource"], False)
|
bumper.client_set_mqtt(client["resource"], False)
|
||||||
return
|
return
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
mqttserverlog.exception("{}".format(e))
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import bumper
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
xmppserverlog = logging.getLogger("xmppserver")
|
xmppserverlog = logging.getLogger("xmppserver")
|
||||||
|
boterrorlog = logging.getLogger("boterror")
|
||||||
|
|
||||||
|
|
||||||
class XMPPServer:
|
class XMPPServer:
|
||||||
|
|
@ -50,8 +51,8 @@ class XMPPServer:
|
||||||
asyncio.create_task(bumper.shutdown())
|
asyncio.create_task(bumper.shutdown())
|
||||||
|
|
||||||
def disconnect(self):
|
def disconnect(self):
|
||||||
try:
|
|
||||||
xmppserverlog.debug("waiting for all client threads to exit")
|
xmppserverlog.debug("waiting for all clients to disconnect")
|
||||||
for client in self.clients:
|
for client in self.clients:
|
||||||
client._disconnect()
|
client._disconnect()
|
||||||
|
|
||||||
|
|
@ -59,9 +60,6 @@ class XMPPServer:
|
||||||
xmppserverlog.debug("shutting down")
|
xmppserverlog.debug("shutting down")
|
||||||
self.server_coro.cancel()
|
self.server_coro.cancel()
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
xmppserverlog.error("{}".format(e))
|
|
||||||
|
|
||||||
|
|
||||||
class XMPPServer_Protocol(asyncio.Protocol):
|
class XMPPServer_Protocol(asyncio.Protocol):
|
||||||
client_id = None
|
client_id = None
|
||||||
|
|
@ -614,17 +612,12 @@ class XMPPAsyncClient:
|
||||||
xmppserverlog.exception("{}".format(e))
|
xmppserverlog.exception("{}".format(e))
|
||||||
|
|
||||||
def _handle_session(self, xml):
|
def _handle_session(self, xml):
|
||||||
try:
|
|
||||||
res = '<iq type="result" id="{}" />'.format(xml.get("id"))
|
res = '<iq type="result" id="{}" />'.format(xml.get("id"))
|
||||||
self._set_state("READY")
|
self._set_state("READY")
|
||||||
self.send(res)
|
self.send(res)
|
||||||
asyncio.Task(self.schedule_ping(30))
|
asyncio.Task(self.schedule_ping(30))
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
xmppserverlog.exception("{}".format(e))
|
|
||||||
|
|
||||||
def _handle_presence(self, xml):
|
def _handle_presence(self, xml):
|
||||||
try:
|
|
||||||
|
|
||||||
if len(xml) and xml[0].tag == "status":
|
if len(xml) and xml[0].tag == "status":
|
||||||
xmppserverlog.debug(
|
xmppserverlog.debug(
|
||||||
|
|
@ -635,9 +628,7 @@ class XMPPAsyncClient:
|
||||||
# Most likely a bot, possibly hello world in text
|
# Most likely a bot, possibly hello world in text
|
||||||
|
|
||||||
# Send dummy return
|
# Send dummy return
|
||||||
self.send(
|
self.send('<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:
|
||||||
|
|
@ -686,9 +677,6 @@ class XMPPAsyncClient:
|
||||||
'<presence to="{}"> dummy </presence>'.format(self.bumper_jid)
|
'<presence to="{}"> dummy </presence>'.format(self.bumper_jid)
|
||||||
)
|
)
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
xmppserverlog.exception("{}".format(e))
|
|
||||||
|
|
||||||
def _parse_data(self, data):
|
def _parse_data(self, data):
|
||||||
|
|
||||||
if data.decode("utf-8").startswith(
|
if data.decode("utf-8").startswith(
|
||||||
|
|
@ -721,6 +709,19 @@ class XMPPAsyncClient:
|
||||||
).replace("ns0:", ""),
|
).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)
|
self._handle_iq(item, newdata)
|
||||||
item.clear()
|
item.clear()
|
||||||
|
|
||||||
|
|
@ -790,7 +791,7 @@ class XMPPAsyncClient:
|
||||||
xmppserverlog.exception("{}".format(e))
|
xmppserverlog.exception("{}".format(e))
|
||||||
|
|
||||||
def _handle_iq(self, xml, data):
|
def _handle_iq(self, xml, data):
|
||||||
try:
|
|
||||||
if len(xml):
|
if len(xml):
|
||||||
child = self._tag_strip_uri(xml[0].tag)
|
child = self._tag_strip_uri(xml[0].tag)
|
||||||
else:
|
else:
|
||||||
|
|
@ -818,6 +819,3 @@ class XMPPAsyncClient:
|
||||||
self._handle_result(xml, data)
|
self._handle_result(xml, data)
|
||||||
else:
|
else:
|
||||||
self._handle_result(xml, data)
|
self._handle_result(xml, data)
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
xmppserverlog.exception("{}".format(e))
|
|
||||||
|
|
|
||||||
|
|
@ -7,15 +7,16 @@ import json
|
||||||
import tinydb
|
import tinydb
|
||||||
import pytest_aiohttp
|
import pytest_aiohttp
|
||||||
import pytest_asyncio
|
import pytest_asyncio
|
||||||
|
import datetime, time
|
||||||
from aiohttp import web
|
from aiohttp import web
|
||||||
|
|
||||||
|
|
||||||
def create_confserver():
|
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):
|
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()
|
confserver.confserver_app()
|
||||||
return confserver.app
|
return confserver.app
|
||||||
|
|
||||||
|
|
@ -32,18 +33,31 @@ def remove_existing_db():
|
||||||
|
|
||||||
|
|
||||||
async def test_confserver_ssl():
|
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()
|
conf_server.confserver_app()
|
||||||
asyncio.create_task(conf_server.start_server())
|
asyncio.create_task(conf_server.start_server())
|
||||||
|
|
||||||
|
|
||||||
async def test_confserver_no_ssl():
|
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()
|
conf_server.confserver_app()
|
||||||
asyncio.create_task(conf_server.start_server())
|
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()
|
remove_existing_db()
|
||||||
bumper.db = "tests/tmp.db" # Set db location for testing
|
bumper.db = "tests/tmp.db" # Set db location for testing
|
||||||
client = await aiohttp_client(create_app)
|
client = await aiohttp_client(create_app)
|
||||||
|
|
@ -51,7 +65,7 @@ async def test_base(aiohttp_client):
|
||||||
resp = await client.get("/")
|
resp = await client.get("/")
|
||||||
assert resp.status == 200
|
assert resp.status == 200
|
||||||
text = await resp.text()
|
text = await resp.text()
|
||||||
assert "Bumper!" in text
|
assert "Bumper!" in text """
|
||||||
|
|
||||||
|
|
||||||
async def test_login(aiohttp_client):
|
async def test_login(aiohttp_client):
|
||||||
|
|
@ -696,6 +710,7 @@ async def test_lg_logs(aiohttp_client):
|
||||||
bumper.bot_set_mqtt("did_1234", True)
|
bumper.bot_set_mqtt("did_1234", True)
|
||||||
confserver = create_confserver()
|
confserver = create_confserver()
|
||||||
client = await aiohttp_client(create_app)
|
client = await aiohttp_client(create_app)
|
||||||
|
bumper.mqtt_helperbot = bumper.mqttserver.MQTTHelperBot("127.0.0.1")
|
||||||
|
|
||||||
# Test return get status
|
# Test return get status
|
||||||
command_getstatus_resp = {
|
command_getstatus_resp = {
|
||||||
|
|
@ -703,7 +718,7 @@ async def test_lg_logs(aiohttp_client):
|
||||||
"resp": "<ctl ret='ok' status='idle'/>",
|
"resp": "<ctl ret='ok' status='idle'/>",
|
||||||
"ret": "ok",
|
"ret": "ok",
|
||||||
}
|
}
|
||||||
confserver.helperbot.send_command = mock.MagicMock(
|
bumper.mqtt_helperbot.send_command = mock.MagicMock(
|
||||||
return_value=async_return(command_getstatus_resp)
|
return_value=async_return(command_getstatus_resp)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -726,14 +741,6 @@ async def test_lg_logs(aiohttp_client):
|
||||||
jsonresp = json.loads(text)
|
jsonresp = json.loads(text)
|
||||||
assert jsonresp["ret"] == "ok"
|
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):
|
async def test_postLookup(aiohttp_client):
|
||||||
remove_existing_db()
|
remove_existing_db()
|
||||||
|
|
@ -762,6 +769,7 @@ async def test_devmgr(aiohttp_client):
|
||||||
bumper.db = "tests/tmp.db" # Set db location for testing
|
bumper.db = "tests/tmp.db" # Set db location for testing
|
||||||
confserver = create_confserver()
|
confserver = create_confserver()
|
||||||
client = await aiohttp_client(create_app)
|
client = await aiohttp_client(create_app)
|
||||||
|
bumper.mqtt_helperbot = bumper.mqttserver.MQTTHelperBot("127.0.0.1")
|
||||||
|
|
||||||
# Test PollSCResult
|
# Test PollSCResult
|
||||||
postbody = {"td": "PollSCResult"}
|
postbody = {"td": "PollSCResult"}
|
||||||
|
|
@ -791,7 +799,7 @@ async def test_devmgr(aiohttp_client):
|
||||||
"resp": "<ctl ret='ok' status='idle'/>",
|
"resp": "<ctl ret='ok' status='idle'/>",
|
||||||
"ret": "ok",
|
"ret": "ok",
|
||||||
}
|
}
|
||||||
confserver.helperbot.send_command = mock.MagicMock(
|
bumper.mqtt_helperbot.send_command = mock.MagicMock(
|
||||||
return_value=async_return(command_getstatus_resp)
|
return_value=async_return(command_getstatus_resp)
|
||||||
)
|
)
|
||||||
resp = await client.post("/api/iot/devmanager.do", json=postbody)
|
resp = await client.post("/api/iot/devmanager.do", json=postbody)
|
||||||
|
|
@ -802,7 +810,7 @@ async def test_devmgr(aiohttp_client):
|
||||||
|
|
||||||
# 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(
|
bumper.mqtt_helperbot.send_command = mock.MagicMock(
|
||||||
return_value=async_return(command_timeout_resp)
|
return_value=async_return(command_timeout_resp)
|
||||||
)
|
)
|
||||||
resp = await client.post("/api/iot/devmanager.do", json=postbody)
|
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)
|
test_resp = json.loads(text)
|
||||||
assert test_resp["ret"] == "fail"
|
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):
|
async def test_dim_devmanager(aiohttp_client):
|
||||||
remove_existing_db()
|
remove_existing_db()
|
||||||
bumper.db = "tests/tmp.db" # Set db location for testing
|
bumper.db = "tests/tmp.db" # Set db location for testing
|
||||||
confserver = create_confserver()
|
confserver = create_confserver()
|
||||||
client = await aiohttp_client(create_app)
|
client = await aiohttp_client(create_app)
|
||||||
|
bumper.mqtt_helperbot = bumper.mqttserver.MQTTHelperBot("127.0.0.1")
|
||||||
|
|
||||||
# Test PollSCResult
|
# Test PollSCResult
|
||||||
postbody = {"td": "PollSCResult"}
|
postbody = {"td": "PollSCResult"}
|
||||||
|
|
@ -857,7 +855,7 @@ async def test_dim_devmanager(aiohttp_client):
|
||||||
"resp": "<ctl ret='ok' status='idle'/>",
|
"resp": "<ctl ret='ok' status='idle'/>",
|
||||||
"ret": "ok",
|
"ret": "ok",
|
||||||
}
|
}
|
||||||
confserver.helperbot.send_command = mock.MagicMock(
|
bumper.mqtt_helperbot.send_command = mock.MagicMock(
|
||||||
return_value=async_return(command_getstatus_resp)
|
return_value=async_return(command_getstatus_resp)
|
||||||
)
|
)
|
||||||
resp = await client.post("/api/dim/devmanager.do", json=postbody)
|
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
|
# 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(
|
bumper.mqtt_helperbot.send_command = mock.MagicMock(
|
||||||
return_value=async_return(command_timeout_resp)
|
return_value=async_return(command_timeout_resp)
|
||||||
)
|
)
|
||||||
resp = await client.post("/api/dim/devmanager.do", json=postbody)
|
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
|
# 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(
|
bumper.mqtt_helperbot.send_command = mock.MagicMock(
|
||||||
return_value=async_return(command_getstatus_resp)
|
return_value=async_return(command_getstatus_resp)
|
||||||
)
|
)
|
||||||
resp = await client.post("/api/dim/devmanager.do", json=postbody)
|
resp = await client.post("/api/dim/devmanager.do", json=postbody)
|
||||||
|
|
|
||||||
145
tests/test_db.py
Normal file
145
tests/test_db.py
Normal file
|
|
@ -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
|
||||||
|
|
@ -5,29 +5,18 @@ from tinydb.storages import MemoryStorage
|
||||||
from tinydb import TinyDB, Query
|
from tinydb import TinyDB, Query
|
||||||
import bumper
|
import bumper
|
||||||
import os
|
import os
|
||||||
import datetime, time
|
|
||||||
import platform
|
import platform
|
||||||
import json
|
import json
|
||||||
import asyncio
|
import asyncio
|
||||||
from testfixtures import LogCapture
|
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():
|
def test_strtobool():
|
||||||
assert bumper.strtobool("t") == True
|
assert bumper.strtobool("t") == True
|
||||||
assert bumper.strtobool("f") == False
|
assert bumper.strtobool("f") == False
|
||||||
assert bumper.strtobool(0) == False
|
assert bumper.strtobool(0) == False
|
||||||
|
|
||||||
|
|
||||||
async def test_start_stop():
|
async def test_start_stop():
|
||||||
with LogCapture() as l:
|
with LogCapture() as l:
|
||||||
if os.path.exists("tests/tmp.db"):
|
if os.path.exists("tests/tmp.db"):
|
||||||
|
|
@ -71,142 +60,3 @@ async def test_start_stop_debug():
|
||||||
)
|
)
|
||||||
assert b.shutting_down == True
|
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
|
|
||||||
|
|
|
||||||
|
|
@ -14,11 +14,12 @@ import time
|
||||||
|
|
||||||
|
|
||||||
async def test_helperbot_message():
|
async def test_helperbot_message():
|
||||||
with LogCapture("helperbot") as l:
|
|
||||||
mqtt_address = ("127.0.0.1", 8883)
|
mqtt_address = ("127.0.0.1", 8883)
|
||||||
mqtt_server = bumper.MQTTServer(mqtt_address)
|
mqtt_server = bumper.MQTTServer(mqtt_address)
|
||||||
await mqtt_server.broker_coro()
|
await mqtt_server.broker_coro()
|
||||||
|
|
||||||
|
with LogCapture() as l:
|
||||||
|
|
||||||
# Test broadcast message
|
# Test broadcast message
|
||||||
mqtt_helperbot = bumper.MQTTHelperBot(mqtt_address)
|
mqtt_helperbot = bumper.MQTTHelperBot(mqtt_address)
|
||||||
await mqtt_helperbot.start_helper_bot()
|
await mqtt_helperbot.start_helper_bot()
|
||||||
|
|
@ -125,20 +126,42 @@ async def test_helperbot_message():
|
||||||
) # Check received message was logged
|
) # Check received message was logged
|
||||||
l.clear()
|
l.clear()
|
||||||
mqtt_helperbot.Client.disconnect()
|
mqtt_helperbot.Client.disconnect()
|
||||||
|
|
||||||
|
# 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 = "<ctl ts='1560904925396' td='errors' old='' new='110'/>"
|
||||||
|
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: <ctl ts='1560904925396' td='errors' old='' new='110'/>",
|
||||||
|
)
|
||||||
|
) # Check received message was logged
|
||||||
|
l.clear()
|
||||||
|
mqtt_helperbot.Client.disconnect()
|
||||||
|
|
||||||
await mqtt_server.broker.shutdown()
|
await mqtt_server.broker.shutdown()
|
||||||
|
|
||||||
|
|
||||||
async def test_helperbot_expire_message():
|
async def test_helperbot_expire_message():
|
||||||
with LogCapture("helperbot") as l:
|
|
||||||
mqtt_address = ("127.0.0.1", 8883)
|
mqtt_address = ("127.0.0.1", 8883)
|
||||||
mqtt_server = bumper.MQTTServer(mqtt_address)
|
mqtt_server = bumper.MQTTServer(mqtt_address)
|
||||||
await mqtt_server.broker_coro()
|
await mqtt_server.broker_coro()
|
||||||
# mqtt_address = ("127.0.0.1", 8883)
|
|
||||||
# mqtt_server = bumper.MQTTServer(mqtt_address)
|
with LogCapture("helperbot") as l:
|
||||||
# broker = hbmqtt.broker.Broker(
|
|
||||||
# mqtt_server.default_config, plugin_namespace="hbmqtt.test.plugins"
|
|
||||||
# )
|
|
||||||
# await broker.start()
|
|
||||||
|
|
||||||
# Test broadcast message
|
# Test broadcast message
|
||||||
mqtt_helperbot = bumper.MQTTHelperBot(mqtt_address)
|
mqtt_helperbot = bumper.MQTTHelperBot(mqtt_address)
|
||||||
|
|
@ -195,6 +218,7 @@ async def test_helperbot_expire_message():
|
||||||
)
|
)
|
||||||
) # Check received message was logged
|
) # Check received message was logged
|
||||||
mqtt_helperbot.Client.disconnect()
|
mqtt_helperbot.Client.disconnect()
|
||||||
|
|
||||||
await mqtt_server.broker.shutdown()
|
await mqtt_server.broker.shutdown()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -202,12 +226,6 @@ async def test_helperbot_sendcommand():
|
||||||
mqtt_address = ("127.0.0.1", 8883)
|
mqtt_address = ("127.0.0.1", 8883)
|
||||||
mqtt_server = bumper.MQTTServer(mqtt_address)
|
mqtt_server = bumper.MQTTServer(mqtt_address)
|
||||||
await mqtt_server.broker_coro()
|
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)
|
mqtt_helperbot = bumper.MQTTHelperBot(mqtt_address)
|
||||||
await mqtt_helperbot.start_helper_bot()
|
await mqtt_helperbot.start_helper_bot()
|
||||||
|
|
|
||||||
|
|
@ -21,11 +21,12 @@ def mock_transport_extra_info(*args, **kwargs):
|
||||||
|
|
||||||
|
|
||||||
async def test_xmpp_server():
|
async def test_xmpp_server():
|
||||||
with LogCapture("xmppserver") as l:
|
|
||||||
xmpp_address = ("127.0.0.1", 5223)
|
xmpp_address = ("127.0.0.1", 5223)
|
||||||
xmpp_server = bumper.XMPPServer(xmpp_address)
|
xmpp_server = bumper.XMPPServer(xmpp_address)
|
||||||
await xmpp_server.start_async_server()
|
await xmpp_server.start_async_server()
|
||||||
|
|
||||||
|
with LogCapture("xmppserver") as l:
|
||||||
|
|
||||||
reader, writer = await asyncio.open_connection("127.0.0.1", 5223)
|
reader, writer = await asyncio.open_connection("127.0.0.1", 5223)
|
||||||
|
|
||||||
writer.write(b"<stream:stream />") # Start stream
|
writer.write(b"<stream:stream />") # Start stream
|
||||||
|
|
@ -52,10 +53,8 @@ async def test_xmpp_server():
|
||||||
await writer.drain()
|
await writer.drain()
|
||||||
|
|
||||||
await asyncio.sleep(0.1)
|
await asyncio.sleep(0.1)
|
||||||
|
|
||||||
xmpp_server.disconnect()
|
xmpp_server.disconnect()
|
||||||
await asyncio.sleep(0.1)
|
|
||||||
assert len(xmpp_server.clients) == 0 # Client count decreased
|
|
||||||
print(l)
|
|
||||||
|
|
||||||
|
|
||||||
async def test_client_connect_no_starttls(*args, **kwargs):
|
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():
|
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:
|
with LogCapture("xmppserver") as l:
|
||||||
|
|
||||||
async def do_stuff_after_start_tls(
|
async def do_stuff_after_start_tls(
|
||||||
|
|
@ -227,10 +231,6 @@ async def test_xmpp_server_client_tls():
|
||||||
|
|
||||||
await writer.drain()
|
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)
|
reader, writer = await asyncio.open_connection("127.0.0.1", 5223)
|
||||||
|
|
||||||
writer.write(
|
writer.write(
|
||||||
|
|
@ -616,3 +616,30 @@ async def test_client_send_iq(*args, **kwargs):
|
||||||
# Reset mock calls
|
# Reset mock calls
|
||||||
mock_send.reset_mock()
|
mock_send.reset_mock()
|
||||||
|
|
||||||
|
# Bot error report
|
||||||
|
test_data = "<iq to='fuid_tmpuser@ecouser.net/IOSF53D07BA' type='set' id='631'><query xmlns='com:ctl'><ctl td='error' errs='102'/></query></iq>".encode(
|
||||||
|
"utf-8"
|
||||||
|
)
|
||||||
|
xmppclient2._parse_data(test_data)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
mock_send.mock_calls[0].args[0]
|
||||||
|
== '<iq from="E0000000000000001234@159.ecorobot.net/atom" id="631" to="fuid_tmpuser@ecouser.net/IOSF53D07BA" type="set"><query xmlns="com:ctl"><ctl errs="102" td="error" /></query></iq>'
|
||||||
|
) # result sent to ecouser.net
|
||||||
|
|
||||||
|
# Reset mock calls
|
||||||
|
mock_send.reset_mock()
|
||||||
|
|
||||||
|
# Bot "DorpError" to all
|
||||||
|
test_data = "<iq to='rl.ecorobot.net' type='set' id='1234'><query xmlns='com:sf'><sf td='pub' t='log' ts='1559893796000' tp='p' k='DeviceAlert' v='DorpError' f='E0000000000000001234@159.ecorobot.net' g='fuid_tmpuser@ecouser.net'/></query></iq>".encode(
|
||||||
|
"utf-8"
|
||||||
|
)
|
||||||
|
xmppclient2._parse_data(test_data)
|
||||||
|
assert (
|
||||||
|
mock_send.mock_calls[0].args[0]
|
||||||
|
== '<iq xmlns="com:sf" from="E0000000000000001234@159.ecorobot.net/atom" id="1234" to="rl.ecorobot.net" type="set"><query xmlns="com:ctl"><sf f="E0000000000000001234@159.ecorobot.net" g="fuid_tmpuser@ecouser.net" k="DeviceAlert" t="log" td="pub" tp="p" ts="1559893796000" v="DorpError" /></query></iq>'
|
||||||
|
) # result sent to ecouser.net
|
||||||
|
|
||||||
|
# Reset mock calls
|
||||||
|
mock_send.reset_mock()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -100,4 +100,3 @@ def test_main(mock_firstrun):
|
||||||
bumper.main()
|
bumper.main()
|
||||||
assert mock_firstrun.called == True
|
assert mock_firstrun.called == True
|
||||||
bumper.ca_cert = "tests/test_certs/ca.crt"
|
bumper.ca_cert = "tests/test_certs/ca.crt"
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue