Is there a way to handle LoRaWAN bi-directional communication using python multi-threading?

So, basically, there are two devices (Elastel eg500, which is basically Raspberry Pi 4). When I am using one device as sender and another as receiver, & using the below code, it is working just fine. Here, the situation is, sender will continuously wait for receiving dta from a radar device using RS-232 communication. When sender receives the data, it will flash its own LEDs & then send a packet to receiver device via LoRaWAN communication. So, the receiver is waiting continuously for receiving LoRa packet. When it receives a packet, it flashes its own LEDs for flash duration period of time.

Sender code:

import threading
import time
import subprocess
import serial

radar_value = 0
flash_duration = 0
flash_lock = threading.Lock()

def radar_data():
    global radar_value
    global flash_duration
    try:
        ser = serial.Serial('/dev/ttyACM1', 115200, timeout=5)
        if ser.isOpen():
            print("Serial port is open.")
            print("Waiting for data...")
            while True:
                data = ser.readline()
                if data:
                    with flash_lock:
                        radar_value = 1
                        flash_duration = max(flash_duration, 10)
                    #print("Received:", data.decode().strip())
                    time.sleep(10)
                else:
                    with flash_lock:
                        radar_value = 0
                    #print("No data received.")
                time.sleep(1)  # Small delay to avoid flooding the output
    except serial.SerialException as e:
        print("Error opening serial port:", str(e))
    except KeyboardInterrupt:
        print("Interrupted by user.")
    finally:
        if 'ser' in locals() and ser.isOpen():
            ser.close()
            print("Serial port closed.")

def send_packet(data):
    command = ["sudo", "/usr/sbin/lora_send", "-f", "903.9", "-d", f"{{{data}}}"]
    try:
        result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True)
        #print(f"Packet sent: {data}, Result: {result.stdout.decode().strip()}")
    except subprocess.CalledProcessError as e:
        print(f"Failed to send data: {e}, Error: {e.stderr.decode().strip()}")

def write_do(device_number, value):
    """Execute the write_do command to control a device."""
    try:
        result = subprocess.run(["write_do", device_number, value], stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True)
        #print(f"Device {device_number} set to {value}, Result: {result.stdout.decode().strip()}")
    except subprocess.CalledProcessError as e:
        print(f"Command failed: {e}, Error: {e.stderr.decode().strip()}")
    except Exception as e:
        print(f"Error executing command: {str(e)}")

def monitor_radar():
    global radar_value
    global flash_duration
    last_state = 0
    while True:
        with flash_lock:
            current_state = radar_value
            if current_state != last_state:
                send_packet(current_state)
                if current_state == 1:
                    #print("Radar active packet sent")
                    flash_duration = max(flash_duration, 10)
                else:
                    print("Radar inactive packet sent")
                last_state = current_state
        time.sleep(1)
        #print(f"Radar value: {radar_value}, Flash duration: {flash_duration}")

def flash_lights():
    global flash_duration
    devices = ["0", "1", "2"]
    while True:
        with flash_lock:
            if flash_duration > 0:
                flash_duration -= 1
                for device in devices:
                    write_do(device, "1")
                time.sleep(0.5)
                for device in devices:
                    write_do(device, "0")
                time.sleep(0.5)
            else:
                time.sleep(1)
        #print(f"Flash duration: {flash_duration}")

if __name__ == "__main__":
    data_thread = threading.Thread(target=radar_data)
    monitor_thread = threading.Thread(target=monitor_radar)
    flash_thread = threading.Thread(target=flash_lights)

    data_thread.start()
    monitor_thread.start()
    flash_thread.start()

    data_thread.join()
    monitor_thread.join()
    flash_thread.join()

Receiver Code:

import subprocess
import threading
import time

flash_thread = None
stop_flashing = threading.Event()

def lora_receive():
    """Function to continuously receive LoRa data using a specific command."""
    command = ["sudo", "/usr/sbin/lora_receive", "-a", "904.3", "-b", "905.0", "&"]
    try:
        while True:
            result = subprocess.run(command, capture_output=True, text=True)
            if result.returncode == 0:
                data = result.stdout.strip()
                #print(f"LoRa receive data: {data}")
                process_packet_data(data)
            else:
                print(f"Failed to receive LoRa packet: {result.stderr}")
    except subprocess.CalledProcessError as e:
        print(f"Failed to receive LoRa packet: {e}")
    except Exception as e:
        print(f"Error during LoRa reception: {str(e)}")

