diff --git a/03. Hardware Implementation/LoRa Communication/Reciever/Reciever_V1.0.py b/03. Hardware Implementation/LoRa Communication/Reciever/Reciever_V1.0.py new file mode 100644 index 0000000..c2d5c48 --- /dev/null +++ b/03. Hardware Implementation/LoRa Communication/Reciever/Reciever_V1.0.py @@ -0,0 +1,74 @@ +# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries +# SPDX-License-Identifier: MIT + +# Simple demo of sending and recieving data with the RFM95 LoRa radio. +# Author: Tony DiCola +import board +import busio +import digitalio + +import adafruit_rfm9x + + +# Define radio parameters. +RADIO_FREQ_MHZ = 433.0 # Frequency of the radio in Mhz. Must match your +# module! Can be a value like 915.0, 433.0, etc. + +# Define pins connected to the chip, use these if wiring up the breakout according to the guide: +CS = digitalio.DigitalInOut(board.CE1) +RESET = digitalio.DigitalInOut(board.D22) + +# Initialize SPI bus. +spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO) + +# Initialze RFM radio +rfm9x = adafruit_rfm9x.RFM9x(spi, CS, RESET, RADIO_FREQ_MHZ, baudrate=100000) + +# Note that the radio is configured in LoRa mode so you can't control sync +# word, encryption, frequency deviation, or other settings! + +# You can however adjust the transmit power (in dB). The default is 13 dB but +# high power radios like the RFM95 can go up to 23 dB: +rfm9x.tx_power = 23 + +# Apply new modem config settings to the radio to improve its effective range +rfm9x.signal_bandwidth = 125000 +rfm9x.coding_rate = 8 +rfm9x.spreading_factor = 12 +rfm9x.enable_crc = True + +# Send a packet. Note you can only send a packet up to 252 bytes in length. +# This is a limitation of the radio packet size, so if you need to send larger +# amounts of data you will need to break it into smaller send calls. Each send +# call will wait for the previous one to finish before continuing. +rfm9x.send(bytes("Hello world!\r\n", "utf-8")) +print("Sent Hello World message!") + +# Wait to receive packets. Note that this library can't receive data at a fast +# rate, in fact it can only receive and process one 252 byte packet at a time. +# This means you should only use this for low bandwidth scenarios, like sending +# and receiving a single message at a time. +print("Waiting for packets...") + +while True: + #packet = rfm9x.receive() + # Optionally change the receive timeout from its default of 0.5 seconds: + packet = rfm9x.receive(timeout=5.0,with_header=True) + # If no packet was received during the timeout then None is returned. + if packet is None: + # Packet has not been received + print("Received nothing! Listening again...") + else: + # Received a packet! + # Print out the raw bytes of the packet: + print("Received (raw bytes): {0}".format(packet)) + # And decode to ASCII text and print it too. Note that you always + # receive raw bytes and need to convert to a text format like ASCII + # if you intend to do string processing on your data. Make sure the + # sending side is sending ASCII data before you try to decode! + packet_text = str(packet, "ascii") + print("Received (ASCII): {0}".format(packet_text)) + # Also read the RSSI (signal strength) of the last received message and + # print it. + rssi = rfm9x.last_rssi + print("Received signal strength: {0} dB".format(rssi)) diff --git a/03. Hardware Implementation/LoRa Communication/Sender/Imager/Imager_V1.0.py b/03. Hardware Implementation/LoRa Communication/Sender/Imager/Imager_V1.0.py new file mode 100644 index 0000000..e15dfc1 --- /dev/null +++ b/03. Hardware Implementation/LoRa Communication/Sender/Imager/Imager_V1.0.py @@ -0,0 +1,131 @@ +""" +Created by Bimsara Gawesh +Last update on 02 March 2025 +Imager for LoRa communication +This module requires a server for the communication +This is currenty support for load image from the current directory and produce numpy array for communication +Version 1.0 + +Key Parameters: +Compatible OS: Raspberry Pi Bustter 2020 +Compatible Python Version: Python 3 +Prerequisites: numpy, pillow + +Note: Please reffer github repository for more information +https://github.com/cepdnaclk/e20-3yp-SkyT +""" + +# Import Python System Libraries +import numpy as np +from PIL import Image + +# Function to print details of the image +def printDetails(image): + """ + Prints detailed information about the image. + + Parameters: + image (PIL.Image): A Pillow Image object. + + Returns: + None + """ + try: + print("Image Details:") + print(f"Format: {image.format}") # Image format (e.g., JPEG, PNG) + print(f"Size: {image.size}") # Tuple (width, height) in pixels + print(f"Mode: {image.mode}") # Color mode (e.g., 'RGB', 'L', 'RGBA') + print(f"Width: {image.width} pixels") + print(f"Height: {image.height} pixels") + print(f"Channels: {len(image.getbands())}") # Number of channels (e.g., 3 for RGB, 1 for grayscale) + + # Additional details + if image.mode == 'P': + print("Note: Image uses a palette (indexed colors).") + if image.info: + print("\nAdditional Metadata:") + for key, value in image.info.items(): + print(f"{key}: {value}") + else: + print("\nNo additional metadata found.") + except AttributeError: + print("Error: Input is not a valid Pillow Image object.") + except Exception as e: + print(f"Error processing image: {e}") + +# Function to print numpy array +def printArrayDetails(array, sample_size=5): + """ + Prints details of a NumPy array, including shape, data type, and a sample of the array. + + Parameters: + array (numpy.ndarray): The NumPy array to analyze. + sample_size (int): Number of elements to display from the beginning and end of the array. + + Returns: + None + """ + try: + if not isinstance(array, np.ndarray): + raise ValueError("Input is not a NumPy array.") + + print("NumPy Array Details:") + print(f"Shape: {array.shape}") # Dimensions of the array + print(f"Data Type: {array.dtype}") # Data type of the array elements + print(f"Number of Elements: {array.size}") # Total number of elements + print(f"Number of Dimensions: {array.ndim}") # Number of dimensions + + # Print a sample of the array + if array.size <= 2 * sample_size: + print("\nArray Data:") + print(array) + else: + print("\nArray Data (Sample):") + print("First few elements:") + print(array.flatten()[:sample_size]) + print("Last few elements:") + print(array.flatten()[-sample_size:]) + + except Exception as e: + print(f"Error processing NumPy array: {e}") + +# Function to load image and convert it into a numpy array +def loadImage(image_path): + """ + Loads an image from the specified path and converts it into a NumPy array. + + Parameters: + image_path (str): Path to the image file. + + Returns: + numpy.ndarray: A NumPy array representing the image. + The shape of the array will be (height, width, channels) for RGB images + or (height, width) for grayscale images. + """ + try: + # Open the image using Pillow + img = Image.open(image_path) + + # Print details of the loaded image + printDetails(img) + + # Convert the image to a NumPy array + img_array = np.array(img) + + # Print array details + printArrayDetails(img_array) + + return img_array + + except Exception as e: + print(f"Error loading image: {e}") + return None + +try: + print("LoRa Server Started...") + imageArr = loadImage("image.webp") +except KeyboardInterrupt: + print("\nProgram interrupted") +finally: + # Clean up + print("GPIO cleaned up and program terminated.") \ No newline at end of file diff --git a/03. Hardware Implementation/LoRa Communication/Sender/Imager/Imager_V1.1.py b/03. Hardware Implementation/LoRa Communication/Sender/Imager/Imager_V1.1.py new file mode 100644 index 0000000..2f84a71 --- /dev/null +++ b/03. Hardware Implementation/LoRa Communication/Sender/Imager/Imager_V1.1.py @@ -0,0 +1,114 @@ +""" +Created by Bimsara Gawesh +Last update on 02 March 2025 +Imager for LoRa communication +This module requires a server for the communication +This is currenty support for load image from the current directory and produce numpy array for communication +Version 1.0 + +Key Parameters: +Compatible OS: Raspberry Pi Bustter 2020 +Compatible Python Version: Python 3 +Prerequisites: numpy, pillow + +Note: Please reffer github repository for more information +https://github.com/cepdnaclk/e20-3yp-SkyT +""" + +# Import Python System Libraries +import numpy as np +from PIL import Image + +# Function to print details of the image +def printDetails(image): + """ + Prints detailed information about the image. + + Parameters: + image (PIL.Image): A Pillow Image object. + + Returns: + None + """ + try: + print("Image Details:") + print(f"Format: {image.format}") # Image format (e.g., JPEG, PNG) + print(f"Size: {image.size}") # Tuple (width, height) in pixels + print(f"Mode: {image.mode}") # Color mode (e.g., 'RGB', 'L', 'RGBA') + print(f"Width: {image.width} pixels") + print(f"Height: {image.height} pixels") + print(f"Channels: {len(image.getbands())}") # Number of channels (e.g., 3 for RGB, 1 for grayscale) + + except AttributeError: + print("Error: Input is not a valid Pillow Image object.") + except Exception as e: + print(f"Error processing image: {e}") + +# Function to print numpy array +def printArrayDetails(array, sample_size=5): + """ + Prints details of a NumPy array, including shape, data type, and a sample of the array. + + Parameters: + array (numpy.ndarray): The NumPy array to analyze. + sample_size (int): Number of elements to display from the beginning and end of the array. + + Returns: + None + """ + try: + if not isinstance(array, np.ndarray): + raise ValueError("Input is not a NumPy array.") + + print("NumPy Array Details:") + print(f"Shape: {array.shape}") # Dimensions of the array + print(f"Data Type: {array.dtype}") # Data type of the array elements + print(f"Number of Elements: {array.size}") # Total number of elements + print(f"Number of Dimensions: {array.ndim}") # Number of dimensions + + # Print a sample of the array + if array.size <= 2 * sample_size: + print("\nArray Data:") + print(array) + else: + + print("\nArray Data (Sample):") + print("First few elements:") + print(array.flatten()[:sample_size]) + print("Last few elements:") + print(array.flatten()[-sample_size:]) + + except Exception as e: + print(f"Error processing NumPy array: {e}") + +# Function to load image and convert it into a numpy array +def loadImage(image_path): + """ + Loads an image from the specified path and converts it into a NumPy array. + + Parameters: + image_path (str): Path to the image file. + + Returns: + numpy.ndarray: A NumPy array representing the image. + The shape of the array will be (height, width, channels) for RGB images + or (height, width) for grayscale images. + """ + try: + # Open the image using Pillow + img = Image.open(image_path) + + # Print details of the loaded image + printDetails(img) + + # Convert the image to a NumPy array + img_array = np.array(img, dtype=np.uint8) + + # Print array details + printArrayDetails(img_array) + + return img_array + + except Exception as e: + print(f"Error loading image: {e}") + return None diff --git a/03. Hardware Implementation/LoRa Communication/Sender/Sender/Sender_V1.0.py b/03. Hardware Implementation/LoRa Communication/Sender/Sender/Sender_V1.0.py new file mode 100644 index 0000000..b068a4d --- /dev/null +++ b/03. Hardware Implementation/LoRa Communication/Sender/Sender/Sender_V1.0.py @@ -0,0 +1,45 @@ +# Import Python System Libraries +import time + +# Import RFM9x +import adafruit_rfm9x + +# Configure LoRa Radio +# Import Blinka Libraries +import busio +from digitalio import DigitalInOut, Direction, Pull +import board + +RADIO_FREQ_MHZ = 433.0 + +print("Board:", end=": ") +print(board.CE0) + +CS = DigitalInOut(board.CE1) +RESET = DigitalInOut(board.D22) +spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO) +rfm9x = adafruit_rfm9x.RFM9x(spi, CS, RESET, RADIO_FREQ_MHZ)# + +# You can however adjust the transmit power (in dB). The default is 13 dB but +# high power radios like the RFM95 can go up to 23 dB: +rfm9x.tx_power = 23 + +# Apply new modem config settings to the radio to improve its effective range +rfm9x.signal_bandwidth = 125000 +rfm9x.coding_rate = 14 +#rfm9x.spreading_factor = 12 +rfm9x.enable_crc = True + +count = 0 + +while True: + data=bytes(str(count),"utf-8") + rfm9x.send(data) + print(f"data sent: {data.decode()}") + + if(count >= 99): + count = 0 + else: + count += 1 + + time.sleep(1) diff --git a/03. Hardware Implementation/LoRa Communication/Sender/Sender/Sender_V1.1.py b/03. Hardware Implementation/LoRa Communication/Sender/Sender/Sender_V1.1.py new file mode 100644 index 0000000..5194e53 --- /dev/null +++ b/03. Hardware Implementation/LoRa Communication/Sender/Sender/Sender_V1.1.py @@ -0,0 +1,80 @@ +""" +Created by Bimsara Gawesh +Last update on 01 March 2025 +Sender for LoRa communication +This is currenty support for the one way communication between two devices + +Key Parameters: +Module Name: LoRa-02 SX1278 +Frequency: 433 MHz +Bandwidth: 125 kHz +Compatible OS: Raspberry Pi Bustter 2020 +Compatible Python Version: Python 3 +Prerequisites: spidev, RPi.GPIO, Adafruit_rfm9x + +Note: Please reffer github repository for more information +https://github.com/cepdnaclk/e20-3yp-SkyT +""" + +# Import Python System Libraries +import time + +# Import RFM9x +import adafruit_rfm9x + +# Configure LoRa Radio +# Import Blinka Libraries +import busio +from digitalio import DigitalInOut, Direction, Pull +import board + +# Frequency for communication in MHz +RADIO_FREQ_MHZ = 433.0 + +# Pin configuration +""" ++-------------+----------------+ +| LoRa SX1278 | Raspberry Pi | ++-------------+----------------+ +| VCC | +3V3 | +| GND | GND | +| SCK | SCK (GPIO 11) | +| MOSI | MOSI (GPIO 10) | +| MISO | MISO (GPIO 9) | +| NSS | CE1 (GPIO 7) | +| REST | GPIO 22 | +| DIO0 | GPIO 0 | ++-------------+----------------+ +""" +CS = DigitalInOut(board.CE1) +RESET = DigitalInOut(board.D22) +spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO) +sx1278 = adafruit_rfm9x.RFM9x(spi, CS, RESET, RADIO_FREQ_MHZ) + +# You can however adjust the transmit power (in dB). The default is 13 dB but +# high power radios like the RFM95 can go up to 23 dB: +sx1278.tx_power = 23 +sx1278.signal_bandwidth = 125000 +sx1278.coding_rate = 14 +#sx1278.spreading_factor = 12 +sx1278.enable_crc = True + +count = 0 + +try: + while True: + data=bytes(str(count),"utf-8") + sx1278.send(data) + print(f"data sent: {data.decode()}") + + if(count >= 99): + count = 0 + else: + count += 1 + + time.sleep(1) +except KeyboardInterrupt: + print("\nProgram interrupted") +finally: + # Clean up + print("GPIO cleaned up and program terminated.") \ No newline at end of file diff --git a/03. Hardware Implementation/LoRa Communication/Sender/Sender/Sender_V1.2.py b/03. Hardware Implementation/LoRa Communication/Sender/Sender/Sender_V1.2.py new file mode 100644 index 0000000..6e9d35b --- /dev/null +++ b/03. Hardware Implementation/LoRa Communication/Sender/Sender/Sender_V1.2.py @@ -0,0 +1,85 @@ +""" +Created by Bimsara Gawesh +Last update on 01 March 2025 +Sender for LoRa communication +This is currenty support for the one way communication between two devices + +Key Parameters: +Module Name: LoRa-02 SX1278 +Frequency: 433 MHz +Bandwidth: 125 kHz +Compatible OS: Raspberry Pi Bustter 2020 +Compatible Python Version: Python 3 +Prerequisites: spidev, RPi.GPIO, Adafruit_rfm9x + +Note: Please reffer github repository for more information +https://github.com/cepdnaclk/e20-3yp-SkyT +""" + +# Import Python System Libraries +import time + +# Import RFM9x +import adafruit_rfm9x + +# Configure LoRa Radio +# Import Blinka Libraries +import busio +from digitalio import DigitalInOut +import board + +# Frequency for communication in MHz +RADIO_FREQ_MHZ = 433.0 + +# Pin configuration +""" ++-------------+----------------+ +| LoRa SX1278 | Raspberry Pi | ++-------------+----------------+ +| VCC | +3V3 | +| GND | GND | +| SCK | SCK (GPIO 11) | +| MOSI | MOSI (GPIO 10) | +| MISO | MISO (GPIO 9) | +| NSS | CE1 (GPIO 7) | +| REST | GPIO 22 | +| DIO0 | NC | +| DIO1 | NC | +| DIO2 | NC | +| DIO3 | NC | +| DIO4 | NC | +| DIO5 | NC | ++-------------+----------------+ +""" +CS = DigitalInOut(board.CE1) +RESET = DigitalInOut(board.D22) +spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO) +sx1278 = adafruit_rfm9x.RFM9x(spi, CS, RESET, RADIO_FREQ_MHZ) + +# You can however adjust the transmit power (in dB). The default is 13 dB but +# high power radios like the RFM95 can go up to 23 dB: +sx1278.tx_power = 23 +sx1278.signal_bandwidth = 125000 +sx1278.coding_rate = 14 +sx1278.enable_crc = True +#sx1278.spreading_factor = 12 + +count = 0 + +try: + while True: + data=bytes(str(count),"utf-8") + sx1278.send(data) + print(f"data sent: {data.decode()}") + + if(count >= 99): + count = 0 + else: + count += 1 + + time.sleep(1) +except KeyboardInterrupt: + print("\nProgram interrupted") +finally: + # Clean up + print("GPIO cleaned up and program terminated.") \ No newline at end of file diff --git a/03. Hardware Implementation/LoRa Communication/Sender/Sender/Sender_V1.3.py b/03. Hardware Implementation/LoRa Communication/Sender/Sender/Sender_V1.3.py new file mode 100644 index 0000000..2a21ebe --- /dev/null +++ b/03. Hardware Implementation/LoRa Communication/Sender/Sender/Sender_V1.3.py @@ -0,0 +1,106 @@ +""" +Created by Bimsara Gawesh +Last update on 01 March 2025 +Sender for LoRa communication +This is currenty support for the one way communication between two devices + +Key Parameters: +Module Name: LoRa-02 SX1278 +Frequency: 433 MHz +Bandwidth: 125 kHz +Compatible OS: Raspberry Pi Bustter 2020 +Compatible Python Version: Python 3 +Prerequisites: spidev, RPi.GPIO, Adafruit_rfm9x + +Note: Please reffer github repository for more information +https://github.com/cepdnaclk/e20-3yp-SkyT +""" + +# Import Python System Libraries +import time + +# Import RFM9x +import adafruit_rfm9x + +# Configure LoRa Radio +# Import Blinka Libraries +import busio +from digitalio import DigitalInOut +import board + +# Frequency for communication in MHz +RADIO_FREQ_MHZ = 433.0 + +# Pin configuration +""" ++-------------+----------------+ +| LoRa SX1278 | Raspberry Pi | ++-------------+----------------+ +| VCC | +3V3 | +| GND | GND | +| SCK | SCK (GPIO 11) | +| MOSI | MOSI (GPIO 10) | +| MISO | MISO (GPIO 9) | +| NSS | CE1 (GPIO 7) | +| REST | GPIO 22 | +| DIO0 | NC | +| DIO1 | NC | +| DIO2 | NC | +| DIO3 | NC | +| DIO4 | NC | +| DIO5 | NC | ++-------------+----------------+ +""" +CS = DigitalInOut(board.CE1) +RESET = DigitalInOut(board.D22) + +# Initialize SPI bus. +spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO) + +# Initialze SX1278 radio +sx1278 = adafruit_rfm9x.RFM9x(spi, CS, RESET, RADIO_FREQ_MHZ) + +# You can however adjust the transmit power (in dB). The default is 13 dB but +# high power radios like the RFM95 can go up to 23 dB: +sx1278.tx_power = 23 +sx1278.signal_bandwidth = 125000 +sx1278.coding_rate = 14 +sx1278.enable_crc = True +#sx1278.spreading_factor = 12 + +# Sender Functions +def sendStrings(stringData, radio, delay=0.5): + """ + This convert the input data to string and then send it through as a byte data + Input parameters: + stringData : The data to send + radio : The Lora radio + delay : Time waiting for sending packet + """ + + if(type(stringData) != str): + stringData = str(stringData) + + data = bytes(stringData, "utf-8") + radio.send(data) + print(f"Data sent: {data.decode()}") + + time.sleep(delay) + +count = 0 + +try: + print("LoRa TX Started...") + while True: + sendStrings(count, sx1278, 1) + + if(count >= 99): + count = 0 + else: + count += 1 + +except KeyboardInterrupt: + print("\nProgram interrupted") +finally: + # Clean up + print("GPIO cleaned up and program terminated.") \ No newline at end of file diff --git a/03. Hardware Implementation/LoRa Communication/Sender/Sender/Sender_V1.4.py b/03. Hardware Implementation/LoRa Communication/Sender/Sender/Sender_V1.4.py new file mode 100644 index 0000000..cc45a8a --- /dev/null +++ b/03. Hardware Implementation/LoRa Communication/Sender/Sender/Sender_V1.4.py @@ -0,0 +1,157 @@ +""" +Created by Bimsara Gawesh +Last update on 02 March 2025 +Sender for LoRa communication +This is currenty support for the one way communication between two devices +Version 1.4 + +Key Parameters: +Module Name: LoRa-02 SX1278 +Frequency: 433 MHz +Bandwidth: 125 kHz +Compatible OS: Raspberry Pi Bustter 2020 +Compatible Python Version: Python 3 +Prerequisites: spidev, RPi.GPIO, Adafruit_rfm9x + +Note: Please reffer github repository for more information +https://github.com/cepdnaclk/e20-3yp-SkyT +""" + +# Import Python System Libraries +import time + +# Import RFM9x +import adafruit_rfm9x + +# Configure LoRa Radio +# Import Blinka Libraries +import busio +from digitalio import DigitalInOut +import board + +# Frequency for communication in MHz +RADIO_FREQ_MHZ = 433.0 + +# Pin configuration +""" ++-------------+----------------+ +| LoRa SX1278 | Raspberry Pi | ++-------------+----------------+ +| VCC | +3V3 | +| GND | GND | +| SCK | SCK (GPIO 11) | +| MOSI | MOSI (GPIO 10) | +| MISO | MISO (GPIO 9) | +| NSS | CE1 (GPIO 7) | +| REST | GPIO 22 | +| DIO0 | NC | +| DIO1 | NC | +| DIO2 | NC | +| DIO3 | NC | +| DIO4 | NC | +| DIO5 | NC | ++-------------+----------------+ +""" +CS = DigitalInOut(board.CE1) +RESET = DigitalInOut(board.D22) + +# Initialize SPI bus. +spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO) + +# Initialze SX1278 radio +sx1278 = adafruit_rfm9x.RFM9x(spi, CS, RESET, RADIO_FREQ_MHZ) + +# You can however adjust the transmit power (in dB). The default is 13 dB but +# high power radios like the RFM95 can go up to 23 dB: +sx1278.tx_power = 23 +sx1278.signal_bandwidth = 125000 +sx1278.coding_rate = 14 +sx1278.enable_crc = True +#sx1278.spreading_factor = 12 + +# Sender Functions +def sendStrings(stringData, radio, delay=0.5): + """ + Converts the input data to a string and sends it as byte data through the LoRa radio. + + Input parameters: + stringData : The data to send (can be a string or any type that can be converted to a string). + radio : The LoRa radio object. + delay : Time to wait after sending the packet (in seconds). + """ + try: + # Convert input data to a string if it isn't already + if not isinstance(stringData, str): + stringData = str(stringData) + + # Convert the string to bytes using UTF-8 encoding + data = bytes(stringData, "utf-8") + + # Check if the data exceeds 250 bytes + if len(data) > 250: + raise ValueError("Data exceeds 250 bytes. Please reduce the size of the input.") + + # Send the byte data through the LoRa radio + radio.send(data) + print(f"Data sent: {stringData} (Length: {len(data)} bytes)") + + # Wait for the specified delay + time.sleep(delay) + + except Exception as e: + print(f"Error sending data: {e}") + +def sendByteArray(byteData, radio, delay=0.5): + """ + Sends a byte array through the LoRa radio. + Ensures the data is less than 250 bytes. + + Input parameters: + byteData : The byte array to send. + radio : The LoRa radio object. + delay : Time to wait after sending the packet (in seconds). + """ + try: + # Check if the input is a byte array + if not isinstance(byteData, bytes): + raise ValueError("Input data must be of type 'bytes'.") + + # Check if the data exceeds 250 bytes + if len(byteData) > 250: + raise ValueError("Data exceeds 250 bytes. Please reduce the size of the input.") + + # Send the byte array + radio.send(byteData) + print(f"Byte array sent: {byteData} (Length: {len(byteData)} bytes)") + + # Wait for the specified delay + time.sleep(delay) + + except Exception as e: + print(f"Error sending data: {e}") + +count = 0 + +try: + print("LoRa TX Started...") + while True: + # sendStrings(count, sx1278, 1) + + # Example byte array + #data = bytes([0x01, 0x02, 0x03, 0x04]) # Replace with your data + #sendByteArray(data, sx1278, 1) # Send data with a 1-second delay + + # Example data to send + data = "Hello, LoRa!" # Replace with your data + sendStrings(data, sx1278, 1) # Send data with a 1-second delay + + if(count >= 99): + count = 0 + else: + count += 1 + +except KeyboardInterrupt: + print("\nProgram interrupted") +finally: + # Clean up + print("GPIO cleaned up and program terminated.") \ No newline at end of file diff --git a/03. Hardware Implementation/LoRa Communication/Sender/Sender/Sender_V1.5.py b/03. Hardware Implementation/LoRa Communication/Sender/Sender/Sender_V1.5.py new file mode 100644 index 0000000..1f42cdd --- /dev/null +++ b/03. Hardware Implementation/LoRa Communication/Sender/Sender/Sender_V1.5.py @@ -0,0 +1,160 @@ +""" +Created by Bimsara Gawesh +Last update on 02 March 2025 +Sender for LoRa communication +This is currenty support for the one way communication between two devices +Version 1.5 + +Key Parameters: +Module Name: LoRa-02 SX1278 +Frequency: 433 MHz +Bandwidth: 125 kHz +Compatible OS: Raspberry Pi Bustter 2020 +Compatible Python Version: Python 3 +Prerequisites: spidev, RPi.GPIO, Adafruit_rfm9x + +Note: Please reffer github repository for more information +https://github.com/cepdnaclk/e20-3yp-SkyT +""" + +# Import Python System Libraries +import time + +# Import RFM9x +import adafruit_rfm9x + +# Configure LoRa Radio +# Import Blinka Libraries +import busio +from digitalio import DigitalInOut +import board + +# Frequency for communication in MHz +RADIO_FREQ_MHZ = 433.0 + +# Delay between two packets in seconds +DELAY = 1 + +# Pin configuration +""" ++-------------+----------------+ +| LoRa SX1278 | Raspberry Pi | ++-------------+----------------+ +| VCC | +3V3 | +| GND | GND | +| SCK | SCK (GPIO 11) | +| MOSI | MOSI (GPIO 10) | +| MISO | MISO (GPIO 9) | +| NSS | CE1 (GPIO 7) | +| REST | GPIO 22 | +| DIO0 | NC | +| DIO1 | NC | +| DIO2 | NC | +| DIO3 | NC | +| DIO4 | NC | +| DIO5 | NC | ++-------------+----------------+ +""" +CS = DigitalInOut(board.CE1) +RESET = DigitalInOut(board.D22) + +# Initialize SPI bus. +spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO) + +# Initialze SX1278 radio +sx1278 = adafruit_rfm9x.RFM9x(spi, CS, RESET, RADIO_FREQ_MHZ) + +# You can however adjust the transmit power (in dB). The default is 13 dB but +# high power radios like the RFM95 can go up to 23 dB: +sx1278.tx_power = 23 +sx1278.signal_bandwidth = 125000 +sx1278.coding_rate = 14 +sx1278.enable_crc = True +#sx1278.spreading_factor = 12 + +# Sender Functions +def sendStrings(stringData, radio=sx1278, delay=DELAY): + """ + Converts the input data to a string and sends it as byte data through the LoRa radio. + + Input parameters: + stringData : The data to send (can be a string or any type that can be converted to a string). + radio : The LoRa radio object. + delay : Time to wait after sending the packet (in seconds). + """ + try: + # Convert input data to a string if it isn't already + if not isinstance(stringData, str): + stringData = str(stringData) + + # Convert the string to bytes using UTF-8 encoding + data = bytes(stringData, "utf-8") + + # Check if the data exceeds 250 bytes + if len(data) > 250: + raise ValueError("Data exceeds 250 bytes. Please reduce the size of the input.") + + # Send the byte data through the LoRa radio + radio.send(data) + print(f"Data sent: {stringData} (Length: {len(data)} bytes)") + + # Wait for the specified delay + time.sleep(delay) + + except Exception as e: + print(f"Error sending data: {e}") + +def sendByteArray(byteData, radio=sx1278, delay=DELAY): + """ + Sends a byte array through the LoRa radio. + Ensures the data is less than 250 bytes. + + Input parameters: + byteData : The byte array to send. + radio : The LoRa radio object. + delay : Time to wait after sending the packet (in seconds). + """ + try: + # Check if the input is a byte array + if not isinstance(byteData, bytes): + raise ValueError("Input data must be of type 'bytes'.") + + # Check if the data exceeds 250 bytes + if len(byteData) > 250: + raise ValueError("Data exceeds 250 bytes. Please reduce the size of the input.") + + # Send the byte array + radio.send(byteData) + print(f"Byte array sent: {byteData} (Length: {len(byteData)} bytes)") + + # Wait for the specified delay + time.sleep(delay) + + except Exception as e: + print(f"Error sending data: {e}") + +count = 0 + +try: + print("LoRa TX Started...") + while True: + # sendStrings(count, sx1278, 1) + + # Example byte array + #data = bytes([0x01, 0x02, 0x03, 0x04]) # Replace with your data + #sendByteArray(data, sx1278, 1) # Send data with a 1-second delay + + # Example data to send + data = "Hello World" # Replace with your data + sendStrings(data) # Send data with a 1-second delay + + if(count >= 99): + count = 0 + else: + count += 1 + +except KeyboardInterrupt: + print("\nProgram interrupted") +finally: + # Clean up + print("GPIO cleaned up and program terminated.") \ No newline at end of file diff --git a/03. Hardware Implementation/LoRa Communication/Sender/Sender/Sender_V1.6.py b/03. Hardware Implementation/LoRa Communication/Sender/Sender/Sender_V1.6.py new file mode 100644 index 0000000..afb77bd --- /dev/null +++ b/03. Hardware Implementation/LoRa Communication/Sender/Sender/Sender_V1.6.py @@ -0,0 +1,196 @@ +""" +Created by Bimsara Gawesh +Last update on 02 March 2025 +Sender for LoRa communication +This is currenty support for the one way communication between two devices +Aditionaly send server info to the reciever +Version 1.6 + +Key Parameters: +Module Name: LoRa-02 SX1278 +Frequency: 433 MHz +Bandwidth: 125 kHz +Compatible OS: Raspberry Pi Bustter 2020 +Compatible Python Version: Python 3 +Prerequisites: spidev, RPi.GPIO, Adafruit_rfm9x + +Note: Please reffer github repository for more information +https://github.com/cepdnaclk/e20-3yp-SkyT +""" + +# Import Python System Libraries +import time + +# Import RFM9x +import adafruit_rfm9x + +# Configure LoRa Radio +# Import Blinka Libraries +import busio +from digitalio import DigitalInOut +import board + +# Frequency for communication in MHz +RADIO_FREQ_MHZ = 433.0 + +# Delay between two packets in seconds +DELAY = 1 + +# Maximum length of a packet +PKT_SIZE = 250 + +# Pin configuration +""" ++-------------+----------------+ +| LoRa SX1278 | Raspberry Pi | ++-------------+----------------+ +| VCC | +3V3 | +| GND | GND | +| SCK | SCK (GPIO 11) | +| MOSI | MOSI (GPIO 10) | +| MISO | MISO (GPIO 9) | +| NSS | CE1 (GPIO 7) | +| REST | GPIO 22 | +| DIO0 | NC | +| DIO1 | NC | +| DIO2 | NC | +| DIO3 | NC | +| DIO4 | NC | +| DIO5 | NC | ++-------------+----------------+ +""" +CS = DigitalInOut(board.CE1) +RESET = DigitalInOut(board.D22) + +# Initialize SPI bus. +spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO) + +# Initialze SX1278 radio +sx1278 = adafruit_rfm9x.RFM9x(spi, CS, RESET, RADIO_FREQ_MHZ) + +# You can however adjust the transmit power (in dB). The default is 13 dB but +# high power radios like the RFM95 can go up to 23 dB: +sx1278.tx_power = 13 +sx1278.signal_bandwidth = 125000 +sx1278.coding_rate = 8 +sx1278.spreading_factor = 8 + +# Sender Functions +def sendStrings(rawData, sender_id="DronePi", radio=sx1278, delay=DELAY): + """ + Converts the input data to a string and sends it as byte data through the LoRa radio. + + Input parameters: + rawData : The data to send (can be a string or any type that can be converted to a string). + radio : The LoRa radio object. + delay : Time to wait after sending the packet (in seconds). + """ + + global PKT_SIZE + + try: + stringData = rawData + + # Convert input data to a string if it isn't already + if not isinstance(rawData, str): + stringData = str(rawData) + + # Convert the string to bytes using UTF-8 encoding + data = bytes(stringData, "utf-8") + + # Check if the data exceeds 250 bytes + if len(data) > PKT_SIZE: + raise ValueError("Data exceeds 250 bytes. Please reduce the size of the input.") + + # Send metadata (senderID, dtype, packet_count) first + metadata = { + "id" : str(sender_id), + "dtype": str(type(rawData).__name__), + "pkts" : str(len(data)//PKT_SIZE + 1) + } + metadata_bytes = str(metadata).encode("utf-8") + + # Sending meta data + radio.send(metadata_bytes) + print(f"Metadata sent: {metadata}") + + time.sleep(delay) + + # Send the byte data through the LoRa radio + radio.send(data) + print(f"Data sent: {stringData} (Length: {len(data)} bytes)") + + # Wait for the specified delay + time.sleep(delay) + + except Exception as e: + print(f"Error sending data: {e}") + +def sendByteArray(byteData, sender_id="DronePi", radio=sx1278, delay=DELAY): + """ + Sends a byte array through the LoRa radio. + Ensures the data is less than 250 bytes. + + Input parameters: + byteData : The byte array to send. + radio : The LoRa radio object. + delay : Time to wait after sending the packet (in seconds). + """ + try: + # Check if the input is a byte array + if not isinstance(byteData, bytes): + raise ValueError("Input data must be of type 'bytes'.") + + # Check if the data exceeds 250 bytes + if len(byteData) > PKT_SIZE: + raise ValueError("Data exceeds 250 bytes. Please reduce the size of the input.") + + # Send metadata (senderID, dtype, packet_count) first + metadata = { + "id" : str(sender_id), + "dtype": str(type(byteData).__name__), + "pkts" : str(len(byteData)//PKT_SIZE + 1) + } + metadata_bytes = str(metadata).encode("utf-8") + + # Sending meta data + radio.send(metadata_bytes) + time.sleep(delay) + + print(f"Metadata sent: {metadata}") + + # Send the byte array + radio.send(byteData) + print(f"Byte array sent: {byteData} (Length: {len(byteData)} bytes)") + + # Wait for the specified delay + time.sleep(delay) + + except Exception as e: + print(f"Error sending data: {e}") + +count = 0 + +try: + print("LoRa TX Started...") + while True: + sendStrings(count) + if(count >= 99): + count = 0 + else: + count += 1 + + # Example byte array + #data = bytes([0x01, 0x02, 0x03, 0x04]) # Replace with your data + #sendByteArray(data, sx1278, 1) # Send data with a 1-second delay + + # Example data to send + #data = "Hello World" # Replace with your data + #sendStrings(data) # Send data with a 1-second delay + + +except KeyboardInterrupt: + print("\nProgram interrupted") +finally: + # Clean up + print("GPIO cleaned up and program terminated.") \ No newline at end of file diff --git a/03. Hardware Implementation/LoRa Communication/Sender/Sender/Sender_V2.0.py b/03. Hardware Implementation/LoRa Communication/Sender/Sender/Sender_V2.0.py new file mode 100644 index 0000000..dc042a2 --- /dev/null +++ b/03. Hardware Implementation/LoRa Communication/Sender/Sender/Sender_V2.0.py @@ -0,0 +1,135 @@ +""" +Created by Bimsara Gawesh +Last update on 02 March 2025 +Sender for LoRa communication +This module requires a server for the communication +This is currenty support for the one way communication between two devices +Version 2.0 + +Key Parameters: +Module Name: LoRa-02 SX1278 +Frequency: 433 MHz +Bandwidth: 125 kHz +Compatible OS: Raspberry Pi Bustter 2020 +Compatible Python Version: Python 3 +Prerequisites: spidev, RPi.GPIO, Adafruit_rfm9x + +Note: Please reffer github repository for more information +https://github.com/cepdnaclk/e20-3yp-SkyT +""" + +# Import Python System Libraries +import time + +# Import RFM9x +import adafruit_rfm9x + +# Configure LoRa Radio +# Import Blinka Libraries +import busio +from digitalio import DigitalInOut +import board + +# Frequency for communication in MHz +RADIO_FREQ_MHZ = 433.0 + +# Delay between two packets in seconds +DELAY = 1 + +# Pin configuration +""" ++-------------+----------------+ +| LoRa SX1278 | Raspberry Pi | ++-------------+----------------+ +| VCC | +3V3 | +| GND | GND | +| SCK | SCK (GPIO 11) | +| MOSI | MOSI (GPIO 10) | +| MISO | MISO (GPIO 9) | +| NSS | CE1 (GPIO 7) | +| REST | GPIO 22 | +| DIO0 | NC | +| DIO1 | NC | +| DIO2 | NC | +| DIO3 | NC | +| DIO4 | NC | +| DIO5 | NC | ++-------------+----------------+ +""" +CS = DigitalInOut(board.CE1) +RESET = DigitalInOut(board.D22) + +# Initialize SPI bus. +spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO) + +# Initialze SX1278 radio +sx1278 = adafruit_rfm9x.RFM9x(spi, CS, RESET, RADIO_FREQ_MHZ) + +# You can however adjust the transmit power (in dB). The default is 13 dB but +# high power radios like the RFM95 can go up to 23 dB: +sx1278.tx_power = 23 +sx1278.signal_bandwidth = 125000 +sx1278.coding_rate = 14 +sx1278.enable_crc = True +#sx1278.spreading_factor = 12 + +# Sender Functions +def sendStrings(stringData, radio=sx1278, delay=DELAY): + """ + Converts the input data to a string and sends it as byte data through the LoRa radio. + + Input parameters: + stringData : The data to send (can be a string or any type that can be converted to a string). + radio : The LoRa radio object. + delay : Time to wait after sending the packet (in seconds). + """ + try: + # Convert input data to a string if it isn't already + if not isinstance(stringData, str): + stringData = str(stringData) + + # Convert the string to bytes using UTF-8 encoding + data = bytes(stringData, "utf-8") + + # Check if the data exceeds 250 bytes + if len(data) > 250: + raise ValueError("Data exceeds 250 bytes. Please reduce the size of the input.") + + # Send the byte data through the LoRa radio + radio.send(data) + print(f"Data sent: {stringData} (Length: {len(data)} bytes)") + + # Wait for the specified delay + time.sleep(delay) + + except Exception as e: + print(f"Error sending data: {e}") + +def sendByteArray(byteData, radio=sx1278, delay=DELAY): + """ + Sends a byte array through the LoRa radio. + Ensures the data is less than 250 bytes. + + Input parameters: + byteData : The byte array to send. + radio : The LoRa radio object. + delay : Time to wait after sending the packet (in seconds). + """ + try: + # Check if the input is a byte array + if not isinstance(byteData, bytes): + raise ValueError("Input data must be of type 'bytes'.") + + # Check if the data exceeds 250 bytes + if len(byteData) > 250: + raise ValueError("Data exceeds 250 bytes. Please reduce the size of the input.") + + # Send the byte array + radio.send(byteData) + print(f"Byte array sent: {byteData} (Length: {len(byteData)} bytes)") + + # Wait for the specified delay + time.sleep(delay) + + except Exception as e: + print(f"Error sending data: {e}") \ No newline at end of file diff --git a/03. Hardware Implementation/LoRa Communication/Sender/Sender/Sender_V2.1.py b/03. Hardware Implementation/LoRa Communication/Sender/Sender/Sender_V2.1.py new file mode 100644 index 0000000..2ddd88d --- /dev/null +++ b/03. Hardware Implementation/LoRa Communication/Sender/Sender/Sender_V2.1.py @@ -0,0 +1,171 @@ +""" +Created by Bimsara Gawesh +Last update on 02 March 2025 +Sender for LoRa communication +This module requires a server for the communication +This is currenty support for the one way communication between two devices +Version 2.1 + +Key Parameters: +Module Name: LoRa-02 SX1278 +Frequency: 433 MHz +Bandwidth: 125 kHz +Compatible OS: Raspberry Pi Bustter 2020 +Compatible Python Version: Python 3 +Prerequisites: spidev, RPi.GPIO, Adafruit_rfm9x + +Note: Please reffer github repository for more information +https://github.com/cepdnaclk/e20-3yp-SkyT +""" + +# Import Python System Libraries +import time + +# Import RFM9x +import adafruit_rfm9x + +# Configure LoRa Radio +# Import Blinka Libraries +import busio +from digitalio import DigitalInOut +import board + +# Frequency for communication in MHz +RADIO_FREQ_MHZ = 433.0 + +# Delay between two packets in seconds +DELAY = 1 + +# Pin configuration +""" ++-------------+----------------+ +| LoRa SX1278 | Raspberry Pi | ++-------------+----------------+ +| VCC | +3V3 | +| GND | GND | +| SCK | SCK (GPIO 11) | +| MOSI | MOSI (GPIO 10) | +| MISO | MISO (GPIO 9) | +| NSS | CE1 (GPIO 7) | +| REST | GPIO 22 | +| DIO0 | NC | +| DIO1 | NC | +| DIO2 | NC | +| DIO3 | NC | +| DIO4 | NC | +| DIO5 | NC | ++-------------+----------------+ +""" +CS = DigitalInOut(board.CE1) +RESET = DigitalInOut(board.D22) + +# Initialize SPI bus. +spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO) + +# Initialze SX1278 radio +sx1278 = adafruit_rfm9x.RFM9x(spi, CS, RESET, RADIO_FREQ_MHZ) + +# You can however adjust the transmit power (in dB). The default is 13 dB but +# high power radios like the RFM95 can go up to 23 dB: +sx1278.tx_power = 23 +sx1278.signal_bandwidth = 125000 +sx1278.coding_rate = 14 +sx1278.enable_crc = True +#sx1278.spreading_factor = 12 + +# Sender Functions +def sendStrings(stringData, radio=sx1278, delay=DELAY): + """ + Converts the input data to a string and sends it as byte data through the LoRa radio. + + Input parameters: + stringData : The data to send (can be a string or any type that can be converted to a string). + radio : The LoRa radio object. + delay : Time to wait after sending the packet (in seconds). + """ + try: + # Convert input data to a string if it isn't already + if not isinstance(stringData, str): + stringData = str(stringData) + + # Convert the string to bytes using UTF-8 encoding + data = bytes(stringData, "utf-8") + + # Check if the data exceeds 250 bytes + if len(data) > 250: + raise ValueError("Data exceeds 250 bytes. Please reduce the size of the input.") + + # Send the byte data through the LoRa radio + radio.send(data) + print(f"Data sent: {stringData} (Length: {len(data)} bytes)") + + # Wait for the specified delay + time.sleep(delay) + + except Exception as e: + print(f"Error sending data: {e}") + +def sendByteArray(byteData, radio=sx1278, delay=DELAY): + """ + Sends a byte array through the LoRa radio. + Ensures the data is less than 250 bytes. + + Input parameters: + byteData : The byte array to send. + radio : The LoRa radio object. + delay : Time to wait after sending the packet (in seconds). + """ + try: + # Check if the input is a byte array + if not isinstance(byteData, bytes): + raise ValueError("Input data must be of type 'bytes'.") + + # Check if the data exceeds 250 bytes + if len(byteData) > 250: + raise ValueError("Data exceeds 250 bytes. Please reduce the size of the input.") + + # Send the byte array + radio.send(byteData) + print(f"Byte array sent: {byteData} (Length: {len(byteData)} bytes)") + + # Wait for the specified delay + time.sleep(delay) + + except Exception as e: + print(f"Error sending data: {e}") + +def sendLargeData(data, radio=sx1278, delay=DELAY): + """ + Sends a large dataset by splitting it into chunks of 250 bytes (or less) and transmitting each chunk. + + Input parameters: + data : The data to send (can be a string, bytes, or bytearray). + radio : The LoRa radio object (defaults to sx1278). + delay : Time to wait after sending each chunk (in seconds). + chunk_size : Maximum size of each chunk (default is 250 bytes). + """ + + chunk_size = 250 # Allowed maximum size of each chunk + + try: + # Convert input data to bytes if it isn't already + if isinstance(data, str): + data = bytes(data, "utf-8") + elif isinstance(data, bytearray): + data = bytes(data) + elif not isinstance(data, bytes): + raise ValueError("Input data must be a string, bytes, or bytearray.") + + # Split the data into chunks + chunks = [data[i:i + chunk_size] for i in range(0, len(data), chunk_size)] + + # Send each chunk + for i, chunk in enumerate(chunks): + print(f"Sending chunk {i + 1}/{len(chunks)} (Length: {len(chunk)} bytes)") + radio.send(chunk) + time.sleep(delay) # Wait before sending the next chunk + + print("All chunks sent successfully.") + + except Exception as e: + print(f"Error sending large data: {e}") \ No newline at end of file diff --git a/03. Hardware Implementation/LoRa Communication/Sender/Sender/Sender_V2.2.py b/03. Hardware Implementation/LoRa Communication/Sender/Sender/Sender_V2.2.py new file mode 100644 index 0000000..87d42c3 --- /dev/null +++ b/03. Hardware Implementation/LoRa Communication/Sender/Sender/Sender_V2.2.py @@ -0,0 +1,224 @@ +""" +Created by Bimsara Gawesh +Last update on 02 March 2025 +Sender for LoRa communication +This module requires a server for the communication +This is currenty support for the one way communication between two devices +Version 2.2 + +Key Parameters: +Module Name: LoRa-02 SX1278 +Frequency: 433 MHz +Bandwidth: 125 kHz +Compatible OS: Raspberry Pi Bustter 2020 +Compatible Python Version: Python 3 +Prerequisites: spidev, RPi.GPIO, Adafruit_rfm9x + +Note: Please reffer github repository for more information +https://github.com/cepdnaclk/e20-3yp-SkyT +""" + +# Import Python System Libraries +import time + +# Import RFM9x +import adafruit_rfm9x + +# Configure LoRa Radio +# Import Blinka Libraries +import busio +from digitalio import DigitalInOut +import board + +# Frequency for communication in MHz +RADIO_FREQ_MHZ = 433.0 + +# Delay between two packets in seconds +DELAY = 1 + +# Pin configuration +""" ++-------------+----------------+ +| LoRa SX1278 | Raspberry Pi | ++-------------+----------------+ +| VCC | +3V3 | +| GND | GND | +| SCK | SCK (GPIO 11) | +| MOSI | MOSI (GPIO 10) | +| MISO | MISO (GPIO 9) | +| NSS | CE1 (GPIO 7) | +| REST | GPIO 22 | +| DIO0 | NC | +| DIO1 | NC | +| DIO2 | NC | +| DIO3 | NC | +| DIO4 | NC | +| DIO5 | NC | ++-------------+----------------+ +""" +CS = DigitalInOut(board.CE1) +RESET = DigitalInOut(board.D22) + +# Initialize SPI bus. +spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO) + +# Initialze SX1278 radio +sx1278 = adafruit_rfm9x.RFM9x(spi, CS, RESET, RADIO_FREQ_MHZ) + +# You can however adjust the transmit power (in dB). The default is 13 dB but +# high power radios like the RFM95 can go up to 23 dB: +sx1278.tx_power = 23 +sx1278.signal_bandwidth = 125000 +sx1278.coding_rate = 14 +sx1278.enable_crc = True +#sx1278.spreading_factor = 12 + +# Sender Functions +def sendStrings(stringData, radio=sx1278, delay=DELAY): + """ + Converts the input data to a string and sends it as byte data through the LoRa radio. + + Input parameters: + stringData : The data to send (can be a string or any type that can be converted to a string). + radio : The LoRa radio object. + delay : Time to wait after sending the packet (in seconds). + """ + try: + # Convert input data to a string if it isn't already + if not isinstance(stringData, str): + stringData = str(stringData) + + # Convert the string to bytes using UTF-8 encoding + data = bytes(stringData, "utf-8") + + # Check if the data exceeds 250 bytes + if len(data) > 250: + raise ValueError("Data exceeds 250 bytes. Please reduce the size of the input.") + + # Send the byte data through the LoRa radio + radio.send(data) + print(f"Data sent: {stringData} (Length: {len(data)} bytes)") + + # Wait for the specified delay + time.sleep(delay) + + except Exception as e: + print(f"Error sending data: {e}") + +def sendByteArray(byteData, radio=sx1278, delay=DELAY): + """ + Sends a byte array through the LoRa radio. + Ensures the data is less than 250 bytes. + + Input parameters: + byteData : The byte array to send. + radio : The LoRa radio object. + delay : Time to wait after sending the packet (in seconds). + """ + try: + # Check if the input is a byte array + if not isinstance(byteData, bytes): + raise ValueError("Input data must be of type 'bytes'.") + + # Check if the data exceeds 250 bytes + if len(byteData) > 250: + raise ValueError("Data exceeds 250 bytes. Please reduce the size of the input.") + + # Send the byte array + radio.send(byteData) + print(f"Byte array sent: {byteData} (Length: {len(byteData)} bytes)") + + # Wait for the specified delay + time.sleep(delay) + + except Exception as e: + print(f"Error sending data: {e}") + +def sendLargeData(data, radio=sx1278, delay=DELAY): + """ + Sends a large dataset by splitting it into chunks of 250 bytes (or less) and transmitting each chunk. + + Input parameters: + data : The data to send (can be a string, bytes, or bytearray). + radio : The LoRa radio object (defaults to sx1278). + delay : Time to wait after sending each chunk (in seconds). + chunk_size : Maximum size of each chunk (default is 250 bytes). + """ + + chunk_size = 250 # Allowed maximum size of each chunk + + try: + # Convert input data to bytes if it isn't already + if isinstance(data, str): + data = bytes(data, "utf-8") + elif isinstance(data, bytearray): + data = bytes(data) + elif not isinstance(data, bytes): + raise ValueError("Input data must be a string, bytes, or bytearray.") + + # Split the data into chunks + chunks = [data[i:i + chunk_size] for i in range(0, len(data), chunk_size)] + + # Send each chunk + for i, chunk in enumerate(chunks): + print(f"Sending chunk {i + 1}/{len(chunks)} (Length: {len(chunk)} bytes)") + radio.send(chunk) + time.sleep(delay) # Wait before sending the next chunk + + print("All chunks sent successfully.") + + except Exception as e: + print(f"Error sending large data: {e}") + +def sendImage(image_array, radio=sx1278, delay=DELAY): + """ + Sends a 2D (grayscale) or 3D (RGB) NumPy array (image) over LoRa by splitting it into chunks. + + Input parameters: + image_array : The 2D (grayscale) or 3D (RGB) NumPy array to send. + radio : The LoRa radio object (defaults to sx1278). + delay : Time to wait after sending each chunk (in seconds). + chunk_size : Maximum size of each chunk (default is 250 bytes). + """ + + chunk_size=250 + + try: + # Check if the image is grayscale (2D) or RGB (3D) + if image_array.ndim == 2: + image_type = "grayscale" + elif image_array.ndim == 3 and image_array.shape[2] == 3: + image_type = "RGB" + else: + raise ValueError("Unsupported image format. Must be 2D (grayscale) or 3D (RGB).") + + # Serialize the image array into bytes + image_bytes = image_array.tobytes() + + # Split the byte stream into chunks + chunks = [image_bytes[i:i + chunk_size] for i in range(0, len(image_bytes), chunk_size)] + + # Send metadata (image shape, dtype, and type) first + metadata = { + "shape": image_array.shape, + "dtype": str(image_array.dtype), + "type": image_type # Add image type (grayscale or RGB) + } + metadata_bytes = str(metadata).encode("utf-8") + + # Sending meta data + radio.send(metadata_bytes) + time.sleep(delay) + + print(f"Metadata sent: {metadata}") + + # Send each chunk + for i, chunk in enumerate(chunks): + print(f"Sending chunk {i + 1}/{len(chunks)} (Length: {len(chunk)} bytes)") + radio.send(chunk) + time.sleep(delay) # Wait before sending the next chunk + + print("Image sent successfully.") + + except Exception as e: + print(f"Error sending image: {e}") \ No newline at end of file diff --git a/03. Hardware Implementation/LoRa Communication/Sender/Sender/Sender_V2.3.py b/03. Hardware Implementation/LoRa Communication/Sender/Sender/Sender_V2.3.py new file mode 100644 index 0000000..2949bf9 --- /dev/null +++ b/03. Hardware Implementation/LoRa Communication/Sender/Sender/Sender_V2.3.py @@ -0,0 +1,288 @@ +""" +Created by Bimsara Gawesh +Last update on 02 March 2025 +Sender for LoRa communication +This module requires a server for the communication +This is currenty support for the one way communication between two devices +Here we send sender ID and the packet number to the reciever +Version 2.3 + +Key Parameters: +Module Name: LoRa-02 SX1278 +Frequency: 433 MHz +Bandwidth: 125 kHz +Compatible OS: Raspberry Pi Bustter 2020 +Compatible Python Version: Python 3 +Prerequisites: spidev, RPi.GPIO, Adafruit_rfm9x + +Note: Please reffer github repository for more information +https://github.com/cepdnaclk/e20-3yp-SkyT +""" + +# Import Python System Libraries +import time + +# Import RFM9x +import adafruit_rfm9x + +# Configure LoRa Radio +# Import Blinka Libraries +import busio +from digitalio import DigitalInOut +import board + +# Frequency for communication in MHz +RADIO_FREQ_MHZ = 433.0 + +# Maximum length of a packet +PKT_SIZE = 250 + +# Delay between two packets in seconds +DELAY = 1 + +# Pin configuration +""" ++-------------+----------------+ +| LoRa SX1278 | Raspberry Pi | ++-------------+----------------+ +| VCC | +3V3 | +| GND | GND | +| SCK | SCK (GPIO 11) | +| MOSI | MOSI (GPIO 10) | +| MISO | MISO (GPIO 9) | +| NSS | CE1 (GPIO 7) | +| REST | GPIO 22 | +| DIO0 | NC | +| DIO1 | NC | +| DIO2 | NC | +| DIO3 | NC | +| DIO4 | NC | +| DIO5 | NC | ++-------------+----------------+ +""" +CS = DigitalInOut(board.CE1) +RESET = DigitalInOut(board.D22) + +# Initialize SPI bus. +spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO) + +# Initialze SX1278 radio +sx1278 = adafruit_rfm9x.RFM9x(spi, CS, RESET, RADIO_FREQ_MHZ) + +# You can however adjust the transmit power (in dB). The default is 13 dB but +# high power radios like the RFM95 can go up to 23 dB: +sx1278.tx_power = 23 +sx1278.signal_bandwidth = 125000 +sx1278.coding_rate = 8 +sx1278.spreading_factor = 8 + +# Sender Functions + +# Sending a string which less than 250 bytes +def sendStrings(rawData, sender_id="DronePi", radio=sx1278, delay=DELAY): + """ + Converts the input data to a string and sends it as byte data through the LoRa radio. + + Input parameters: + rawData : The data to send (can be a string or any type that can be converted to a string). + radio : The LoRa radio object. + delay : Time to wait after sending the packet (in seconds). + """ + + global PKT_SIZE + + try: + stringData = rawData + + # Convert input data to a string if it isn't already + if not isinstance(rawData, str): + stringData = str(rawData) + + # Convert the string to bytes using UTF-8 encoding + data = bytes(stringData, "utf-8") + + # Check if the data exceeds 250 bytes + if len(data) > PKT_SIZE: + raise ValueError(f"Data exceeds {PKT_SIZE} bytes. Please reduce the size of the input.") + + # Send metadata (senderID, dtype, packet_count) first + metadata = { + "id" : str(sender_id), + "dtype": str(type(rawData).__name__), + "pkts" : str(len(data)//PKT_SIZE + 1) + } + metadata_bytes = ("Header: " + str(metadata)).encode("utf-8") + + # Sending meta data + radio.send(metadata_bytes) + print(f"Metadata sent: {metadata}") + + time.sleep(delay) + + # Send the byte data through the LoRa radio + radio.send(data) + print(f"Data sent: {stringData} (Length: {len(data)} bytes)") + + # Wait for the specified delay + time.sleep(delay) + + except Exception as e: + print(f"Error sending data: {e}") + +# Sending a byte array which less than 250 bytes +def sendByteArray(byteData, sender_id="DronePi", radio=sx1278, delay=DELAY): + """ + Sends a byte array through the LoRa radio. + Ensures the data is less than 250 bytes. + + Input parameters: + byteData : The byte array to send. + radio : The LoRa radio object. + delay : Time to wait after sending the packet (in seconds). + """ + global PKT_SIZE + + try: + # Check if the input is a byte array + if not isinstance(byteData, bytes): + raise ValueError("Input data must be of type 'bytes'.") + + # Check if the data exceeds 250 bytes + if len(byteData) > PKT_SIZE: + raise ValueError(f"Data exceeds {PKT_SIZE} bytes. Please reduce the size of the input.") + + # Send metadata (senderID, dtype, packet_count) first + metadata = { + "id" : str(sender_id), + "dtype": str(type(byteData).__name__), + "pkts" : str(len(byteData)//PKT_SIZE + 1) + } + metadata_bytes = ("Header: " + str(metadata)).encode("utf-8") + + # Sending meta data + radio.send(metadata_bytes) + time.sleep(delay) + + print(f"Metadata sent: {metadata}") + + # Send the byte array + radio.send(byteData) + print(f"Byte array sent: {byteData} (Length: {len(byteData)} bytes)") + + # Wait for the specified delay + time.sleep(delay) + + except Exception as e: + print(f"Error sending data: {e}") + +# Sending a string which lager than 250 bytes +def sendLargeData(rawData, sender_id='DronePi', radio=sx1278, delay=DELAY, chunk_size=PKT_SIZE): + """ + Sends a large dataset by splitting it into chunks of 250 bytes (or less) and transmitting each chunk. + Each chunk is prefixed with the sender ID and packet number. + + Input parameters: + rawData : The data to send (can be a string, bytes, or bytearray). + sender_id : The unique ID of the sender. + radio : The LoRa radio object (defaults to sx1278). + delay : Time to wait after sending each chunk (in seconds). + chunk_size : Maximum size of each chunk (default is 250 bytes). + """ + + try: + # Convert input data to bytes if it isn't already + if isinstance(rawData, str): + data = bytes(rawData, "utf-8") + elif isinstance(rawData, bytearray): + data = bytes(rawData) + elif not isinstance(rawData, bytes): + raise ValueError("Input data must be a string, bytes, or bytearray.") + + # Split the data into chunks + chunks = [data[i:i + chunk_size] for i in range(0, len(data), chunk_size)] + + # Send metadata (senderID, dtype, packet_count) first + metadata = { + "id" : str(sender_id), + "dtype": str(type(rawData).__name__), + "pkts" : str(len(chunks)), + "psize": str(chunk_size) + } + metadata_bytes = ("Header: " + str(metadata)).encode("utf-8") + + # Sending meta data + radio.send(metadata_bytes) + time.sleep(delay) + + print(f"Metadata sent: {metadata}") + + # Send each chunk with sender ID and packet number + for packet_number, chunk in enumerate(chunks): + # Create a packet with packet number, and chunk data + packet = packet_number.to_bytes(2, "big") + chunk + print(f"Sending packet {packet_number + 1}/{len(chunks)} (Length: {len(packet)} bytes)") + radio.send(packet) + time.sleep(delay) # Wait before sending the next chunk + + print("All chunks sent successfully.") + + except Exception as e: + print(f"Error sending large data: {e}") + +# Sending a image which lager than 250 bytes +def sendImage(image_array, sender_id="DronePi", radio=sx1278, delay=DELAY, chunk_size=PKT_SIZE): + """ + Sends a 2D (grayscale) or 3D (RGB) NumPy array (image) over LoRa by splitting it into chunks. + Each chunk is prefixed with the sender ID and packet number. + + Input parameters: + image_array : The 2D (grayscale) or 3D (RGB) NumPy array to send. + sender_id : The unique ID of the sender. + radio : The LoRa radio object (defaults to sx1278). + delay : Time to wait after sending each chunk (in seconds). + chunk_size : Maximum size of each chunk (default is 250 bytes). + """ + try: + # Check if the image is grayscale (2D) or RGB (3D) + if image_array.ndim == 2: + image_type = "GRAY" + elif image_array.ndim == 3 and image_array.shape[2] == 3: + image_type = "RGB" + else: + raise ValueError("Unsupported image format. Must be 2D (grayscale) or 3D (RGB).") + + # Serialize the image array into bytes + image_bytes = image_array.tobytes() + + # Split the byte stream into chunks + chunks = [image_bytes[i:i + chunk_size] for i in range(0, len(image_bytes), chunk_size)] + + # Send metadata (image shape, dtype, and type) first + metadata = { + "id" : str(sender_id), + "shape": image_array.shape, + "dtype": str(image_array.dtype), + "type": image_type, # Add image type (grayscale or RGB) + "pkts" : str(len(chunks)), + "psize": str(chunk_size) + } + metadata_bytes = ("Header: " + str(metadata)).encode("utf-8") + + # Sending meta data + radio.send(metadata_bytes) + print(f"Metadata sent: {metadata}") + + time.sleep(delay) + + # Send each chunk with sender ID and packet number + for packet_number, chunk in enumerate(chunks): + # Create a packet with packet number, and chunk data + packet = packet_number.to_bytes(2, "big") + chunk + print(f"Sending packet {packet_number + 1}/{len(chunks)} (Length: {len(packet)} bytes)") + radio.send(packet) + time.sleep(delay) # Wait before sending the next chunk + + print("Image sent successfully.") + + except Exception as e: + print(f"Error sending image: {e}") \ No newline at end of file diff --git a/03. Hardware Implementation/LoRa Communication/Sender/Sender/Sender_V2.4.py b/03. Hardware Implementation/LoRa Communication/Sender/Sender/Sender_V2.4.py new file mode 100644 index 0000000..71e5ad1 --- /dev/null +++ b/03. Hardware Implementation/LoRa Communication/Sender/Sender/Sender_V2.4.py @@ -0,0 +1,293 @@ +""" +Created by Bimsara Gawesh +Last update on 02 March 2025 +Sender for LoRa communication +This module requires a server for the communication +This is currenty support for the one way communication between two devices +Here we send sender ID and the packet number to the reciever +Version 2.3 + +Key Parameters: +Module Name: LoRa-02 SX1278 +Frequency: 433 MHz +Bandwidth: 125 kHz +Compatible OS: Raspberry Pi Bustter 2020 +Compatible Python Version: Python 3 +Prerequisites: spidev, RPi.GPIO, Adafruit_rfm9x + +Note: Please reffer github repository for more information +https://github.com/cepdnaclk/e20-3yp-SkyT +""" + +# Import Python System Libraries +import time + +# Import RFM9x +import adafruit_rfm9x + +# Configure LoRa Radio +# Import Blinka Libraries +import busio +from digitalio import DigitalInOut +import board + +# Frequency for communication in MHz +RADIO_FREQ_MHZ = 433.0 + +# Maximum length of a packet +PKT_SIZE = 250 + +# Delay between two packets in seconds +DELAY = 1 + +# Pin configuration +""" ++-------------+----------------+ +| LoRa SX1278 | Raspberry Pi | ++-------------+----------------+ +| VCC | +3V3 | +| GND | GND | +| SCK | SCK (GPIO 11) | +| MOSI | MOSI (GPIO 10) | +| MISO | MISO (GPIO 9) | +| NSS | CE1 (GPIO 7) | +| REST | GPIO 22 | +| DIO0 | NC | +| DIO1 | NC | +| DIO2 | NC | +| DIO3 | NC | +| DIO4 | NC | +| DIO5 | NC | ++-------------+----------------+ +""" +CS = DigitalInOut(board.CE1) +RESET = DigitalInOut(board.D22) + +# Initialize SPI bus. +spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO) + +# Initialze SX1278 radio +sx1278 = adafruit_rfm9x.RFM9x(spi, CS, RESET, RADIO_FREQ_MHZ) + +# You can however adjust the transmit power (in dB). The default is 13 dB but +# high power radios like the RFM95 can go up to 23 dB: +sx1278.tx_power = 23 +sx1278.signal_bandwidth = 125000 +sx1278.coding_rate = 8 +sx1278.spreading_factor = 8 + +# Sender Functions + +# Sending a string which less than 250 bytes +def sendStrings(rawData, sender_id="DronePi", radio=sx1278, delay=DELAY): + """ + Converts the input data to a string and sends it as byte data through the LoRa radio. + + Input parameters: + rawData : The data to send (can be a string or any type that can be converted to a string). + radio : The LoRa radio object. + delay : Time to wait after sending the packet (in seconds). + """ + + global PKT_SIZE + + try: + stringData = rawData + + # Convert input data to a string if it isn't already + if not isinstance(rawData, str): + stringData = str(rawData) + + # Convert the string to bytes using UTF-8 encoding + data = bytes(stringData, "utf-8") + + # Check if the data exceeds 250 bytes + if len(data) > PKT_SIZE: + raise ValueError(f"Data exceeds {PKT_SIZE} bytes. Please reduce the size of the input.") + + # Send metadata (senderID, dtype, packet_count) first + metadata = { + "id" : str(sender_id), + "dtype": str(type(rawData).__name__), + "pkts" : "1", + "size" : str(PKT_SIZE) + } + metadata_bytes = ("HEAD: " + str(metadata)).encode("utf-8") + + # Sending meta data + radio.send(metadata_bytes) + print(f"Metadata sent: {metadata}") + + time.sleep(delay) + + # Send the byte data through the LoRa radio + radio.send(data) + print(f"Data sent: {stringData} (Length: {len(data)} bytes)") + + # Wait for the specified delay + time.sleep(delay) + + except Exception as e: + print(f"Error sending data: {e}") + +# Sending a byte array which less than 250 bytes +def sendByteArray(byteData, sender_id="DronePi", radio=sx1278, delay=DELAY): + """ + Sends a byte array through the LoRa radio. + Ensures the data is less than 250 bytes. + + Input parameters: + byteData : The byte array to send. + radio : The LoRa radio object. + delay : Time to wait after sending the packet (in seconds). + """ + global PKT_SIZE + + try: + # Check if the input is a byte array + if not isinstance(byteData, bytes): + raise ValueError("Input data must be of type 'bytes'.") + + # Check if the data exceeds 250 bytes + if len(byteData) > PKT_SIZE: + raise ValueError(f"Data exceeds {PKT_SIZE} bytes. Please reduce the size of the input.") + + # Send metadata (senderID, dtype, packet_count) first + metadata = { + "id" : str(sender_id), + "dtype": str(type(byteData).__name__), + "pkts" : "1", + "size" : str(PKT_SIZE) + } + metadata_bytes = ("HEAD: " + str(metadata)).encode("utf-8") + + # Sending meta data + radio.send(metadata_bytes) + time.sleep(delay) + + print(f"Metadata sent: {metadata}") + + # Send the byte array + radio.send(byteData) + print(f"Byte array sent: {byteData} (Length: {len(byteData)} bytes)") + + # Wait for the specified delay + time.sleep(delay) + + except Exception as e: + print(f"Error sending data: {e}") + +# Sending a string which lager than 250 bytes +def sendLargeData(rawData, sender_id='DronePi', radio=sx1278, delay=DELAY, chunk_size=PKT_SIZE): + """ + Sends a large dataset by splitting it into chunks of 250 bytes (or less) and transmitting each chunk. + Each chunk is prefixed with the sender ID and packet number. + + Input parameters: + rawData : The data to send (can be a string, bytes, or bytearray). + sender_id : The unique ID of the sender. + radio : The LoRa radio object (defaults to sx1278). + delay : Time to wait after sending each chunk (in seconds). + chunk_size : Maximum size of each chunk (default is 250 bytes). + """ + + try: + # Convert input data to bytes if it isn't already + if isinstance(rawData, str): + data = bytes(rawData, "utf-8") + elif isinstance(rawData, bytearray): + data = bytes(rawData) + elif not isinstance(rawData, bytes): + raise ValueError("Input data must be a string, bytes, or bytearray.") + + # Split the data into chunks + chunks = [data[i:i + chunk_size] for i in range(0, len(data), chunk_size)] + + # Send metadata (senderID, dtype, packet_count) first + metadata = { + "id" : str(sender_id), + "dtype": str(type(rawData).__name__), + "pkts" : str(len(chunks)), + "size": str(chunk_size) + } + metadata_bytes = ("HEAD: " + str(metadata)).encode("utf-8") + + # Sending meta data + radio.send(metadata_bytes) + time.sleep(delay) + + print(f"Metadata sent: {metadata}") + + # Send each chunk with sender ID and packet number + for packet_number, chunk in enumerate(chunks): + # Create a packet with packet number, and chunk data + packet = packet_number.to_bytes(2, "big") + chunk + print(f"Sending packet {packet_number + 1}/{len(chunks)} (Length: {len(packet)} bytes)") + radio.send(packet) + time.sleep(delay) # Wait before sending the next chunk + + print("All chunks sent successfully.") + + except Exception as e: + print(f"Error sending large data: {e}") + +# Sending a image which lager than 250 bytes +def sendImage(image_array, sender_id="DronePi", radio=sx1278, delay=DELAY, chunk_size=PKT_SIZE): + """ + Sends a 2D (grayscale) or 3D (RGB) NumPy array (image) over LoRa by splitting it into chunks. + Each chunk is prefixed with the sender ID and packet number. + + Input parameters: + image_array : The 2D (grayscale) or 3D (RGB) NumPy array to send. + sender_id : The unique ID of the sender. + radio : The LoRa radio object (defaults to sx1278). + delay : Time to wait after sending each chunk (in seconds). + chunk_size : Maximum size of each chunk (default is 250 bytes). + """ + try: + if(image_array is None): + raise ValueError("Image couldn't be null.") + + # Check if the image is grayscale (2D) or RGB (3D) + if image_array.ndim == 2: + image_type = "GRAY" + elif image_array.ndim == 3 and image_array.shape[2] == 3: + image_type = "RGB" + else: + raise ValueError("Unsupported image format. Must be 2D (grayscale) or 3D (RGB).") + + # Serialize the image array into bytes + image_bytes = image_array.tobytes() + + # Split the byte stream into chunks + chunks = [image_bytes[i:i + chunk_size] for i in range(0, len(image_bytes), chunk_size)] + + # Send metadata (image shape, dtype, and type) first + metadata = { + "id" : str(sender_id), + "shape": image_array.shape, + "dtype": str(image_array.dtype), + "type": image_type, # Add image type (grayscale or RGB) + "pkts" : str(len(chunks)), + "size": str(chunk_size) + } + metadata_bytes = ("HEAD: " + str(metadata)).encode("utf-8") + + # Sending meta data + radio.send(metadata_bytes) + print(f"Metadata sent: {metadata}") + + time.sleep(delay) + + # Send each chunk with sender ID and packet number + for packet_number, chunk in enumerate(chunks): + # Create a packet with packet number, and chunk data + packet = packet_number.to_bytes(2, "big") + chunk + print(f"Sending packet {packet_number + 1}/{len(chunks)} (Length: {len(packet)} bytes)") + radio.send(packet) + time.sleep(delay) # Wait before sending the next chunk + + print("Image sent successfully.") + + except Exception as e: + print(f"Error sending image: {e}") \ No newline at end of file diff --git a/03. Hardware Implementation/LoRa Communication/Sender/Sender/Sender_V2.5.py b/03. Hardware Implementation/LoRa Communication/Sender/Sender/Sender_V2.5.py new file mode 100644 index 0000000..46410a2 --- /dev/null +++ b/03. Hardware Implementation/LoRa Communication/Sender/Sender/Sender_V2.5.py @@ -0,0 +1,301 @@ +""" +Created by Bimsara Gawesh +Last update on 02 March 2025 +Sender for LoRa communication +This module requires a server for the communication +This is currenty support for the one way communication between two devices +Here we send sender ID and the packet number to the reciever +Version 2.5 + +Key Parameters: +Module Name: LoRa-02 SX1278 +Frequency: 433 MHz +Bandwidth: 125 kHz +Compatible OS: Raspberry Pi Bustter 2020 +Compatible Python Version: Python 3 +Prerequisites: spidev, RPi.GPIO, Adafruit_rfm9x + +Note: Please reffer github repository for more information +https://github.com/cepdnaclk/e20-3yp-SkyT +""" + +# Import Python System Libraries +import time + +# Import RFM9x +import adafruit_rfm9x + +# Configure LoRa Radio +# Import Blinka Libraries +import busio +from digitalio import DigitalInOut +import board + +# Frequency for communication in MHz +RADIO_FREQ_MHZ = 433.0 + +# Maximum length of a packet +PKT_SIZE = 200 + +# Delay between two packets in seconds +DELAY = 0.8 + +# Pin configuration +""" ++-------------+----------------+ +| LoRa SX1278 | Raspberry Pi | ++-------------+----------------+ +| VCC | +3V3 | +| GND | GND | +| SCK | SCK (GPIO 11) | +| MOSI | MOSI (GPIO 10) | +| MISO | MISO (GPIO 9) | +| NSS | CE1 (GPIO 7) | +| REST | GPIO 22 | +| DIO0 | NC | +| DIO1 | NC | +| DIO2 | NC | +| DIO3 | NC | +| DIO4 | NC | +| DIO5 | NC | ++-------------+----------------+ +""" +CS = DigitalInOut(board.CE1) +RESET = DigitalInOut(board.D22) + +# Initialize SPI bus. +spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO) + +# Initialze SX1278 radio +sx1278 = adafruit_rfm9x.RFM9x(spi, CS, RESET, RADIO_FREQ_MHZ) + +# You can however adjust the transmit power (in dB). The default is 13 dB but +# high power radios like the RFM95 can go up to 23 dB: +sx1278.tx_power = 23 +sx1278.signal_bandwidth = 125000 +sx1278.coding_rate = 8 +sx1278.spreading_factor = 8 + +# Sender Functions + +# Sending a string which less than 250 bytes +def sendStrings(rawData, sender_id="DronePi", radio=sx1278, delay=DELAY): + """ + Converts the input data to a string and sends it as byte data through the LoRa radio. + + Input parameters: + rawData : The data to send (can be a string or any type that can be converted to a string). + radio : The LoRa radio object. + delay : Time to wait after sending the packet (in seconds). + """ + + global PKT_SIZE + + try: + stringData = rawData + + # Convert input data to a string if it isn't already + if not isinstance(rawData, str): + stringData = str(rawData) + + # Convert the string to bytes using UTF-8 encoding + data = bytes(stringData, "utf-8") + + # Check if the data exceeds 250 bytes + if len(data) > PKT_SIZE: + raise ValueError(f"Data exceeds {PKT_SIZE} bytes. Please reduce the size of the input.") + + # Send metadata (senderID, dtype, packet_count) first + metadata = { + "id" : str(sender_id), + "dtype": str(type(rawData).__name__), + "pkts" : "1", + "size" : str(PKT_SIZE) + } + metadata_bytes = ("HEAD: " + str(metadata)).encode("utf-8") + + # Sending meta data + radio.send(metadata_bytes) + print(f"Metadata sent: {metadata}") + + time.sleep(delay) + + # Create a packet with packet number, and data + packet_number = 1 + packet = packet_number.to_bytes(3, "big") + data + + # Send the byte data through the LoRa radio + radio.send(packet) + print(f"Data sent: {stringData} (Length: {len(packet)} bytes)") + + # Wait for the specified delay + time.sleep(delay) + + except Exception as e: + print(f"Error sending data: {e}") + +# Sending a byte array which less than 250 bytes +def sendByteArray(byteData, sender_id="DronePi", radio=sx1278, delay=DELAY): + """ + Sends a byte array through the LoRa radio. + Ensures the data is less than 250 bytes. + + Input parameters: + byteData : The byte array to send. + radio : The LoRa radio object. + delay : Time to wait after sending the packet (in seconds). + """ + global PKT_SIZE + + try: + # Check if the input is a byte array + if not isinstance(byteData, bytes): + raise ValueError("Input data must be of type 'bytes'.") + + # Check if the data exceeds 250 bytes + if len(byteData) > PKT_SIZE: + raise ValueError(f"Data exceeds {PKT_SIZE} bytes. Please reduce the size of the input.") + + # Send metadata (senderID, dtype, packet_count) first + metadata = { + "id" : str(sender_id), + "dtype": str(type(byteData).__name__), + "pkts" : "1", + "size" : str(PKT_SIZE) + } + metadata_bytes = ("HEAD: " + str(metadata)).encode("utf-8") + + # Sending meta data + radio.send(metadata_bytes) + time.sleep(delay) + + print(f"Metadata sent: {metadata}") + + # Create a packet with packet number, and data + packet_number = 1 + packet = packet_number.to_bytes(3, "big") + byteData + + # Send the byte data through the LoRa radio + radio.send(packet) + print(f"Data sent: {byteData} (Length: {len(packet)} bytes)") + + # Wait for the specified delay + time.sleep(delay) + + except Exception as e: + print(f"Error sending data: {e}") + +# Sending a string which lager than 250 bytes +def sendLargeData(rawData, sender_id='DronePi', radio=sx1278, delay=DELAY, chunk_size=PKT_SIZE): + """ + Sends a large dataset by splitting it into chunks of 250 bytes (or less) and transmitting each chunk. + Each chunk is prefixed with the sender ID and packet number. + + Input parameters: + rawData : The data to send (can be a string, bytes, or bytearray). + sender_id : The unique ID of the sender. + radio : The LoRa radio object (defaults to sx1278). + delay : Time to wait after sending each chunk (in seconds). + chunk_size : Maximum size of each chunk (default is 250 bytes). + """ + + try: + # Convert input data to bytes if it isn't already + if isinstance(rawData, str): + data = bytes(rawData, "utf-8") + elif isinstance(rawData, bytearray): + data = bytes(rawData) + elif not isinstance(rawData, bytes): + raise ValueError("Input data must be a string, bytes, or bytearray.") + + # Split the data into chunks + chunks = [data[i:i + chunk_size] for i in range(0, len(data), chunk_size)] + + # Send metadata (senderID, dtype, packet_count) first + metadata = { + "id" : str(sender_id), + "dtype": str(type(rawData).__name__), + "pkts" : str(len(chunks)), + "size": str(chunk_size) + } + metadata_bytes = ("HEAD: " + str(metadata)).encode("utf-8") + + # Sending meta data + radio.send(metadata_bytes) + time.sleep(delay) + + print(f"Metadata sent: {metadata}") + + # Send each chunk with sender ID and packet number + for packet_number, chunk in enumerate(chunks): + # Create a packet with packet number, and chunk data + packet = packet_number.to_bytes(3, "big") + chunk + print(f"Sending packet {packet_number + 1}/{len(chunks)} (Length: {len(packet)} bytes)") + radio.send(packet) + time.sleep(delay) # Wait before sending the next chunk + + print("All chunks sent successfully.") + + except Exception as e: + print(f"Error sending large data: {e}") + +# Sending a image which lager than 250 bytes +def sendImage(image_array, sender_id="DronePi", radio=sx1278, delay=DELAY, chunk_size=PKT_SIZE): + """ + Sends a 2D (grayscale) or 3D (RGB) NumPy array (image) over LoRa by splitting it into chunks. + Each chunk is prefixed with the sender ID and packet number. + + Input parameters: + image_array : The 2D (grayscale) or 3D (RGB) NumPy array to send. + sender_id : The unique ID of the sender. + radio : The LoRa radio object (defaults to sx1278). + delay : Time to wait after sending each chunk (in seconds). + chunk_size : Maximum size of each chunk (default is 250 bytes). + """ + try: + if(image_array is None): + raise ValueError("Image couldn't be null.") + + # Check if the image is grayscale (2D) or RGB (3D) + if image_array.ndim == 2: + image_type = "GRAY" + elif image_array.ndim == 3 and image_array.shape[2] == 3: + image_type = "RGB" + else: + raise ValueError("Unsupported image format. Must be 2D (grayscale) or 3D (RGB).") + + # Serialize the image array into bytes + image_bytes = image_array.tobytes() + + # Split the byte stream into chunks + chunks = [image_bytes[i:i + chunk_size] for i in range(0, len(image_bytes), chunk_size)] + + # Send metadata (image shape, dtype, and type) first + metadata = { + "id" : str(sender_id), + "shape": image_array.shape, + "dtype": str(image_array.dtype), + "type": image_type, # Add image type (grayscale or RGB) + "pkts" : str(len(chunks)), + "size": str(chunk_size) + } + metadata_bytes = ("HEAD: " + str(metadata)).encode("utf-8") + + # Sending meta data + radio.send(metadata_bytes) + print(f"Metadata sent: {metadata}") + + time.sleep(delay) + + # Send each chunk with sender ID and packet number + for packet_number, chunk in enumerate(chunks): + # Create a packet with packet number, and chunk data + packet = packet_number.to_bytes(3, "big") + chunk + print(f"Sending packet {packet_number + 1}/{len(chunks)} (Length: {len(packet)} bytes)") + radio.send(packet) + time.sleep(delay) # Wait before sending the next chunk + + print("Image sent successfully.") + + except Exception as e: + print(f"Error sending image: {e}") \ No newline at end of file diff --git a/03. Hardware Implementation/LoRa Communication/Sender/Sender/Sender_V3.0.py b/03. Hardware Implementation/LoRa Communication/Sender/Sender/Sender_V3.0.py new file mode 100644 index 0000000..bb9789d --- /dev/null +++ b/03. Hardware Implementation/LoRa Communication/Sender/Sender/Sender_V3.0.py @@ -0,0 +1,314 @@ +""" +Created by Bimsara Gawesh +Last update on 02 March 2025 +Sender for LoRa communication +This module requires a server for the communication +This is currenty support for the one way communication between two devices with acknowlagement (Reliabble Data Transmission) +Version 3.0 + +Key Parameters: +Module Name: LoRa-02 SX1278 +Frequency: 433 MHz +Bandwidth: 125 kHz +Compatible OS: Raspberry Pi Bustter 2020 +Compatible Python Version: Python 3 +Prerequisites: spidev, RPi.GPIO, Adafruit_rfm9x + +Note: Please reffer github repository for more information +https://github.com/cepdnaclk/e20-3yp-SkyT +""" + +# Import Python System Libraries +import time + +# Import RFM9x +import adafruit_rfm9x + +# Configure LoRa Radio +# Import Blinka Libraries +import busio +from digitalio import DigitalInOut +import board + +# Frequency for communication in MHz +RADIO_FREQ_MHZ = 433.0 + +# Maximum length of a packet +PKT_SIZE = 200 + +# Delay between two packets in seconds +DELAY = 0.8 + +# Delay for waiting for a ACK +WAIT = 2 + +# Maximum number of trys for establish the connection +MAX_TRY = 5 + +# Pin configuration +""" ++-------------+----------------+ +| LoRa SX1278 | Raspberry Pi | ++-------------+----------------+ +| VCC | +3V3 | +| GND | GND | +| SCK | SCK (GPIO 11) | +| MOSI | MOSI (GPIO 10) | +| MISO | MISO (GPIO 9) | +| NSS | CE1 (GPIO 7) | +| REST | GPIO 22 | +| DIO0 | NC | +| DIO1 | NC | +| DIO2 | NC | +| DIO3 | NC | +| DIO4 | NC | +| DIO5 | NC | ++-------------+----------------+ +""" +CS = DigitalInOut(board.CE1) +RESET = DigitalInOut(board.D22) + +# Initialize SPI bus. +spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO) + +# Initialze SX1278 radio +sx1278 = adafruit_rfm9x.RFM9x(spi, CS, RESET, RADIO_FREQ_MHZ) + +# You can however adjust the transmit power (in dB). The default is 13 dB but +# high power radios like the RFM95 can go up to 23 dB: +sx1278.tx_power = 23 +sx1278.signal_bandwidth = 125000 +sx1278.coding_rate = 8 +sx1278.spreading_factor = 8 + +# Sender Functions + +# Function to send meadata and waiting for the ACK +def sendMetaData(metaData, radio=sx1278, delay=DELAY): + metadata_bytes = ("HEAD: " + str(metaData)).encode("utf-8") + + for i in range(MAX_TRY): + # Sending meta data + radio.send(metadata_bytes) + print(f"Metadata sent: {metaData}") + + time.sleep(delay) + + # Look for a new packet - wait up to 2 seconds: + packet = radio.receive(timeout=2, with_header=True) + + if(packet is not None): + packet_text = str(packet, "ascii") + print("Received (ASCII): {0}".format(packet_text)) + time.sleep(delay) + return True + + # Return result + return False + +# Sending a string which less than 250 bytes +def sendStrings(rawData, sender_id="DronePi", radio=sx1278, delay=DELAY): + """ + Converts the input data to a string and sends it as byte data through the LoRa radio. + + Input parameters: + rawData : The data to send (can be a string or any type that can be converted to a string). + radio : The LoRa radio object. + delay : Time to wait after sending the packet (in seconds). + """ + + global PKT_SIZE + + try: + stringData = rawData + + # Convert input data to a string if it isn't already + if not isinstance(rawData, str): + stringData = str(rawData) + + # Convert the string to bytes using UTF-8 encoding + data = bytes(stringData, "utf-8") + + # Check if the data exceeds 250 bytes + if len(data) > PKT_SIZE: + raise ValueError(f"Data exceeds {PKT_SIZE} bytes. Please reduce the size of the input.") + + # Send metadata (senderID, dtype, packet_count) first + metadata = { + "id" : str(sender_id), + "dtype": str(type(rawData).__name__), + "pkts" : "1", + "size" : str(PKT_SIZE) + } + + if not sendMetaData(metadata): + raise ValueError("Unable to build up a connection.") + + # Create a packet with packet number, and data + packet_number = 1 + packet = packet_number.to_bytes(3, "big") + data + + # Send the byte data through the LoRa radio + radio.send(packet) + print(f"Data sent: {stringData} (Length: {len(packet)} bytes)") + + # Wait for the specified delay + time.sleep(delay) + + except Exception as e: + print(f"Error sending data: {e}") + +# Sending a byte array which less than 250 bytes +def sendByteArray(byteData, sender_id="DronePi", radio=sx1278, delay=DELAY): + """ + Sends a byte array through the LoRa radio. + Ensures the data is less than 250 bytes. + + Input parameters: + byteData : The byte array to send. + radio : The LoRa radio object. + delay : Time to wait after sending the packet (in seconds). + """ + global PKT_SIZE + + try: + # Check if the input is a byte array + if not isinstance(byteData, bytes): + raise ValueError("Input data must be of type 'bytes'.") + + # Check if the data exceeds 250 bytes + if len(byteData) > PKT_SIZE: + raise ValueError(f"Data exceeds {PKT_SIZE} bytes. Please reduce the size of the input.") + + # Send metadata (senderID, dtype, packet_count) first + metadata = { + "id" : str(sender_id), + "dtype": str(type(byteData).__name__), + "pkts" : "1", + "size" : str(PKT_SIZE) + } + + # Send metadata + if not sendMetaData(metadata): + raise ValueError("Unable to build up a connection.") + + # Create a packet with packet number, and data + packet_number = 1 + packet = packet_number.to_bytes(3, "big") + byteData + + # Send the byte data through the LoRa radio + radio.send(packet) + print(f"Data sent: {byteData} (Length: {len(packet)} bytes)") + + # Wait for the specified delay + time.sleep(delay) + + except Exception as e: + print(f"Error sending data: {e}") + +# Sending a string which lager than 250 bytes +def sendLargeData(rawData, sender_id='DronePi', radio=sx1278, delay=DELAY, chunk_size=PKT_SIZE): + """ + Sends a large dataset by splitting it into chunks of 250 bytes (or less) and transmitting each chunk. + Each chunk is prefixed with the sender ID and packet number. + + Input parameters: + rawData : The data to send (can be a string, bytes, or bytearray). + sender_id : The unique ID of the sender. + radio : The LoRa radio object (defaults to sx1278). + delay : Time to wait after sending each chunk (in seconds). + chunk_size : Maximum size of each chunk (default is 250 bytes). + """ + + try: + # Convert input data to bytes if it isn't already + if isinstance(rawData, str): + data = bytes(rawData, "utf-8") + elif isinstance(rawData, bytearray): + data = bytes(rawData) + elif not isinstance(rawData, bytes): + raise ValueError("Input data must be a string, bytes, or bytearray.") + + # Split the data into chunks + chunks = [data[i:i + chunk_size] for i in range(0, len(data), chunk_size)] + + # Send metadata (senderID, dtype, packet_count) first + metadata = { + "id" : str(sender_id), + "dtype": str(type(rawData).__name__), + "pkts" : str(len(chunks)), + "size": str(chunk_size) + } + + if not sendMetaData(metadata): + raise ValueError("Unable to build up a connection.") + + # Send each chunk with sender ID and packet number + for packet_number, chunk in enumerate(chunks): + # Create a packet with packet number, and chunk data + packet = packet_number.to_bytes(3, "big") + chunk + print(f"Sending packet {packet_number + 1}/{len(chunks)} (Length: {len(packet)} bytes)") + radio.send(packet) + time.sleep(delay) # Wait before sending the next chunk + + print("All chunks sent successfully.") + + except Exception as e: + print(f"Error sending large data: {e}") + +# Sending a image which lager than 250 bytes +def sendImage(image_array, sender_id="DronePi", radio=sx1278, delay=DELAY, chunk_size=PKT_SIZE): + """ + Sends a 2D (grayscale) or 3D (RGB) NumPy array (image) over LoRa by splitting it into chunks. + Each chunk is prefixed with the sender ID and packet number. + + Input parameters: + image_array : The 2D (grayscale) or 3D (RGB) NumPy array to send. + sender_id : The unique ID of the sender. + radio : The LoRa radio object (defaults to sx1278). + delay : Time to wait after sending each chunk (in seconds). + chunk_size : Maximum size of each chunk (default is 250 bytes). + """ + try: + if(image_array is None): + raise ValueError("Image couldn't be null.") + + # Check if the image is grayscale (2D) or RGB (3D) + if image_array.ndim == 2: + image_type = "GRAY" + elif image_array.ndim == 3 and image_array.shape[2] == 3: + image_type = "RGB" + else: + raise ValueError("Unsupported image format. Must be 2D (grayscale) or 3D (RGB).") + + # Serialize the image array into bytes + image_bytes = image_array.tobytes() + + # Split the byte stream into chunks + chunks = [image_bytes[i:i + chunk_size] for i in range(0, len(image_bytes), chunk_size)] + + # Send metadata (image shape, dtype, and type) first + metadata = { + "id" : str(sender_id), + "dtype": str(image_array.dtype), + "pkts" : str(len(chunks)), + "size": str(chunk_size), + "shape": image_array.shape, + "type": image_type # Add image type (grayscale or RGB) + } + + if not sendMetaData(metadata): + raise ValueError("Unable to build up a connection.") + + # Send each chunk with sender ID and packet number + for packet_number, chunk in enumerate(chunks): + # Create a packet with packet number, and chunk data + packet = packet_number.to_bytes(3, "big") + chunk + print(f"Sending packet {packet_number + 1}/{len(chunks)} (Length: {len(packet)} bytes)") + radio.send(packet) + time.sleep(delay) # Wait before sending the next chunk + + print("Image sent successfully.") + + except Exception as e: + print(f"Error sending image: {e}") \ No newline at end of file diff --git a/03. Hardware Implementation/LoRa Communication/Sender/Server/Server_V1.0.py b/03. Hardware Implementation/LoRa Communication/Sender/Server/Server_V1.0.py new file mode 100644 index 0000000..590decc --- /dev/null +++ b/03. Hardware Implementation/LoRa Communication/Sender/Server/Server_V1.0.py @@ -0,0 +1,82 @@ +""" +Created by Bimsara Gawesh +Last update on 02 March 2025 +Server for LoRa communication +This module requires a Sender for the communication +This is currenty support for the one way communication between two devices +Work for up to Sender_V2.2 +Version 1.0 +""" + +# Import Python System Libraries +import numpy as np + +# Import Sender +from Sender import sendStrings, sendByteArray, sendLargeData, sendImage + +# Dummy data set +count = 0 + +byteData = bytes([0x01, 0x02, 0x03, 0x04]) + +stringData = "Hello World" + +Large_String = """**The Importance of Computers in Modern Society** + +Computers have become an essential part of modern life, transforming the way we work, communicate, and access information. From personal use to large-scale industries, computers play a crucial role in various aspects of our daily activities. They have revolutionized education, business, healthcare, and entertainment, making tasks more efficient and accessible. As technology continues to evolve, computers are becoming even more powerful, influencing every sector of society. + +One of the most significant impacts of computers is in the field of education. With the advent of digital learning, students can now access a wealth of information at their fingertips. Online courses, e-books, and educational videos provide opportunities for people worldwide to learn new skills without attending traditional classrooms. Additionally, computers help educators create engaging content, automate administrative tasks, and conduct virtual classes, making education more interactive and efficient. + +In business, computers have streamlined operations, increasing productivity and efficiency. Companies rely on computers for data management, communication, marketing, and financial transactions. With the rise of e-commerce, businesses can reach a global audience, allowing customers to purchase products and services online. Computer software also helps companies analyze market trends, manage supply chains, and improve customer service. As a result, businesses can operate more effectively and compete in a rapidly evolving marketplace. + +Healthcare has also greatly benefited from the advancements in computer technology. Medical professionals use computers for diagnosing diseases, managing patient records, and conducting research. Hospitals and clinics rely on specialized software to track patient histories, schedule appointments, and store critical medical data. Moreover, cutting-edge technologies such as artificial intelligence and machine learning are assisting in the development of new treatments, improving the accuracy of medical diagnoses, and even predicting potential health risks. Telemedicine, made possible by computers and the internet, enables doctors to consult with patients remotely, increasing access to healthcare services. + +Computers have also revolutionized communication, allowing people to connect instantly across the globe. Social media platforms, emails, and video conferencing have made it easier for individuals and businesses to stay connected. The internet, powered by computers, has created a digital world where people can share ideas, collaborate on projects, and engage in discussions regardless of their geographical location. This has not only strengthened personal relationships but has also enhanced professional networking, enabling businesses and organizations to work together efficiently. + +Entertainment has seen a significant transformation with the advent of computers. From streaming services and video games to digital art and music production, computers provide endless possibilities for creative expression. High-quality graphics, virtual reality, and artificial intelligence have pushed the boundaries of what is possible in gaming and film production. Additionally, content creators use computers to edit videos, compose music, and develop software applications, shaping the future of entertainment and digital media. + +Despite their numerous benefits, computers also pose challenges, such as cybersecurity threats, data privacy concerns, and digital addiction. Hackers and cybercriminals exploit vulnerabilities to steal sensitive information, leading to financial losses and privacy breaches. To address these issues, cybersecurity measures, including firewalls, encryption, and antivirus software, are essential to protect personal and organizational data. Furthermore, excessive screen time can lead to health issues, such as eye strain and decreased physical activity, highlighting the importance of balanced computer usage. + +In conclusion, computers have become an indispensable part of modern society, impacting education, business, healthcare, communication, and entertainment. Their ability to process vast amounts of information quickly and efficiently has made life more convenient and productive. While computers present challenges, proper usage and security measures can mitigate risks. As technology continues to advance, computers will play an even greater role in shaping the future, making them one of the most important inventions in human history. +""" + +Image = np.array([ + [0, 50, 100, 150, 200, 250, 200, 150], + [50, 100, 150, 200, 250, 200, 150, 100], + [100, 150, 200, 250, 200, 150, 100, 50], + [150, 200, 250, 200, 150, 100, 50, 0], + [200, 250, 200, 150, 100, 50, 0, 50], + [250, 200, 150, 100, 50, 0, 50, 100], + [200, 150, 100, 50, 0, 50, 100, 150], + [150, 100, 50, 0, 50, 100, 150, 200] +], dtype=np.uint8) + +# Serialize the image array into bytes +image_bytes = Image.tobytes() + +# Server Code +try: + print("LoRa Server Started...") + # Example counter data sending + #sendStrings(count) + #count = 0 if count >= 99 else count + 1 + + # Example byte array + #sendByteArray(byteData) # Send data with a 1-second delay + + # Example data to send + #sendStrings(stringData) # Send data with a 1-second delay + + # Send the large dataset - String + #sendLargeData(Large_String) + + # Send the large dataset - Image + while True: + sendImage(Image) + + +except KeyboardInterrupt: + print("\nProgram interrupted") +finally: + # Clean up + print("GPIO cleaned up and program terminated.") \ No newline at end of file diff --git a/03. Hardware Implementation/LoRa Communication/Sender/Server/Server_V2.0.py b/03. Hardware Implementation/LoRa Communication/Sender/Server/Server_V2.0.py new file mode 100644 index 0000000..7c7ed34 --- /dev/null +++ b/03. Hardware Implementation/LoRa Communication/Sender/Server/Server_V2.0.py @@ -0,0 +1,83 @@ +""" +Created by Bimsara Gawesh +Last update on 02 March 2025 +Server for LoRa communication +This module requires a Sender for the communication +This is currenty support for the one way communication between two devices +Work for Sender_V2.3 and newer +Version 2.0 +""" + +# Import Python System Libraries +import numpy as np + +# Import Sender +from Sender import sendStrings, sendByteArray, sendLargeData, sendImage + +# Dummy data set +count = 0 + +byteData = bytes([0x01, 0x02, 0x03, 0x04]) + +stringData = "Hello World" + +Large_String = """**The Importance of Computers in Modern Society** + +Computers have become an essential part of modern life, transforming the way we work, communicate, and access information. From personal use to large-scale industries, computers play a crucial role in various aspects of our daily activities. They have revolutionized education, business, healthcare, and entertainment, making tasks more efficient and accessible. As technology continues to evolve, computers are becoming even more powerful, influencing every sector of society. + +One of the most significant impacts of computers is in the field of education. With the advent of digital learning, students can now access a wealth of information at their fingertips. Online courses, e-books, and educational videos provide opportunities for people worldwide to learn new skills without attending traditional classrooms. Additionally, computers help educators create engaging content, automate administrative tasks, and conduct virtual classes, making education more interactive and efficient. + +In business, computers have streamlined operations, increasing productivity and efficiency. Companies rely on computers for data management, communication, marketing, and financial transactions. With the rise of e-commerce, businesses can reach a global audience, allowing customers to purchase products and services online. Computer software also helps companies analyze market trends, manage supply chains, and improve customer service. As a result, businesses can operate more effectively and compete in a rapidly evolving marketplace. + +Healthcare has also greatly benefited from the advancements in computer technology. Medical professionals use computers for diagnosing diseases, managing patient records, and conducting research. Hospitals and clinics rely on specialized software to track patient histories, schedule appointments, and store critical medical data. Moreover, cutting-edge technologies such as artificial intelligence and machine learning are assisting in the development of new treatments, improving the accuracy of medical diagnoses, and even predicting potential health risks. Telemedicine, made possible by computers and the internet, enables doctors to consult with patients remotely, increasing access to healthcare services. + +Computers have also revolutionized communication, allowing people to connect instantly across the globe. Social media platforms, emails, and video conferencing have made it easier for individuals and businesses to stay connected. The internet, powered by computers, has created a digital world where people can share ideas, collaborate on projects, and engage in discussions regardless of their geographical location. This has not only strengthened personal relationships but has also enhanced professional networking, enabling businesses and organizations to work together efficiently. + +Entertainment has seen a significant transformation with the advent of computers. From streaming services and video games to digital art and music production, computers provide endless possibilities for creative expression. High-quality graphics, virtual reality, and artificial intelligence have pushed the boundaries of what is possible in gaming and film production. Additionally, content creators use computers to edit videos, compose music, and develop software applications, shaping the future of entertainment and digital media. + +Despite their numerous benefits, computers also pose challenges, such as cybersecurity threats, data privacy concerns, and digital addiction. Hackers and cybercriminals exploit vulnerabilities to steal sensitive information, leading to financial losses and privacy breaches. To address these issues, cybersecurity measures, including firewalls, encryption, and antivirus software, are essential to protect personal and organizational data. Furthermore, excessive screen time can lead to health issues, such as eye strain and decreased physical activity, highlighting the importance of balanced computer usage. + +In conclusion, computers have become an indispensable part of modern society, impacting education, business, healthcare, communication, and entertainment. Their ability to process vast amounts of information quickly and efficiently has made life more convenient and productive. While computers present challenges, proper usage and security measures can mitigate risks. As technology continues to advance, computers will play an even greater role in shaping the future, making them one of the most important inventions in human history. +""" + +Image = np.array([ + [0, 50, 100, 150, 200, 250, 200, 150], + [50, 100, 150, 200, 250, 200, 150, 100], + [100, 150, 200, 250, 200, 150, 100, 50], + [150, 200, 250, 200, 150, 100, 50, 0], + [200, 250, 200, 150, 100, 50, 0, 50], + [250, 200, 150, 100, 50, 0, 50, 100], + [200, 150, 100, 50, 0, 50, 100, 150], + [150, 100, 50, 0, 50, 100, 150, 200] +], dtype=np.uint8) + +# Serialize the image array into bytes +image_bytes = Image.tobytes() + +# Server Code +try: + print("LoRa Server Started...") + # Example counter data sending + #sendStrings(count) + #count = 0 if count >= 99 else count + 1 + + # Example byte array + #sendByteArray(byteData) # Send data with a 1-second delay + + # Example data to send + sendStrings(stringData) # Send data with a 1-second delay + + # Send the large dataset - String + #senderID = "DronePi" + #sendLargeData(Large_String, senderID) + + # Send the large dataset - Image + #while True: + # sendImage(Image) + + +except KeyboardInterrupt: + print("\nProgram interrupted") +finally: + # Clean up + print("GPIO cleaned up and program terminated.") \ No newline at end of file diff --git a/03. Hardware Implementation/LoRa Communication/Sender/Server/Server_V2.1.py b/03. Hardware Implementation/LoRa Communication/Sender/Server/Server_V2.1.py new file mode 100644 index 0000000..8fac8f0 --- /dev/null +++ b/03. Hardware Implementation/LoRa Communication/Sender/Server/Server_V2.1.py @@ -0,0 +1,85 @@ +""" +Created by Bimsara Gawesh +Last update on 02 March 2025 +Server for LoRa communication +This module requires a Sender for the communication +This is currenty support for the one way communication between two devices +Work for Sender_V2.3 and newer +Version 2.1 +""" + +# Import Python System Libraries +import numpy as np + +# Import Sender +from Sender import sendStrings, sendByteArray, sendLargeData, sendImage + +# Dummy data set +count = 0 + +byteData = bytes([0x01, 0x02, 0x03, 0x04]) + +stringData = "Hello World" + +Large_String = """**The Importance of Computers in Modern Society** + +Computers have become an essential part of modern life, transforming the way we work, communicate, and access information. From personal use to large-scale industries, computers play a crucial role in various aspects of our daily activities. They have revolutionized education, business, healthcare, and entertainment, making tasks more efficient and accessible. As technology continues to evolve, computers are becoming even more powerful, influencing every sector of society. + +One of the most significant impacts of computers is in the field of education. With the advent of digital learning, students can now access a wealth of information at their fingertips. Online courses, e-books, and educational videos provide opportunities for people worldwide to learn new skills without attending traditional classrooms. Additionally, computers help educators create engaging content, automate administrative tasks, and conduct virtual classes, making education more interactive and efficient. + +In business, computers have streamlined operations, increasing productivity and efficiency. Companies rely on computers for data management, communication, marketing, and financial transactions. With the rise of e-commerce, businesses can reach a global audience, allowing customers to purchase products and services online. Computer software also helps companies analyze market trends, manage supply chains, and improve customer service. As a result, businesses can operate more effectively and compete in a rapidly evolving marketplace. + +Healthcare has also greatly benefited from the advancements in computer technology. Medical professionals use computers for diagnosing diseases, managing patient records, and conducting research. Hospitals and clinics rely on specialized software to track patient histories, schedule appointments, and store critical medical data. Moreover, cutting-edge technologies such as artificial intelligence and machine learning are assisting in the development of new treatments, improving the accuracy of medical diagnoses, and even predicting potential health risks. Telemedicine, made possible by computers and the internet, enables doctors to consult with patients remotely, increasing access to healthcare services. + +Computers have also revolutionized communication, allowing people to connect instantly across the globe. Social media platforms, emails, and video conferencing have made it easier for individuals and businesses to stay connected. The internet, powered by computers, has created a digital world where people can share ideas, collaborate on projects, and engage in discussions regardless of their geographical location. This has not only strengthened personal relationships but has also enhanced professional networking, enabling businesses and organizations to work together efficiently. + +Entertainment has seen a significant transformation with the advent of computers. From streaming services and video games to digital art and music production, computers provide endless possibilities for creative expression. High-quality graphics, virtual reality, and artificial intelligence have pushed the boundaries of what is possible in gaming and film production. Additionally, content creators use computers to edit videos, compose music, and develop software applications, shaping the future of entertainment and digital media. + +Despite their numerous benefits, computers also pose challenges, such as cybersecurity threats, data privacy concerns, and digital addiction. Hackers and cybercriminals exploit vulnerabilities to steal sensitive information, leading to financial losses and privacy breaches. To address these issues, cybersecurity measures, including firewalls, encryption, and antivirus software, are essential to protect personal and organizational data. Furthermore, excessive screen time can lead to health issues, such as eye strain and decreased physical activity, highlighting the importance of balanced computer usage. + +In conclusion, computers have become an indispensable part of modern society, impacting education, business, healthcare, communication, and entertainment. Their ability to process vast amounts of information quickly and efficiently has made life more convenient and productive. While computers present challenges, proper usage and security measures can mitigate risks. As technology continues to advance, computers will play an even greater role in shaping the future, making them one of the most important inventions in human history. +""" + +Image_Array = np.array([ + [0, 50, 100, 150, 200, 250, 200, 150], + [50, 100, 150, 200, 250, 200, 150, 100], + [100, 150, 200, 250, 200, 150, 100, 50], + [150, 200, 250, 200, 150, 100, 50, 0], + [200, 250, 200, 150, 100, 50, 0, 50], + [250, 200, 150, 100, 50, 0, 50, 100], + [200, 150, 100, 50, 0, 50, 100, 150], + [150, 100, 50, 0, 50, 100, 150, 200] +], dtype=np.uint8) + +# Serialize the image array into bytes +image_bytes = Image.tobytes() + + + +# Server Code +try: + print("LoRa Server Started...") + # Example counter data sending + #sendStrings(count) + #count = 0 if count >= 99 else count + 1 + + # Example byte array + #sendByteArray(byteData) # Send data with a 1-second delay + + # Example data to send + #sendStrings(stringData) # Send data with a 1-second delay + + # Send the large dataset - String + #senderID = "DronePi" + #sendLargeData(Large_String, senderID) + + # Send the large dataset - Image + #while True: + # sendImage(Image_Array) + + +except KeyboardInterrupt: + print("\nProgram interrupted") +finally: + # Clean up + print("GPIO cleaned up and program terminated.") \ No newline at end of file diff --git a/03. Hardware Implementation/LoRa Communication/Sender/Server/Server_V3.0.py b/03. Hardware Implementation/LoRa Communication/Sender/Server/Server_V3.0.py new file mode 100644 index 0000000..cc7a539 --- /dev/null +++ b/03. Hardware Implementation/LoRa Communication/Sender/Server/Server_V3.0.py @@ -0,0 +1,73 @@ +""" +Created by Bimsara Gawesh +Last update on 02 March 2025 +Server for LoRa communication +This module requires a Sender for the communication +This is currenty support for the one way communication between two devices +Work for Sender_V2.3 and newer +Version 3.0 + +Required Helper Files +Sender.py, Imager.py +""" + +# Import Sender +from Sender import sendStrings, sendByteArray, sendLargeData, sendImage + +# Import Imager +from Imager import loadImage + +# Dummy data set +count = 0 + +byteData = bytes([0x01, 0x02, 0x03, 0x04]) + +stringData = "Hello World" + +Large_String = """**The Importance of Computers in Modern Society** + +Computers have become an essential part of modern life, transforming the way we work, communicate, and access information. From personal use to large-scale industries, computers play a crucial role in various aspects of our daily activities. They have revolutionized education, business, healthcare, and entertainment, making tasks more efficient and accessible. As technology continues to evolve, computers are becoming even more powerful, influencing every sector of society. + +One of the most significant impacts of computers is in the field of education. With the advent of digital learning, students can now access a wealth of information at their fingertips. Online courses, e-books, and educational videos provide opportunities for people worldwide to learn new skills without attending traditional classrooms. Additionally, computers help educators create engaging content, automate administrative tasks, and conduct virtual classes, making education more interactive and efficient. + +In business, computers have streamlined operations, increasing productivity and efficiency. Companies rely on computers for data management, communication, marketing, and financial transactions. With the rise of e-commerce, businesses can reach a global audience, allowing customers to purchase products and services online. Computer software also helps companies analyze market trends, manage supply chains, and improve customer service. As a result, businesses can operate more effectively and compete in a rapidly evolving marketplace. + +Healthcare has also greatly benefited from the advancements in computer technology. Medical professionals use computers for diagnosing diseases, managing patient records, and conducting research. Hospitals and clinics rely on specialized software to track patient histories, schedule appointments, and store critical medical data. Moreover, cutting-edge technologies such as artificial intelligence and machine learning are assisting in the development of new treatments, improving the accuracy of medical diagnoses, and even predicting potential health risks. Telemedicine, made possible by computers and the internet, enables doctors to consult with patients remotely, increasing access to healthcare services. + +Computers have also revolutionized communication, allowing people to connect instantly across the globe. Social media platforms, emails, and video conferencing have made it easier for individuals and businesses to stay connected. The internet, powered by computers, has created a digital world where people can share ideas, collaborate on projects, and engage in discussions regardless of their geographical location. This has not only strengthened personal relationships but has also enhanced professional networking, enabling businesses and organizations to work together efficiently. + +Entertainment has seen a significant transformation with the advent of computers. From streaming services and video games to digital art and music production, computers provide endless possibilities for creative expression. High-quality graphics, virtual reality, and artificial intelligence have pushed the boundaries of what is possible in gaming and film production. Additionally, content creators use computers to edit videos, compose music, and develop software applications, shaping the future of entertainment and digital media. + +Despite their numerous benefits, computers also pose challenges, such as cybersecurity threats, data privacy concerns, and digital addiction. Hackers and cybercriminals exploit vulnerabilities to steal sensitive information, leading to financial losses and privacy breaches. To address these issues, cybersecurity measures, including firewalls, encryption, and antivirus software, are essential to protect personal and organizational data. Furthermore, excessive screen time can lead to health issues, such as eye strain and decreased physical activity, highlighting the importance of balanced computer usage. + +In conclusion, computers have become an indispensable part of modern society, impacting education, business, healthcare, communication, and entertainment. Their ability to process vast amounts of information quickly and efficiently has made life more convenient and productive. While computers present challenges, proper usage and security measures can mitigate risks. As technology continues to advance, computers will play an even greater role in shaping the future, making them one of the most important inventions in human history. +""" + + +# Server Code +try: + print("LoRa Server Started...") + # Example counter data sending + #sendStrings(count) + #count = 0 if count >= 99 else count + 1 + + # Example byte array + #sendByteArray(byteData) # Send data with a 1-second delay + + # Example data to send + #sendStrings(stringData) # Send data with a 1-second delay + + # Send the large dataset - String + #senderID = "DronePi" + #sendLargeData(Large_String, senderID) + + # Send the large dataset - Image + Image = loadImage("image1.webp") + sendImage(Image) + + +except KeyboardInterrupt: + print("\nProgram interrupted") +finally: + # Clean up + print("GPIO cleaned up and program terminated.") \ No newline at end of file diff --git a/03. Hardware Implementation/LoRa Communication/Sender/Transmitter.py b/03. Hardware Implementation/LoRa Communication/Sender/Transmitter.py new file mode 100644 index 0000000..a45975b --- /dev/null +++ b/03. Hardware Implementation/LoRa Communication/Sender/Transmitter.py @@ -0,0 +1,67 @@ +# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries +# SPDX-License-Identifier: MIT + +# Example to send a packet periodically +# Author: Jerry Needell +# +import time +import board +import busio +import digitalio +import adafruit_rfm9x + +# set the time interval (seconds) for sending packets +transmit_interval = 10 + +# Define radio parameters. +RADIO_FREQ_MHZ = 433.0 # Frequency of the radio in Mhz. Must match your +# module! Can be a value like 915.0, 433.0, etc. + +# Define pins connected to the chip. +CS = digitalio.DigitalInOut(board.CE1) +RESET = digitalio.DigitalInOut(board.D25) + +# Initialize SPI bus. +spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO) + +# Initialze RFM radio +rfm9x = adafruit_rfm9x.RFM9x(spi, CS, RESET, RADIO_FREQ_MHZ) + +# Note that the radio is configured in LoRa mode so you can't control sync +# word, encryption, frequency deviation, or other settings! + +# You can however adjust the transmit power (in dB). The default is 13 dB but +# high power radios like the RFM95 can go up to 23 dB: +rfm9x.tx_power = 23 + +rfm9x.signal_bandwidth = 125000 +rfm9x.coding_rate = 8 +rfm9x.spreading_factor = 12 +rfm9x.enable_crc = True + +# initialize counter +counter = 0 +# send a broadcast mesage +rfm9x.send(bytes("message number {}".format(counter), "UTF-8")) + +# Wait to receive packets. +print("Waiting for packets...") +# initialize flag and timer +send_reading = False +time_now = time.monotonic() +while True: + # Look for a new packet - wait up to 5 seconds: + packet = rfm9x.receive(timeout=5.0) + # If no packet was received during the timeout then None is returned. + if packet is not None: + # Received a packet! + # Print out the raw bytes of the packet: + print("Received (raw bytes): {0}".format(packet)) + # send reading after any packet received + if time.monotonic() - time_now > transmit_interval: + # reset timeer + time_now = time.monotonic() + # clear flag to send data + send_reading = False + counter = counter + 1 + rfm9x.send(bytes("message number {}".format(counter), "UTF-8")) diff --git a/03. Hardware Implementation/LoRa Communication/Sender/tempCodeRunnerFile.py b/03. Hardware Implementation/LoRa Communication/Sender/tempCodeRunnerFile.py new file mode 100644 index 0000000..7fab09b --- /dev/null +++ b/03. Hardware Implementation/LoRa Communication/Sender/tempCodeRunnerFile.py @@ -0,0 +1,2 @@ +b.pyplot as plt +import io \ No newline at end of file diff --git a/03. Hardware Implementation/LoRa Communication/Sender/test.py b/03. Hardware Implementation/LoRa Communication/Sender/test.py new file mode 100644 index 0000000..6b7ff81 --- /dev/null +++ b/03. Hardware Implementation/LoRa Communication/Sender/test.py @@ -0,0 +1,18 @@ +import numpy as np +import matplotlib.pyplot as plt + +# Create a simple 8x8 grayscale image +image_array = np.array([ + [0, 50, 100, 150, 200, 250, 200, 150], + [50, 100, 150, 200, 250, 200, 150, 100], + [100, 150, 200, 250, 200, 150, 100, 50], + [150, 200, 250, 200, 150, 100, 50, 0], + [200, 250, 200, 150, 100, 50, 0, 50], + [250, 200, 150, 100, 50, 0, 50, 100], + [200, 150, 100, 50, 0, 50, 100, 150], + [150, 100, 50, 0, 50, 100, 150, 200] +], dtype=np.uint8) + +# Convert to image +plt.imshow(image_array, cmap='gray') +plt.show() \ No newline at end of file