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
shafeen Ahmed is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.