Skip to content

Instantly share code, notes, and snippets.

@sleventyeleven
Last active July 19, 2026 07:03
Show Gist options
  • Select an option

  • Save sleventyeleven/4f6fe63451b179e21aed64628c2c8628 to your computer and use it in GitHub Desktop.

Select an option

Save sleventyeleven/4f6fe63451b179e21aed64628c2c8628 to your computer and use it in GitHub Desktop.
simple pyserial script to send commands encoded as weather data over LoRa
import serial
import time
# Configure the serial port.
# Replace '/dev/ttyUSB0' with your actual port:
# Windows: 'COM3', 'COM4', etc.
# Mac/Linux: '/dev/ttyUSB0', '/dev/ttyAMA0', etc.
SERIAL_PORT = '/dev/ttyS4'
BAUD_RATE = 115200
target_addr = 10
local_addr = 12
network_id = 18
network_band = 915000000
try:
ser = serial.Serial(
port=SERIAL_PORT,
baudrate=BAUD_RATE,
bytesize=serial.EIGHTBITS,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
timeout=1.0
)
except Exception as e:
print(f"Error opening serial port: {e}")
exit()
# Simple mapping dictionary to encode hex characters into plausible weather metrics.
# We will use the decimals of different weather readings to encode our payload data.
HEX_MAP = {
'0': (15.1, 45.1), '1': (15.2, 45.2), '2': (15.3, 45.3), '3': (15.4, 45.4),
'4': (15.5, 45.5), '5': (15.6, 45.6), '6': (15.7, 45.7), '7': (15.8, 45.8),
'8': (16.1, 46.1), '9': (16.2, 46.2), 'a': (16.3, 46.3), 'b': (16.4, 46.4),
'c': (16.5, 46.5), 'd': (16.6, 46.6), 'e': (16.7, 46.7), 'f': (16.8, 46.8)
}
# Reverse mapping for decoding
REV_MAP_TEMP = {v[0]: k for k, v in HEX_MAP.items()}
REV_MAP_HUMID = {v[1]: k for k, v in HEX_MAP.items()}
def encode_to_weather(hex_payload):
"""
Encodes a hexadecimal payload string into a series of mock weather telemetry packets.
For demonstration, each hex character pair is mapped to simulated Temp (T) and Humidity (H) decimals.
"""
encoded_packets = []
# Ensure lowercase hex
clean_hex = hex_payload.lower().strip()
# Process the hex string in pairs
for i in range(0, len(clean_hex), 2):
char1 = clean_hex[i]
char2 = clean_hex[i + 1] if i + 1 < len(clean_hex) else '0'
t_val = HEX_MAP.get(char1, (15.0, 45.0))[0]
h_val = HEX_MAP.get(char2, (15.0, 45.0))[1]
# Format the fake weather string
fake_packet = f"ID:WS915;T:{t_val}C;H:{h_val}%;P:1013.2hPa;W:2.4m/s"
encoded_packets.append(fake_packet)
return encoded_packets
def send_command(command_str):
"""Formats and sends an AT command to the module."""
full_command = f"{command_str}\r\n"
ser.write(full_command.encode('utf-8'))
print(f"[Sent]: {command_str}")
# Basic initialization sequence
time.sleep(1)
send_command("AT") # Test if the module responds with "+OK"
time.sleep(2)
send_command(f"AT+ADDRESS={local_addr}") # Set Address
time.sleep(2)
send_command(f"AT+NETWORKID={network_id}") # Set Network
time.sleep(2)
send_command(f"AT+BAND={network_band}") # Set Band
time.sleep(2)
# Example Usage
if __name__ == "__main__":
# Simulated command to send: "CMD: RUN WHOAMI" converted to hex
original_data = "CMD: WHOAMI"
hex_data = original_data.encode('utf-8').hex()
print(f"Original String: {original_data}")
print(f"Hex Representation: {hex_data}\n")
# Encode payload as benign weather data
weather_packets = encode_to_weather(hex_data)
print("--- Transmitted Weather Packets ---")
time.sleep(1)
start_msg = f"START:{len(weather_packets)}"
len_start_msg = len(start_msg)
send_command(f"AT+SEND={target_addr},{len_start_msg},{start_msg}")
time.sleep(1)
for pkt in weather_packets:
length = len(pkt)
send_command(f"AT+SEND={target_addr},{length},{pkt}")
time.sleep(1)
send_command(f"AT+SEND={target_addr},3,END")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment