From fc8f89f412a794fb604c6fd605e927eb97aa9eed Mon Sep 17 00:00:00 2001 From: angoosh Date: Wed, 9 Apr 2025 23:18:11 +0200 Subject: [PATCH] mby functional system? --- Comms/LoRa_esp32_comm/LoRa_esp32_comm.ino | 640 ++++++++++++++++++++++ Comms/ZKJ_tmp_message_1.json | 23 + Comms/ZKJ_tmp_message_2.json | 20 + Comms/logs/app.log | 145 +++++ Comms/main.py | 416 ++++++++++++++ Comms/zkj.json | 10 + 6 files changed, 1254 insertions(+) create mode 100644 Comms/LoRa_esp32_comm/LoRa_esp32_comm.ino create mode 100644 Comms/ZKJ_tmp_message_1.json create mode 100644 Comms/ZKJ_tmp_message_2.json create mode 100644 Comms/logs/app.log create mode 100755 Comms/main.py create mode 100644 Comms/zkj.json diff --git a/Comms/LoRa_esp32_comm/LoRa_esp32_comm.ino b/Comms/LoRa_esp32_comm/LoRa_esp32_comm.ino new file mode 100644 index 0000000..1a5a530 --- /dev/null +++ b/Comms/LoRa_esp32_comm/LoRa_esp32_comm.ino @@ -0,0 +1,640 @@ +#include +#include +#include +#include +#include +#include + +HardwareSerial uart(0); + +bool LoRa_Setup = false; + +// WiFi credential +// Use different ssid for both module to avoid confusion +// example: +// const char* ssid = "ESP32-LoRa-Chat1"; for user 1 +// const char* ssid = "ESP32-LoRa-Chat2"; for user 2 +//const char* ssid = "ESP32-LoRa-Chat"; +const char* password = "chatpass123"; + +WebServer server(80); + +#define MAX_MESSAGES 50 +String messageBuffer[MAX_MESSAGES]; +int messageCount = 0; + +const char index_html[] PROGMEM = R"rawliteral( + + + + + + ESP32 LoRa Chat + + + +
+ +
+ +
+ Connecting... +
+ +
+
+
+ + +
+
+ + + + +)rawliteral"; + +void LoRa_Join(){ + uint32_t time = millis(); + bool msg_done = true; + + uart.println("AT+MODE=LWOTAA"); + delay(1000); + + while(1){ + if(msg_done){ + uart.println("AT+JOIN"); + msg_done = false; + } + if(uart.available()){ + String str = uart.readStringUntil('\n'); + Serial.println(str); + + if(strcmp(str.c_str(), "+JOIN: Join failed\r") == 0){ + msg_done = true; + } + if(strcmp(str.c_str(), "+JOIN: Done\r") == 0){ + if(!msg_done){ + break; + } + } + } + } +} + +void LoRa_Send_MSG(char* msg){ + uart.println(msg); + while(1){ + if(uart.available()){ + String str = uart.readStringUntil('\n'); + Serial.println(str); + if(strcmp(str.c_str(), "+MSG: Done\r") == 0){ + break; + } + } + } +} + +uint8_t lora_msg[32][51]; + +void LoRa_Send_MSGHEX(const char* msg, uint8_t port){//parses string into multiple messages if needed + //clear send buffer + for(int i = 0; i < 32; i++){ + for(int j = 0; j < 51; j++){ + lora_msg[i][j] = 0; + } + } + //get how many messages we will need (32 max = 1536 characters) + int len = strlen(msg); + int msg_no = len / 48; + if((len % 48) != 0){ + msg_no ++; + } + //prepare messages + for(int i = 0; i < msg_no; i++){ + if(len > 48){ + lora_msg[i][0] = 51; + lora_msg[i][1] = i+1; + lora_msg[i][2] = msg_no; + for(int j = 0; j < 48; j++){ + lora_msg[i][3+j] = msg[j+i*48]; + } + len -= 48; + } + else{ + lora_msg[i][0] = len+3; + lora_msg[i][1] = i+1; + lora_msg[i][2] = msg_no; + for(int j = 0; j < len; j++){ + lora_msg[i][3+j] = msg[j+i*48]; + } + len = 0; + } + } + //send messages + uart.printf("AT+PORT=%hhu\n", port); + delay(300); + for(int i = 0; i < 32; i++){ + if(lora_msg[i][0] != 0){ + uart.print("AT+MSGHEX=\""); + Serial.print("AT+MSGHEX=\""); + for(int j = 0; j < lora_msg[i][0]; j++){ + uart.printf("%02X",lora_msg[i][j]); + Serial.printf("%02X",lora_msg[i][j]); + } + uart.println("\""); + Serial.println("\""); + } + else{ + return; + } + + while(1){ + if(uart.available()){ + String str = uart.readStringUntil('\n'); + Serial.println(str); + if(strcmp(str.c_str(), "+MSGHEX: Done\r") == 0){ + break; + } + } + } + } +} + +int asciiToHex(char *asciiHexChar){ + uint8_t hi, lo; + uint8_t x; + + x = (asciiHexChar[0] & 0x4F); + hi = (x & 0x0F) + ((x >> 6) * 9); + x = (asciiHexChar[1] & 0x4F); + lo = (x & 0x0F) + ((x >> 6) * 9); + + return (hi << 4) + lo; +} + + +int rx_buffer[32][51]; +int rx_index = 0; + +void LoRa_Receive_MSG(){ + if(uart.available()){ + String str = uart.readStringUntil('\n'); + Serial.println(str); + if(str.indexOf("MSG: PORT: 1; RX:") > 0){ + char rxBytes[3] = {0,0,0}; + int rx_len = 51; + for(int i = 0; i < rx_len; i++){ + for(int j = 0; j < 2; j++){ + rxBytes[j] = str.c_str()[i*2+j+20]; + } + rx_buffer[rx_index][i] = asciiToHex(rxBytes); + if(i == 0){ + rx_len = rx_buffer[rx_index][0]; + } + } + if(rx_buffer[rx_index][1] == rx_buffer[rx_index][2]){ + //transmit whole message + rx_index = 0; + String rxString = ""; + + for(int i = 0; i < 32; i++){ + for(int j = 3; j < (rx_buffer[i][0]); j++){ + rxString += (char)rx_buffer[i][j]; + } + if(rx_buffer[i][0] < 51){ + break; + } + } + addMessageToBuffer(rxString); + } + } + } +} + +void setup() { + Serial.begin(115200); + uart.begin(9600, SERIAL_8N1, RX, TX); + + if(!SPIFFS.begin(true)) { + Serial.println("SPIFFS initialization failed!"); + return; + } + + Serial.println("Initializing LoRa..."); + //add LoRa E5 module init here + pinMode(5, OUTPUT); + digitalWrite(5, LOW); + delay(1000); + digitalWrite(5, HIGH); + delay(2000); + + if(!LoRa_Setup){ + LoRa_Join(); + char batt[1] = {20}; + LoRa_Send_MSGHEX(batt, 7); + delay(1000); + uart.println("AT+CLASS=C"); + //LoRa E5 module init done + char ssid[22]; + sprintf(ssid, "ESP_Chat_%012llx", ESP.getEfuseMac()); + WiFi.softAP(ssid, password); + Serial.println("Access Point Started"); + Serial.print("IP Address: "); + Serial.println(WiFi.softAPIP()); + + server.on("/", HTTP_GET, handleRoot); + server.on("/send", HTTP_POST, handleSendMessage); + server.on("/messages", HTTP_GET, handleGetMessages); + + server.begin(); + Serial.println("Web Server Started"); + } + Serial.println("Init DONE"); +} + +void handleRoot() { + server.send(200, "text/html", index_html); +} + +void handleSendMessage() { + if (server.hasArg("plain")) { + StaticJsonDocument<200> doc; + DeserializationError error = deserializeJson(doc, server.arg("plain")); + + if (!error) { + String message = doc["message"].as(); + String sender = doc["sender"].as(); + + Serial.println("Sending message"); + Serial.print("Sender: "); + Serial.println(sender); + Serial.print("Message: "); + Serial.println(message); + + String lora_msg = sender + ": " + message; + LoRa_Send_MSGHEX(lora_msg.c_str(), 8); + + addMessageToBuffer(sender + ": " + message); + + server.send(200, "application/json", "{\"status\":\"sent\"}"); + } else { + server.send(400, "application/json", "{\"error\":\"Invalid JSON\"}"); + } + } +} + +void handleGetMessages() { + StaticJsonDocument<2048> doc; + JsonArray array = doc.createNestedArray("messages"); + + for(int i = 0; i < messageCount; i++) { + array.add(messageBuffer[i]); + } + + String response; + serializeJson(doc, response); + server.send(200, "application/json", response); +} + +void addMessageToBuffer(String message) { + if (messageCount >= MAX_MESSAGES) { + for(int i = 0; i < MAX_MESSAGES - 1; i++) { + messageBuffer[i] = messageBuffer[i + 1]; + } + messageCount--; + } + messageBuffer[messageCount++] = message; +} + +String incoming = ""; +int incomingByte = 0; + +void loop() { + if(!LoRa_Setup){ + server.handleClient(); + LoRa_Receive_MSG(); + } + else{ + if(Serial.available()){ + String str = Serial.readStringUntil('\n'); + Serial.println(str); + uart.println(str); + } + + if(uart.available()){ + String str = uart.readStringUntil('\n'); + Serial.println(str); + } + } + + //if(uart.available()){ + // String str = uart.readStringUntil('\n'); + // Serial.println(str); + // if(str.indexOf("MSG: PORT: 1; RX:") > 0){ + // Serial.println("yayy"); + // } + //} + //delay(1000); + + //if(Serial.available()){ + // String str = Serial.readStringUntil('\n'); + // uart.println(str); + //} + /* + if (Serial.available() > 0) { + incomingByte = Serial.read(); + + if(incomingByte != '#'){ + incoming += (char)incomingByte; + } + + if(incomingByte == '#'){ + addMessageToBuffer(incoming); + incoming = ""; + } + } + */ + /* + int packetSize = LoRa.parsePacket(); + if (packetSize) { + byte recipient = LoRa.read(); + byte sender = LoRa.read(); + + String incoming = ""; + while (LoRa.available()) { + incoming += (char)LoRa.read(); + } + + if (recipient == localAddress) { + addMessageToBuffer(incoming); + } + }*/ +} diff --git a/Comms/ZKJ_tmp_message_1.json b/Comms/ZKJ_tmp_message_1.json new file mode 100644 index 0000000..d3dbc8b --- /dev/null +++ b/Comms/ZKJ_tmp_message_1.json @@ -0,0 +1,23 @@ +{ + "device": "test", + "devEui": "2cf7f1203230a02e", + "app": "comms", + "appId": "d60506c4-09de-4ca1-b147-f13be7b90380", + "rx_metadata": [ + { + "gateway": "353036202b000e00", + "time": "2025-04-09T16:19:55.924657+00:00", + "rssi": -38, + "snr": 10.25 + } + ], + "frame_port": 8, + "frame_count": 3, + "data": "EAEBYW5nb29zaDogdGVzdA==", + "payload": { + "msgprts": 1.0, + "len": 16.0, + "message": "angoosh: test", + "msgno": 1.0 + } +} \ No newline at end of file diff --git a/Comms/ZKJ_tmp_message_2.json b/Comms/ZKJ_tmp_message_2.json new file mode 100644 index 0000000..c716bfe --- /dev/null +++ b/Comms/ZKJ_tmp_message_2.json @@ -0,0 +1,20 @@ +{ + "device": "test", + "app": "comms", + "rx_metadata": [ + { + "gateway": "353036202b000e00", + "time": "2025-04-09T15:31:03.252565+00:00", + "rssi": -41, + "snr": 9.25 + } + ], + "frame_port": 8, + "frame_count": 11, + "payload": { + "message": "th of multiple messages for forward processing", + "len": 49.0, + "msgno": 2.0, + "msgprts": 2.0 + } +} \ No newline at end of file diff --git a/Comms/logs/app.log b/Comms/logs/app.log new file mode 100644 index 0000000..ea7a818 --- /dev/null +++ b/Comms/logs/app.log @@ -0,0 +1,145 @@ + + +[2025-04-05 10:53:00.980581] MQTT Subscribtion started +[2025-04-05 10:53:00.980590] Time: 2025-04-05 10:53:00.980596 +[2025-04-05 10:53:00.980603] Server: 10.0.69.69 +[2025-04-05 10:53:00.980609] appId: +[2025-04-05 10:53:00.980615] psw: +[2025-04-05 10:54:08.025691] disconnect + + +[2025-04-05 10:54:53.086109] MQTT Subscribtion started +[2025-04-05 10:54:53.086116] Time: 2025-04-05 10:54:53.086119 +[2025-04-05 10:54:53.086122] Server: 10.0.69.69 +[2025-04-05 10:54:53.086125] appId: +[2025-04-05 10:54:53.086128] psw: +[2025-04-05 10:57:35.874296] disconnect + + +[2025-04-09 17:23:37.501367] MQTT Subscribtion started +[2025-04-09 17:23:37.501374] Time: 2025-04-09 17:23:37.501377 +[2025-04-09 17:23:37.501380] Server: 10.0.69.69 +[2025-04-09 17:23:37.501384] appId: +[2025-04-09 17:23:37.501387] psw: +[2025-04-09 17:24:38.121184] disconnect + + +[2025-04-09 17:24:40.002282] MQTT Subscribtion started +[2025-04-09 17:24:40.002297] Time: 2025-04-09 17:24:40.002305 +[2025-04-09 17:24:40.002313] Server: 10.0.69.69 +[2025-04-09 17:24:40.002323] appId: +[2025-04-09 17:24:40.002330] psw: +[2025-04-09 17:25:53.568712] disconnect + + +[2025-04-09 17:25:54.845438] MQTT Subscribtion started +[2025-04-09 17:25:54.845445] Time: 2025-04-09 17:25:54.845448 +[2025-04-09 17:25:54.845451] Server: 10.0.69.69 +[2025-04-09 17:25:54.845454] appId: +[2025-04-09 17:25:54.845457] psw: +[2025-04-09 17:26:41.579455] disconnect + + +[2025-04-09 17:26:42.390092] MQTT Subscribtion started +[2025-04-09 17:26:42.390098] Time: 2025-04-09 17:26:42.390101 +[2025-04-09 17:26:42.390104] Server: 10.0.69.69 +[2025-04-09 17:26:42.390107] appId: +[2025-04-09 17:26:42.390110] psw: + + +[2025-04-09 17:27:34.512989] MQTT Subscribtion started +[2025-04-09 17:27:34.512995] Time: 2025-04-09 17:27:34.512997 +[2025-04-09 17:27:34.513000] Server: 10.0.69.69 +[2025-04-09 17:27:34.513004] appId: +[2025-04-09 17:27:34.513006] psw: + + +[2025-04-09 17:28:27.480157] MQTT Subscribtion started +[2025-04-09 17:28:27.480164] Time: 2025-04-09 17:28:27.480167 +[2025-04-09 17:28:27.480170] Server: 10.0.69.69 +[2025-04-09 17:28:27.480173] appId: +[2025-04-09 17:28:27.480176] psw: + + +[2025-04-09 17:29:35.171782] MQTT Subscribtion started +[2025-04-09 17:29:35.171789] Time: 2025-04-09 17:29:35.171792 +[2025-04-09 17:29:35.171795] Server: 10.0.69.69 +[2025-04-09 17:29:35.171798] appId: +[2025-04-09 17:29:35.171801] psw: + + +[2025-04-09 17:30:19.792010] MQTT Subscribtion started +[2025-04-09 17:30:19.792019] Time: 2025-04-09 17:30:19.792022 +[2025-04-09 17:30:19.792025] Server: 10.0.69.69 +[2025-04-09 17:30:19.792029] appId: +[2025-04-09 17:30:19.792032] psw: + + +[2025-04-09 17:53:18.410457] MQTT Subscribtion started +[2025-04-09 17:53:18.410463] Time: 2025-04-09 17:53:18.410466 +[2025-04-09 17:53:18.410470] Server: 10.0.69.69 +[2025-04-09 17:53:18.410473] appId: +[2025-04-09 17:53:18.410476] psw: +[2025-04-09 17:54:49.122914] disconnect + + +[2025-04-09 17:54:50.284824] MQTT Subscribtion started +[2025-04-09 17:54:50.284833] Time: 2025-04-09 17:54:50.284838 +[2025-04-09 17:54:50.284843] Server: 10.0.69.69 +[2025-04-09 17:54:50.284849] appId: +[2025-04-09 17:54:50.284855] psw: +[2025-04-09 17:56:02.531867] disconnect + + +[2025-04-09 17:56:03.462168] MQTT Subscribtion started +[2025-04-09 17:56:03.462176] Time: 2025-04-09 17:56:03.462181 +[2025-04-09 17:56:03.462187] Server: 10.0.69.69 +[2025-04-09 17:56:03.462193] appId: +[2025-04-09 17:56:03.462199] psw: +[2025-04-09 18:00:06.088614] disconnect + + +[2025-04-09 18:00:07.107735] MQTT Subscribtion started +[2025-04-09 18:00:07.107742] Time: 2025-04-09 18:00:07.107745 +[2025-04-09 18:00:07.107748] Server: 10.0.69.69 +[2025-04-09 18:00:07.107751] appId: +[2025-04-09 18:00:07.107754] psw: + + +[2025-04-09 18:04:00.060780] MQTT Subscribtion started +[2025-04-09 18:04:00.060789] Time: 2025-04-09 18:04:00.060794 +[2025-04-09 18:04:00.060799] Server: 10.0.69.69 +[2025-04-09 18:04:00.060805] appId: +[2025-04-09 18:04:00.060810] psw: +[2025-04-09 18:05:45.152635] disconnect + + +[2025-04-09 18:05:46.662378] MQTT Subscribtion started +[2025-04-09 18:05:46.662385] Time: 2025-04-09 18:05:46.662388 +[2025-04-09 18:05:46.662391] Server: 10.0.69.69 +[2025-04-09 18:05:46.662394] appId: +[2025-04-09 18:05:46.662397] psw: +[2025-04-09 18:07:01.511033] disconnect + + +[2025-04-09 18:07:02.767217] MQTT Subscribtion started +[2025-04-09 18:07:02.767224] Time: 2025-04-09 18:07:02.767227 +[2025-04-09 18:07:02.767230] Server: 10.0.69.69 +[2025-04-09 18:07:02.767233] appId: +[2025-04-09 18:07:02.767236] psw: +[2025-04-09 18:07:28.701363] disconnect + + +[2025-04-09 18:09:25.011915] MQTT Subscribtion started +[2025-04-09 18:09:25.011923] Time: 2025-04-09 18:09:25.011926 +[2025-04-09 18:09:25.011930] Server: 10.0.69.69 +[2025-04-09 18:09:25.011933] appId: +[2025-04-09 18:09:25.011936] psw: +[2025-04-09 18:13:26.440723] disconnect + + +[2025-04-09 18:19:50.218010] MQTT Subscribtion started +[2025-04-09 18:19:50.218016] Time: 2025-04-09 18:19:50.218020 +[2025-04-09 18:19:50.218023] Server: 10.0.69.69 +[2025-04-09 18:19:50.218026] appId: +[2025-04-09 18:19:50.218029] psw: diff --git a/Comms/main.py b/Comms/main.py new file mode 100755 index 0000000..226c127 --- /dev/null +++ b/Comms/main.py @@ -0,0 +1,416 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Mon Mar 28 19:30:56 2022 + +@author: angoosh +""" + +import paho.mqtt.client as mqtt #knihovna pro prijem mqtt packetu +import paho.mqtt.publish as publish +import json #knihovna pro praci s json formatem +import datetime #knihovna pro nacteni casu +import os, os.path #os knihovna +import errno #knihovna pro chyby +import sys #knihovna pro praci s interpretrem +import psycopg2 #knihovna pro praci s postgresql databazi +import re #regex + +#nacti aktualni pracovni slozku +WORKDIR = os.getcwd() + +DEVICES=["2cf7f1203230a02e"] + +#MQTT port +PORT = 1884 +APPID = "" +PSW = "" +#promenne pro jednotlive moznosti zapisu +write_json = 0 +write_db = 0 +keep_last = 0; + +#nacteni argumentu +arguments = sys.argv +argument_index = 0; + +#kam se maji ukladat jednotliva csv a json data a logy +JSON_PATH = WORKDIR+'/data/json/' +LOG_PATH = WORKDIR+'/logs/' + +#funkce pro povoleni zapisu dat do json +def enableJson(): + global write_json + write_json = 1 + return 0 + +#funkce pro povoleni zapisu dat do databaze +def enableDB(): + global write_db + write_db = 1 + return 0 + +#funkce pro vypnuti historie json souboru +def discardOldJsonData(): + global keep_last + keep_last = 1 + return 0 + +#funkce pro nacteni prihlasovacich udaju a dalsich metadat ze souboru +def jsonLogin(index): + global APPEUI, APPID, PSW, DB_HOST, DB_NAME, DB_USER, DB_PASS, DB_TABLE + loaded_json = '' + login_json = arguments[index + 1] + + with open(login_json, 'r') as file: + for line in file: + loaded_json += line + login_creds = json.loads(loaded_json) + APPEUI = login_creds['appeui'] + APPID = login_creds['appid'] + PSW = login_creds['psw'] + try: + DB_HOST = login_creds['DB_HOST'] + DB_NAME = login_creds['DB_NAME'] + DB_USER = login_creds['DB_USER'] + DB_PASS = login_creds['DB_PASS'] + DB_TABLE = login_creds['DB_TABLE'] + except: + pass + return 1 + +#nastav APPID +def setAppId(index): + global APPID + APPID = arguments[index + 1] + return 1 + +#nastav APPEUI +def setAppEui(index): + global APPEUI + APPEUI = arguments[index + 1] + return 1 + +#nastav APPKEY +def setPsw(index): + global PSW + PSW = arguments[index + 1] + return 1 + +#nastav adresu databazoveho serveru +def set_dbHost(index): + global DB_HOST + DB_HOST = arguments[index + 1] + return 1 + +#nastav jmeno databaze +def set_dbName(index): + global DB_NAME + DB_NAME = arguments[index + 1] + return 1 + +#nastav uzivatele databaze +def set_dbUser(index): + global DB_USER + DB_USER = arguments[index + 1] + return 1 + +#nastav heslo pro databazoveho uzivatele +def set_dbPass(index): + global DB_PASS + DB_PASS = arguments[index + 1] + return 1 + +#zobraz help pro vsecky argumenty +def appHelp(): + print('mqtt_sub.py [OPTIONS]') + print(' -j Save messages to json, json per message') + print(' -do Discard old jsons, also json is not saved with time in name') + print(' -db Save data to postgres database') + print(' -dbhost Database hostmane') + print(' -dbname Database name') + print(' -dbuser Database user') + print(' -dbpass Database password') + print(' -l [FILE] Load login data from specified') + print(' -s [SERVER] MQTT server address') + print(' -a [ID] Id of application on server') + print(' -p [PASS] API key for mqtt') + print(' -h print this help message') + exit() + +#zkontroluj, zda souborova cesta existuje +def checkPath(path): + try: + os.makedirs(path) + except OSError as exc: # Python >2.5 + if exc.errno == errno.EEXIST and os.path.isdir(path): + pass + else: raise + +#konverze bajtu na cislo +def bytes_to_decimal(i,d): + xx = i - 127 + dec = (-d if xx < 0 else d)/100 + return xx + dec + +#co se ma provest pri pripojeni na mqtt server +def on_connect(client, userdata, flags, rc): + client.subscribe('application/+/device/+/event/up') + +#co se ma stat, kdyz prijme mqtt packet +def on_message(client, userdata, msg): + +#nacteni zpravy + j_msg = json.loads(msg.payload.decode('utf-8')) + +#nacteni identifikace zarizeni, ze ktereho zprava prisla + app_name = j_msg['deviceInfo']['applicationName'] + dev_name = j_msg['deviceInfo']['deviceName'] + app_id = j_msg['deviceInfo']['applicationId'] + dev_eui = j_msg['deviceInfo']['devEui'] + + msg_b64_data = j_msg['data'] + + if app_name != "comms": + return + +#nacteni metadat zpravy + rx_metadata_in = j_msg['rxInfo'] + rx_metadata = [] + for gateway in range(len(rx_metadata_in)): + rx_metadata.append({}) + try: + rx_metadata[gateway]['gateway'] = rx_metadata_in[gateway]['gatewayId'] + except: + rx_metadata[gateway]['gateway'] = 'Unknown' + try: + rx_metadata[gateway]['time'] = rx_metadata_in[gateway]['gwTime'] + except: + rx_metadata[gateway]['time'] = 'Unknown' + try: + rx_metadata[gateway]['rssi'] = rx_metadata_in[gateway]['rssi'] + except: + rx_metadata[gateway]['rssi'] = 'Unknown' + try: + rx_metadata[gateway]['snr'] = rx_metadata_in[gateway]['snr'] + except: + rx_metadata[gateway]['snr'] = 'Unknown' + + try: + frame_port = j_msg['fPort'] + frame_count = j_msg['fCnt'] + except: + frame_port = 0; + frame_count = 0; + +#nacteni obsahu zpravy + decoded_payload_dict = j_msg['object'] + +#priprava pro json, co se ulozi + message_dict = { + 'device': dev_name, + 'devEui': dev_eui, + 'app': app_name, + 'appId': app_id, + 'rx_metadata': rx_metadata, + 'frame_port': frame_port, + 'frame_count': frame_count, + 'data': msg_b64_data, + 'payload': decoded_payload_dict + } + + #print(message_dict) +#ulozeni zpravy pro preposlani do json + json_out = json.dumps(message_dict, indent = 4) + with open('ZKJ_tmp_message_'+str(int(decoded_payload_dict["msgno"]))+'.json','w') as file: + file.write(json_out) + + if decoded_payload_dict["msgno"] == decoded_payload_dict["msgprts"]: + for i in range(1,33): + try: + with open('ZKJ_tmp_message_'+str(i)+'.json','r') as file: + loaded_json = '' + for line in file: + loaded_json += line + msg = json.loads(loaded_json) + #print(msg) + downlink = { + 'devEui': msg['devEui'], + 'confirmed': False, + 'fPort': 1, + 'data': msg['data'] + } + try: + for device in DEVICES: + lst = list(downlink['data']) + lst[7] = 'f' + downlink['data'] = ''.join(lst) + ttn_client.publish("application/"+msg['appId']+"/device/"+device+"/command/down", json.dumps(downlink, indent = 4)) + except Exception as e: print(e) + except: + pass + +#ulozeni dat do json + if write_json == 1: + json_out = json.dumps(message_dict, indent = 4) + + checkPath(JSON_PATH) + if keep_last == 1: + with open(JSON_PATH+'ZKJ_Comms_'+dev_id+'.json','w') as file: + file.write(json_out) + else: + with open(JSON_PATH+'ZKJ_Comms_'+dev_id+'_'+str(datetime.datetime.now())+'.json','w') as file: + file.write(json_out) + +#ulozeni dat do databaze + if write_db == 1: +#orezani jmena zarizeni na pouze modelovy nazev + + with open(LOG_PATH+'app.log','a') as log: + log.write("dev_name: "+dev_name+"\n") +#datovy string co se ma ulozit do databaze + db_string = dev_name+","+decoded_payload_dict['message'] + +#header sloupccu databazove tabulky, pouzije se pouze, kdyz tabulka nebude existovat + db_columns = "Id SERIAL PRIMARY KEY, "+\ + "DevName VARCHAR(100), "+\ + "Message VARCHAR(100), "+\ + "created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP" + +#header sloupcu do kterych se ma zapsat db_string. db_string a db_col_wrt musi mit stejne poradi headeru a dat + db_col_wrt = "DevName,"+\ + "Message" + + +#pripojeni na databazi, kontrola zda tabulka existuje a nasledne zapsani dat + con = psycopg2.connect("host="+DB_HOST+" dbname="+DB_NAME+" user="+DB_USER+" password="+DB_PASS) + cur = con.cursor() + cur.execute("SELECT EXISTS ( SELECT FROM pg_tables WHERE schemaname = 'public' AND tablename = \'"+DB_TABLE+"\');") + if not cur.fetchone()[0]: + try: + cur.execute("CREATE TABLE "+DB_TABLE+"("+db_columns+")") + cur.execute("INSERT INTO "+DB_TABLE+"("+db_col_wrt+") VALUES("+db_string+")") + con.commit() + except (psycopg2.DatabaseError): + if con: + con.rollback() + + sys.exit(1) + + finally: + if con: + con.close() + else: + try: + cur.execute("INSERT INTO "+DB_TABLE+"("+db_col_wrt+") VALUES("+db_string+")") + con.commit() + except (psycopg2.DatabaseError): + if con: + con.rollback() + + sys.exit(1) + + finally: + if con: + con.close() + +print("Starting app") +#kontrola, zda application log soubor existuje +checkPath(LOG_PATH) +try: + with open(LOG_PATH+"app.log","a") as log: + pass +except: + with open(LOG_PATH+"app.log","w") as log: + log.write('LOG_START\n') + +#proskenovani jednotlivych argumentu +for arg in range(1, len(sys.argv)): + if arguments[arg] == '-j': + arg += enableJson() + elif arguments[arg] == '-do': + arg += discardOldJsonData() + elif arguments[arg] == '-l': + arg += jsonLogin(arg) + elif arguments[arg] == '-a': + arg += setAppId(arg) + elif arguments[arg] == '-s': + arg += setAppEui(arg) + elif arguments[arg] == '-p': + arg += setPsw(arg) + elif arguments[arg] == '-h': + appHelp() + elif arguments[arg] == '-db': + arg += enableDB() + elif arguments[arg] == '-dbhost': + arg += set_dbHost(arg) + elif arguments[arg] == '-dbname': + arg += set_dbName(arg) + elif arguments[arg] == '-dbuser': + arg += set_dbUser(arg) + elif arguments[arg] == '-dbpass': + arg += set_dbPass(arg) + else: + pass + +#Init message +print('MQTT Subscribtion started') +print('Time: ', str(datetime.datetime.now())) +print('Server: ', APPEUI) +print('appId: ', APPID) +print('psw: ', PSW) +print('') + +with open(LOG_PATH+'app.log','a') as log: + log.write("\n\n["+str(datetime.datetime.now())+"] MQTT Subscribtion started\n") + log.write("["+str(datetime.datetime.now())+"] Time: "+str(datetime.datetime.now())+"\n") + log.write("["+str(datetime.datetime.now())+"] Server: "+APPEUI+"\n") + log.write("["+str(datetime.datetime.now())+"] appId: "+APPID+"\n") + log.write("["+str(datetime.datetime.now())+"] psw: "+PSW+"\n") + +if write_json == 1: + print('Saving data to json') + if keep_last == 0: + print('Keeping only the newest json') + else: + print('Keeping all jsons') + print('Json path: '+JSON_PATH) + print('') + + with open(LOG_PATH+'app.log','a') as log: + log.write("["+str(datetime.datetime.now())+"] Saving data to json\n") + if keep_last == 0: + log.write("["+str(datetime.datetime.now())+"] Keeping only the newest json\n") + else: + log.write("["+str(datetime.datetime.now())+"] Keeping all jsons\n") + log.write("["+str(datetime.datetime.now())+"] Json path: "+JSON_PATH+"\n") + +if write_db == 1: + print('Saving data to postgreSQL database') + print('Server: ', DB_HOST) + print('Database: ', DB_NAME) + print('User: ', DB_USER) + print('Password: ', DB_PASS) + print('') + + with open(LOG_PATH+'app.log','a') as log: + log.write("["+str(datetime.datetime.now())+"] Saving data to postgreSQL database\n") + log.write("["+str(datetime.datetime.now())+"] Server: "+DB_HOST+"\n") + log.write("["+str(datetime.datetime.now())+"] Database: "+DB_NAME+"\n") + log.write("["+str(datetime.datetime.now())+"] User: "+DB_USER+"\n") + log.write("["+str(datetime.datetime.now())+"] Password: "+DB_PASS+"\n") + +# set paho.mqtt callback +ttn_client = mqtt.Client() +ttn_client.on_connect = on_connect +ttn_client.on_message = on_message +ttn_client.username_pw_set(APPID, PSW) +ttn_client.connect(APPEUI, PORT, 60) #MQTT port over TLS + +try: + ttn_client.loop_forever() +except KeyboardInterrupt: + print('disconnect') + with open(LOG_PATH+'app.log','a') as log: + log.write("["+str(datetime.datetime.now())+"] disconnect\n") + ttn_client.disconnect() diff --git a/Comms/zkj.json b/Comms/zkj.json new file mode 100644 index 0000000..3602094 --- /dev/null +++ b/Comms/zkj.json @@ -0,0 +1,10 @@ +{ + "appeui": "10.0.69.69", + "appid": "", + "psw": "", + "DB_HOST": "localhost", + "DB_NAME": "dedbeef", + "DB_USER": "python-test", + "DB_PASS": "password", + "DB_TABLE": "messages" +}