def get_lora_data():
    """Function to repeatedly fetch LoRa data."""
    while True:
        try:
            result = subprocess.run(["get_lora_data"], capture_output=True, text=True)
            if result.returncode == 0:
                data = result.stdout.strip()
                #print(f"LoRa get data: {data}")
                process_packet_data(data)
            else:
                print(f"Failed to fetch LoRa data: {result.stderr}")
        except subprocess.CalledProcessError as e:
            print(f"Failed to fetch LoRa data: {e}")
        except Exception as e:
            print(f"Error during data fetching: {str(e)}")
        time.sleep(1)  # Adjust the sleep time as necessary

def process_packet_data(data):
    """Process the data received from LoRa and control lights accordingly."""
    global flash_thread
    #print(f"Processing packet data: {data}")
    if data == "{1}":
        if flash_thread is None or not flash_thread.is_alive():
            stop_flashing.clear()
            flash_thread = threading.Thread(target=flash_lights, args=(["0", "1", "2"],))
            flash_thread.start()
    elif data == "{0}":
        stop_flashing.set()
        control_lights(False)
        #print("Stopped flashing due to {0} packet.")

def control_lights(turn_on):
    """Control lights based on the received data."""
    devices = ["0", "1", "2"]
    if turn_on:
        flash_lights(devices)
    else:
        for device in devices:
            write_do(device, '0')

def flash_lights(devices):
    """Flash lights based on the received data."""
    #print("Starting flash_lights.")
    while not stop_flashing.is_set():
        for device in devices:
            write_do(device, "1")
        time.sleep(0.5)
        for device in devices:
            write_do(device, "0")
        time.sleep(0.5)
    #print("Stopped flashing lights.")

def write_do(device_number, value):
    """Execute the write_do command to control a device."""
    try:
        result = subprocess.run(["write_do", device_number, value], stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True)
        '''if result.returncode == 0:
            print(f"Device {device_number} set to {value}, Result: {result.stdout.decode().strip()}")
        else:
            print(f"Command failed: {result.stderr.decode().strip()}")'''
    except subprocess.CalledProcessError as e:
        print(f"Command failed: {e}")
    except Exception as e:
        print(f"Error executing command: {str(e)}")

if __name__ == "__main__":
    # Start threads for both LoRa data fetching methods
    thread1 = threading.Thread(target=lora_receive)
    thread2 = threading.Thread(target=get_lora_data)
    thread1.start()
    thread2.start()

    thread1.join()
    thread2.join()

Problem is when I tried to make both devices bi-directional, that is both devices can send & receive, it is not working properly. So the scenario is, both device should wait continuously for receiving data from Radar via RS-232 as well as from other device via LoRa communication. When I combined these code, it is not working. I think there is issue with thread here.

I tried the below code. I expected it would work, but it didn’t. It receives data via RS-232 & sends packet via LoRawan but the other device does not receive any packet via LoRaWaN. Code is given below:|

import time
import subprocess
import serial
import json

# Global variables
radar_value = 0
flash_duration = 0
flash_lock = threading.Lock()
stop_flashing = threading.Event()
flash_thread = None

def load_config():
    global flash_duration
    try:
        with open('config.json', 'r') as f:
            config = json.load(f)
            flash_duration = config.get('flash_duration', 10)
            print(f"Config loaded: flash_duration={flash_duration}")
    except Exception as e:
        print(f"Failed to load config: {str(e)}")

def radar_data():
    global radar_value
    global flash_duration
    try:
        ser = serial.Serial('/dev/ttyACM1', 115200, timeout=5)
        if ser.isOpen():
            print("Serial port is open.")
            print("Waiting for data...")
            while True:
                data = ser.readline()
                if data:
                    with flash_lock:
                        radar_value = 1
                        flash_duration = max(flash_duration, 10)
                    print("Received from radar:", data.decode().strip())
                    time.sleep(10)
                else:
                    with flash_lock:
                        radar_value = 0
                    print("No data received from radar.")
                time.sleep(1)  # Small delay to avoid flooding the output
    except serial.SerialException as e:
        print("Error opening serial port:", str(e))
    except KeyboardInterrupt:
        print("Interrupted by user.")
    finally:
        if 'ser' in locals() and ser.isOpen():
            ser.close()
            print("Serial port closed.")

