2021-08-18 16:48:17 +00:00
|
|
|
import paho.mqtt.client as mqtt
|
|
|
|
from dbHelper import MaDbHelper
|
2021-08-19 08:29:23 +00:00
|
|
|
from pairingHandler import MaPairingHandler
|
2021-08-19 09:27:39 +00:00
|
|
|
import logging, coloredlogs, os, sys, random, string
|
2021-08-19 08:29:23 +00:00
|
|
|
|
|
|
|
coloredlogs.install(level='INFO', fmt='%(asctime)s - [%(levelname)s] %(message)s')
|
2021-08-18 16:48:17 +00:00
|
|
|
|
|
|
|
class MlmAccess:
|
|
|
|
def __init__(self):
|
2021-08-19 08:29:23 +00:00
|
|
|
logging.info("=== MlmAccess ===")
|
|
|
|
|
2021-08-19 09:27:39 +00:00
|
|
|
self._config = self._readConfig()
|
|
|
|
|
2021-08-18 16:48:17 +00:00
|
|
|
self._initDb()
|
|
|
|
self._initMqtt()
|
|
|
|
|
2021-08-19 08:29:23 +00:00
|
|
|
self._pairingHanlder = MaPairingHandler(self._mqtt, self._db)
|
|
|
|
|
|
|
|
self._mqtt.loop_forever()
|
|
|
|
|
2021-08-18 16:48:17 +00:00
|
|
|
def _initDb(self):
|
2021-08-19 08:29:23 +00:00
|
|
|
logging.info("Initializing Database")
|
2021-08-19 09:27:39 +00:00
|
|
|
self._db = MaDbHelper(self._config)
|
2021-08-18 16:48:17 +00:00
|
|
|
initUsers = [
|
2021-08-19 09:27:39 +00:00
|
|
|
("backend", self._config["MQTT_BACKEND_PASSWORD"], ["mlmAccess/#"], ["mlmAccess/#"]),
|
|
|
|
("pair-actor", self._config["PAIR_SECRET"], ["mlmAccess/pair/request/actor"], ["mlmAccess/pair/response/actor"])
|
2021-08-18 16:48:17 +00:00
|
|
|
]
|
|
|
|
|
|
|
|
for username, password, publishAclPatterns, subscribeAclPatterns in initUsers:
|
2021-08-19 08:29:23 +00:00
|
|
|
if not self._db.addUser(username, password, publishAclPatterns, subscribeAclPatterns):
|
|
|
|
self._db.updateUser(username, password, publishAclPatterns, subscribeAclPatterns)
|
2021-08-18 16:48:17 +00:00
|
|
|
|
|
|
|
def _initMqtt(self):
|
2021-08-19 08:29:23 +00:00
|
|
|
logging.info("Initializing MQTT")
|
|
|
|
self._mqtt = client = mqtt.Client(client_id="backend")
|
2021-08-19 09:27:39 +00:00
|
|
|
self._mqtt.username_pw_set("backend", self._config["MQTT_BACKEND_PASSWORD"])
|
2021-08-18 16:48:17 +00:00
|
|
|
|
2021-08-19 08:29:23 +00:00
|
|
|
self._mqtt.on_connect = self._mqttOnConnect
|
|
|
|
self._mqtt.on_message = self._mqttOnMessage
|
2021-08-18 16:48:17 +00:00
|
|
|
|
2021-08-19 09:27:39 +00:00
|
|
|
self._mqtt.connect(self._config["MQTT_HOST"], self._config["MQTT_PORT"], 60)
|
2021-08-18 17:08:57 +00:00
|
|
|
|
2021-08-18 16:48:17 +00:00
|
|
|
def _mqttOnConnect(self, client, userdata, flags, rc):
|
|
|
|
if rc != 0:
|
2021-08-19 08:29:23 +00:00
|
|
|
logging.error(f"Error connecting to MQTT broker: {rc}")
|
|
|
|
return
|
|
|
|
|
|
|
|
logging.info("Successfully connected to MQTT broker")
|
|
|
|
|
|
|
|
logging.info("Subscribing to actor subjects:")
|
|
|
|
for user in self._db.getAllUsers():
|
|
|
|
if user.startswith("actor-"):
|
|
|
|
actorSubject = f"mlmAccess/actor/{user.replace('actor-', '')}/status"
|
|
|
|
logging.info(f"* {actorSubject}")
|
|
|
|
client.subscribe(actorSubject)
|
2021-08-18 16:48:17 +00:00
|
|
|
|
2021-08-19 08:29:23 +00:00
|
|
|
# call hooks of child objects
|
|
|
|
self._pairingHanlder._mqttOnConnect(client, userdata, flags, rc)
|
2021-08-18 16:48:17 +00:00
|
|
|
|
|
|
|
def _mqttOnMessage(self, client, userdata, message):
|
2021-08-19 08:29:23 +00:00
|
|
|
topic = message.topic
|
|
|
|
topic = topic.replace("mlmAccess/", "")
|
|
|
|
messageContent = str(message.payload.decode("utf-8"))
|
2021-08-18 17:08:57 +00:00
|
|
|
|
2021-08-19 08:29:23 +00:00
|
|
|
logging.info(f"Message on topic {topic}: {messageContent}")
|
2021-08-18 16:48:17 +00:00
|
|
|
|
2021-08-19 08:29:23 +00:00
|
|
|
if topic.startswith("pair"):
|
|
|
|
self._pairingHanlder.handlePairingRequest(topic, messageContent)
|
2021-08-18 16:48:17 +00:00
|
|
|
|
2021-08-19 09:27:39 +00:00
|
|
|
def _readConfig(self):
|
|
|
|
|
|
|
|
configKeyPrefix = "MLMACCESS_"
|
|
|
|
|
|
|
|
requiredConfigKeys = [
|
|
|
|
'MYSQL_USER',
|
|
|
|
'MYSQL_PASSWORD',
|
|
|
|
'MYSQL_DATABASE',
|
|
|
|
'PAIR_SECRET'
|
|
|
|
]
|
|
|
|
|
|
|
|
allowedConfigKeys = [
|
|
|
|
'MYSQL_HOST',
|
|
|
|
'MYSQL_PORT',
|
|
|
|
'MQTT_HOST',
|
|
|
|
'MQTT_PORT',
|
|
|
|
]
|
|
|
|
|
|
|
|
backendPassword = ''.join(random.choices(string.ascii_uppercase + string.ascii_lowercase + string.digits, k=20))
|
|
|
|
config = {
|
|
|
|
"MYSQL_HOST": "mysql",
|
|
|
|
"MYSQL_PORT": 4306,
|
|
|
|
"MQTT_HOST": "mqtt",
|
|
|
|
"MQTT_PORT": 1883,
|
|
|
|
"MQTT_BACKEND_PASSWORD": backendPassword
|
|
|
|
}
|
|
|
|
|
|
|
|
for configKey in requiredConfigKeys:
|
|
|
|
if configKeyPrefix + configKey not in os.environ:
|
|
|
|
logging.error(f"Required environment value {configKeyPrefix + configKey} is not set")
|
|
|
|
sys.exit(1)
|
|
|
|
config[configKey] = os.environ[configKeyPrefix + configKey]
|
|
|
|
|
|
|
|
for configKey in allowedConfigKeys:
|
|
|
|
if configKeyPrefix + configKey in os.environ:
|
|
|
|
config[configKey] = os.environ[configKeyPrefix + configKey]
|
|
|
|
|
|
|
|
logging.info("CONFIG:")
|
|
|
|
for key, value in config.items():
|
|
|
|
logging.info(" * {:25}: {}".format(key, value))
|
|
|
|
|
|
|
|
return config
|
|
|
|
|
2021-08-18 16:48:17 +00:00
|
|
|
if __name__ == "__main__":
|
|
|
|
MlmAccess()
|