Configured customer broker
This commit is contained in:
@@ -1,5 +1,8 @@
|
|||||||
from flask import Flask
|
from flask import Flask
|
||||||
|
|
||||||
|
from src.controllers.mqtt_forwarder import MQTTForwarder
|
||||||
|
from src.services.mqtt_service import MQTTService
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
|
||||||
@@ -9,4 +12,10 @@ def hello_world():
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
app.run()
|
|
||||||
|
local_broker = MQTTService("127.0.0.1", 1883)
|
||||||
|
api_broker = MQTTService("192.168.15.120", 8883)
|
||||||
|
|
||||||
|
forwarder = MQTTForwarder(local_broker, api_broker)
|
||||||
|
|
||||||
|
app.run(host="0.0.0.0", port=5000, debug=False)
|
||||||
|
|||||||
@@ -3,11 +3,12 @@ version: "3.8"
|
|||||||
services:
|
services:
|
||||||
customer-api:
|
customer-api:
|
||||||
build: .
|
build: .
|
||||||
container_name: "Flask-API"
|
container_name: "customer-api"
|
||||||
ports:
|
ports:
|
||||||
- "5000:5000"
|
- "5000:5000"
|
||||||
depends_on:
|
depends_on:
|
||||||
- mongo
|
- mongo
|
||||||
|
- mosquitto
|
||||||
environment:
|
environment:
|
||||||
- MONGO_URI=mongodb://mongo:27017/mydb
|
- MONGO_URI=mongodb://mongo:27017/mydb
|
||||||
|
|
||||||
@@ -22,4 +23,17 @@ services:
|
|||||||
- "27017:27017"
|
- "27017:27017"
|
||||||
volumes:
|
volumes:
|
||||||
- ./mongo-data:/data/db
|
- ./mongo-data:/data/db
|
||||||
- ./mongo-init:/docker-entrypoint-initdb.d
|
- ./mongo-init:/docker-entrypoint-initdb.d
|
||||||
|
|
||||||
|
mosquitto:
|
||||||
|
image: eclipse-mosquitto:latest
|
||||||
|
container_name: "customer-broker"
|
||||||
|
ports:
|
||||||
|
- "1883:1883"
|
||||||
|
- "8883:8883"
|
||||||
|
volumes:
|
||||||
|
- ./mosquitto/config:/mosquitto/config
|
||||||
|
- ./mosquitto/data:/mosquitto/data
|
||||||
|
- ./mosquitto/log:/mosquitto/log
|
||||||
|
- ./mosquitto/certs:/mosquitto/certs
|
||||||
|
|
||||||
|
|||||||
25
api-customer/mosquitto/certs/mosquitto.crt
Normal file
25
api-customer/mosquitto/certs/mosquitto.crt
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIEMTCCAxmgAwIBAgIUSj7h3y4SaFxuD6AeIkuZytZf8uEwDQYJKoZIhvcNAQEL
|
||||||
|
BQAwgacxCzAJBgNVBAYTAkJFMREwDwYDVQQIDAhMacODwqhnZTERMA8GA1UEBwwI
|
||||||
|
TGnDg8KoZ2UxDTALBgNVBAoMBEhFUEwxHDAaBgNVBAsME0JvYXJkIG1hdGUgY3Vz
|
||||||
|
dG9tZXIxFzAVBgNVBAMMDjE5Mi4xNjguMTUuMTI1MSwwKgYJKoZIhvcNAQkBFh1s
|
||||||
|
YXVyZW50LmNyZW1hQHN0dWRlbnQuaGVwbC5iZTAeFw0yNTEyMjkxMTE5MDZaFw0y
|
||||||
|
NjEyMjkxMTE5MDZaMIGnMQswCQYDVQQGEwJCRTERMA8GA1UECAwITGnDg8KoZ2Ux
|
||||||
|
ETAPBgNVBAcMCExpw4PCqGdlMQ0wCwYDVQQKDARIRVBMMRwwGgYDVQQLDBNCb2Fy
|
||||||
|
ZCBtYXRlIGN1c3RvbWVyMRcwFQYDVQQDDA4xOTIuMTY4LjE1LjEyNTEsMCoGCSqG
|
||||||
|
SIb3DQEJARYdbGF1cmVudC5jcmVtYUBzdHVkZW50LmhlcGwuYmUwggEiMA0GCSqG
|
||||||
|
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDgRZbs1AKWZVdsytDagCRTtUrEasxzICMG
|
||||||
|
8yTAz71dqZR2FXgEHVLTpVp6cFBRB3EeRxFdo1S8te0SJ5L6aAvQIhQyUY3QF5f7
|
||||||
|
83AbauhjXIzvvnN/2RJhgU5VxRg1BTze2W3Ek3KND/GNbi6Sd+gACscjef5qnpYO
|
||||||
|
xki4qZFB/tE5nRCtZy4/7AxKGDHwy89orWrEABOP54LyFppjjzItsUkZHb++jhU6
|
||||||
|
lztKbjBydnEX3lusNw8jm1HdUaIJTuoD5az/tsQs+UjHTaFxt128YP+Bckpcegri
|
||||||
|
C7D+wRLsonVI6P0NcoGG+yzQz0w6i0PTgTNifKyl0jRau9y4VAh/AgMBAAGjUzBR
|
||||||
|
MB0GA1UdDgQWBBQcpMTyO6+JlsUUXDXTS/rFmO0ohzAfBgNVHSMEGDAWgBQcpMTy
|
||||||
|
O6+JlsUUXDXTS/rFmO0ohzAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUA
|
||||||
|
A4IBAQC5N6HhY4VMZp0gInSDZ1RrM08w3k4/3uqHa5MmRlYVb30KPy7T8wkARfiw
|
||||||
|
FCtVojYSBbIIZeSoXKLRlSvHQvKij1sajZeOtGyb6p6x+LMWGuNJ3h6HfAzjIu53
|
||||||
|
f/V4agfBp7Ljxi4T71jxvGISH7UFJs3kldQ9K737w8Wvb85CqqalzM5zVzltpHb/
|
||||||
|
nNIzKZbqxXCGhtJu8Y4gi2bW+QjxaVCtYxY6jgy5J7KhJtZDoExHCXKFOYm8u1Bd
|
||||||
|
N4J1o6M1udA4v3lHDr0dE5j7UvP7LIbhgCoGTOXaknm+UtqoKF2FKCPF2um5ral6
|
||||||
|
Bxv7rANBb73Aw2g06OyHLq3Fc35k
|
||||||
|
-----END CERTIFICATE-----
|
||||||
28
api-customer/mosquitto/certs/mosquitto.key
Normal file
28
api-customer/mosquitto/certs/mosquitto.key
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDgRZbs1AKWZVds
|
||||||
|
ytDagCRTtUrEasxzICMG8yTAz71dqZR2FXgEHVLTpVp6cFBRB3EeRxFdo1S8te0S
|
||||||
|
J5L6aAvQIhQyUY3QF5f783AbauhjXIzvvnN/2RJhgU5VxRg1BTze2W3Ek3KND/GN
|
||||||
|
bi6Sd+gACscjef5qnpYOxki4qZFB/tE5nRCtZy4/7AxKGDHwy89orWrEABOP54Ly
|
||||||
|
FppjjzItsUkZHb++jhU6lztKbjBydnEX3lusNw8jm1HdUaIJTuoD5az/tsQs+UjH
|
||||||
|
TaFxt128YP+BckpcegriC7D+wRLsonVI6P0NcoGG+yzQz0w6i0PTgTNifKyl0jRa
|
||||||
|
u9y4VAh/AgMBAAECggEAINWvag8ELfa6XQA4obTfHK5POwCT3EsZNbxFZkFD7UGV
|
||||||
|
rdAo2Rld9gSggYqOB776Lb+j6DywfEx6YA0RNL4k9Jz4rgFIrO23X7jdcfYt/dYg
|
||||||
|
AD229UHXshTXXjFUAPc6WTomGwCnZcWuzNET2nfZrJ/nVedXe06qk5EuNnMFBE8/
|
||||||
|
GsiSuULI32KtlTBhO5TS9PmJfj1+CByQLcYSTG8k8VN9NXEB3kjbCMKgl0BfuALj
|
||||||
|
Iwbbbz4ffrkzMkm0wXiq+Slad/50pIOPG1LU0KOmgaSv1sTI4hZqHJNRfig5IoP/
|
||||||
|
8E/dNJCJOAVpgoQY+SbNmaGEQjB7Fvr/qDaH67BxsQKBgQD8aZ3czUbe7VUmlLJ7
|
||||||
|
UavshgyGsox9O1Iwn2LAfP5IP441ODoqD8Wsup/P+c/zEboRlgAw/thPpVuXuXWj
|
||||||
|
3tO7OuKUSUp0PW3mqDakSzQggxff+OSbHvXzNgzG4OwwM7V2yKQdVml375ACkqB2
|
||||||
|
jdhoy9Rq8IFJ6W3cPLa1TDLFGQKBgQDjdZXGMjVv8sqhuuT+vXxLGtuhBp6dn/Ck
|
||||||
|
Mlvo/QTwADcFO5IKZwT9wt0aUOLIbTub1ZdzbrWS1YCkn13EE98W7/T+DKgc8zG/
|
||||||
|
KOIasy/U8sOFTr8o2ozCIl2umy833fRtB8IZQOaSa9UZb6Hr62do2i50FtJKSMGM
|
||||||
|
kMt+ZSgVVwKBgCwOh0ZV8ivRAw7T339U1wxWrXMJUSo+o27nMwZkCsIzja/OW6Ch
|
||||||
|
1h/7Bw/3C4viqTaOlwP2R21HcIBAF799kjlY4tl9HWjCnB8pdzggBD40g4NNXyGQ
|
||||||
|
Ot+zrHE+KxuSuva7uKGCRrBveRRp4WYwBfjssuvjhL2Q5+MMGdv1K9tpAoGAXtOU
|
||||||
|
n04rTQKRS5+Y/EKO4NjPm3AhDGGzdyCvhJCHUG8mgP32wnN0dz6X4vK5uQkhArSn
|
||||||
|
MS6EcDSmLvtpoecO6IcdQhSQuZEBukoXCT6OwF58+MR9mVCTwhOFrtdvdgEId7P2
|
||||||
|
TYTrGzvtWW9at/op4GKlXyxsex+d4TY0P/t4HH0CgYEA/Bet4dUNzBaHI5mP/vLH
|
||||||
|
ntEkqXmV0KTiv1RlhrqqYVa9Ct9Dsl2L8TkzlObQ5B0vHVHsVLMSTiUFkE9HmEa9
|
||||||
|
Tow0xmylB0PmOfXCwMBpsgh8iNqOrf8fsyIatTbG1nl3Qnbx+fFay8mnOIRZw59+
|
||||||
|
Bc8O+xK3JTWZ9ybWbohZH7E=
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
16
api-customer/mosquitto/config/mosquitto.conf
Normal file
16
api-customer/mosquitto/config/mosquitto.conf
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
persistence true
|
||||||
|
persistence_location /mosquitto/data/
|
||||||
|
|
||||||
|
log_dest file /mosquitto/log/mosquitto.log
|
||||||
|
|
||||||
|
listener 1883
|
||||||
|
|
||||||
|
allow_anonymous false
|
||||||
|
password_file /mosquitto/config/passwords
|
||||||
|
|
||||||
|
listener 8883
|
||||||
|
protocol mqtt
|
||||||
|
|
||||||
|
certfile /mosquitto/certs/mosquitto.crt
|
||||||
|
keyfile /mosquitto/certs/mosquitto.key
|
||||||
|
tls_version tlsv1.2
|
||||||
0
api-customer/mosquitto/config/passwords
Normal file
0
api-customer/mosquitto/config/passwords
Normal file
@@ -1 +1,2 @@
|
|||||||
flask
|
flask
|
||||||
|
paho-mqtt
|
||||||
0
api-customer/src/__init__.py
Normal file
0
api-customer/src/__init__.py
Normal file
0
api-customer/src/controllers/__init__.py
Normal file
0
api-customer/src/controllers/__init__.py
Normal file
43
api-customer/src/controllers/mqtt_forwarder.py
Normal file
43
api-customer/src/controllers/mqtt_forwarder.py
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import json
|
||||||
|
import time
|
||||||
|
|
||||||
|
from src.services.mqtt_service import MQTTService
|
||||||
|
|
||||||
|
|
||||||
|
class MQTTForwarder:
|
||||||
|
|
||||||
|
client_id : str
|
||||||
|
local_broker : MQTTService
|
||||||
|
central_broker : MQTTService
|
||||||
|
|
||||||
|
def __init__(self, client_id : str, local_mqtt: MQTTService, central_mqtt: MQTTService):
|
||||||
|
self.client_id = client_id
|
||||||
|
self.local_broker = local_mqtt
|
||||||
|
self.central_broker = central_mqtt
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
self.local_broker.subscribe("board-mate/", self.__forward)
|
||||||
|
|
||||||
|
def __forward(self, msg: str):
|
||||||
|
self.central_broker.publish(self.client_id, f"/board-mate/${self.client_id}/telemetry", msg)
|
||||||
|
|
||||||
|
"""def start(self):
|
||||||
|
self.local.subscribe("board-mate/+/telemetry", self.handle_message)
|
||||||
|
|
||||||
|
def handle_message(self, topic: str, payload: str):
|
||||||
|
print(f"[FORWARD] {topic} -> central")
|
||||||
|
|
||||||
|
message = json.loads(payload)
|
||||||
|
message["source"] = "client-server"
|
||||||
|
message["forwarded_at"] = int(time.time())
|
||||||
|
|
||||||
|
self.central.publish(
|
||||||
|
client_id="client-forwarder",
|
||||||
|
topic=f"clients/{self.extract_client_id(topic)}/telemetry",
|
||||||
|
data=json.dumps(message),
|
||||||
|
qos=1
|
||||||
|
)
|
||||||
|
|
||||||
|
def extract_client_id(self, topic: str) -> str:
|
||||||
|
# ex: board-mate/pi-123/telemetry
|
||||||
|
return topic.split("/")[1]"""
|
||||||
0
api-customer/src/services/__init__.py
Normal file
0
api-customer/src/services/__init__.py
Normal file
55
api-customer/src/services/mqtt_service.py
Normal file
55
api-customer/src/services/mqtt_service.py
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import json
|
||||||
|
import time
|
||||||
|
from typing import Callable
|
||||||
|
|
||||||
|
import paho.mqtt.client as mqtt
|
||||||
|
from paho.mqtt.client import Client
|
||||||
|
|
||||||
|
|
||||||
|
class MQTTService:
|
||||||
|
|
||||||
|
client : Client
|
||||||
|
|
||||||
|
def __init__(self, address: str, port: int):
|
||||||
|
self.address = address
|
||||||
|
self.port = port
|
||||||
|
self.client = mqtt.Client()
|
||||||
|
|
||||||
|
def publish(self, client_id: str, topic: str, data: str, qos: int = 0):
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.__connect()
|
||||||
|
|
||||||
|
payload = {
|
||||||
|
"timestamp": int(time.time()),
|
||||||
|
"data": data
|
||||||
|
}
|
||||||
|
result = self.client.publish(topic, json.dumps(payload), qos=qos)
|
||||||
|
result.wait_for_publish()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print("MQTT error:", e)
|
||||||
|
self.__disconnect()
|
||||||
|
|
||||||
|
def subscribe(self, topic: str, handler: Callable[[str], None]):
|
||||||
|
def on_message(client, userdata, msg):
|
||||||
|
handler(msg.payload.decode())
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.__connect()
|
||||||
|
self.client.message_callback_add(topic, on_message)
|
||||||
|
self.client.subscribe(topic)
|
||||||
|
except Exception as e:
|
||||||
|
print("MQTT error:", e)
|
||||||
|
self.__disconnect()
|
||||||
|
|
||||||
|
|
||||||
|
def __connect(self):
|
||||||
|
if not self.client.is_connected():
|
||||||
|
self.client.connect(self.address, self.port)
|
||||||
|
self.client.loop_start()
|
||||||
|
|
||||||
|
def __disconnect(self):
|
||||||
|
if self.client.is_connected():
|
||||||
|
self.client.disconnect()
|
||||||
|
self.client.loop_stop()
|
||||||
Binary file not shown.
Reference in New Issue
Block a user