- Add Dockerfile
- Add Config in backend using env vars - Clean up mock actor
This commit is contained in:
parent
cbffbc92a6
commit
b6f8b54bc2
9 changed files with 121 additions and 36 deletions
1
backend/.dockerignore
Normal file
1
backend/.dockerignore
Normal file
|
@ -0,0 +1 @@
|
||||||
|
__pycache__
|
8
backend/Dockerfile
Normal file
8
backend/Dockerfile
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
FROM python:3-alpine
|
||||||
|
|
||||||
|
RUN apk --no-cache add build-base openldap-dev python2-dev python3-dev
|
||||||
|
RUN pip3 install python-ldap requests coloredlogs
|
||||||
|
|
||||||
|
COPY ./* ./
|
||||||
|
|
||||||
|
ENTRYPOINT [ "python3", "mlmAccess.py" ]
|
6
backend/actor.py
Normal file
6
backend/actor.py
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
class MaActor:
|
||||||
|
def __init__(self, id):
|
||||||
|
self._id = id
|
||||||
|
|
||||||
|
def _mqttOnConnect(self, client, userdata, flags, rc):
|
||||||
|
client.subscribe("mlmAccess/pair/request/actor")
|
|
@ -2,22 +2,23 @@ import pymysql
|
||||||
import json
|
import json
|
||||||
|
|
||||||
class MaDbHelper:
|
class MaDbHelper:
|
||||||
def __init__(self):
|
def __init__(self, config):
|
||||||
self.mysqlConn = pymysql.connect(host='localhost',
|
self.mysqlConn = pymysql.connect(host=config["MYSQL_HOST"],
|
||||||
user='root',
|
user=config["MYSQL_USER"],
|
||||||
passwd='MlmAccess',
|
passwd=config["MYSQL_PASSWORD"],
|
||||||
db='MlmAccess',
|
db=config["MYSQL_DATABASE"],
|
||||||
port=4306)
|
port=config["MYSQL_PORT"])
|
||||||
|
|
||||||
self.mysqlCur = self.mysqlConn.cursor()
|
self.mysqlCur = self.mysqlConn.cursor()
|
||||||
|
self._initDb()
|
||||||
|
|
||||||
def _initDb(self):
|
def _initDb(self):
|
||||||
"""
|
"""
|
||||||
Generates required tables and users
|
Generates required tables
|
||||||
"""
|
"""
|
||||||
|
|
||||||
"""
|
query = """
|
||||||
CREATE TABLE vmq_auth_acl
|
CREATE TABLE IF NOT EXISTS vmq_auth_acl
|
||||||
(
|
(
|
||||||
mountpoint VARCHAR(10) NOT NULL,
|
mountpoint VARCHAR(10) NOT NULL,
|
||||||
client_id VARCHAR(128) NOT NULL,
|
client_id VARCHAR(128) NOT NULL,
|
||||||
|
@ -29,6 +30,12 @@ class MaDbHelper:
|
||||||
)
|
)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
self.mysqlCur.execute(
|
||||||
|
query
|
||||||
|
)
|
||||||
|
|
||||||
|
self.mysqlConn.commit()
|
||||||
|
|
||||||
def addUser(self, username, password, publishAclPatterns, subscribeAclPatterns):
|
def addUser(self, username, password, publishAclPatterns, subscribeAclPatterns):
|
||||||
|
|
||||||
if self.userExists(username):
|
if self.userExists(username):
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import paho.mqtt.client as mqtt
|
import paho.mqtt.client as mqtt
|
||||||
from dbHelper import MaDbHelper
|
from dbHelper import MaDbHelper
|
||||||
from pairingHandler import MaPairingHandler
|
from pairingHandler import MaPairingHandler
|
||||||
import logging, coloredlogs
|
import logging, coloredlogs, os, sys, random, string
|
||||||
|
|
||||||
coloredlogs.install(level='INFO', fmt='%(asctime)s - [%(levelname)s] %(message)s')
|
coloredlogs.install(level='INFO', fmt='%(asctime)s - [%(levelname)s] %(message)s')
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@ class MlmAccess:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
logging.info("=== MlmAccess ===")
|
logging.info("=== MlmAccess ===")
|
||||||
|
|
||||||
|
self._config = self._readConfig()
|
||||||
|
|
||||||
self._initDb()
|
self._initDb()
|
||||||
self._initMqtt()
|
self._initMqtt()
|
||||||
|
|
||||||
|
@ -18,10 +20,10 @@ class MlmAccess:
|
||||||
|
|
||||||
def _initDb(self):
|
def _initDb(self):
|
||||||
logging.info("Initializing Database")
|
logging.info("Initializing Database")
|
||||||
self._db = MaDbHelper()
|
self._db = MaDbHelper(self._config)
|
||||||
initUsers = [
|
initUsers = [
|
||||||
("backend", "backend", ["mlmAccess/#"], ["mlmAccess/#"]),
|
("backend", self._config["MQTT_BACKEND_PASSWORD"], ["mlmAccess/#"], ["mlmAccess/#"]),
|
||||||
("pair-actor", "pair-actor", ["mlmAccess/pair/request/actor"], ["mlmAccess/pair/response/actor"])
|
("pair-actor", self._config["PAIR_SECRET"], ["mlmAccess/pair/request/actor"], ["mlmAccess/pair/response/actor"])
|
||||||
]
|
]
|
||||||
|
|
||||||
for username, password, publishAclPatterns, subscribeAclPatterns in initUsers:
|
for username, password, publishAclPatterns, subscribeAclPatterns in initUsers:
|
||||||
|
@ -31,12 +33,12 @@ class MlmAccess:
|
||||||
def _initMqtt(self):
|
def _initMqtt(self):
|
||||||
logging.info("Initializing MQTT")
|
logging.info("Initializing MQTT")
|
||||||
self._mqtt = client = mqtt.Client(client_id="backend")
|
self._mqtt = client = mqtt.Client(client_id="backend")
|
||||||
self._mqtt.username_pw_set("backend", "backend")
|
self._mqtt.username_pw_set("backend", self._config["MQTT_BACKEND_PASSWORD"])
|
||||||
|
|
||||||
self._mqtt.on_connect = self._mqttOnConnect
|
self._mqtt.on_connect = self._mqttOnConnect
|
||||||
self._mqtt.on_message = self._mqttOnMessage
|
self._mqtt.on_message = self._mqttOnMessage
|
||||||
|
|
||||||
self._mqtt.connect("localhost", 1883, 60)
|
self._mqtt.connect(self._config["MQTT_HOST"], self._config["MQTT_PORT"], 60)
|
||||||
|
|
||||||
def _mqttOnConnect(self, client, userdata, flags, rc):
|
def _mqttOnConnect(self, client, userdata, flags, rc):
|
||||||
if rc != 0:
|
if rc != 0:
|
||||||
|
@ -65,5 +67,48 @@ class MlmAccess:
|
||||||
if topic.startswith("pair"):
|
if topic.startswith("pair"):
|
||||||
self._pairingHanlder.handlePairingRequest(topic, messageContent)
|
self._pairingHanlder.handlePairingRequest(topic, messageContent)
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
MlmAccess()
|
MlmAccess()
|
|
@ -1,5 +1,5 @@
|
||||||
services:
|
services:
|
||||||
broker:
|
mqtt:
|
||||||
image: vernemq/vernemq:1.11.0
|
image: vernemq/vernemq:1.11.0
|
||||||
environment:
|
environment:
|
||||||
- DOCKER_VERNEMQ_ACCEPT_EULA=yes
|
- DOCKER_VERNEMQ_ACCEPT_EULA=yes
|
||||||
|
@ -7,7 +7,7 @@ services:
|
||||||
- DOCKER_VERNEMQ_PLUGINS__VMQ_ACL=off
|
- DOCKER_VERNEMQ_PLUGINS__VMQ_ACL=off
|
||||||
- DOCKER_VERNEMQ_PLUGINS__VMQ_DIVERSITY=on
|
- DOCKER_VERNEMQ_PLUGINS__VMQ_DIVERSITY=on
|
||||||
- DOCKER_VERNEMQ_VMQ_DIVERSITY__AUTH_MYSQL__ENABLED=on
|
- DOCKER_VERNEMQ_VMQ_DIVERSITY__AUTH_MYSQL__ENABLED=on
|
||||||
- DOCKER_VERNEMQ_VMQ_DIVERSITY__MYSQL__HOST=mysql-server
|
- DOCKER_VERNEMQ_VMQ_DIVERSITY__MYSQL__HOST=mysql
|
||||||
- DOCKER_VERNEMQ_VMQ_DIVERSITY__MYSQL__PORT=3306
|
- DOCKER_VERNEMQ_VMQ_DIVERSITY__MYSQL__PORT=3306
|
||||||
- DOCKER_VERNEMQ_VMQ_DIVERSITY__MYSQL__USER=root
|
- DOCKER_VERNEMQ_VMQ_DIVERSITY__MYSQL__USER=root
|
||||||
- DOCKER_VERNEMQ_VMQ_DIVERSITY__MYSQL__PASSWORD=MlmAccess
|
- DOCKER_VERNEMQ_VMQ_DIVERSITY__MYSQL__PASSWORD=MlmAccess
|
||||||
|
@ -21,7 +21,7 @@ services:
|
||||||
- ./data/vernemq/data:/vernemq/data
|
- ./data/vernemq/data:/vernemq/data
|
||||||
- ./data/vernemq/log:/vernemq/log
|
- ./data/vernemq/log:/vernemq/log
|
||||||
|
|
||||||
mysql-server:
|
mysql:
|
||||||
image: mariadb
|
image: mariadb
|
||||||
restart: always
|
restart: always
|
||||||
command: --default-authentication-plugin=mysql_native_password
|
command: --default-authentication-plugin=mysql_native_password
|
||||||
|
@ -37,7 +37,7 @@ services:
|
||||||
image: phpmyadmin/phpmyadmin
|
image: phpmyadmin/phpmyadmin
|
||||||
restart: always
|
restart: always
|
||||||
environment:
|
environment:
|
||||||
- PMA_HOST=mysql-server
|
- PMA_HOST=mysql
|
||||||
- PMA_USER=root
|
- PMA_USER=root
|
||||||
- PMA_PASSWORD=MlmAccess
|
- PMA_PASSWORD=MlmAccess
|
||||||
- UPLOAD_LIMIT=512M
|
- UPLOAD_LIMIT=512M
|
||||||
|
|
|
@ -3,7 +3,7 @@ import logging, coloredlogs
|
||||||
|
|
||||||
coloredlogs.install(level='INFO', fmt='%(asctime)s - [%(levelname)s] %(message)s')
|
coloredlogs.install(level='INFO', fmt='%(asctime)s - [%(levelname)s] %(message)s')
|
||||||
|
|
||||||
PAIR_ID = "106"
|
PAIR_ID = "101"
|
||||||
|
|
||||||
def on_connect(client, userdata, flags, rc):
|
def on_connect(client, userdata, flags, rc):
|
||||||
global PAIR_ID
|
global PAIR_ID
|
||||||
|
|
|
@ -1,28 +1,36 @@
|
||||||
import paho.mqtt.client as mqtt
|
import paho.mqtt.client as mqtt
|
||||||
|
import logging, coloredlogs
|
||||||
|
|
||||||
|
coloredlogs.install(level='INFO', fmt='%(asctime)s - [%(levelname)s] %(message)s')
|
||||||
|
|
||||||
|
ACTOR_ID = "101"
|
||||||
|
ACTOR_PASSWORD = "MgUiSW1dloFt9TVKJM5E"
|
||||||
|
|
||||||
# The callback for when the client receives a CONNACK response from the server.
|
|
||||||
def on_connect(client, userdata, flags, rc):
|
def on_connect(client, userdata, flags, rc):
|
||||||
print("Connected with result code "+str(rc))
|
global ACTOR_ID
|
||||||
# Subscribing in on_connect() means that if we lose the connection and
|
|
||||||
# reconnect then subscriptions will be renewed.
|
if rc != 0:
|
||||||
print("Subscribing to topic","mlmAccess/pair/response/actor")
|
logging.error(f"Error connecting to MQTT broker: {rc}")
|
||||||
print(client.subscribe("mlmAccess/actor/102/action"))
|
return
|
||||||
print("Publishing message to topic","mlmAccess/pair/request/actor")
|
|
||||||
print(client.publish("mlmAccess/actor/102/status", "0", retain=True))
|
logging.info("Successfully connected to MQTT broker")
|
||||||
|
|
||||||
|
client.subscribe(f"mlmAccess/actor/{ACTOR_ID}/action")
|
||||||
|
client.publish(f"mlmAccess/actor/{ACTOR_ID}/status", "0", retain=True)
|
||||||
|
|
||||||
def on_message(client, userdata, message):
|
def on_message(client, userdata, message):
|
||||||
print("message received " ,str(message.payload.decode("utf-8")))
|
messageContent = str(message.payload.decode("utf-8"))
|
||||||
print("message topic=",message.topic)
|
logging.info(f"Got request to perform action: {messageContent}")
|
||||||
print("message qos=",message.qos)
|
# report back action to let the backend know that it was executed successfully
|
||||||
print("message retain flag=",message.retain)
|
client.publish(f"mlmAccess/actor/{ACTOR_ID}/status", messageContent, retain=True)
|
||||||
|
|
||||||
client = mqtt.Client(client_id="actor-102")
|
client = mqtt.Client(client_id=f"actor-{ACTOR_ID}")
|
||||||
client.username_pw_set("actor-102", "YWT2JPOEZH")
|
client.username_pw_set(f"actor-{ACTOR_ID}", ACTOR_PASSWORD)
|
||||||
|
|
||||||
client.on_connect = on_connect
|
client.on_connect = on_connect
|
||||||
client.on_message = on_message
|
client.on_message = on_message
|
||||||
|
|
||||||
print("connecting to broker")
|
logging.info("Initializing MQTT")
|
||||||
print(client.connect("localhost", 1883, 60))
|
client.connect("localhost", 1883, 60)
|
||||||
|
|
||||||
client.loop_forever()
|
client.loop_forever()
|
10
runBackend.sh
Executable file
10
runBackend.sh
Executable file
|
@ -0,0 +1,10 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
export MLMACCESS_MYSQL_USER=root
|
||||||
|
export MLMACCESS_MYSQL_PASSWORD=MlmAccess
|
||||||
|
export MLMACCESS_MYSQL_DATABASE=MlmAccess
|
||||||
|
export MLMACCESS_MYSQL_HOST=localhost
|
||||||
|
export MLMACCESS_MQTT_HOST=localhost
|
||||||
|
export MLMACCESS_PAIR_SECRET=pair-actor
|
||||||
|
|
||||||
|
python3 backend/mlmAccess.py
|
Loading…
Reference in a new issue