def send_packet(data):
    command = ["sudo", "/usr/sbin/lora_send", "-f", "903.9", "-d", f"{{{data}}}"]
    try:
        result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True)
        print(f"Packet sent: {data}, Result: {result.stdout.decode().strip()}")
    except subprocess.CalledProcessError as e:
        print(f"Failed to send data: {e}, Error: {e.stderr.decode().strip()}")

def write_do(device_number, value):
    """Execute the write_do command to control a device."""
    try:
        result = subprocess.run(["write_do", device_number, value], stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True)
        print(f"Device {device_number} set to {value}, Result: {result.stdout.decode().strip()}")
    except subprocess.CalledProcessError as e:
        print(f"Command failed: {e}, Error: {e.stderr.decode().strip()}")
    except Exception as e:
        print(f"Error executing command: {str(e)}")

def monitor_radar():
    global radar_value
    global flash_duration
    last_state = 0
    while True:
        with flash_lock:
            current_state = radar_value
            if current_state != last_state:
                send_packet(current_state)
                if current_state == 1:
                    print("Radar active packet sent")
                    flash_duration = max(flash_duration, 10)
                else:
                    print("Radar inactive packet sent")
                last_state = current_state
        time.sleep(1)
        print(f"Radar value: {radar_value}, Flash duration: {flash_duration}")

def flash_lights():
    global flash_duration
    devices = ["0", "1", "2"]
    while True:
        with flash_lock:
            if flash_duration > 0:
                flash_duration -= 1
                for device in devices:
                    write_do(device, "1")
                time.sleep(0.5)
                for device in devices:
                    write_do(device, "0")
                time.sleep(0.5)
            else:
                time.sleep(1)
        print(f"Flash duration: {flash_duration}")

def lora_receive():
    """Function to continuously receive LoRa data using a specific command."""
    command = ["sudo", "/usr/sbin/lora_receive", "-a", "904.3", "-b", "905.0", "&"]
    try:
        while True:
            result = subprocess.run(command, capture_output=True, text=True)
            if result.returncode == 0:
                data = result.stdout.strip()
                print(f"Received LoRa data: {data}")
                process_packet_data(data)
            else:
                print(f"Failed to receive LoRa packet: {result.stderr}")
    except subprocess.CalledProcessError as e:
        print(f"Failed to receive LoRa packet: {e}")
    except Exception as e:
        print(f"Error during LoRa reception: {str(e)}")

def get_lora_data():
    """Function to repeatedly fetch LoRa data."""
    while True:
        try:
            result = subprocess.run(["get_lora_data"], capture_output=True, text=True)
            if result.returncode == 0:
                data = result.stdout.strip()
                print(f"Fetched LoRa data: {data}")
                process_packet_data(data)
            else:
                print(f"Failed to fetch LoRa data: {result.stderr}")
        except subprocess.CalledProcessError as e:
            print(f"Failed to fetch LoRa data: {e}")
        except Exception as e:
            print(f"Error during data fetching: {str(e)}")
        time.sleep(1)  # Adjust the sleep time as necessary

def process_packet_data(data):
    """Process the data received from LoRa and control lights accordingly."""
    global flash_thread
    print(f"Processing packet data: {data}")
    if data == "{1}":
        if flash_thread is None or not flash_thread.is_alive():
            stop_flashing.clear()
            flash_thread = threading.Thread(target=flash_lights, args=(["0", "1", "2"],))
            flash_thread.start()
    elif data == "{0}":
        stop_flashing.set()
        control_lights(False)
        print("Stopped flashing due to {0} packet.")

def control_lights(turn_on):
    """Control lights based on the received data."""
    devices = ["0", "1", "2"]
    if turn_on:
        flash_lights(devices)
    else:
        for device in devices:
            write_do(device, '0')

if __name__ == "__main__":
    load_config()

    # Start threads for radar data, monitoring, flashing lights, and LoRa communication
    data_thread = threading.Thread(target=radar_data)
    monitor_thread = threading.Thread(target=monitor_radar)
    flash_thread = threading.Thread(target=flash_lights)
    lora_receive_thread = threading.Thread(target=lora_receive)
    get_lora_data_thread = threading.Thread(target=get_lora_data)

    data_thread.start()
    monitor_thread.start()
    flash_thread.start()
    lora_receive_thread.start()
    get_lora_data_thread.start()

    data_thread.join()
    monitor_thread.join()
    flash_thread.join()
    lora_receive_thread.join()
    get_lora_data_thread.join()

type here

New contributor

shafeen Ahmed is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật