diff --git a/serial_to_mqtt_bridge/create_exe.bat b/serial_to_mqtt_bridge/create_exe.bat index 8325f9ce8b788acd06373fae703433e700745186..105ee7ffd842b374ee99e78f18523ba8c518bb1e 100644 --- a/serial_to_mqtt_bridge/create_exe.bat +++ b/serial_to_mqtt_bridge/create_exe.bat @@ -26,23 +26,29 @@ if errorlevel 1 ( pip install -r requirements.txt ) -:: Generate spec file -echo Generating spec file... +:: Generate spec files +echo Generating spec files... python -m PyInstaller --onefile --name serial_to_mqtt serial_to_mqtt.py +python -m PyInstaller --onefile --name serial_to_mqtt_sim serial_to_mqtt_sim.py -:: Compile program -echo Compiling program... +:: Compile programs +echo Compiling programs... python -m PyInstaller serial_to_mqtt.spec +python -m PyInstaller serial_to_mqtt_sim.spec -:: Move exe file to main directory -echo Moving exe file to main directory... +:: Move exe files to main directory +echo Moving exe files to main directory... move /Y dist\serial_to_mqtt.exe .\serial_to_mqtt.exe +move /Y dist\serial_to_mqtt_sim.exe .\serial_to_mqtt_sim.exe :: Clean temporary folders echo Cleaning temporary folders... rmdir /S /Q build rmdir /S /Q dist del /F /Q serial_to_mqtt.spec +del /F /Q serial_to_mqtt_sim.spec -echo Binary created successfully in .\serial_to_mqtt.exe +echo Binaries created successfully: +echo - serial_to_mqtt.exe +echo - serial_to_mqtt_sim.exe pause \ No newline at end of file diff --git a/serial_to_mqtt_bridge/serial_to_mqtt.exe b/serial_to_mqtt_bridge/serial_to_mqtt.exe index c55ed39921c2990ac26366e78bdd56cb7500d2b8..4b7bc4f522f449d3be072b527729cd47d6ec882a 100644 Binary files a/serial_to_mqtt_bridge/serial_to_mqtt.exe and b/serial_to_mqtt_bridge/serial_to_mqtt.exe differ diff --git a/serial_to_mqtt_bridge/serial_to_mqtt.py b/serial_to_mqtt_bridge/serial_to_mqtt.py index 30e83e4827f0d3a6b755d3eaf6bd550a6e147b3b..06a7e4f62a957c32f44c2e1c9a07b78c85d931dc 100755 --- a/serial_to_mqtt_bridge/serial_to_mqtt.py +++ b/serial_to_mqtt_bridge/serial_to_mqtt.py @@ -146,7 +146,7 @@ if __name__ == "__main__": parser.add_argument("--serial_port", type=str, help="Serial port to connect to (e.g., COM3) or 'sim' for simulation mode") parser.add_argument("--baud_rate", type=int, default=config.get('serial', {}).get('baud_rate', 115200), help="Baud rate for serial communication") parser.add_argument("--file_path", type=str, default=config.get('sim', {}).get('file_path', "sim_data.txt"), help="Path to the file with data for MQTT") - parser.add_argument("--mqtt_broker", type=str, default=config.get('mqtt', {}).get('broker', "localhost"), help="MQTT broker address") + parser.add_argument("--mqtt_broker", type=str, default=config.get('mqtt', {}).get('broker', "192.168.52.5"), help="MQTT broker address") parser.add_argument("--mqtt_port", type=int, default=config.get('mqtt', {}).get('port', 1883), help="MQTT port") parser.add_argument("--mqtt_topic", type=str, default=config.get('mqtt', {}).get('topic', "serial2MQTT"), help="MQTT topic to publish data") parser.add_argument("--sim_interval", type=int, default=config.get('sim', {}).get('interval', 1), help="Interval in seconds for sending data from file") diff --git a/serial_to_mqtt_bridge/serial_to_mqtt_sim.exe b/serial_to_mqtt_bridge/serial_to_mqtt_sim.exe new file mode 100644 index 0000000000000000000000000000000000000000..e81340b199bdac3804277e7ea656f1666929fe07 Binary files /dev/null and b/serial_to_mqtt_bridge/serial_to_mqtt_sim.exe differ diff --git a/serial_to_mqtt_bridge/serial_to_mqtt_sim.py b/serial_to_mqtt_bridge/serial_to_mqtt_sim.py new file mode 100755 index 0000000000000000000000000000000000000000..8ed50b4ded3bd6f7f916d0a9e2eba8e99e595817 --- /dev/null +++ b/serial_to_mqtt_bridge/serial_to_mqtt_sim.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python +import paho.mqtt.client as mqtt +import time +import argparse +import yaml +import os +import random + +# Built-in simulation data +SIM_DATA = [ + "dongle_t=c000d0009,beacon_t=c000beac0004 rssi=49,char=22,channel=37,tx_power=8,temp=928,pH=372,pHRaw=46,battery=3002,timestamp=", + "dongle_t=c000d0009,beacon_t=c000beac0004 rssi=46,char=22,channel=39,tx_power=8,temp=3914,pH=3391,pHRaw=423,battery=2158,timestamp=", + "dongle_t=c000d0009,beacon_t=c000beac0004 rssi=60,char=38,channel=37,tx_power=8,temp=1645,pH=600,pHRaw=75,battery=512,timestamp=", + "dongle_t=c000d0009,beacon_t=c000beac0004 rssi=69,char=21,channel=39,tx_power=8,temp=833,pH=1331,pHRaw=166,battery=259,timestamp=", + "dongle_t=c000d0009,beacon_t=c000beac0004 rssi=51,char=20,channel=37,tx_power=8,temp=1574,pH=2811,pHRaw=351,battery=405,timestamp=", + "dongle_t=c000d0009,beacon_t=c000beac0004 rssi=85,char=24,channel=39,tx_power=8,temp=1390,pH=914,pHRaw=114,battery=523,timestamp=", + "dongle_t=c000d0009,beacon_t=c000beac0004 rssi=50,char=22,channel=39,tx_power=8,temp=667,pH=2074,pHRaw=259,battery=2569,timestamp=", + "dongle_t=c000d0009,beacon_t=c000beac0004 rssi=48,char=24,channel=37,tx_power=8,temp=4090,pH=1586,pHRaw=198,battery=3991,timestamp=", + "dongle_t=c000d0009,beacon_t=c000beac0004 rssi=46,char=20,channel=39,tx_power=8,temp=2689,pH=1329,pHRaw=166,battery=479,timestamp=", + "dongle_t=c000d0009,beacon_t=c000beac0004 rssi=76,char=22,channel=38,tx_power=8,temp=2734,pH=3961,pHRaw=495,battery=3025,timestamp=" +] + +def generate_sim_data(): + """ + Generates random simulation data in the same format as the original data + """ + valid_chars = list(range(13, 25)) + [37, 38] + rssi = random.randint(45, 92) + char = random.choice(valid_chars) + channel = random.randint(37, 39) + tx_power = 8 + temp = random.randint(0, 4095) + pH = random.randint(0, 4095) + pHRaw = int(pH/8) + battery = random.randint(0, 4095) + + return (f"dongle_t=c000d0009,beacon_t=c000beac0004 " + f"rssi={rssi},char={char},channel={channel},tx_power={tx_power}," + f"temp={temp},pH={pH},pHRaw={pHRaw},battery={battery},timestamp=") + +# Load default configuration from YAML file +def load_config(file_path="config.yaml"): + """ + Load configuration from YAML file. + If file doesn't exist or there's an error, return empty dict. + Default values are handled in argument parser. + """ + if not os.path.exists(file_path): + print(f"Warning: Configuration file '{file_path}' not found. Using default values from command line arguments.") + return {} + + try: + with open(file_path, 'r') as file: + return yaml.safe_load(file) or {} + except Exception as e: + print(f"Warning: Error reading configuration file '{file_path}': {str(e)}. Using default values from command line arguments.") + return {} + +# MQTT connection initialization +client = mqtt.Client() + +def connect_mqtt(broker, port): + client.connect(broker, port, 60) + client.loop_start() + +def cyclic_data_generator(): + """ + Generator that yields data from SIM_DATA cyclically + """ + while True: + for data in SIM_DATA: + yield data + +def random_data_generator(): + """ + Generator that yields random simulation data + """ + while True: + yield generate_sim_data() + +# Main function to handle simulation data +def main(use_random_data=False, mqtt_broker="localhost", mqtt_port=1883, mqtt_topic="serial2MQTT", sim_interval=1): + connect_mqtt(mqtt_broker, mqtt_port) + + # Choose data generator based on mode + data_generator = random_data_generator() if use_random_data else cyclic_data_generator() + cnt = 0 + + try: + while True: + # Get the next data line + line = next(data_generator) + cnt = cnt + 1 + msg = mqtt_topic + "," + line + str(cnt) + client.publish(mqtt_topic,msg) + print(f"Sent to MQTT broker={mqtt_broker} in topic={mqtt_topic} msg={msg}") + time.sleep(sim_interval) + + except KeyboardInterrupt: + print("Program terminated.") + finally: + client.loop_stop() + client.disconnect() + +if __name__ == "__main__": + # Load configuration from YAML + config = load_config() + + # Argument parser for configuration + parser = argparse.ArgumentParser(description="Simulate serial data and publish to MQTT.") + parser.add_argument("--random", action="store_true", help="Use random data instead of predefined simulation data") + parser.add_argument("--mqtt_broker", type=str, default=config.get('mqtt', {}).get('broker', "localhost"), help="MQTT broker address") + parser.add_argument("--mqtt_port", type=int, default=config.get('mqtt', {}).get('port', 1883), help="MQTT port") + parser.add_argument("--mqtt_topic", type=str, default=config.get('mqtt', {}).get('topic', "serial2MQTT"), help="MQTT topic to publish data") + parser.add_argument("--sim_interval", type=int, default=config.get('sim', {}).get('interval', 1), help="Interval in seconds for sending data") + args = parser.parse_args() + + # Run main with configuration from YAML and/or command line arguments + main( + use_random_data=args.random, + mqtt_broker=args.mqtt_broker, + mqtt_port=args.mqtt_port, + mqtt_topic=args.mqtt_topic, + sim_interval=args.sim_interval + ) \ No newline at end of file