Merge pull request #88 from bmartin5692/wip-confserver-jinja2
confserver revamp
This commit is contained in:
commit
a5883f8fa2
27 changed files with 2067 additions and 1310 deletions
2
Pipfile
2
Pipfile
|
|
@ -11,6 +11,8 @@ pyyaml = "~=5.2"
|
|||
atomicwrites = "~=1.3"
|
||||
yarl = "~=1.3.0"
|
||||
multidict = "~=4.5.2"
|
||||
aiohttp-jinja2 = "*"
|
||||
jinja2 = "*"
|
||||
|
||||
[dev-packages]
|
||||
black = "*"
|
||||
|
|
|
|||
56
Pipfile.lock
generated
56
Pipfile.lock
generated
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "315b25b9f7d46a6ea88fb08170ad935b35aa2717743be4eca137e52e595066de"
|
||||
"sha256": "740f61688ce679591a1b01f41abc1fa979f8fb1552d598e68868bc47712ba937"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {},
|
||||
|
|
@ -32,6 +32,14 @@
|
|||
"index": "pypi",
|
||||
"version": "==3.6.2"
|
||||
},
|
||||
"aiohttp-jinja2": {
|
||||
"hashes": [
|
||||
"sha256:2dfe29cfd278d07cd0a851afb98471bc8ce2a830968443e40d67636f3c035d79",
|
||||
"sha256:3b4dfe1bfd5542e254a769c18cb58d62f7f92755fec127e38d0da3436900b240"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.2.0"
|
||||
},
|
||||
"async-timeout": {
|
||||
"hashes": [
|
||||
"sha256:0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f",
|
||||
|
|
@ -82,6 +90,47 @@
|
|||
],
|
||||
"version": "==2.8"
|
||||
},
|
||||
"jinja2": {
|
||||
"hashes": [
|
||||
"sha256:74320bb91f31270f9551d46522e33af46a80c3d619f4a4bf42b3164d30b5911f",
|
||||
"sha256:9fe95f19286cfefaa917656583d020be14e7859c6b0252588391e47db34527de"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.10.3"
|
||||
},
|
||||
"markupsafe": {
|
||||
"hashes": [
|
||||
"sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473",
|
||||
"sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161",
|
||||
"sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235",
|
||||
"sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5",
|
||||
"sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff",
|
||||
"sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b",
|
||||
"sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1",
|
||||
"sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e",
|
||||
"sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183",
|
||||
"sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66",
|
||||
"sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1",
|
||||
"sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1",
|
||||
"sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e",
|
||||
"sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b",
|
||||
"sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905",
|
||||
"sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735",
|
||||
"sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d",
|
||||
"sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e",
|
||||
"sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d",
|
||||
"sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c",
|
||||
"sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21",
|
||||
"sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2",
|
||||
"sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5",
|
||||
"sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b",
|
||||
"sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6",
|
||||
"sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f",
|
||||
"sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f",
|
||||
"sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7"
|
||||
],
|
||||
"version": "==1.1.1"
|
||||
},
|
||||
"multidict": {
|
||||
"hashes": [
|
||||
"sha256:024b8129695a952ebd93373e45b5d341dbb87c17ce49637b34000093f243dd4f",
|
||||
|
|
@ -636,10 +685,9 @@
|
|||
},
|
||||
"wcwidth": {
|
||||
"hashes": [
|
||||
"sha256:3df37372226d6e63e1b1e1eda15c594bca98a22d33a23832a90998faa96bc65e",
|
||||
"sha256:f4ebe71925af7b40a864553f761ed559b43544f8f71746c2d756c7fe788ade7c"
|
||||
"sha256:8fd29383f539be45b20bd4df0dc29c20ba48654a41e661925e612311e9f3c603"
|
||||
],
|
||||
"version": "==0.1.7"
|
||||
"version": "==0.1.8"
|
||||
},
|
||||
"wrapt": {
|
||||
"hashes": [
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
1542
bumper/confserver.py
1542
bumper/confserver.py
File diff suppressed because it is too large
Load diff
|
|
@ -286,7 +286,8 @@ def bot_add(sn, did, devclass, resource, company):
|
|||
def bot_remove(did):
|
||||
bots = db_get().table("bots")
|
||||
bot = bot_get(did)
|
||||
bots.remove(doc_ids=[bot.doc_id])
|
||||
if bot:
|
||||
bots.remove(doc_ids=[bot.doc_id])
|
||||
|
||||
|
||||
def bot_get(did):
|
||||
|
|
@ -344,6 +345,11 @@ def client_add(userid, realm, resource):
|
|||
bumperlog.info("Adding new client with resource {}".format(newclient.resource))
|
||||
client_full_upsert(newclient.asdict())
|
||||
|
||||
def client_remove(resource):
|
||||
clients = db_get().table("clients")
|
||||
client = client_get(resource)
|
||||
if client:
|
||||
clients.remove(doc_ids=[client.doc_id])
|
||||
|
||||
def client_get(resource):
|
||||
clients = db_get().table("clients")
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ class MQTTHelperBot:
|
|||
|
||||
def __init__(self, address):
|
||||
self.address = address
|
||||
self.client_id = "helper1@bumper/helper1"
|
||||
self.client_id = "helperbot@bumper/helperbot"
|
||||
self.command_responses = []
|
||||
|
||||
async def start_helper_bot(self):
|
||||
|
|
@ -35,7 +35,7 @@ class MQTTHelperBot:
|
|||
try:
|
||||
if self.Client is None:
|
||||
self.Client = MQTTClient(
|
||||
client_id=self.client_id, config={"check_hostname": False}
|
||||
client_id=self.client_id, config={"check_hostname": False, "reconnect_retries": 20}
|
||||
)
|
||||
|
||||
await self.Client.connect(
|
||||
|
|
@ -44,89 +44,26 @@ class MQTTHelperBot:
|
|||
)
|
||||
await self.Client.subscribe(
|
||||
[
|
||||
("iot/p2p/+/+/+/+/helper1/bumper/helper1/+/+/+", QOS_0),
|
||||
("iot/p2p/+/+/+/+/helperbot/bumper/helperbot/+/+/+", QOS_0),
|
||||
("iot/p2p/+", QOS_0),
|
||||
("iot/atr/+", QOS_0),
|
||||
]
|
||||
)
|
||||
|
||||
asyncio.create_task(self.get_msg())
|
||||
# except ConnectionRefusedError as e:
|
||||
# helperbotlog.Error(e)
|
||||
# pass
|
||||
|
||||
except ConnectionRefusedError as e:
|
||||
helperbotlog.Error(e)
|
||||
pass
|
||||
# except asyncio.CancelledError as e:
|
||||
# pass
|
||||
|
||||
except asyncio.CancelledError as e:
|
||||
pass
|
||||
|
||||
except hbmqtt.client.ConnectException as e:
|
||||
helperbotlog.Error(e)
|
||||
pass
|
||||
# except hbmqtt.client.ConnectException as e:
|
||||
# helperbotlog.Error(e)
|
||||
# pass
|
||||
|
||||
except Exception as e:
|
||||
helperbotlog.exception("{}".format(e))
|
||||
|
||||
async def get_msg(self):
|
||||
while True:
|
||||
message = await self.Client.deliver_message()
|
||||
|
||||
if str(message.topic).split("/")[6] == "helper1":
|
||||
# Response to command
|
||||
helperbotlog.debug(
|
||||
"Received Response - Topic: {} - Message: {}".format(
|
||||
message.topic, str(message.data.decode("utf-8"))
|
||||
)
|
||||
)
|
||||
self.command_responses.append(
|
||||
{
|
||||
"time": time.time(),
|
||||
"topic": message.topic,
|
||||
"payload": str(message.data.decode("utf-8")),
|
||||
}
|
||||
)
|
||||
elif str(message.topic).split("/")[3] == "helper1":
|
||||
# Helperbot sending command
|
||||
helperbotlog.debug(
|
||||
"Send Command - Topic: {} - Message: {}".format(
|
||||
message.topic, str(message.data.decode("utf-8"))
|
||||
)
|
||||
)
|
||||
elif str(message.topic).split("/")[1] == "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(
|
||||
"Received Broadcast - Topic: {} - Message: {}".format(
|
||||
message.topic, str(message.data.decode("utf-8"))
|
||||
)
|
||||
)
|
||||
|
||||
else:
|
||||
helperbotlog.debug(
|
||||
"Received Message - Topic: {} - Message: {}".format(
|
||||
message.topic, str(message.data.decode("utf-8"))
|
||||
)
|
||||
)
|
||||
|
||||
# Cleanup "expired messages" > 60 seconds from time
|
||||
for msg in self.command_responses:
|
||||
expire_time = (
|
||||
datetime.fromtimestamp(msg["time"])
|
||||
+ timedelta(seconds=self.expire_msg_seconds)
|
||||
).timestamp()
|
||||
if time.time() > expire_time:
|
||||
helperbotlog.debug(
|
||||
"Pruning Message Due To Expiration - Message Topic: {}".format(
|
||||
msg["topic"]
|
||||
)
|
||||
)
|
||||
self.command_responses.remove(msg)
|
||||
|
||||
async def wait_for_resp(self, requestid):
|
||||
try:
|
||||
|
||||
|
|
@ -139,8 +76,7 @@ class MQTTHelperBot:
|
|||
if len(self.command_responses) > 0:
|
||||
for msg in self.command_responses:
|
||||
topic = str(msg["topic"]).split("/")
|
||||
if topic[6] == "helper1" and topic[10] == requestid:
|
||||
# helperbotlog.debug('VacBot MQTT Response: Topic: %s Payload: %s' % (msg['topic'], msg['payload']))
|
||||
if topic[6] == "helperbot" and topic[10] == requestid:
|
||||
if topic[11] == "j":
|
||||
resppayload = json.loads(msg["payload"])
|
||||
else:
|
||||
|
|
@ -175,7 +111,7 @@ class MQTTHelperBot:
|
|||
async def send_command(self, cmdjson, requestid):
|
||||
if not self.Client._handler.writer is None:
|
||||
try:
|
||||
ttopic = "iot/p2p/{}/helper1/bumper/helper1/{}/{}/{}/q/{}/{}".format(
|
||||
ttopic = "iot/p2p/{}/helperbot/bumper/helperbot/{}/{}/{}/q/{}/{}".format(
|
||||
cmdjson["cmdName"],
|
||||
cmdjson["toId"],
|
||||
cmdjson["toType"],
|
||||
|
|
@ -207,7 +143,7 @@ class MQTTHelperBot:
|
|||
|
||||
|
||||
class MQTTServer:
|
||||
default_config = {}
|
||||
default_config = None
|
||||
broker = None
|
||||
|
||||
async def broker_coro(self):
|
||||
|
|
@ -215,24 +151,38 @@ class MQTTServer:
|
|||
mqttserverlog.info(
|
||||
"Starting MQTT Server at {}:{}".format(self.address[0], self.address[1])
|
||||
)
|
||||
self.broker = hbmqtt.broker.Broker(config=self.default_config)
|
||||
|
||||
try:
|
||||
await self.broker.start()
|
||||
|
||||
except hbmqtt.broker.BrokerException as e:
|
||||
mqttserverlog.exception(e)
|
||||
asyncio.create_task(bumper.shutdown())
|
||||
#asyncio.create_task(bumper.shutdown())
|
||||
pass
|
||||
|
||||
except Exception as e:
|
||||
mqttserverlog.exception("{}".format(e))
|
||||
asyncio.create_task(bumper.shutdown())
|
||||
#asyncio.create_task(bumper.shutdown())
|
||||
pass
|
||||
|
||||
def __init__(self, address):
|
||||
def __init__(self, address, **kwargs):
|
||||
try:
|
||||
self.address = address
|
||||
|
||||
# Default config opts
|
||||
passwd_file = os.path.join(
|
||||
os.path.join(bumper.data_dir, "passwd")
|
||||
) # For file auth, set user:hash in passwd file see (https://hbmqtt.readthedocs.io/en/latest/references/hbmqtt.html#configuration-example)
|
||||
|
||||
allow_anon = False
|
||||
|
||||
for key, value in kwargs.items():
|
||||
if key == "password_file":
|
||||
passwd_file = kwargs["password_file"]
|
||||
|
||||
elif key == "allow_anonymous":
|
||||
allow_anon = kwargs["allow_anonymous"] # Set to True to allow anonymous authentication
|
||||
|
||||
# The below adds a plugin to the hbmqtt.broker.plugins without having to futz with setup.py
|
||||
distribution = pkg_resources.Distribution("hbmqtt.broker.plugins")
|
||||
bumper_plugin = pkg_resources.EntryPoint.parse(
|
||||
|
|
@ -252,17 +202,17 @@ class MQTTServer:
|
|||
"keyfile": bumper.server_key,
|
||||
},
|
||||
},
|
||||
"sys_interval": 10,
|
||||
"sys_interval": 0,
|
||||
"auth": {
|
||||
"allow-anonymous": False, # Set to True to allow anonymous authentication
|
||||
"password-file": os.path.join(
|
||||
os.path.join(bumper.data_dir, "passwd")
|
||||
), # For file auth, set user:hash in passwd file see (https://hbmqtt.readthedocs.io/en/latest/references/hbmqtt.html#configuration-example)
|
||||
"allow-anonymous": allow_anon,
|
||||
"password-file": passwd_file,
|
||||
"plugins": ["bumper"], # Bumper plugin provides auth and handling of bots/clients connecting
|
||||
},
|
||||
"topic-check": {"enabled": False},
|
||||
}
|
||||
|
||||
self.broker = hbmqtt.broker.Broker(config=self.default_config)
|
||||
|
||||
except Exception as e:
|
||||
mqttserverlog.exception("{}".format(e))
|
||||
|
||||
|
|
@ -284,13 +234,6 @@ class BumperMQTTServer_Plugin:
|
|||
|
||||
async def authenticate(self, *args, **kwargs):
|
||||
authenticated = False
|
||||
if not self.auth_config:
|
||||
# auth config section not found
|
||||
self.context.logger.warning(
|
||||
"'auth' section not found in context configuration"
|
||||
)
|
||||
return False
|
||||
|
||||
|
||||
try:
|
||||
session = kwargs.get("session", None)
|
||||
|
|
@ -320,7 +263,7 @@ class BumperMQTTServer_Plugin:
|
|||
realm = tmpclientdetail[0]
|
||||
resource = tmpclientdetail[1]
|
||||
|
||||
if userid == "helper1":
|
||||
if userid == "helperbot":
|
||||
mqttserverlog.info(f"Bumper Authentication Success - Helperbot: {client_id}")
|
||||
authenticated = True
|
||||
else:
|
||||
|
|
@ -383,8 +326,6 @@ class BumperMQTTServer_Plugin:
|
|||
self.context.logger.debug(f"{(len(self._users))} user(s) read from file {password_file}")
|
||||
except FileNotFoundError:
|
||||
self.context.logger.warning(f"Password file {password_file} not found")
|
||||
else:
|
||||
self.context.logger.debug("Configuration parameter 'password_file' not found")
|
||||
|
||||
async def on_broker_client_connected(self, client_id):
|
||||
|
||||
|
|
@ -401,6 +342,69 @@ class BumperMQTTServer_Plugin:
|
|||
bumper.client_set_mqtt(client["resource"], True)
|
||||
return
|
||||
|
||||
async def on_broker_message_received(self, client_id, message):
|
||||
self.handle_helperbot_msg(client_id, message)
|
||||
|
||||
def handle_helperbot_msg(self, client_id, message):
|
||||
|
||||
if str(message.topic).split("/")[6] == "helperbot":
|
||||
# Response to command
|
||||
helperbotlog.debug(
|
||||
"Received Response - Topic: {} - Message: {}".format(
|
||||
message.topic, str(message.data.decode("utf-8"))
|
||||
)
|
||||
)
|
||||
bumper.mqtt_helperbot.command_responses.append(
|
||||
{
|
||||
"time": time.time(),
|
||||
"topic": message.topic,
|
||||
"payload": str(message.data.decode("utf-8")),
|
||||
}
|
||||
)
|
||||
elif str(message.topic).split("/")[3] == "helperbot":
|
||||
# Helperbot sending command
|
||||
helperbotlog.debug(
|
||||
"Send Command - Topic: {} - Message: {}".format(
|
||||
message.topic, str(message.data.decode("utf-8"))
|
||||
)
|
||||
)
|
||||
elif str(message.topic).split("/")[1] == "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(
|
||||
"Received Broadcast - Topic: {} - Message: {}".format(
|
||||
message.topic, str(message.data.decode("utf-8"))
|
||||
)
|
||||
)
|
||||
|
||||
else:
|
||||
helperbotlog.debug(
|
||||
"Received Message - Topic: {} - Message: {}".format(
|
||||
message.topic, str(message.data.decode("utf-8"))
|
||||
)
|
||||
)
|
||||
|
||||
# Cleanup "expired messages" > 60 seconds from time
|
||||
for msg in bumper.mqtt_helperbot.command_responses:
|
||||
expire_time = (
|
||||
datetime.fromtimestamp(msg["time"])
|
||||
+ timedelta(seconds=bumper.mqtt_helperbot.expire_msg_seconds)
|
||||
).timestamp()
|
||||
if time.time() > expire_time:
|
||||
helperbotlog.debug(
|
||||
"Pruning Message Due To Expiration - Message Topic: {}".format(
|
||||
msg["topic"]
|
||||
)
|
||||
)
|
||||
bumper.mqtt_helperbot.command_responses.remove(msg)
|
||||
|
||||
|
||||
async def on_broker_client_disconnected(self, client_id):
|
||||
|
||||
didsplit = str(client_id).split("@")
|
||||
|
|
|
|||
13
bumper/plugins.py
Normal file
13
bumper/plugins.py
Normal file
|
|
@ -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
|
||||
|
||||
|
||||
69
bumper/plugins/bumper_confserver_portal_appsvr.py
Normal file
69
bumper/plugins/bumper_confserver_portal_appsvr.py
Normal file
|
|
@ -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()
|
||||
|
||||
72
bumper/plugins/bumper_confserver_portal_dim.py
Normal file
72
bumper/plugins/bumper_confserver_portal_dim.py
Normal file
|
|
@ -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()
|
||||
|
||||
76
bumper/plugins/bumper_confserver_portal_iot.py
Normal file
76
bumper/plugins/bumper_confserver_portal_iot.py
Normal file
|
|
@ -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()
|
||||
|
||||
108
bumper/plugins/bumper_confserver_portal_lg.py
Normal file
108
bumper/plugins/bumper_confserver_portal_lg.py
Normal file
|
|
@ -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"] = '<ctl count="30"/>'
|
||||
|
||||
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()
|
||||
|
||||
37
bumper/plugins/bumper_confserver_portal_neng.py
Normal file
37
bumper/plugins/bumper_confserver_portal_neng.py
Normal file
|
|
@ -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()
|
||||
|
||||
49
bumper/plugins/bumper_confserver_portal_pim.py
Normal file
49
bumper/plugins/bumper_confserver_portal_pim.py
Normal file
|
|
@ -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()
|
||||
|
||||
120
bumper/plugins/bumper_confserver_portal_users.py
Normal file
120
bumper/plugins/bumper_confserver_portal_users.py
Normal file
|
|
@ -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()
|
||||
|
||||
28
bumper/plugins/bumper_confserver_v1_global_auth.py
Normal file
28
bumper/plugins/bumper_confserver_v1_global_auth.py
Normal file
|
|
@ -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()
|
||||
|
||||
58
bumper/plugins/bumper_confserver_v1_private_ad.py
Normal file
58
bumper/plugins/bumper_confserver_v1_private_ad.py
Normal file
|
|
@ -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()
|
||||
|
||||
54
bumper/plugins/bumper_confserver_v1_private_campaign.py
Normal file
54
bumper/plugins/bumper_confserver_v1_private_campaign.py
Normal file
|
|
@ -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()
|
||||
|
||||
115
bumper/plugins/bumper_confserver_v1_private_common.py
Normal file
115
bumper/plugins/bumper_confserver_v1_private_common.py
Normal file
|
|
@ -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()
|
||||
|
||||
59
bumper/plugins/bumper_confserver_v1_private_message.py
Normal file
59
bumper/plugins/bumper_confserver_v1_private_message.py
Normal file
|
|
@ -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()
|
||||
|
||||
48
bumper/plugins/bumper_confserver_v1_private_shop.py
Normal file
48
bumper/plugins/bumper_confserver_v1_private_shop.py
Normal file
|
|
@ -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()
|
||||
|
||||
76
bumper/plugins/bumper_confserver_v1_private_user.py
Normal file
76
bumper/plugins/bumper_confserver_v1_private_user.py
Normal file
|
|
@ -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()
|
||||
|
||||
29
bumper/plugins/bumper_confserver_v2_private_user.py
Normal file
29
bumper/plugins/bumper_confserver_v2_private_user.py
Normal file
|
|
@ -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()
|
||||
|
||||
196
data/web/templates/home.jinja2
Normal file
196
data/web/templates/home.jinja2
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
|
||||
<title>Bumper</title>
|
||||
<meta http-equiv="refresh" content="5" />
|
||||
<script>
|
||||
function restartService(service) {
|
||||
console.log("restart service", service);
|
||||
fetch('restart_' + service)
|
||||
.then((response) => {
|
||||
return response.json();
|
||||
})
|
||||
.then((myJson) => {
|
||||
alert("Restarting " + service + ": " + myJson["status"])
|
||||
console.log("restart",service,"-",myJson["status"]);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function removeBot(did) {
|
||||
console.log("remove bot",did);
|
||||
fetch('bot/remove/' + did)
|
||||
.then((response) => {
|
||||
return response.json();
|
||||
})
|
||||
.then((myJson) => {
|
||||
alert("Removing Bot (DID) - " + did + " - " + myJson["status"])
|
||||
console.log("remove bot",did, myJson["status"]);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
function removeClient(resource) {
|
||||
|
||||
console.log("remove client",resource);
|
||||
fetch('client/remove/' + resource)
|
||||
.then((response) => {
|
||||
return response.json();
|
||||
})
|
||||
.then((myJson) => {
|
||||
alert("Removing Client - resource - " + resource + " - " + myJson["status"])
|
||||
console.log("remove client",resource, myJson["status"]);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<ul id="navigation">
|
||||
{% for item in navigation %}
|
||||
<li><a href="{{ item.href }}">{{ item.caption }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
<div class="col-8">
|
||||
<h1>Bumper</h1>
|
||||
|
||||
<!-- Section Stats -->
|
||||
<div class="card bg-light border-dark">
|
||||
<div class="card-header">
|
||||
<h2 class="card-title">Server Status</h2>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
|
||||
<div class="card border border-dark">
|
||||
<div class="card card-header">
|
||||
<h3 class="card-title">MQTT Server</h3>
|
||||
<div>Action: <button type="button" class="btn btn-outline-danger btn-sm" onclick="restartService('MQTTServer');">Restart Service</button></div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
Status: {% if mqtt_server[0].state == "started" %} <span class="badge badge-success">{{ mqtt_server[0].state }}</span> {% else %} <span class="badge badge-danger">{{ mqtt_server[0].state }}</span> {% endif %}
|
||||
Sessions: {{ mqtt_server[1].sessions[0].count }}
|
||||
|
||||
<table class="table table-striped table-bordered table-responsive-lg">
|
||||
<thead class="thead-dark">
|
||||
<TH>username</TH><TH>clientid</TH><TH>state</TH>
|
||||
</thead>
|
||||
{% for sess in mqtt_server[1].sessions[1].clients %}
|
||||
<TR>
|
||||
<TD>{{ sess[0].username }}</TD>
|
||||
<TD>{{ sess[0].client_id }}</TD>
|
||||
<TD {% if sess[0].state == "connected" %} class="table-success" {% endif %}> {{ sess[0].state }} </TD>
|
||||
</TR>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</br>
|
||||
|
||||
<div class="card border border-dark">
|
||||
<div class="card card-header">
|
||||
<h3 class="card-title">XMPP Server</h3>
|
||||
<div>Action: <button type="button" class="btn btn-outline-danger btn-sm" onclick="restartService('XMPPServer');">Restart Service</button></div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
Status: {% if xmpp_server.server._serving == True %} <span class="badge badge-success">running</span> {% else %} <span class="badge badge-danger">not running</span> {% endif %}
|
||||
Clients: {{ xmpp_server.clients | length }}
|
||||
|
||||
<table class="table table-striped table-bordered table-responsive-lg">
|
||||
<thead class="thead-dark">
|
||||
<TH>uid</TH><TH>jid</TH><TH>state</TH>
|
||||
</thead>
|
||||
{% for client in xmpp_server.clients %}
|
||||
<TR>
|
||||
<TD>{{ client.uid }}</TD>
|
||||
<TD>{{ client.bumper_jid }}</TD>
|
||||
<TD {% if client.state == 4 %} class="table-success" {% endif %}>{% if client.state == 4 %} connected {% else %} not connected {% endif %}</TD>
|
||||
</TR>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</br>
|
||||
|
||||
<div class="card border border-dark">
|
||||
<div class="card card-header">
|
||||
<h3 class="card-title">Helperbot</h3>
|
||||
<div>Action: <button type="button" class="btn btn-outline-danger btn-sm" onclick="restartService('Helperbot');">Restart Service</button></div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
Status: {% if helperbot[0].state == "connected" %} <span class="badge badge-success">{{ helperbot[0].state }}</span> {% else %} <span class="badge badge-danger">{{ helperbot[0].state }}</span> {% endif %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</br>
|
||||
|
||||
<!-- Section Bots -->
|
||||
<div class="card border-dark">
|
||||
<div class="card-header">
|
||||
<h2 class="card-title">Bots</h2>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<table class="table table-striped table-bordered table-responsive-lg">
|
||||
<thead class="thead-dark">
|
||||
<TH>SN</TH><TH>Nickname</TH><TH>Class</TH><TH>DID</TH><TH>Resource</TH><TH>Company</TH><TH>MQTT Connected</TH><TH>XMPP Connected</TH><TH>Action</TH>
|
||||
</thead>
|
||||
{% for bot in bots %}
|
||||
<TR>
|
||||
<TD>{{ bot.name }}</TD>
|
||||
<TD>{{ bot.nick }}</TD>
|
||||
<TD>{{ bot.class }}</TD>
|
||||
<TD>{{ bot.did }}</TD>
|
||||
<TD>{{ bot.resource }} </TD>
|
||||
<TD>{{ bot.company}} </TD>
|
||||
|
||||
<TD {% if bot.mqtt_connection == True %} class="table-success" {% endif %}> {{ bot.mqtt_connection }} </TD>
|
||||
<TD {% if bot.xmpp_connection == True %} class="table-success" {% endif %}> {{ bot.xmpp_connection }}</TD>
|
||||
<TD> <button type="button" class="btn btn-outline-danger btn-sm" onclick="removeBot('{{ bot.did }}');">Remove</button> </TD>
|
||||
</TR>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</br>
|
||||
|
||||
<!-- Section Clients -->
|
||||
<div class="card border-dark">
|
||||
<div class="card-header">
|
||||
<h2 class="card-title">Clients</h2>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<table class="table table-striped table-bordered table-responsive-lg">
|
||||
<thead class="thead-dark">
|
||||
<TH>User ID</TH><TH>Realm</TH><TH>Resource</TH><TH>MQTT Connected</TH><TH>XMPP Connected</TH><TH>Action</TH>
|
||||
</thead>
|
||||
{% for client in clients %}
|
||||
<TR>
|
||||
<TD>{{ client.userid }}</TD>
|
||||
<TD>{{ client.realm }}</TD>
|
||||
<TD>{{ client.resource }}</TD>
|
||||
<TD {% if client.mqtt_connection == True %} class="table-success" {% endif %}> {{ client.mqtt_connection }} </TD>
|
||||
<TD {% if client.xmpp_connection == True %} class="table-success" {% endif %}> {{ client.xmpp_connection }}</TD>
|
||||
<TD> <button type="button" class="btn btn-outline-danger btn-sm" onclick="removeClient('{{ client.resource }}');">Remove</button> </TD>
|
||||
</TR>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
aiohttp==3.6.2
|
||||
aiohttp-jinja2==1.2.0
|
||||
async-timeout==3.0.1
|
||||
atomicwrites==1.3.0
|
||||
attrs==19.3.0
|
||||
|
|
@ -6,9 +7,11 @@ chardet==3.0.4
|
|||
docopt==0.6.2
|
||||
hbmqtt==0.9.5
|
||||
idna==2.8
|
||||
Jinja2==2.10.3
|
||||
MarkupSafe==1.1.1
|
||||
multidict==4.5.2
|
||||
passlib==1.7.2
|
||||
PyYAML==5.2
|
||||
PyYAML==5.3b1
|
||||
six==1.13.0
|
||||
tinydb==3.15.2
|
||||
transitions==0.7.1
|
||||
|
|
|
|||
|
|
@ -9,6 +9,9 @@ import pytest_aiohttp
|
|||
import pytest_asyncio
|
||||
import datetime, time
|
||||
from aiohttp import web
|
||||
import logging
|
||||
from testfixtures import LogCapture
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
|
||||
def create_confserver():
|
||||
|
|
@ -37,6 +40,31 @@ async def test_confserver_ssl():
|
|||
conf_server.confserver_app()
|
||||
asyncio.create_task(conf_server.start_server())
|
||||
|
||||
async def test_confserver_exceptions():
|
||||
with LogCapture() as l:
|
||||
|
||||
conf_server = bumper.ConfServer(("127.0.0.1", 8007), usessl=True)
|
||||
conf_server.confserver_app()
|
||||
conf_server.site = web.TCPSite
|
||||
|
||||
#bind permission
|
||||
conf_server.site.start = mock.Mock(side_effect=OSError(1, "error while attempting to bind on address ('127.0.0.1', 8007): permission denied"))
|
||||
await conf_server.start_server()
|
||||
|
||||
#asyncio Cancel
|
||||
conf_server.site = web.TCPSite
|
||||
conf_server.site.start = mock.Mock(side_effect=asyncio.CancelledError)
|
||||
await conf_server.start_server()
|
||||
|
||||
#general exception
|
||||
conf_server.site = web.TCPSite
|
||||
conf_server.site.start = mock.Mock(side_effect=Exception(1, "general"))
|
||||
await conf_server.start_server()
|
||||
|
||||
l.check_present(
|
||||
("confserver", "ERROR", "error while attempting to bind on address ('127.0.0.1', 8007): permission denied")
|
||||
)
|
||||
|
||||
|
||||
async def test_confserver_no_ssl():
|
||||
conf_server = bumper.ConfServer(("127.0.0.1", 111111), usessl=False)
|
||||
|
|
@ -62,10 +90,16 @@ async def test_base(aiohttp_client):
|
|||
|
||||
# Start MQTT
|
||||
mqtt_address = ("127.0.0.1", 8883)
|
||||
mqtt_server = bumper.MQTTServer(mqtt_address)
|
||||
mqtt_server = bumper.MQTTServer(mqtt_address, password_file="tests/passwd")
|
||||
bumper.mqtt_server = mqtt_server
|
||||
await mqtt_server.broker_coro()
|
||||
|
||||
# Start XMPP
|
||||
xmpp_address = ("127.0.0.1", 5223)
|
||||
xmpp_server = bumper.XMPPServer(xmpp_address)
|
||||
bumper.xmpp_server = xmpp_server
|
||||
await xmpp_server.start_async_server()
|
||||
|
||||
# Start Helperbot
|
||||
mqtt_helperbot = bumper.MQTTHelperBot(mqtt_address)
|
||||
bumper.mqtt_helperbot = mqtt_helperbot
|
||||
|
|
@ -79,13 +113,16 @@ async def test_base(aiohttp_client):
|
|||
|
||||
await mqtt_server.broker.shutdown()
|
||||
|
||||
bumper.xmpp_server.disconnect()
|
||||
|
||||
|
||||
async def test_restartService(aiohttp_client):
|
||||
remove_existing_db()
|
||||
bumper.db = "tests/tmp.db" # Set db location for testing
|
||||
|
||||
# Start MQTT
|
||||
mqtt_address = ("127.0.0.1", 8883)
|
||||
mqtt_server = bumper.MQTTServer(mqtt_address)
|
||||
mqtt_server = bumper.MQTTServer(mqtt_address, password_file="tests/passwd")
|
||||
bumper.mqtt_server = mqtt_server
|
||||
await mqtt_server.broker_coro()
|
||||
|
||||
|
|
@ -116,6 +153,16 @@ async def test_restartService(aiohttp_client):
|
|||
|
||||
xmpp_server.disconnect()
|
||||
|
||||
async def test_RemoveBot(aiohttp_client):
|
||||
client = await aiohttp_client(create_app)
|
||||
resp = await client.get("/bot/remove/test_did")
|
||||
assert resp.status == 200
|
||||
|
||||
async def test_RemoveClient(aiohttp_client):
|
||||
client = await aiohttp_client(create_app)
|
||||
resp = await client.get("/client/remove/test_resource")
|
||||
assert resp.status == 200
|
||||
|
||||
|
||||
async def test_login(aiohttp_client):
|
||||
remove_existing_db()
|
||||
|
|
|
|||
|
|
@ -141,5 +141,8 @@ def test_client_db():
|
|||
bumper.client_get("resource_123")["xmpp_connection"] == False
|
||||
) # Test that xmpp was set False for client
|
||||
assert (
|
||||
len(bumper.get_disconnected_xmpp_clients()) == 1
|
||||
len(bumper.get_disconnected_xmpp_clients()) > 0
|
||||
) # Test len of connected xmpp clients is 1
|
||||
|
||||
bumper.client_remove("resource_123")
|
||||
assert bumper.client_get("resource_123") == None
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import time
|
|||
|
||||
async def test_helperbot_message():
|
||||
mqtt_address = ("127.0.0.1", 8883)
|
||||
mqtt_server = bumper.MQTTServer(mqtt_address)
|
||||
mqtt_server = bumper.MQTTServer(mqtt_address, password_file="tests/passwd")
|
||||
await mqtt_server.broker_coro()
|
||||
|
||||
with LogCapture() as l:
|
||||
|
|
@ -31,10 +31,9 @@ async def test_helperbot_message():
|
|||
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
|
||||
|
||||
await asyncio.wait_for(mqtt_helperbot.Client.deliver_message(), timeout=0.1)
|
||||
|
||||
l.check_present(
|
||||
(
|
||||
"helperbot",
|
||||
|
|
@ -53,20 +52,19 @@ async def test_helperbot_message():
|
|||
) # Check helperbot is connected
|
||||
msg_payload = "{}"
|
||||
msg_topic_name = (
|
||||
"iot/p2p/GetWKVer/helper1/bumper/helper1/bot_serial/ls1ok3/wC3g/q/iCmuqp/j"
|
||||
"iot/p2p/GetWKVer/helperbot/bumper/helperbot/bot_serial/ls1ok3/wC3g/q/iCmuqp/j"
|
||||
)
|
||||
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
|
||||
|
||||
await asyncio.wait_for(mqtt_helperbot.Client.deliver_message(), timeout=0.1)
|
||||
|
||||
l.check_present(
|
||||
(
|
||||
"helperbot",
|
||||
"DEBUG",
|
||||
"Send Command - Topic: iot/p2p/GetWKVer/helper1/bumper/helper1/bot_serial/ls1ok3/wC3g/q/iCmuqp/j - Message: {}",
|
||||
"Send Command - Topic: iot/p2p/GetWKVer/helperbot/bumper/helperbot/bot_serial/ls1ok3/wC3g/q/iCmuqp/j - Message: {}",
|
||||
)
|
||||
) # Check send command message was logged
|
||||
l.clear()
|
||||
|
|
@ -80,20 +78,19 @@ async def test_helperbot_message():
|
|||
) # Check helperbot is connected
|
||||
msg_payload = '{"ret":"ok","ver":"0.13.5"}'
|
||||
msg_topic_name = (
|
||||
"iot/p2p/GetWKVer/bot_serial/ls1ok3/wC3g/helper1/bumper/helper1/p/iCmuqp/j"
|
||||
"iot/p2p/GetWKVer/bot_serial/ls1ok3/wC3g/helperbot/bumper/helperbot/p/iCmuqp/j"
|
||||
)
|
||||
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
|
||||
|
||||
await asyncio.wait_for(mqtt_helperbot.Client.deliver_message(), timeout=0.1)
|
||||
|
||||
l.check_present(
|
||||
(
|
||||
"helperbot",
|
||||
"DEBUG",
|
||||
'Received Response - Topic: iot/p2p/GetWKVer/bot_serial/ls1ok3/wC3g/helper1/bumper/helper1/p/iCmuqp/j - Message: {"ret":"ok","ver":"0.13.5"}',
|
||||
'Received Response - Topic: iot/p2p/GetWKVer/bot_serial/ls1ok3/wC3g/helperbot/bumper/helperbot/p/iCmuqp/j - Message: {"ret":"ok","ver":"0.13.5"}',
|
||||
)
|
||||
) # Check received response message was logged
|
||||
l.clear()
|
||||
|
|
@ -107,21 +104,20 @@ async def test_helperbot_message():
|
|||
) # Check helperbot is connected
|
||||
msg_payload = "test"
|
||||
msg_topic_name = (
|
||||
"iot/p2p/GetWKVer/bot_serial/ls1ok3/wC3g/TESTBAD/bumper/helper1/p/iCmuqp/j"
|
||||
"iot/p2p/GetWKVer/bot_serial/ls1ok3/wC3g/TESTBAD/bumper/helperbot/p/iCmuqp/j"
|
||||
)
|
||||
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
|
||||
|
||||
await asyncio.wait_for(mqtt_helperbot.Client.deliver_message(), timeout=0.1)
|
||||
|
||||
|
||||
l.check_present(
|
||||
(
|
||||
"helperbot",
|
||||
"DEBUG",
|
||||
"Received Message - Topic: iot/p2p/GetWKVer/bot_serial/ls1ok3/wC3g/TESTBAD/bumper/helper1/p/iCmuqp/j - Message: test",
|
||||
"Received Message - Topic: iot/p2p/GetWKVer/bot_serial/ls1ok3/wC3g/TESTBAD/bumper/helperbot/p/iCmuqp/j - Message: test",
|
||||
)
|
||||
) # Check received message was logged
|
||||
l.clear()
|
||||
|
|
@ -138,10 +134,8 @@ async def test_helperbot_message():
|
|||
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
|
||||
|
||||
await asyncio.wait_for(mqtt_helperbot.Client.deliver_message(), timeout=0.1)
|
||||
|
||||
l.check_present(
|
||||
(
|
||||
|
|
@ -158,20 +152,21 @@ async def test_helperbot_message():
|
|||
|
||||
async def test_helperbot_expire_message():
|
||||
mqtt_address = ("127.0.0.1", 8883)
|
||||
mqtt_server = bumper.MQTTServer(mqtt_address)
|
||||
mqtt_server = bumper.MQTTServer(mqtt_address, password_file="tests/passwd")
|
||||
await mqtt_server.broker_coro()
|
||||
|
||||
with LogCapture("helperbot") as l:
|
||||
|
||||
# Test broadcast message
|
||||
mqtt_helperbot = bumper.MQTTHelperBot(mqtt_address)
|
||||
bumper.mqtt_helperbot = mqtt_helperbot
|
||||
await mqtt_helperbot.start_helper_bot()
|
||||
assert (
|
||||
mqtt_helperbot.Client._connected_state._value == True
|
||||
) # Check helperbot is connected
|
||||
|
||||
expire_msg_payload = '{"ret":"ok","ver":"0.13.5"}'
|
||||
expire_msg_topic_name = "iot/p2p/GetWKVer/bot_serial/ls1ok3/wC3g/helper1/bumper/helper1/p/testgood/j"
|
||||
expire_msg_topic_name = "iot/p2p/GetWKVer/bot_serial/ls1ok3/wC3g/helperbot/bumper/helperbot/p/testgood/j"
|
||||
currenttime = time.time()
|
||||
mqtt_helperbot.command_responses.append(
|
||||
{
|
||||
|
|
@ -187,7 +182,7 @@ async def test_helperbot_expire_message():
|
|||
"payload": expire_msg_payload,
|
||||
} in mqtt_helperbot.command_responses # check message is in command_responses
|
||||
|
||||
await asyncio.sleep(0.2)
|
||||
await asyncio.sleep(0.1)
|
||||
mqtt_helperbot.expire_msg_seconds = (
|
||||
0.1
|
||||
) # Set expire message seconds to 0.1 so we don't wait 10 seconds
|
||||
|
|
@ -197,10 +192,9 @@ async def test_helperbot_expire_message():
|
|||
msg_topic_name, msg_payload.encode(), hbmqtt.client.QOS_0
|
||||
) # Send another message to force get_msg
|
||||
|
||||
try:
|
||||
await asyncio.wait_for(mqtt_helperbot.Client.deliver_message(), timeout=0.1)
|
||||
except asyncio.TimeoutError:
|
||||
pass
|
||||
|
||||
await asyncio.wait_for(mqtt_helperbot.Client.deliver_message(), timeout=0.1)
|
||||
|
||||
|
||||
assert {
|
||||
"time": currenttime,
|
||||
|
|
@ -222,12 +216,14 @@ async def test_helperbot_expire_message():
|
|||
await mqtt_server.broker.shutdown()
|
||||
|
||||
|
||||
|
||||
async def test_helperbot_sendcommand():
|
||||
mqtt_address = ("127.0.0.1", 8883)
|
||||
mqtt_server = bumper.MQTTServer(mqtt_address)
|
||||
mqtt_server = bumper.MQTTServer(mqtt_address, password_file="tests/passwd")
|
||||
await mqtt_server.broker_coro()
|
||||
|
||||
mqtt_helperbot = bumper.MQTTHelperBot(mqtt_address)
|
||||
bumper.mqtt_helperbot = mqtt_helperbot
|
||||
await mqtt_helperbot.start_helper_bot()
|
||||
assert (
|
||||
mqtt_helperbot.Client._connected_state._value == True
|
||||
|
|
@ -267,7 +263,7 @@ async def test_helperbot_sendcommand():
|
|||
# Send response beforehand
|
||||
msg_payload = '{"ret":"ok","ver":"0.13.5"}'
|
||||
msg_topic_name = (
|
||||
"iot/p2p/GetWKVer/bot_serial/ls1ok3/wC3g/helper1/bumper/helper1/p/testgood/j"
|
||||
"iot/p2p/GetWKVer/bot_serial/ls1ok3/wC3g/helperbot/bumper/helperbot/p/testgood/j"
|
||||
)
|
||||
await mqtt_helperbot.Client.publish(
|
||||
msg_topic_name, msg_payload.encode(), hbmqtt.client.QOS_0
|
||||
|
|
@ -306,7 +302,7 @@ async def test_helperbot_sendcommand():
|
|||
# Send response beforehand
|
||||
msg_payload = "<ctl ret='ok' type='Brush' left='4142' total='18000'/>"
|
||||
msg_topic_name = (
|
||||
"iot/p2p/GetLifeSpan/bot_serial/ls1ok3/wC3g/helper1/bumper/helper1/p/testx/q"
|
||||
"iot/p2p/GetLifeSpan/bot_serial/ls1ok3/wC3g/helperbot/bumper/helperbot/p/testx/q"
|
||||
)
|
||||
await mqtt_helperbot.Client.publish(
|
||||
msg_topic_name, msg_payload.encode(), hbmqtt.client.QOS_0
|
||||
|
|
@ -351,7 +347,7 @@ async def test_helperbot_sendcommand():
|
|||
msg_payload = '{"body":{"code":0,"data":{"area":0,"cid":"111","start":"1569378657","time":6,"type":"auto"},"msg":"ok"},"header":{"fwVer":"1.6.4","hwVer":"0.1.1","pri":1,"ts":"1569380074036","tzm":480,"ver":"0.0.1"}}'
|
||||
|
||||
msg_topic_name = (
|
||||
"iot/p2p/getStats/bot_serial/ls1ok3/wC3g/helper1/bumper/helper1/p/testj/j"
|
||||
"iot/p2p/getStats/bot_serial/ls1ok3/wC3g/helperbot/bumper/helperbot/p/testj/j"
|
||||
)
|
||||
await mqtt_helperbot.Client.publish(
|
||||
msg_topic_name, msg_payload.encode(), hbmqtt.client.QOS_0
|
||||
|
|
@ -370,6 +366,7 @@ async def test_helperbot_sendcommand():
|
|||
await mqtt_server.broker.shutdown()
|
||||
|
||||
|
||||
|
||||
async def test_mqttserver():
|
||||
if os.path.exists("tests/tmp.db"):
|
||||
os.remove("tests/tmp.db") # Remove existing db
|
||||
|
|
@ -378,26 +375,7 @@ async def test_mqttserver():
|
|||
|
||||
mqtt_address = ("127.0.0.1", 8883)
|
||||
|
||||
mqtt_server = bumper.MQTTServer(mqtt_address)
|
||||
|
||||
mqtt_server.default_config = {
|
||||
"listeners": {
|
||||
"default": {"type": "tcp"},
|
||||
"tls1": {
|
||||
"bind": "{}:{}".format(mqtt_address[0], mqtt_address[1]),
|
||||
"ssl": "on",
|
||||
"certfile": bumper.server_cert,
|
||||
"keyfile": bumper.server_key,
|
||||
},
|
||||
},
|
||||
"sys_interval": 10,
|
||||
"auth": {
|
||||
"allow-anonymous": True, # Set to True to allow anonymous authentication
|
||||
"password-file": "tests/passwd", # For file auth, set user:hash in passwd file see (https://hbmqtt.readthedocs.io/en/latest/references/hbmqtt.html#configuration-example)
|
||||
"plugins": ["bumper"], # Bumper plugin provides auth and handling of bots/clients connecting
|
||||
},
|
||||
"topic-check": {"enabled": False},
|
||||
}
|
||||
mqtt_server = bumper.MQTTServer(mqtt_address, password_file="tests/passwd", allow_anonymous=True)
|
||||
|
||||
await mqtt_server.broker_coro()
|
||||
|
||||
|
|
@ -463,147 +441,41 @@ async def test_mqttserver():
|
|||
) # Check client is disconnected
|
||||
|
||||
# bad password
|
||||
try:
|
||||
with LogCapture() as l:
|
||||
|
||||
await test_client.Client.connect(
|
||||
f"mqtts://test-client:notvalid!@{test_client.address[0]}:{test_client.address[1]}/",
|
||||
cafile=bumper.ca_cert, cleansession=True
|
||||
)
|
||||
|
||||
assert (
|
||||
test_client.Client._connected_state._value == False
|
||||
) # Check client is connected
|
||||
|
||||
except Exception as ae:
|
||||
pass
|
||||
|
||||
l.check_present(
|
||||
("mqttserver", "INFO", "File Authentication Failed - Username: test-client - ClientID: test-file-auth"),
|
||||
order_matters=False
|
||||
)
|
||||
# no username in file
|
||||
try:
|
||||
await test_client.Client.connect(
|
||||
f"mqtts://test-client-noexist:notvalid!@{test_client.address[0]}:{test_client.address[1]}/",
|
||||
cafile=bumper.ca_cert, cleansession=True
|
||||
)
|
||||
|
||||
assert (
|
||||
test_client.Client._connected_state._value == False
|
||||
) # Check client is connected
|
||||
|
||||
except Exception as ae:
|
||||
pass
|
||||
|
||||
|
||||
|
||||
await asyncio.sleep(0.1)
|
||||
|
||||
await mqtt_server.broker.shutdown()
|
||||
await asyncio.sleep(0.1)
|
||||
|
||||
async def test_passwordfile_badhash_mqttserver():
|
||||
mqtt_address = ("127.0.0.1", 8883)
|
||||
|
||||
mqtt_server = bumper.MQTTServer(mqtt_address)
|
||||
|
||||
mqtt_server.default_config = {
|
||||
"listeners": {
|
||||
"default": {"type": "tcp"},
|
||||
"tls1": {
|
||||
"bind": "{}:{}".format(mqtt_address[0], mqtt_address[1]),
|
||||
"ssl": "on",
|
||||
"certfile": bumper.server_cert,
|
||||
"keyfile": bumper.server_key,
|
||||
},
|
||||
},
|
||||
"sys_interval": 10,
|
||||
"auth": {
|
||||
"allow-anonymous": True, # Set to True to allow anonymous authentication
|
||||
"password-file": "tests/passwd_bad", # For file auth, set user:hash in passwd file see (https://hbmqtt.readthedocs.io/en/latest/references/hbmqtt.html#configuration-example)
|
||||
"plugins": ["bumper"], # Bumper plugin provides auth and handling of bots/clients connecting
|
||||
},
|
||||
"topic-check": {"enabled": False},
|
||||
}
|
||||
|
||||
await mqtt_server.broker_coro()
|
||||
await asyncio.sleep(0.1)
|
||||
|
||||
# bad password
|
||||
try:
|
||||
test_client = bumper.MQTTHelperBot(mqtt_address)
|
||||
|
||||
await test_client.Client.connect(
|
||||
f"mqtts://test-client:notvalid!@{test_client.address[0]}:{test_client.address[1]}/",
|
||||
cafile=bumper.ca_cert, cleansession=True
|
||||
l.check_present(
|
||||
("mqttserver", "INFO", 'File Authentication Failed - No Entry for Username: test-client-noexist - ClientID: test-file-auth'),
|
||||
order_matters=False
|
||||
)
|
||||
|
||||
assert (
|
||||
test_client.Client._connected_state._value == False
|
||||
) # Check client is connected
|
||||
|
||||
|
||||
except Exception as ae:
|
||||
pass
|
||||
|
||||
await mqtt_server.broker.shutdown()
|
||||
await asyncio.sleep(0.1)
|
||||
|
||||
|
||||
async def test_nofileauth_mqttserver():
|
||||
try:
|
||||
with LogCapture() as l:
|
||||
|
||||
mqtt_address = ("127.0.0.1", 8883)
|
||||
|
||||
mqtt_server = bumper.MQTTServer(mqtt_address)
|
||||
|
||||
mqtt_server.default_config = {
|
||||
"listeners": {
|
||||
"default": {"type": "tcp"},
|
||||
"tls1": {
|
||||
"bind": "{}:{}".format(mqtt_address[0], mqtt_address[1]),
|
||||
"ssl": "on",
|
||||
"certfile": bumper.server_cert,
|
||||
"keyfile": bumper.server_key,
|
||||
},
|
||||
},
|
||||
"sys_interval": 10,
|
||||
"auth": {
|
||||
"allow-anonymous": True, # Set to True to allow anonymous authentication
|
||||
"password-file": "tests/passwd-notfound", # For file auth, set user:hash in passwd file see (https://hbmqtt.readthedocs.io/en/latest/references/hbmqtt.html#configuration-example)
|
||||
"plugins": ["bumper"], # Bumper plugin provides auth and handling of bots/clients connecting
|
||||
},
|
||||
"topic-check": {"enabled": False},
|
||||
}
|
||||
|
||||
await mqtt_server.broker_coro()
|
||||
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
async def test_passwordfile_opt_missing_mqttserver():
|
||||
try:
|
||||
|
||||
mqtt_address = ("127.0.0.1", 8883)
|
||||
|
||||
mqtt_server = bumper.MQTTServer(mqtt_address)
|
||||
|
||||
mqtt_server.default_config = {
|
||||
"listeners": {
|
||||
"default": {"type": "tcp"},
|
||||
"tls1": {
|
||||
"bind": "{}:{}".format(mqtt_address[0], mqtt_address[1]),
|
||||
"ssl": "on",
|
||||
"certfile": bumper.server_cert,
|
||||
"keyfile": bumper.server_key,
|
||||
},
|
||||
},
|
||||
"sys_interval": 10,
|
||||
"auth": {
|
||||
"allow-anonymous": True, # Set to True to allow anonymous authentication
|
||||
|
||||
"plugins": ["bumper"], # Bumper plugin provides auth and handling of bots/clients connecting
|
||||
},
|
||||
"topic-check": {"enabled": False},
|
||||
}
|
||||
|
||||
mqtt_server = bumper.MQTTServer(mqtt_address, password_file="tests/passwd-notfound")
|
||||
await mqtt_server.broker_coro()
|
||||
await mqtt_server.broker.shutdown()
|
||||
|
||||
except:
|
||||
pass
|
||||
l.check_present(
|
||||
("hbmqtt.broker.plugins.bumper", "WARNING", 'Password file tests/passwd-notfound not found'),
|
||||
order_matters=False
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue