diff --git a/bumper/__init__.py b/bumper/__init__.py
index 1ef871e..ff03f00 100644
--- a/bumper/__init__.py
+++ b/bumper/__init__.py
@@ -12,6 +12,9 @@ from logging.handlers import RotatingFileHandler
import socket
import sys
+import importlib
+import pkgutil
+from pkgutil import extend_path
def strtobool(strbool):
if str(strbool).lower() in ["true", "1", "t", "y", "on", "yes"]:
@@ -32,6 +35,8 @@ os.makedirs(data_dir, exist_ok=True) # Ensure data directory exists or create
certs_dir = os.environ.get("BUMPER_CERTS") or os.path.join(bumper_dir, "certs")
os.makedirs(certs_dir, exist_ok=True) # Ensure data directory exists or create
+
+
# Certs
ca_cert = os.environ.get("BUMPER_CA") or os.path.join(certs_dir, "ca.crt")
server_cert = os.environ.get("BUMPER_CERT") or os.path.join(certs_dir, "bumper.crt")
@@ -57,6 +62,16 @@ conf_server = None
conf_server_2 = None
xmpp_server = None
+# Plugins
+sys.path.append(os.path.join(bumper_dir, "bumper", "plugins"))
+sys.path.append(os.path.join(data_dir, "plugins"))
+
+discovered_plugins = {
+ name: importlib.import_module(name)
+ for finder, name, ispkg in pkgutil.iter_modules()
+ if name.startswith('bumper_')
+}
+
shutting_down = False
# Set format for all logs
@@ -206,10 +221,8 @@ async def start():
# 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())
+ asyncio.create_task(conf_server.start_site(conf_server.app, address=bumper_listen, port=conf1_listen_port, usessl=True))
+ asyncio.create_task(conf_server.start_site(conf_server.app, address=bumper_listen, port=conf2_listen_port, usessl=False))
# Start maintenance
while not shutting_down:
diff --git a/bumper/confserver.py b/bumper/confserver.py
index 618f42c..0e019f2 100644
--- a/bumper/confserver.py
+++ b/bumper/confserver.py
@@ -8,6 +8,7 @@ import random
import bumper
import os
from bumper.models import *
+from bumper import plugins
from datetime import datetime, timedelta
import asyncio
from aiohttp import web
@@ -47,14 +48,17 @@ class ConfServer:
self.app = None
self.site = None
self.runner = None
+ self.runners = []
self.excludelogging = ["base", "remove-bot", "remove-client", "restart-service"]
def get_milli_time(self, timetoconvert):
return int(round(timetoconvert * 1000))
def confserver_app(self):
- self.app = web.Application(loop=asyncio.get_event_loop(), middlewares=[self.log_all_requests])
- aiohttp_jinja2.setup(self.app, loader=jinja2.FileSystemLoader(os.path.join(bumper.data_dir, "web","templates")))
+ self.app = web.Application(loop=asyncio.get_event_loop(), middlewares=[
+ self.log_all_requests,
+ ])
+ aiohttp_jinja2.setup(self.app, loader=jinja2.FileSystemLoader(os.path.join(bumper.data_dir, "web","templates")))
self.app.add_routes(
[
@@ -62,99 +66,67 @@ class ConfServer:
web.get("", self.handle_base, name="base"),
web.get("/bot/remove/{did}", self.handle_RemoveBot, name='remove-bot'),
web.get("/client/remove/{resource}", self.handle_RemoveClient, name='remove-client'),
- web.get("/restart_{service}", self.handle_RestartService, name='restart-service'),
- web.get(
- "/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/login",
- self.handle_login,
- ),
- web.get(
- "/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/checkLogin",
- self.handle_login,
- ),
- web.get( # EcoVacs Home GetUserAccountInfo
- "/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/getUserAccountInfo",
- self.handle_getUserAccountInfo,
- ),
- web.get(
- "/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/logout",
- self.handle_logout,
- ),
- web.get(
- "/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/getAuthCode",
- self.handle_getAuthCode,
- ),
- web.get( # EcoVacs Home GetAuthCode
- "/{apiversion}/{apptype}/auth/getAuthCode", self.handle_getAuthCode
- ),
- web.get(
- "/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/checkAgreement",
- self.handle_checkAgreement,
- ),
- web.get( # EcoVacs Home CheckAgreement
- "/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/checkAgreementBatch",
- self.handle_checkAgreement,
- ),
- web.get(
- "/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/common/checkVersion",
- self.handle_checkVersion,
- ),
- web.get( # EcoVacs Home CheckAPPVersion
- "/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/common/checkAPPVersion",
- self.handle_checkAPPVersion,
- ),
- web.get( # EcoVacs Home Upload Device Info
- "/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/common/uploadDeviceInfo",
- self.handle_uploadDeviceInfo,
- ),
- web.get( # EcoVacs Home GetAdByPositionType
- "/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/ad/getAdByPositionType",
- self.handle_getAdByPositionType,
- ),
- web.get( # EcoVacs Home Get Boot Screen
- "/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/ad/getBootScreen",
- self.handle_getBootScreen,
- ),
- web.get( # EcoVacs Home message hasUnreadMsg
- "/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/message/hasUnreadMsg",
- self.handle_hasUnreadMessage,
- ),
- web.post( # EcoVacs Home neng message hasUnreadMsg
- "/api/neng/message/hasUnreadMsg", self.handle_neng_hasUnreadMessage
- ),
- web.get( # EcoVacs Home message getMsgList
- "/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/message/getMsgList",
- self.handle_getMsgList,
- ),
- web.get( # EcoVacs Home common getSystemReminder
- "/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/common/getSystemReminder",
- self.handle_getSystemReminder,
- ),
- web.get( # EcoVacs Home shop getCnWapShopConfig
- "/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/shop/getCnWapShopConfig",
- self.handle_getCnWapShopConfig,
- ),
- web.get(
- "/{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/campaign/homePageAlert",
- self.handle_homePageAlert,
- ),
- web.post("/api/users/user.do", self.handle_usersapi),
- web.get("/api/users/user.do", self.handle_usersapi),
- web.post("/api/appsvr/app.do", self.handle_appsvr_api), # EcoVacs Home
- web.get("/api/appsvr/app.do", self.handle_appsvr_api), # EcoVacs Home
- web.post(
- "/api/pim/product/getProductIotMap", self.handle_getProductIotMap, name='getProductIotMap'
- ),
- web.post("/api/lg/log.do", self.handle_lg_log), # EcoVacs Home
- web.post("/api/iot/devmanager.do", self.handle_devmanager_botcommand),
- web.post(
- "/api/dim/devmanager.do", self.handle_dim_devmanager
- ), # EcoVacs Home
+ web.get("/restart_{service}", self.handle_RestartService, name='restart-service'),
web.post("/lookup.do", self.handle_lookup),
- web.get("/api/pim/file/get/{id}", self.handle_pimFile)
+
]
)
- # Direct register from app:
- # /{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/directRegister
+
+ # common api paths
+ api_v1 = {"prefix": "/v1/", "app": web.Application()} # for /v1/
+ api_v2 = {"prefix": "/v2/", "app": web.Application()} # for /v2/
+ portal_api = {"prefix": "/api/", "app": web.Application()} # for /api/
+
+ apis = {
+ "api_v1": api_v1,
+ "api_v2": api_v2,
+ "portal_api": portal_api,
+
+ }
+
+ # Load plugins
+ for plug in bumper.discovered_plugins:
+ if isinstance(bumper.discovered_plugins[plug].plugin, bumper.plugins.ConfServerApp):
+ plugin = bumper.discovered_plugins[plug].plugin
+ if plugin.plugin_type == "sub_api": # app or sub_api
+ if plugin.sub_api in apis:
+ if plugin.routes:
+ logging.debug(f"Adding confserver sub_api ({plugin.name})")
+ apis[plugin.sub_api]["app"].add_routes(plugin.routes)
+
+ elif plugin.plugin_type == "app":
+ if plugin.path_prefix and plugin.app:
+ logging.debug(f"Adding confserver plugin ({plugin.name})")
+ self.app.add_subapp(plugin.path_prefix, plugin.app)
+
+ for api in apis:
+ self.app.add_subapp(apis[api]["prefix"], apis[api]["app"])
+
+ for resource in self.app.router.resources():
+ print(resource)
+
+
+
+ async def start_site(self, app, address='localhost', port=8080, usessl=False):
+ runner = web.AppRunner(app)
+ self.runners.append(runner)
+ await runner.setup()
+ if usessl:
+ ssl_ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
+ ssl_ctx.load_cert_chain(bumper.server_cert, bumper.server_key)
+ site = web.TCPSite(
+ runner,
+ host=address,
+ port=port,
+ ssl_context=ssl_ctx,
+ )
+
+ else:
+ site = web.TCPSite(
+ runner, host=address, port=port
+ )
+
+ await site.start()
async def start_server(self):
try:
@@ -486,655 +458,6 @@ class ConfServer:
except Exception as e:
confserverlog.exception("{}".format(e))
- def handle_getUserAccountInfo(self, request):
- try:
- user_devid = request.match_info.get("devid", "")
- countrycode = request.match_info.get("country", "us")
- apptype = request.match_info.get("apptype", "")
- user = bumper.user_by_deviceid(user_devid)
-
- if "global_" in apptype: # EcoVacs Home
- login_details = EcoVacsHome_Login()
- login_details.ucUid = "fuid_{}".format(user["userid"])
- login_details.loginName = "fusername_{}".format(user["userid"])
- login_details.mobile = None
- else:
- login_details = EcoVacs_Login()
-
- login_details.uid = "fuid_{}".format(user["userid"])
- login_details.username = "fusername_{}".format(user["userid"])
- login_details.country = countrycode
- login_details.email = "null@null.com"
-
- body = {
- "code": bumper.RETURN_API_SUCCESS,
- "data": {
- "email": login_details.email,
- "hasMobile": "N",
- "hasPassword": "Y",
- "uid": login_details.uid,
- "userName": login_details.username,
- "obfuscatedMobile": None,
- "mobile": None,
- "loginName": login_details.loginName,
- },
- "msg": "操作成功",
- "time": self.get_milli_time(datetime.utcnow().timestamp()),
- }
- return web.json_response(body)
-
- except Exception as e:
- confserverlog.exception("{}".format(e))
-
- def check_token(self, apptype, countrycode, user, token):
- try:
- if bumper.check_token(user["userid"], token):
-
- if "global_" in apptype: # EcoVacs Home
- login_details = EcoVacsHome_Login()
- login_details.ucUid = "fuid_{}".format(user["userid"])
- login_details.loginName = "fusername_{}".format(user["userid"])
- login_details.mobile = None
- else:
- login_details = EcoVacs_Login()
-
- login_details.accessToken = token
- login_details.uid = "fuid_{}".format(user["userid"])
- login_details.username = "fusername_{}".format(user["userid"])
- login_details.country = countrycode
- login_details.email = "null@null.com"
-
- body = {
- "code": bumper.RETURN_API_SUCCESS,
- "data": json.loads(login_details.toJSON()),
- # {
- # "accessToken": self.generate_token(tmpuser), # Generate a token
- # "country": countrycode,
- # "email": "null@null.com",
- # "uid": "fuid_{}".format(tmpuser["userid"]),
- # "username": "fusername_{}".format(tmpuser["userid"]),
- # },
- "msg": "操作成功",
- "time": self.get_milli_time(datetime.utcnow().timestamp()),
- }
- return web.json_response(body)
-
- else:
- body = {
- "code": bumper.ERR_TOKEN_INVALID,
- "data": None,
- "msg": "当前密码错误",
- "time": self.get_milli_time(datetime.utcnow().timestamp()),
- }
- return web.json_response(body)
-
- except Exception as e:
- confserverlog.exception("{}".format(e))
-
- def generate_token(self, user):
- try:
- tmpaccesstoken = uuid.uuid4().hex
- bumper.user_add_token(user["userid"], tmpaccesstoken)
- return tmpaccesstoken
-
- except Exception as e:
- confserverlog.exception("{}".format(e))
-
- def generate_authcode(self, user, countrycode, token):
- try:
- tmpauthcode = "{}_{}".format(countrycode, uuid.uuid4().hex)
- bumper.user_add_authcode(user["userid"], token, tmpauthcode)
- return tmpauthcode
-
- except Exception as e:
- confserverlog.exception("{}".format(e))
-
- def _auth_any(self, devid, apptype, country, request):
- try:
- user_devid = devid
- countrycode = country
- user = bumper.user_by_deviceid(user_devid)
- bots = bumper.db_get().table("bots").all()
-
- if user: # Default to user 0
- tmpuser = user
- if "global_" in apptype: # EcoVacs Home
- login_details = EcoVacsHome_Login()
- login_details.ucUid = "fuid_{}".format(tmpuser["userid"])
- login_details.loginName = "fusername_{}".format(tmpuser["userid"])
- login_details.mobile = None
- else:
- login_details = EcoVacs_Login()
-
- login_details.accessToken = self.generate_token(tmpuser)
- login_details.uid = "fuid_{}".format(tmpuser["userid"])
- login_details.username = "fusername_{}".format(tmpuser["userid"])
- login_details.country = countrycode
- login_details.email = "null@null.com"
- bumper.user_add_device(tmpuser["userid"], user_devid)
- else:
- bumper.user_add("tmpuser") # Add a new user
- tmpuser = bumper.user_get("tmpuser")
- if "global_" in apptype: # EcoVacs Home
- login_details = EcoVacsHome_Login()
- login_details.ucUid = "fuid_{}".format(tmpuser["userid"])
- login_details.loginName = "fusername_{}".format(tmpuser["userid"])
- login_details.mobile = None
- else:
- login_details = EcoVacs_Login()
-
- login_details.accessToken = self.generate_token(tmpuser)
- login_details.uid = "fuid_{}".format(tmpuser["userid"])
- login_details.username = "fusername_{}".format(tmpuser["userid"])
- login_details.country = countrycode
- login_details.email = "null@null.com"
- bumper.user_add_device(tmpuser["userid"], user_devid)
-
- for bot in bots: # Add all bots to the user
- if "did" in bot:
- bumper.user_add_bot(tmpuser["userid"], bot["did"])
- else:
- confserverlog.error("No DID for bot: {}".format(bot))
-
- if "checkLogin" in request.path: # If request was to check a token do so
- checkToken = self.check_token(
- apptype, countrycode, tmpuser, request.query["accessToken"]
- )
- isGood = json.loads(checkToken.text)
- if isGood["code"] == "0000":
- return isGood
-
- # Deactivate old tokens and authcodes
- bumper.user_revoke_expired_tokens(tmpuser["userid"])
-
- body = {
- "code": bumper.RETURN_API_SUCCESS,
- "data": json.loads(login_details.toJSON()),
- # {
- # "accessToken": self.generate_token(tmpuser), # Generate a token
- # "country": countrycode,
- # "email": "null@null.com",
- # "uid": "fuid_{}".format(tmpuser["userid"]),
- # "username": "fusername_{}".format(tmpuser["userid"]),
- # },
- "msg": "操作成功",
- "time": self.get_milli_time(datetime.utcnow().timestamp()),
- }
-
- return body
-
- except Exception as e:
- confserverlog.exception("{}".format(e))
-
- async def handle_logout(self, request):
- try:
- user_devid = request.match_info.get("devid", "")
- if not user_devid == "":
- user = bumper.user_by_deviceid(user_devid)
- if user:
- if bumper.check_token(user["userid"], request.query["accessToken"]):
- # Deactivate old tokens and authcodes
- bumper.user_revoke_token(
- user["userid"], request.query["accessToken"]
- )
-
- body = {
- "code": bumper.RETURN_API_SUCCESS,
- "data": None,
- "msg": "操作成功",
- "time": self.get_milli_time(datetime.utcnow().timestamp()),
- }
-
- return web.json_response(body)
-
- except Exception as e:
- confserverlog.exception("{}".format(e))
-
- async def handle_getAuthCode(self, request):
- try:
- apptype = request.match_info.get("apptype", "")
- user_devid = request.match_info.get("devid", "") # Ecovacs
- if user_devid == "":
- user_devid = request.query["deviceId"] # Ecovacs Home
-
- if not user_devid == "":
- user = bumper.user_by_deviceid(user_devid)
- token = ""
- if user:
- if "accessToken" in request.query:
- token = bumper.user_get_token(
- user["userid"], request.query["accessToken"]
- )
- if token:
- authcode = ""
- if not "authcode" in token:
- authcode = self.generate_authcode(
- user,
- request.match_info.get("country", "us"),
- request.query["accessToken"],
- )
- else:
- authcode = token["authcode"]
- if "global" in apptype:
- body = {
- "code": bumper.RETURN_API_SUCCESS,
- "data": {
- "authCode": authcode,
- "ecovacsUid": request.query["uid"],
- },
- "msg": "操作成功",
- "success": True,
- "time": self.get_milli_time(
- datetime.utcnow().timestamp()
- ),
- }
- else:
- body = {
- "code": bumper.RETURN_API_SUCCESS,
- "data": {
- "authCode": authcode,
- "ecovacsUid": request.query["uid"],
- },
- "msg": "操作成功",
- "time": self.get_milli_time(
- datetime.utcnow().timestamp()
- ),
- }
- return web.json_response(body)
-
- body = {
- "code": bumper.ERR_TOKEN_INVALID,
- "data": None,
- "msg": "当前密码错误",
- "time": self.get_milli_time(datetime.utcnow().timestamp()),
- }
-
- return web.json_response(body)
-
- except Exception as e:
- confserverlog.exception("{}".format(e))
-
- async def handle_checkVersion(self, request):
- try:
- body = {
- "code": bumper.RETURN_API_SUCCESS,
- "data": {
- "c": None,
- "img": None,
- "r": 0,
- "t": None,
- "u": None,
- "ut": 0,
- "v": None,
- },
- "msg": "操作成功",
- "time": self.get_milli_time(datetime.utcnow().timestamp()),
- }
-
- return web.json_response(body)
-
- except Exception as e:
- confserverlog.exception("{}".format(e))
-
- async def handle_checkAPPVersion(self, request): # EcoVacs Home
- try:
- body = {
- "code": bumper.RETURN_API_SUCCESS,
- "data": {
- "c": None,
- "downPageUrl": None,
- "img": None,
- "nextAlertTime": None,
- "r": 0,
- "t": None,
- "u": None,
- "ut": 0,
- "v": None,
- },
- "msg": "操作成功",
- "success": True,
- "time": self.get_milli_time(datetime.utcnow().timestamp()),
- }
-
- return web.json_response(body)
-
- except Exception as e:
- confserverlog.exception("{}".format(e))
-
- async def handle_uploadDeviceInfo(self, request): # EcoVacs Home
- try:
- body = {
- "code": bumper.RETURN_API_SUCCESS,
- "data": None,
- "msg": "操作成功",
- "success": True,
- "time": self.get_milli_time(datetime.utcnow().timestamp()),
- }
-
- return web.json_response(body)
-
- except Exception as e:
- confserverlog.exception("{}".format(e))
-
- async def handle_getAdByPositionType(self, request): # EcoVacs Home
- try:
- body = {
- "code": bumper.RETURN_API_SUCCESS,
- "data": None,
- "msg": "操作成功",
- "success": True,
- "time": self.get_milli_time(datetime.utcnow().timestamp()),
- }
-
- return web.json_response(body)
-
- except Exception as e:
- confserverlog.exception("{}".format(e))
-
- async def handle_getBootScreen(self, request): # EcoVacs Home
- try:
- body = {
- "code": bumper.RETURN_API_SUCCESS,
- "data": None,
- "msg": "操作成功",
- "success": True,
- "time": self.get_milli_time(datetime.utcnow().timestamp()),
- }
-
- return web.json_response(body)
-
- except Exception as e:
- confserverlog.exception("{}".format(e))
-
- async def handle_hasUnreadMessage(self, request): # EcoVacs Home
- try:
- body = {
- "code": bumper.RETURN_API_SUCCESS,
- "data": "N",
- "msg": "操作成功",
- "success": True,
- "time": self.get_milli_time(datetime.utcnow().timestamp()),
- }
-
- return web.json_response(body)
-
- except Exception as e:
- confserverlog.exception("{}".format(e))
-
- async def handle_neng_hasUnreadMessage(self, request): # EcoVacs Home
- try:
- body = {"code": 0, "data": {"hasUnRead": True}}
-
- return web.json_response(body)
-
- except Exception as e:
- confserverlog.exception("{}".format(e))
-
- async def handle_getMsgList(self, request): # EcoVacs Home
- try:
- body = {
- "code": bumper.RETURN_API_SUCCESS,
- "data": {"hasNextPage": 0, "items": []},
- "msg": "操作成功",
- "success": True,
- "time": self.get_milli_time(datetime.utcnow().timestamp()),
- }
-
- return web.json_response(body)
-
- except Exception as e:
- confserverlog.exception("{}".format(e))
-
- async def handle_getCnWapShopConfig(self, request): # EcoVacs Home
- try:
- body = {
- "code": bumper.RETURN_API_SUCCESS,
- "data": {
- "myShopShowFlag": "N",
- "myShopUrl": "",
- "shopIndexShowFlag": "N",
- "shopIndexUrl": "",
- },
- "msg": "操作成功",
- "success": True,
- "time": self.get_milli_time(datetime.utcnow().timestamp()),
- }
-
- return web.json_response(body)
-
- except Exception as e:
- confserverlog.exception("{}".format(e))
-
- async def handle_getSystemReminder(self, request): # EcoVacs Home
- try:
- body = {
- "code": bumper.RETURN_API_SUCCESS,
- "data": {
- "iosGradeTime": {"iodGradeFlag": "N"},
- "openNotification": {
- "openNotificationContent": None,
- "openNotificationFlag": "N",
- "openNotificationTitle": None,
- },
- },
- "msg": "操作成功",
- "success": True,
- "time": self.get_milli_time(datetime.utcnow().timestamp()),
- }
-
- return web.json_response(body)
-
- except Exception as e:
- confserverlog.exception("{}".format(e))
-
- async def handle_checkAgreement(self, request):
- try:
- apptype = request.match_info.get("apptype", "")
- if "global_" in apptype:
- body = {
- "code": bumper.RETURN_API_SUCCESS,
- "data": [
- {
- "force": "N",
- "id": "20180804040641_7d746faf18b8cb22a50d145598fe4c90",
- "type": "USER",
- "url": "https://bumper.ecovacs.com/content/agreement?id=20180804040641_7d746faf18b8cb22a50d145598fe4c90&language=EN", # "https://gl-us-wap.ecovacs.com/content/agreement?id=20180804040641_7d746faf18b8cb22a50d145598fe4c90&language=EN
- "version": "1.01",
- },
- {
- "force": "N",
- "id": "20180804040245_4e7c56dfb7ebd3b81b1f2747d0859fac",
- "type": "PRIVACY",
- "url": "https://bumper.ecovacs.com/content/agreement?id=20180804040245_4e7c56dfb7ebd3b81b1f2747d0859fac&language=EN", # "https://gl-us-wap.ecovacs.com/content/agreement?id=20180804040245_4e7c56dfb7ebd3b81b1f2747d0859fac&language=EN"
- "version": "1.01",
- },
- ],
- "msg": "操作成功",
- "success": True,
- "time": self.get_milli_time(datetime.utcnow().timestamp()),
- }
- else:
- body = {
- "code": bumper.RETURN_API_SUCCESS,
- "data": [],
- "msg": "操作成功",
- "time": self.get_milli_time(datetime.utcnow().timestamp()),
- }
-
- return web.json_response(body)
-
- except Exception as e:
- confserverlog.exception("{}".format(e))
-
- async def handle_homePageAlert(self, request):
- try:
- nextAlert = self.get_milli_time(
- (datetime.now() + timedelta(hours=12)).timestamp()
- )
-
- body = {
- "code": bumper.RETURN_API_SUCCESS,
- "data": {
- "clickSchemeUrl": None,
- "clickWebUrl": None,
- "hasCampaign": "N",
- "imageUrl": None,
- "nextAlertTime": nextAlert,
- "serverTime": self.get_milli_time(datetime.utcnow().timestamp()),
- },
- "msg": "操作成功",
- "time": self.get_milli_time(datetime.utcnow().timestamp()),
- }
-
- return web.json_response(body)
-
- except Exception as e:
- confserverlog.exception("{}".format(e))
-
- async def handle_getProductIotMap(self, request):
- try:
- body = {
- "code": bumper.RETURN_API_SUCCESS,
- "data": EcoVacsHomeProducts,
- }
- return web.json_response(body)
-
- except Exception as e:
- confserverlog.exception("{}".format(e))
-
- async def handle_usersapi(self, request):
- if not request.method == "GET": # Skip GET for now
- try:
-
- body = {}
- postbody = {}
- if request.content_type == "application/x-www-form-urlencoded":
- postbody = await request.post()
-
- else:
- postbody = json.loads(await request.text())
-
- todo = postbody["todo"]
- if todo == "FindBest":
- service = postbody["service"]
- if service == "EcoMsgNew":
- srvip = bumper.bumper_announce_ip
- srvport = 5223
- confserverlog.info(
- "Announcing EcoMsgNew Server to bot as: {}:{}".format(
- srvip, srvport
- )
- )
- msgserver = {"ip": srvip, "port": srvport, "result": "ok"}
- msgserver = json.dumps(msgserver)
- msgserver = msgserver.replace(
- " ", ""
- ) # bot seems to be very picky about having no spaces, only way was with text
-
- return web.json_response(text=msgserver)
-
- elif service == "EcoUpdate":
- srvip = "47.88.66.164" # EcoVacs Server
- srvport = 8005
- confserverlog.info(
- "Announcing EcoUpdate Server to bot as: {}:{}".format(
- srvip, srvport
- )
- )
- body = {"result": "ok", "ip": srvip, "port": srvport}
-
- elif todo == "loginByItToken":
- if "userId" in postbody:
- if bumper.check_authcode(postbody["userId"], postbody["token"]):
- body = {
- "resource": postbody["resource"],
- "result": "ok",
- "todo": "result",
- "token": postbody["token"],
- "userId": postbody["userId"],
- }
- else: # EcoVacs Home LoginByITToken
- loginToken = bumper.loginByItToken(postbody["token"])
- if not loginToken == {}:
- body = {
- "resource": postbody["resource"],
- "result": "ok",
- "todo": "result",
- "token": loginToken["token"],
- "userId": loginToken["userid"],
- }
- else:
- body = {"result": "fail", "todo": "result"}
-
- elif todo == "GetDeviceList":
- body = {
- "devices": bumper.db_get().table("bots").all(),
- "result": "ok",
- "todo": "result",
- }
-
- elif todo == "SetDeviceNick":
- bumper.bot_set_nick(postbody["did"], postbody["nick"])
- body = {"result": "ok", "todo": "result"}
-
- elif todo == "AddOneDevice":
- bumper.bot_set_nick(postbody["did"], postbody["nick"])
- body = {"result": "ok", "todo": "result"}
-
- elif todo == "DeleteOneDevice":
- bumper.bot_remove(postbody["did"])
- body = {"result": "ok", "todo": "result"}
-
- return web.json_response(body)
-
- except Exception as e:
- confserverlog.exception("{}".format(e))
-
- # Return fail for GET
- body = {"result": "fail", "todo": "result"}
- return web.json_response(body)
-
- async def handle_appsvr_api(self, request):
- if not request.method == "GET": # Skip GET for now
- try:
-
- body = {}
- postbody = {}
- if request.content_type == "application/x-www-form-urlencoded":
- postbody = await request.post()
-
- else:
- postbody = json.loads(await request.text())
-
- todo = postbody["todo"]
-
- if todo == "GetGlobalDeviceList": # EcoVacs Home
- bots = bumper.db_get().table("bots").all()
- botlist = []
- for bot in bots:
- if bot["class"] != "":
- b = bumper.bot_toEcoVacsHome_JSON(bot)
- if (
- not b is None
- ): # Happens if the bot isn't on the EcoVacs Home list
- botlist.append(json.loads(b))
-
- body = {
- "code": 0,
- "devices": botlist,
- "ret": "ok",
- "todo": "result",
- }
-
- return web.json_response(body)
-
- except Exception as e:
- confserverlog.exception("{}".format(e))
-
- # Return fail for GET
- body = {"result": "fail", "todo": "result"}
- return web.json_response(body)
-
async def handle_lookup(self, request):
try:
@@ -1182,181 +505,6 @@ class ConfServer:
except Exception as e:
confserverlog.exception("{}".format(e))
- async def handle_lg_log(self, request): # EcoVacs Home
- try:
- json_body = json.loads(await request.text())
-
- randomid = "".join(random.sample(string.ascii_letters, 6))
- did = json_body["did"]
-
- botdetails = bumper.bot_get(did)
- if botdetails:
- if not "cmdName" in json_body:
- if "td" in json_body:
- json_body["cmdName"] = json_body["td"]
-
- if not "toId" in json_body:
- json_body["toId"] = did
-
- if not "toType" in json_body:
- json_body["toType"] = botdetails["class"]
-
- if not "toRes" in json_body:
- json_body["toRes"] = botdetails["resource"]
-
- if not "payloadType" in json_body:
- json_body["payloadType"] = "x"
-
- if not "payload" in json_body:
- #json_body["payload"] = ""
- if json_body["td"] == "GetCleanLogs":
- json_body["td"] = "q"
- json_body["payload"] = ''
-
- if did != "":
- bot = bumper.bot_get(did)
- if bot["company"] == "eco-ng":
- retcmd = await bumper.mqtt_helperbot.send_command(
- json_body, randomid
- )
- body = retcmd
- confserverlog.debug("Send Bot - {}".format(json_body))
- confserverlog.debug("Bot Response - {}".format(body))
- logs = []
- logsroot = ET.fromstring(retcmd["resp"])
- if logsroot.attrib["ret"] == "ok":
- cleanlogs = logsroot.getchildren()
- for l in cleanlogs:
- cleanlog = {
- "ts": l.attrib['s'],
- "area": l.attrib['a'],
- "last": l.attrib['l'],
- "cleanType": l.attrib['t'],
- #imageUrl allows for providing images of cleanings, something to look into later
- #"imageUrl": "https://localhost:8007",
- }
- logs.append(cleanlog)
- body = {
- "ret": "ok",
- "logs": logs,
- }
-
- else:
- body = {"ret": "ok", "logs": []}
-
- confserverlog.debug("lg logs return: {}".format(json.dumps(body)))
- return web.json_response(body)
- else:
- # No response, send error back
- confserverlog.error(
- "No bots with DID: {} connected to MQTT".format(
- json_body["toId"]
- )
- )
- body = {"id": randomid, "errno": bumper.ERR_COMMON, "ret": "fail"}
- return web.json_response(body)
-
- except Exception as e:
- confserverlog.exception("{}".format(e))
-
- async def handle_devmanager_botcommand(self, request):
- try:
- json_body = json.loads(await request.text())
-
- randomid = "".join(random.sample(string.ascii_letters, 6))
- did = ""
- if "toId" in json_body: # Its a command
- did = json_body["toId"]
-
- if did != "":
- bot = bumper.bot_get(did)
- if bot["company"] == "eco-ng":
- retcmd = await bumper.mqtt_helperbot.send_command(
- json_body, randomid
- )
- body = retcmd
- confserverlog.debug("Send Bot - {}".format(json_body))
- confserverlog.debug("Bot Response - {}".format(body))
- return web.json_response(body)
- else:
- # No response, send error back
- confserverlog.error(
- "No bots with DID: {} connected to MQTT".format(
- json_body["toId"]
- )
- )
- body = {
- "id": randomid,
- "errno": 500,
- "ret": "fail",
- "debug": "wait for response timed out",
- }
- return web.json_response(body)
-
- else:
- if "td" in json_body: # Seen when doing initial wifi config
- if json_body["td"] == "PollSCResult":
- body = {"ret": "ok"}
- return web.json_response(body)
-
- if json_body["td"] == "HasUnreadMsg": # EcoVacs Home
- body = {"ret": "ok", "unRead": False}
- return web.json_response(body)
-
- except Exception as e:
- confserverlog.exception("{}".format(e))
-
- async def handle_dim_devmanager(self, request): # Used in EcoVacs Home App
- try:
- json_body = json.loads(await request.text())
-
- randomid = "".join(random.sample(string.ascii_letters, 6))
- did = ""
- if "toId" in json_body: # Its a command
- did = json_body["toId"]
-
- if did != "":
- bot = bumper.bot_get(did)
- if bot["company"] == "eco-ng" and bot["mqtt_connection"] == True:
- retcmd = await bumper.mqtt_helperbot.send_command(
- json_body, randomid
- )
- body = retcmd
- confserverlog.debug("Send Bot - {}".format(json_body))
- confserverlog.debug("Bot Response - {}".format(body))
- return web.json_response(body)
- else:
- # No response, send error back
- confserverlog.error(
- "No bots with DID: {} connected to MQTT".format(
- json_body["toId"]
- )
- )
- body = {"id": randomid, "errno": bumper.ERR_COMMON, "ret": "fail"}
- return web.json_response(body)
-
- else:
- if "td" in json_body: # Seen when doing initial wifi config
- if json_body["td"] == "PollSCResult":
- body = {"ret": "ok"}
- return web.json_response(body)
-
- if json_body["td"] == "HasUnreadMsg": # EcoVacs Home
- body = {"ret": "ok", "unRead": False}
- return web.json_response(body)
-
- except Exception as e:
- confserverlog.exception("{}".format(e))
-
-
- async def handle_pimFile(self, request):
- try:
- fileID = request.match_info.get("id", "")
-
- return web.FileResponse(os.path.join(bumper.data_dir,"web","robotvac_image.jpg"))
-
- except Exception as e:
- confserverlog.exception("{}".format(e))
async def disconnect(self):
try:
@@ -1366,3 +514,356 @@ class ConfServer:
except Exception as e:
confserverlog.exception("{}".format(e))
+ class ConfServer_GeneralFunctions:
+ def __init__(self):
+ pass
+
+ def get_milli_time(self, timetoconvert):
+ return int(round(timetoconvert * 1000))
+
+ class ConfServer_AuthHandler:
+ def __init__(self):
+ self.get_milli_time = bumper.ConfServer.ConfServer_GeneralFunctions().get_milli_time
+ pass
+
+ def generate_token(self, user):
+ try:
+ tmpaccesstoken = uuid.uuid4().hex
+ bumper.user_add_token(user["userid"], tmpaccesstoken)
+ return tmpaccesstoken
+
+ except Exception as e:
+ confserverlog.exception("{}".format(e))
+
+ def generate_authcode(self, user, countrycode, token):
+ try:
+ tmpauthcode = "{}_{}".format(countrycode, uuid.uuid4().hex)
+ bumper.user_add_authcode(user["userid"], token, tmpauthcode)
+ return tmpauthcode
+
+ except Exception as e:
+ confserverlog.exception("{}".format(e))
+
+
+ async def login(self, request):
+ try:
+ user_devid = request.match_info.get("devid", "")
+ countrycode = request.match_info.get("country", "us")
+ apptype = request.match_info.get("apptype", "")
+ confserverlog.info(
+ "client with devid {} attempting login".format(user_devid)
+ )
+ if bumper.use_auth:
+ if (
+ not user_devid == ""
+ ): # Performing basic "auth" using devid, super insecure
+ user = bumper.user_by_deviceid(user_devid)
+ if "checkLogin" in request.path:
+ self.check_token(
+ apptype, countrycode, user, request.query["accessToken"]
+ )
+ else:
+ if "global_" in apptype: # EcoVacs Home
+ login_details = EcoVacsHome_Login()
+ login_details.ucUid = "fuid_{}".format(user["userid"])
+ login_details.loginName = "fusername_{}".format(
+ user["userid"]
+ )
+ login_details.mobile = None
+
+ else:
+ login_details = EcoVacs_Login()
+
+ # Deactivate old tokens and authcodes
+ bumper.user_revoke_expired_tokens(user["userid"])
+
+ login_details.accessToken = self.generate_token(user)
+ login_details.uid = "fuid_{}".format(user["userid"])
+ login_details.username = "fusername_{}".format(user["userid"])
+ login_details.country = countrycode
+ login_details.email = "null@null.com"
+
+ body = {
+ "code": API_ERRORS[RETURN_API_SUCCESS],
+ "data": json.loads(login_details.toJSON()),
+ # {
+ # "accessToken": self.generate_token(tmpuser), # Generate a token
+ # "country": countrycode,
+ # "email": "null@null.com",
+ # "uid": "fuid_{}".format(tmpuser["userid"]),
+ # "username": "fusername_{}".format(tmpuser["userid"]),
+ # },
+ "msg": "操作成功",
+ "time": self.get_milli_time(datetime.utcnow().timestamp()),
+ }
+
+ return web.json_response(body)
+
+ body = {
+ "code": bumper.ERR_USER_NOT_ACTIVATED,
+ "data": None,
+ "msg": "当前密码错误",
+ "time": self.get_milli_time(datetime.utcnow().timestamp()),
+ }
+
+ return web.json_response(body)
+
+ else:
+ return web.json_response(
+ self._auth_any(user_devid, apptype, countrycode, request)
+ )
+
+ except Exception as e:
+ confserverlog.exception("{}".format(e))
+
+
+ async def get_AuthCode(self, request):
+ try:
+ apptype = request.match_info.get("apptype", "")
+ user_devid = request.match_info.get("devid", "") # Ecovacs
+ if user_devid == "":
+ user_devid = request.query["deviceId"] # Ecovacs Home
+
+ if not user_devid == "":
+ user = bumper.user_by_deviceid(user_devid)
+ token = ""
+ if user:
+ if "accessToken" in request.query:
+ token = bumper.user_get_token(
+ user["userid"], request.query["accessToken"]
+ )
+ if token:
+ authcode = ""
+ if not "authcode" in token:
+ authcode = self.generate_authcode(
+ user,
+ request.match_info.get("country", "us"),
+ request.query["accessToken"],
+ )
+ else:
+ authcode = token["authcode"]
+ if "global" in apptype:
+ body = {
+ "code": bumper.RETURN_API_SUCCESS,
+ "data": {
+ "authCode": authcode,
+ "ecovacsUid": request.query["uid"],
+ },
+ "msg": "操作成功",
+ "success": True,
+ "time": self.get_milli_time(
+ datetime.utcnow().timestamp()
+ ),
+ }
+ else:
+ body = {
+ "code": bumper.RETURN_API_SUCCESS,
+ "data": {
+ "authCode": authcode,
+ "ecovacsUid": request.query["uid"],
+ },
+ "msg": "操作成功",
+ "time": self.get_milli_time(
+ datetime.utcnow().timestamp()
+ ),
+ }
+ return web.json_response(body)
+
+ body = {
+ "code": bumper.ERR_TOKEN_INVALID,
+ "data": None,
+ "msg": "当前密码错误",
+ "time": self.get_milli_time(datetime.utcnow().timestamp()),
+ }
+
+ return web.json_response(body)
+
+ except Exception as e:
+ confserverlog.exception("{}".format(e))
+
+ def check_token(self, apptype, countrycode, user, token):
+ try:
+ if bumper.check_token(user["userid"], token):
+
+ if "global_" in apptype: # EcoVacs Home
+ login_details = EcoVacsHome_Login()
+ login_details.ucUid = "fuid_{}".format(user["userid"])
+ login_details.loginName = "fusername_{}".format(user["userid"])
+ login_details.mobile = None
+ else:
+ login_details = EcoVacs_Login()
+
+ login_details.accessToken = token
+ login_details.uid = "fuid_{}".format(user["userid"])
+ login_details.username = "fusername_{}".format(user["userid"])
+ login_details.country = countrycode
+ login_details.email = "null@null.com"
+
+ body = {
+ "code": bumper.RETURN_API_SUCCESS,
+ "data": json.loads(login_details.toJSON()),
+ # {
+ # "accessToken": self.generate_token(tmpuser), # Generate a token
+ # "country": countrycode,
+ # "email": "null@null.com",
+ # "uid": "fuid_{}".format(tmpuser["userid"]),
+ # "username": "fusername_{}".format(tmpuser["userid"]),
+ # },
+ "msg": "操作成功",
+ "time": self.get_milli_time(datetime.utcnow().timestamp()),
+ }
+ return web.json_response(body)
+
+ else:
+ body = {
+ "code": bumper.ERR_TOKEN_INVALID,
+ "data": None,
+ "msg": "当前密码错误",
+ "time": self.get_milli_time(datetime.utcnow().timestamp()),
+ }
+ return web.json_response(body)
+
+ except Exception as e:
+ confserverlog.exception("{}".format(e))
+
+ def _auth_any(self, devid, apptype, country, request):
+ try:
+ user_devid = devid
+ countrycode = country
+ user = bumper.user_by_deviceid(user_devid)
+ bots = bumper.db_get().table("bots").all()
+
+ if user: # Default to user 0
+ tmpuser = user
+ if "global_" in apptype: # EcoVacs Home
+ login_details = EcoVacsHome_Login()
+ login_details.ucUid = "fuid_{}".format(tmpuser["userid"])
+ login_details.loginName = "fusername_{}".format(tmpuser["userid"])
+ login_details.mobile = None
+ else:
+ login_details = EcoVacs_Login()
+
+ login_details.accessToken = self.generate_token(tmpuser)
+ login_details.uid = "fuid_{}".format(tmpuser["userid"])
+ login_details.username = "fusername_{}".format(tmpuser["userid"])
+ login_details.country = countrycode
+ login_details.email = "null@null.com"
+ bumper.user_add_device(tmpuser["userid"], user_devid)
+ else:
+ bumper.user_add("tmpuser") # Add a new user
+ tmpuser = bumper.user_get("tmpuser")
+ if "global_" in apptype: # EcoVacs Home
+ login_details = EcoVacsHome_Login()
+ login_details.ucUid = "fuid_{}".format(tmpuser["userid"])
+ login_details.loginName = "fusername_{}".format(tmpuser["userid"])
+ login_details.mobile = None
+ else:
+ login_details = EcoVacs_Login()
+
+ login_details.accessToken = self.generate_token(tmpuser)
+ login_details.uid = "fuid_{}".format(tmpuser["userid"])
+ login_details.username = "fusername_{}".format(tmpuser["userid"])
+ login_details.country = countrycode
+ login_details.email = "null@null.com"
+ bumper.user_add_device(tmpuser["userid"], user_devid)
+
+ for bot in bots: # Add all bots to the user
+ if "did" in bot:
+ bumper.user_add_bot(tmpuser["userid"], bot["did"])
+ else:
+ confserverlog.error("No DID for bot: {}".format(bot))
+
+ if "checkLogin" in request.path: # If request was to check a token do so
+ checkToken = self.check_token(
+ apptype, countrycode, tmpuser, request.query["accessToken"]
+ )
+ isGood = json.loads(checkToken.text)
+ if isGood["code"] == "0000":
+ return isGood
+
+ # Deactivate old tokens and authcodes
+ bumper.user_revoke_expired_tokens(tmpuser["userid"])
+
+ body = {
+ "code": bumper.RETURN_API_SUCCESS,
+ "data": json.loads(login_details.toJSON()),
+ # {
+ # "accessToken": self.generate_token(tmpuser), # Generate a token
+ # "country": countrycode,
+ # "email": "null@null.com",
+ # "uid": "fuid_{}".format(tmpuser["userid"]),
+ # "username": "fusername_{}".format(tmpuser["userid"]),
+ # },
+ "msg": "操作成功",
+ "time": self.get_milli_time(datetime.utcnow().timestamp()),
+ }
+
+ return body
+
+ except Exception as e:
+ confserverlog.exception("{}".format(e))
+
+
+ def getUserAccountInfo(self, request):
+ try:
+ user_devid = request.match_info.get("devid", "")
+ countrycode = request.match_info.get("country", "us")
+ apptype = request.match_info.get("apptype", "")
+ user = bumper.user_by_deviceid(user_devid)
+
+ if "global_" in apptype: # EcoVacs Home
+ login_details = EcoVacsHome_Login()
+ login_details.ucUid = "fuid_{}".format(user["userid"])
+ login_details.loginName = "fusername_{}".format(user["userid"])
+ login_details.mobile = None
+ else:
+ login_details = EcoVacs_Login()
+
+ login_details.uid = "fuid_{}".format(user["userid"])
+ login_details.username = "fusername_{}".format(user["userid"])
+ login_details.country = countrycode
+ login_details.email = "null@null.com"
+
+ body = {
+ "code": bumper.RETURN_API_SUCCESS,
+ "data": {
+ "email": login_details.email,
+ "hasMobile": "N",
+ "hasPassword": "Y",
+ "uid": login_details.uid,
+ "userName": login_details.username,
+ "obfuscatedMobile": None,
+ "mobile": None,
+ "loginName": login_details.loginName,
+ },
+ "msg": "操作成功",
+ "time": self.get_milli_time(datetime.utcnow().timestamp()),
+ }
+ return web.json_response(body)
+
+ except Exception as e:
+ confserverlog.exception("{}".format(e))
+
+ async def logout(self, request):
+ try:
+ user_devid = request.match_info.get("devid", "")
+ if not user_devid == "":
+ user = bumper.user_by_deviceid(user_devid)
+ if user:
+ if bumper.check_token(user["userid"], request.query["accessToken"]):
+ # Deactivate old tokens and authcodes
+ bumper.user_revoke_token(
+ user["userid"], request.query["accessToken"]
+ )
+
+ body = {
+ "code": bumper.RETURN_API_SUCCESS,
+ "data": None,
+ "msg": "操作成功",
+ "time": self.get_milli_time(datetime.utcnow().timestamp()),
+ }
+
+ return web.json_response(body)
+
+ except Exception as e:
+ confserverlog.exception("{}".format(e))
\ No newline at end of file
diff --git a/bumper/plugins.py b/bumper/plugins.py
new file mode 100644
index 0000000..d1cbc9b
--- /dev/null
+++ b/bumper/plugins.py
@@ -0,0 +1,13 @@
+#!/usr/bin/env python3
+import asyncio
+from aiohttp import web
+
+class ConfServerApp():
+ name = None
+ plugin_type = None
+ path_prefix = None
+ app = None
+ sub_api = None
+ routes = None
+
+
diff --git a/bumper/plugins/bumper_confserver_portal_appsvr.py b/bumper/plugins/bumper_confserver_portal_appsvr.py
new file mode 100644
index 0000000..523ec71
--- /dev/null
+++ b/bumper/plugins/bumper_confserver_portal_appsvr.py
@@ -0,0 +1,69 @@
+#!/usr/bin/env python3
+import asyncio
+from aiohttp import web
+from bumper import plugins
+import logging
+import bumper
+from bumper.models import *
+from bumper import plugins
+from datetime import datetime, timedelta
+
+
+class portal_api_appsvr(plugins.ConfServerApp):
+
+ def __init__(self):
+ self.name = "portal_api_appsvr"
+ self.plugin_type = "sub_api"
+ self.sub_api = "portal_api"
+
+ self.routes = [
+
+ web.route("*", "/appsvr/app.do", self.handle_appsvr_api, name="portal_api_appsvr_app"),
+
+ ]
+
+ self.get_milli_time = bumper.ConfServer.ConfServer_GeneralFunctions().get_milli_time
+
+ async def handle_appsvr_api(self, request):
+ if not request.method == "GET": # Skip GET for now
+ try:
+
+ body = {}
+ postbody = {}
+ if request.content_type == "application/x-www-form-urlencoded":
+ postbody = await request.post()
+
+ else:
+ postbody = json.loads(await request.text())
+
+ todo = postbody["todo"]
+
+ if todo == "GetGlobalDeviceList": # EcoVacs Home
+ bots = bumper.db_get().table("bots").all()
+ botlist = []
+ for bot in bots:
+ if bot["class"] != "":
+ b = bumper.bot_toEcoVacsHome_JSON(bot)
+ if (
+ not b is None
+ ): # Happens if the bot isn't on the EcoVacs Home list
+ botlist.append(json.loads(b))
+
+ body = {
+ "code": 0,
+ "devices": botlist,
+ "ret": "ok",
+ "todo": "result",
+ }
+
+ return web.json_response(body)
+
+ except Exception as e:
+ logging.exception("{}".format(e))
+
+ # Return fail for GET
+ body = {"result": "fail", "todo": "result"}
+ return web.json_response(body)
+
+plugin = portal_api_appsvr()
+
diff --git a/bumper/plugins/bumper_confserver_portal_dim.py b/bumper/plugins/bumper_confserver_portal_dim.py
new file mode 100644
index 0000000..78e4583
--- /dev/null
+++ b/bumper/plugins/bumper_confserver_portal_dim.py
@@ -0,0 +1,72 @@
+#!/usr/bin/env python3
+import asyncio
+from aiohttp import web
+from bumper import plugins
+import logging
+import bumper
+from bumper.models import *
+from bumper import plugins
+from datetime import datetime, timedelta
+import string
+import random
+
+
+class portal_api_dim(plugins.ConfServerApp):
+
+ def __init__(self):
+ self.name = "portal_api_dimr"
+ self.plugin_type = "sub_api"
+ self.sub_api = "portal_api"
+
+ self.routes = [
+
+ web.route("*", "/dim/devmanager.do", self.handle_dim_devmanager, name="portal_api_dim_devmanager"),
+
+ ]
+
+ self.get_milli_time = bumper.ConfServer.ConfServer_GeneralFunctions().get_milli_time
+
+ async def handle_dim_devmanager(self, request): # Used in EcoVacs Home App
+ try:
+ json_body = json.loads(await request.text())
+
+ randomid = "".join(random.sample(string.ascii_letters, 6))
+ did = ""
+ if "toId" in json_body: # Its a command
+ did = json_body["toId"]
+
+ if did != "":
+ bot = bumper.bot_get(did)
+ if bot["company"] == "eco-ng" and bot["mqtt_connection"] == True:
+ retcmd = await bumper.mqtt_helperbot.send_command(
+ json_body, randomid
+ )
+ body = retcmd
+ logging.debug("Send Bot - {}".format(json_body))
+ logging.debug("Bot Response - {}".format(body))
+ return web.json_response(body)
+ else:
+ # No response, send error back
+ logging.error(
+ "No bots with DID: {} connected to MQTT".format(
+ json_body["toId"]
+ )
+ )
+ body = {"id": randomid, "errno": bumper.ERR_COMMON, "ret": "fail"}
+ return web.json_response(body)
+
+ else:
+ if "td" in json_body: # Seen when doing initial wifi config
+ if json_body["td"] == "PollSCResult":
+ body = {"ret": "ok"}
+ return web.json_response(body)
+
+ if json_body["td"] == "HasUnreadMsg": # EcoVacs Home
+ body = {"ret": "ok", "unRead": False}
+ return web.json_response(body)
+
+ except Exception as e:
+ logging.exception("{}".format(e))
+
+plugin = portal_api_dim()
+
diff --git a/bumper/plugins/bumper_confserver_portal_iot.py b/bumper/plugins/bumper_confserver_portal_iot.py
new file mode 100644
index 0000000..6023db6
--- /dev/null
+++ b/bumper/plugins/bumper_confserver_portal_iot.py
@@ -0,0 +1,76 @@
+#!/usr/bin/env python3
+import asyncio
+from aiohttp import web
+from bumper import plugins
+import logging
+import bumper
+from bumper.models import *
+from bumper import plugins
+from datetime import datetime, timedelta
+import string
+import random
+
+class portal_api_iot(plugins.ConfServerApp):
+
+ def __init__(self):
+ self.name = "portal_api_iot"
+ self.plugin_type = "sub_api"
+ self.sub_api = "portal_api"
+
+ self.routes = [
+
+ web.route("*", "/iot/devmanager.do", self.handle_devmanager_botcommand, name="portal_api_iot_devmanager"),
+
+ ]
+
+ self.get_milli_time = bumper.ConfServer.ConfServer_GeneralFunctions().get_milli_time
+
+ async def handle_devmanager_botcommand(self, request):
+ try:
+ json_body = json.loads(await request.text())
+
+ randomid = "".join(random.sample(string.ascii_letters, 6))
+ did = ""
+ if "toId" in json_body: # Its a command
+ did = json_body["toId"]
+
+ if did != "":
+ bot = bumper.bot_get(did)
+ if bot["company"] == "eco-ng":
+ retcmd = await bumper.mqtt_helperbot.send_command(
+ json_body, randomid
+ )
+ body = retcmd
+ logging.debug("Send Bot - {}".format(json_body))
+ logging.debug("Bot Response - {}".format(body))
+ return web.json_response(body)
+ else:
+ # No response, send error back
+ logging.error(
+ "No bots with DID: {} connected to MQTT".format(
+ json_body["toId"]
+ )
+ )
+ body = {
+ "id": randomid,
+ "errno": 500,
+ "ret": "fail",
+ "debug": "wait for response timed out",
+ }
+ return web.json_response(body)
+
+ else:
+ if "td" in json_body: # Seen when doing initial wifi config
+ if json_body["td"] == "PollSCResult":
+ body = {"ret": "ok"}
+ return web.json_response(body)
+
+ if json_body["td"] == "HasUnreadMsg": # EcoVacs Home
+ body = {"ret": "ok", "unRead": False}
+ return web.json_response(body)
+
+ except Exception as e:
+ logging.exception("{}".format(e))
+
+plugin = portal_api_iot()
+
diff --git a/bumper/plugins/bumper_confserver_portal_lg.py b/bumper/plugins/bumper_confserver_portal_lg.py
new file mode 100644
index 0000000..c43d59b
--- /dev/null
+++ b/bumper/plugins/bumper_confserver_portal_lg.py
@@ -0,0 +1,108 @@
+#!/usr/bin/env python3
+import asyncio
+from aiohttp import web
+from bumper import plugins
+import logging
+import bumper
+from bumper.models import *
+from bumper import plugins
+from datetime import datetime, timedelta
+import os
+import string
+import random
+import xml.etree.ElementTree as ET
+
+class portal_api_lg(plugins.ConfServerApp):
+
+ def __init__(self):
+ self.name = "portal_api_lg"
+ self.plugin_type = "sub_api"
+ self.sub_api = "portal_api"
+
+ self.routes = [
+
+ web.route("*", "/lg/log.do", self.handle_lg_log, name="portal_api_lg_log"),
+
+ ]
+
+ self.get_milli_time = bumper.ConfServer.ConfServer_GeneralFunctions().get_milli_time
+
+ async def handle_lg_log(self, request): # EcoVacs Home
+ try:
+ json_body = json.loads(await request.text())
+
+ randomid = "".join(random.sample(string.ascii_letters, 6))
+ did = json_body["did"]
+
+ botdetails = bumper.bot_get(did)
+ if botdetails:
+ if not "cmdName" in json_body:
+ if "td" in json_body:
+ json_body["cmdName"] = json_body["td"]
+
+ if not "toId" in json_body:
+ json_body["toId"] = did
+
+ if not "toType" in json_body:
+ json_body["toType"] = botdetails["class"]
+
+ if not "toRes" in json_body:
+ json_body["toRes"] = botdetails["resource"]
+
+ if not "payloadType" in json_body:
+ json_body["payloadType"] = "x"
+
+ if not "payload" in json_body:
+ #json_body["payload"] = ""
+ if json_body["td"] == "GetCleanLogs":
+ json_body["td"] = "q"
+ json_body["payload"] = ''
+
+ if did != "":
+ bot = bumper.bot_get(did)
+ if bot["company"] == "eco-ng":
+ retcmd = await bumper.mqtt_helperbot.send_command(
+ json_body, randomid
+ )
+ body = retcmd
+ logging.debug("Send Bot - {}".format(json_body))
+ logging.debug("Bot Response - {}".format(body))
+ logs = []
+ logsroot = ET.fromstring(retcmd["resp"])
+ if logsroot.attrib["ret"] == "ok":
+ cleanlogs = logsroot.getchildren()
+ for l in cleanlogs:
+ cleanlog = {
+ "ts": l.attrib['s'],
+ "area": l.attrib['a'],
+ "last": l.attrib['l'],
+ "cleanType": l.attrib['t'],
+ #imageUrl allows for providing images of cleanings, something to look into later
+ #"imageUrl": "https://localhost:8007",
+ }
+ logs.append(cleanlog)
+ body = {
+ "ret": "ok",
+ "logs": logs,
+ }
+
+ else:
+ body = {"ret": "ok", "logs": []}
+
+ logging.debug("lg logs return: {}".format(json.dumps(body)))
+ return web.json_response(body)
+ else:
+ # No response, send error back
+ logging.error(
+ "No bots with DID: {} connected to MQTT".format(
+ json_body["toId"]
+ )
+ )
+ body = {"id": randomid, "errno": bumper.ERR_COMMON, "ret": "fail"}
+ return web.json_response(body)
+
+ except Exception as e:
+ logging.exception("{}".format(e))
+
+plugin = portal_api_lg()
+
diff --git a/bumper/plugins/bumper_confserver_portal_neng.py b/bumper/plugins/bumper_confserver_portal_neng.py
new file mode 100644
index 0000000..944c3aa
--- /dev/null
+++ b/bumper/plugins/bumper_confserver_portal_neng.py
@@ -0,0 +1,37 @@
+#!/usr/bin/env python3
+import asyncio
+from aiohttp import web
+from bumper import plugins
+import logging
+import bumper
+from bumper.models import *
+from bumper import plugins
+from datetime import datetime, timedelta
+
+
+class portal_api_neng(plugins.ConfServerApp):
+
+ def __init__(self):
+ self.name = "portal_api_neng"
+ self.plugin_type = "sub_api"
+ self.sub_api = "portal_api"
+
+ self.routes = [
+
+ web.route("*", "/neng/message/hasUnreadMsg", self.handle_neng_hasUnreadMessage, name="portal_api_neng_hasUnreadMessage"),
+
+ ]
+
+ self.get_milli_time = bumper.ConfServer.ConfServer_GeneralFunctions().get_milli_time
+
+ async def handle_neng_hasUnreadMessage(self, request): # EcoVacs Home
+ try:
+ body = {"code": 0, "data": {"hasUnRead": True}}
+
+ return web.json_response(body)
+
+ except Exception as e:
+ logging.exception("{}".format(e))
+
+plugin = portal_api_neng()
+
diff --git a/bumper/plugins/bumper_confserver_portal_pim.py b/bumper/plugins/bumper_confserver_portal_pim.py
new file mode 100644
index 0000000..2473823
--- /dev/null
+++ b/bumper/plugins/bumper_confserver_portal_pim.py
@@ -0,0 +1,49 @@
+#!/usr/bin/env python3
+import asyncio
+from aiohttp import web
+from bumper import plugins
+import logging
+import bumper
+from bumper.models import *
+from bumper import plugins
+from datetime import datetime, timedelta
+import os
+
+class portal_api_pim(plugins.ConfServerApp):
+
+ def __init__(self):
+ self.name = "portal_api_pim"
+ self.plugin_type = "sub_api"
+ self.sub_api = "portal_api"
+
+ self.routes = [
+
+ web.route("*", "/pim/product/getProductIotMap", self.handle_getProductIotMap, name="portal_api_pim_getProductIotMap"),
+ web.route("*", "/pim/file/get/{id}", self.handle_pimFile, name="portal_api_pim_file"),
+
+ ]
+
+ self.get_milli_time = bumper.ConfServer.ConfServer_GeneralFunctions().get_milli_time
+
+ async def handle_getProductIotMap(self, request):
+ try:
+ body = {
+ "code": bumper.RETURN_API_SUCCESS,
+ "data": EcoVacsHomeProducts,
+ }
+ return web.json_response(body)
+
+ except Exception as e:
+ logging.exception("{}".format(e))
+
+ async def handle_pimFile(self, request):
+ try:
+ fileID = request.match_info.get("id", "")
+
+ return web.FileResponse(os.path.join(bumper.data_dir,"web","robotvac_image.jpg"))
+
+ except Exception as e:
+ logging.exception("{}".format(e))
+
+plugin = portal_api_pim()
+
diff --git a/bumper/plugins/bumper_confserver_portal_users.py b/bumper/plugins/bumper_confserver_portal_users.py
new file mode 100644
index 0000000..fd4d5f8
--- /dev/null
+++ b/bumper/plugins/bumper_confserver_portal_users.py
@@ -0,0 +1,120 @@
+#!/usr/bin/env python3
+import asyncio
+from aiohttp import web
+from bumper import plugins
+import logging
+import bumper
+from bumper.models import *
+from bumper import plugins
+from datetime import datetime, timedelta
+
+
+class portal_api_users(plugins.ConfServerApp):
+
+ def __init__(self):
+ self.name = "portal_api_users"
+ self.plugin_type = "sub_api"
+ self.sub_api = "portal_api"
+
+ self.routes = [
+
+ web.route("*", "/users/user.do", self.handle_usersapi, name="portal_api_users_user"),
+
+ ]
+
+ self.get_milli_time = bumper.ConfServer.ConfServer_GeneralFunctions().get_milli_time
+
+ async def handle_usersapi(self, request):
+ if not request.method == "GET": # Skip GET for now
+ try:
+
+ body = {}
+ postbody = {}
+ if request.content_type == "application/x-www-form-urlencoded":
+ postbody = await request.post()
+
+ else:
+ postbody = json.loads(await request.text())
+
+ todo = postbody["todo"]
+ if todo == "FindBest":
+ service = postbody["service"]
+ if service == "EcoMsgNew":
+ srvip = bumper.bumper_announce_ip
+ srvport = 5223
+ logging.info(
+ "Announcing EcoMsgNew Server to bot as: {}:{}".format(
+ srvip, srvport
+ )
+ )
+ msgserver = {"ip": srvip, "port": srvport, "result": "ok"}
+ msgserver = json.dumps(msgserver)
+ msgserver = msgserver.replace(
+ " ", ""
+ ) # bot seems to be very picky about having no spaces, only way was with text
+
+ return web.json_response(text=msgserver)
+
+ elif service == "EcoUpdate":
+ srvip = "47.88.66.164" # EcoVacs Server
+ srvport = 8005
+ logging.info(
+ "Announcing EcoUpdate Server to bot as: {}:{}".format(
+ srvip, srvport
+ )
+ )
+ body = {"result": "ok", "ip": srvip, "port": srvport}
+
+ elif todo == "loginByItToken":
+ if "userId" in postbody:
+ if bumper.check_authcode(postbody["userId"], postbody["token"]):
+ body = {
+ "resource": postbody["resource"],
+ "result": "ok",
+ "todo": "result",
+ "token": postbody["token"],
+ "userId": postbody["userId"],
+ }
+ else: # EcoVacs Home LoginByITToken
+ loginToken = bumper.loginByItToken(postbody["token"])
+ if not loginToken == {}:
+ body = {
+ "resource": postbody["resource"],
+ "result": "ok",
+ "todo": "result",
+ "token": loginToken["token"],
+ "userId": loginToken["userid"],
+ }
+ else:
+ body = {"result": "fail", "todo": "result"}
+
+ elif todo == "GetDeviceList":
+ body = {
+ "devices": bumper.db_get().table("bots").all(),
+ "result": "ok",
+ "todo": "result",
+ }
+
+ elif todo == "SetDeviceNick":
+ bumper.bot_set_nick(postbody["did"], postbody["nick"])
+ body = {"result": "ok", "todo": "result"}
+
+ elif todo == "AddOneDevice":
+ bumper.bot_set_nick(postbody["did"], postbody["nick"])
+ body = {"result": "ok", "todo": "result"}
+
+ elif todo == "DeleteOneDevice":
+ bumper.bot_remove(postbody["did"])
+ body = {"result": "ok", "todo": "result"}
+
+ return web.json_response(body)
+
+ except Exception as e:
+ logging.exception("{}".format(e))
+
+ # Return fail for GET
+ body = {"result": "fail", "todo": "result"}
+ return web.json_response(body)
+
+plugin = portal_api_users()
+
diff --git a/bumper/plugins/bumper_confserver_v1_global_auth.py b/bumper/plugins/bumper_confserver_v1_global_auth.py
new file mode 100644
index 0000000..bbceb70
--- /dev/null
+++ b/bumper/plugins/bumper_confserver_v1_global_auth.py
@@ -0,0 +1,28 @@
+#!/usr/bin/env python3
+import asyncio
+from aiohttp import web
+from bumper import plugins
+import logging
+import bumper
+from bumper.models import *
+from bumper import plugins
+from datetime import datetime, timedelta
+
+
+class v1_global_auth(plugins.ConfServerApp):
+
+ def __init__(self):
+ self.name = "v1_global_auth"
+ self.plugin_type = "sub_api"
+ self.sub_api = "api_v1"
+
+ authhandler = bumper.ConfServer.ConfServer_AuthHandler()
+ self.routes = [
+ web.route("*", "/global/auth/getAuthCode", authhandler.get_AuthCode, name="v1_global_auth_getAuthCode"),
+ ]
+
+ self.get_milli_time = bumper.ConfServer.ConfServer_GeneralFunctions().get_milli_time
+
+
+plugin = v1_global_auth()
+
diff --git a/bumper/plugins/bumper_confserver_v1_private_ad.py b/bumper/plugins/bumper_confserver_v1_private_ad.py
new file mode 100644
index 0000000..2e7df5b
--- /dev/null
+++ b/bumper/plugins/bumper_confserver_v1_private_ad.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env python3
+import asyncio
+from aiohttp import web
+from bumper import plugins
+import logging
+import bumper
+from bumper.models import *
+from bumper import plugins
+from datetime import datetime, timedelta
+
+
+class v1_private_ad(plugins.ConfServerApp):
+
+ def __init__(self):
+ self.name = "v1_private_ad"
+ self.plugin_type = "sub_api"
+ self.sub_api = "api_v1"
+
+ self.routes = [
+ web.route("*", "/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/ad/getAdByPositionType", self.handle_getAdByPositionType, name="v1_ad_getAdByPositionType"),
+ web.route("*", "/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/ad/getBootScreen", self.handle_getBootScreen, name="v1_ad_getBootScreen"),
+
+ ]
+
+ self.get_milli_time = bumper.ConfServer.ConfServer_GeneralFunctions().get_milli_time
+
+ async def handle_getAdByPositionType(self, request): # EcoVacs Home
+ try:
+ body = {
+ "code": bumper.RETURN_API_SUCCESS,
+ "data": None,
+ "msg": "操作成功",
+ "success": True,
+ "time": self.get_milli_time(datetime.utcnow().timestamp()),
+ }
+
+ return web.json_response(body)
+
+ except Exception as e:
+ logging.exception("{}".format(e))
+
+ async def handle_getBootScreen(self, request): # EcoVacs Home
+ try:
+ body = {
+ "code": bumper.RETURN_API_SUCCESS,
+ "data": None,
+ "msg": "操作成功",
+ "success": True,
+ "time": self.get_milli_time(datetime.utcnow().timestamp()),
+ }
+
+ return web.json_response(body)
+
+ except Exception as e:
+ logging.exception("{}".format(e))
+
+plugin = v1_private_ad()
+
diff --git a/bumper/plugins/bumper_confserver_v1_private_campaign.py b/bumper/plugins/bumper_confserver_v1_private_campaign.py
new file mode 100644
index 0000000..468ca8c
--- /dev/null
+++ b/bumper/plugins/bumper_confserver_v1_private_campaign.py
@@ -0,0 +1,54 @@
+#!/usr/bin/env python3
+import asyncio
+from aiohttp import web
+from bumper import plugins
+import logging
+import bumper
+from bumper.models import *
+from bumper import plugins
+from datetime import datetime, timedelta
+
+
+class v1_private_campaign(plugins.ConfServerApp):
+
+ def __init__(self):
+ self.name = "v1_private_campaign"
+ self.plugin_type = "sub_api"
+ self.sub_api = "api_v1"
+
+ self.routes = [
+
+ web.route("*", "/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/campaign/homePageAlert", self.handle_homePageAlert, name="v1_campaign_homePageAlert"),
+
+ ]
+
+ self.get_milli_time = bumper.ConfServer.ConfServer_GeneralFunctions().get_milli_time
+
+ async def handle_homePageAlert(self, request):
+ try:
+ nextAlert = self.get_milli_time(
+ (datetime.now() + timedelta(hours=12)).timestamp()
+ )
+
+ body = {
+ "code": bumper.RETURN_API_SUCCESS,
+ "data": {
+ "clickSchemeUrl": None,
+ "clickWebUrl": None,
+ "hasCampaign": "N",
+ "imageUrl": None,
+ "nextAlertTime": nextAlert,
+ "serverTime": self.get_milli_time(datetime.utcnow().timestamp()),
+ },
+ "msg": "操作成功",
+ "time": self.get_milli_time(datetime.utcnow().timestamp()),
+ }
+
+ return web.json_response(body)
+
+ except Exception as e:
+ logging.exception("{}".format(e))
+
+
+plugin = v1_private_campaign()
+
diff --git a/bumper/plugins/bumper_confserver_v1_private_common.py b/bumper/plugins/bumper_confserver_v1_private_common.py
new file mode 100644
index 0000000..71a0034
--- /dev/null
+++ b/bumper/plugins/bumper_confserver_v1_private_common.py
@@ -0,0 +1,115 @@
+#!/usr/bin/env python3
+import asyncio
+from aiohttp import web
+from bumper import plugins
+import logging
+import bumper
+from bumper.models import *
+from bumper import plugins
+from datetime import datetime, timedelta
+
+
+class v1_private_common(plugins.ConfServerApp):
+
+ def __init__(self):
+ self.name = "v1_private_common"
+ self.plugin_type = "sub_api"
+ self.sub_api = "api_v1"
+
+ self.routes = [
+ web.route("*", "/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/common/checkAPPVersion", self.handle_checkAPPVersion, name="v1_common_checkAppVersion"),
+ web.route("*", "/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/common/checkVersion", self.handle_checkVersion, name="v1_common_checkVersion"),
+ web.route("*", "/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/common/uploadDeviceInfo", self.handle_uploadDeviceInfo, name="v1_common_uploadDeviceInfo"),
+ web.route("*", "/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/common/getSystemReminder", self.handle_getSystemReminder, name="v1_common_getSystemReminder"),
+
+ ]
+
+ self.get_milli_time = bumper.ConfServer.ConfServer_GeneralFunctions().get_milli_time
+
+ async def handle_checkVersion(self, request):
+ try:
+ body = {
+ "code": bumper.RETURN_API_SUCCESS,
+ "data": {
+ "c": None,
+ "img": None,
+ "r": 0,
+ "t": None,
+ "u": None,
+ "ut": 0,
+ "v": None,
+ },
+ "msg": "操作成功",
+ "time": self.get_milli_time(datetime.utcnow().timestamp()),
+ }
+
+ return web.json_response(body)
+
+ except Exception as e:
+ logging.exception("{}".format(e))
+
+ async def handle_checkAPPVersion(self, request): # EcoVacs Home
+ try:
+ body = {
+ "code": bumper.RETURN_API_SUCCESS,
+ "data": {
+ "c": None,
+ "downPageUrl": None,
+ "img": None,
+ "nextAlertTime": None,
+ "r": 0,
+ "t": None,
+ "u": None,
+ "ut": 0,
+ "v": None,
+ },
+ "msg": "操作成功",
+ "success": True,
+ "time": self.get_milli_time(datetime.utcnow().timestamp()),
+ }
+
+ return web.json_response(body)
+
+ except Exception as e:
+ logging.exception("{}".format(e))
+
+ async def handle_uploadDeviceInfo(self, request): # EcoVacs Home
+ try:
+ body = {
+ "code": bumper.RETURN_API_SUCCESS,
+ "data": None,
+ "msg": "操作成功",
+ "success": True,
+ "time": self.get_milli_time(datetime.utcnow().timestamp()),
+ }
+
+ return web.json_response(body)
+
+ except Exception as e:
+ logging.exception("{}".format(e))
+
+ async def handle_getSystemReminder(self, request): # EcoVacs Home
+ try:
+ body = {
+ "code": bumper.RETURN_API_SUCCESS,
+ "data": {
+ "iosGradeTime": {"iodGradeFlag": "N"},
+ "openNotification": {
+ "openNotificationContent": None,
+ "openNotificationFlag": "N",
+ "openNotificationTitle": None,
+ },
+ },
+ "msg": "操作成功",
+ "success": True,
+ "time": self.get_milli_time(datetime.utcnow().timestamp()),
+ }
+
+ return web.json_response(body)
+
+ except Exception as e:
+ logging.exception("{}".format(e))
+
+
+plugin = v1_private_common()
+
diff --git a/bumper/plugins/bumper_confserver_v1_private_message.py b/bumper/plugins/bumper_confserver_v1_private_message.py
new file mode 100644
index 0000000..7e1d6d1
--- /dev/null
+++ b/bumper/plugins/bumper_confserver_v1_private_message.py
@@ -0,0 +1,59 @@
+#!/usr/bin/env python3
+import asyncio
+from aiohttp import web
+from bumper import plugins
+import logging
+import bumper
+from bumper.models import *
+from bumper import plugins
+from datetime import datetime, timedelta
+
+
+class v1_private_message(plugins.ConfServerApp):
+
+ def __init__(self):
+ self.name = "v1_private_message"
+ self.plugin_type = "sub_api"
+ self.sub_api = "api_v1"
+
+ self.routes = [
+
+ web.route("*", "/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/message/hasUnreadMsg", self.handle_hasUnreadMessage, name="v1_message_hasUnreadMsg"),
+ web.route("*", "/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/message/getMsgList", self.handle_getMsgList, name="v1_message_getMsgList"),
+
+ ]
+
+ self.get_milli_time = bumper.ConfServer.ConfServer_GeneralFunctions().get_milli_time
+
+ async def handle_hasUnreadMessage(self, request): # EcoVacs Home
+ try:
+ body = {
+ "code": bumper.RETURN_API_SUCCESS,
+ "data": "N",
+ "msg": "操作成功",
+ "success": True,
+ "time": self.get_milli_time(datetime.utcnow().timestamp()),
+ }
+
+ return web.json_response(body)
+
+ except Exception as e:
+ logging.exception("{}".format(e))
+
+ async def handle_getMsgList(self, request): # EcoVacs Home
+ try:
+ body = {
+ "code": bumper.RETURN_API_SUCCESS,
+ "data": {"hasNextPage": 0, "items": []},
+ "msg": "操作成功",
+ "success": True,
+ "time": self.get_milli_time(datetime.utcnow().timestamp()),
+ }
+
+ return web.json_response(body)
+
+ except Exception as e:
+ logging.exception("{}".format(e))
+
+plugin = v1_private_message()
+
diff --git a/bumper/plugins/bumper_confserver_v1_private_shop.py b/bumper/plugins/bumper_confserver_v1_private_shop.py
new file mode 100644
index 0000000..343f13a
--- /dev/null
+++ b/bumper/plugins/bumper_confserver_v1_private_shop.py
@@ -0,0 +1,48 @@
+#!/usr/bin/env python3
+import asyncio
+from aiohttp import web
+from bumper import plugins
+import logging
+import bumper
+from bumper.models import *
+from bumper import plugins
+from datetime import datetime, timedelta
+
+
+class v1_private_shop(plugins.ConfServerApp):
+
+ def __init__(self):
+ self.name = "v1_private_shop"
+ self.plugin_type = "sub_api"
+ self.sub_api = "api_v1"
+
+ self.routes = [
+
+ web.route("*", "/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/shop/getCnWapShopConfig", self.handle_getCnWapShopConfig, name="v1_shop_getCnWapShopConfig"),
+
+ ]
+
+ self.get_milli_time = bumper.ConfServer.ConfServer_GeneralFunctions().get_milli_time
+
+ async def handle_getCnWapShopConfig(self, request): # EcoVacs Home
+ try:
+ body = {
+ "code": bumper.RETURN_API_SUCCESS,
+ "data": {
+ "myShopShowFlag": "N",
+ "myShopUrl": "",
+ "shopIndexShowFlag": "N",
+ "shopIndexUrl": "",
+ },
+ "msg": "操作成功",
+ "success": True,
+ "time": self.get_milli_time(datetime.utcnow().timestamp()),
+ }
+
+ return web.json_response(body)
+
+ except Exception as e:
+ logging.exception("{}".format(e))
+
+plugin = v1_private_shop()
+
diff --git a/bumper/plugins/bumper_confserver_v1_private_user.py b/bumper/plugins/bumper_confserver_v1_private_user.py
new file mode 100644
index 0000000..397fcd1
--- /dev/null
+++ b/bumper/plugins/bumper_confserver_v1_private_user.py
@@ -0,0 +1,76 @@
+#!/usr/bin/env python3
+import asyncio
+from aiohttp import web
+from bumper import plugins
+import logging
+import bumper
+from bumper.models import *
+from bumper import plugins
+from datetime import datetime, timedelta
+
+
+class v1_private_user(plugins.ConfServerApp):
+
+ def __init__(self):
+
+ self.name = "v1_private_user"
+ self.plugin_type = "sub_api"
+ self.sub_api = "api_v1"
+
+ authhandler = bumper.ConfServer.ConfServer_AuthHandler()
+ self.routes = [
+ web.route("*", "/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/login", authhandler.login, name="v1_user_login"),
+ web.route("*", "/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/checkLogin", authhandler.login, name="v1_user_checkLogin"),
+ web.route("*", "/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/getAuthCode", authhandler.get_AuthCode, name="v1_user_getAuthCode"),
+ web.route("*", "/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/logout", authhandler.logout, name="v1_user_logout"),
+ web.route("*", "/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/checkAgreement", self.handle_checkAgreement,name="v1_user_checkAgreement"),
+ web.route("*", "/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/checkAgreementBatch", self.handle_checkAgreement,name="v1_user_checkAgreementBatch"),
+ web.route("*", "/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/getUserAccountInfo", authhandler.getUserAccountInfo,name="v1_user_getUserAccountInfo"),
+ # Direct register from app:
+ # /{apiversion}/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/directRegister
+
+ ]
+
+ self.get_milli_time = bumper.ConfServer.ConfServer_GeneralFunctions().get_milli_time
+
+ async def handle_checkAgreement(self, request):
+ try:
+ apptype = request.match_info.get("apptype", "")
+ if "global_" in apptype:
+ body = {
+ "code": bumper.RETURN_API_SUCCESS,
+ "data": [
+ {
+ "force": "N",
+ "id": "20180804040641_7d746faf18b8cb22a50d145598fe4c90",
+ "type": "USER",
+ "url": "https://bumper.ecovacs.com/content/agreement?id=20180804040641_7d746faf18b8cb22a50d145598fe4c90&language=EN", # "https://gl-us-wap.ecovacs.com/content/agreement?id=20180804040641_7d746faf18b8cb22a50d145598fe4c90&language=EN
+ "version": "1.01",
+ },
+ {
+ "force": "N",
+ "id": "20180804040245_4e7c56dfb7ebd3b81b1f2747d0859fac",
+ "type": "PRIVACY",
+ "url": "https://bumper.ecovacs.com/content/agreement?id=20180804040245_4e7c56dfb7ebd3b81b1f2747d0859fac&language=EN", # "https://gl-us-wap.ecovacs.com/content/agreement?id=20180804040245_4e7c56dfb7ebd3b81b1f2747d0859fac&language=EN"
+ "version": "1.01",
+ },
+ ],
+ "msg": "操作成功",
+ "success": True,
+ "time": self.get_milli_time(datetime.utcnow().timestamp()),
+ }
+ else:
+ body = {
+ "code": bumper.RETURN_API_SUCCESS,
+ "data": [],
+ "msg": "操作成功",
+ "time": self.get_milli_time(datetime.utcnow().timestamp()),
+ }
+
+ return web.json_response(body)
+
+ except Exception as e:
+ logging.exception("{}".format(e))
+
+plugin = v1_private_user()
+
diff --git a/bumper/plugins/bumper_confserver_v2_private_user.py b/bumper/plugins/bumper_confserver_v2_private_user.py
new file mode 100644
index 0000000..5a3c7a3
--- /dev/null
+++ b/bumper/plugins/bumper_confserver_v2_private_user.py
@@ -0,0 +1,29 @@
+#!/usr/bin/env python3
+import asyncio
+from aiohttp import web
+from bumper import plugins
+import logging
+import bumper
+from bumper.models import *
+from bumper import plugins
+from datetime import datetime, timedelta
+
+
+class v2_private_user(plugins.ConfServerApp):
+
+ def __init__(self):
+
+ self.name = "v2_private_user"
+ self.plugin_type = "sub_api"
+ self.sub_api = "api_v2"
+
+ authhandler = bumper.ConfServer.ConfServer_AuthHandler()
+ self.routes = [
+ web.route("*", "/private/{country}/{language}/{devid}/{apptype}/{appversion}/{devtype}/{aid}/user/checkLogin", authhandler.login, name="v2_user_checkLogin"),
+ ]
+
+ self.get_milli_time = bumper.ConfServer.ConfServer_GeneralFunctions().get_milli_time
+
+
+plugin = v2_private_user()
+