ehong-tl / micropySX126X

Semtech SX126X LoRa driver for Micropython and CircuitPython.
MIT License
97 stars 22 forks source link

Sending a message to a specific recipient #22

Closed KievWolf closed 6 months ago

KievWolf commented 6 months ago

There is a need to create a point-to-multipoint network In which commands would be sent from one device to a specific recipient - for example, “there is one remote control, but you need to turn on different lamps by pressing buttons 1, 2, 3, etc.” Is it possible to implement this using this library? I can’t find how to send a message to a specific recipient; moreover, the device address is not written anywhere (unlike the u-lora library). Thank you

KievWolf commented 6 months ago

I tried to implement it like this in main.py

device_addresses = { 'DEV2': b'\x05\x06\x07\x08', 'DEV3: b'\x09\x0A\x0B\x0C' }

Send func

def send_message(message, dest_device): dest_address = device_addresses.get(dest_device) if dest_address: sx.send(message, destination=dest_address) print(f"Message send to device {dest_device}.") print(SX1262.getRSSI(sx)) else: print("Wrong name of device. Please try again")

message_to_send = b'Hello from DEV1' destination_device = input("Input neme of receiver (DEV2 или DEV3): ")

send_message(message_to_send, destination_device)

Next, Since the method send() does not have an attribute destination, I added it to the library sx1262.py Messages have started to be sent and the receiving party is receiving them.. BUT - when unpacking the tuple - an error appears "need more than 2 values to unpack" - I understand that this happens because 3 values are sent (message, address, error status), and the method recv() expects only two. How can I fix this in the method? Or tell me how to implement such a function without "crutches" Tnx

ehong-tl commented 6 months ago

Hi @KievWolf

Instead of modifying the library, why don't you add destination address in the packet, and do checking on the receiving side?

For example.

# Device 1
from sx1262 import SX1262
import time

DEVICE_ADDRESS = bytearray([0x10])
DESTINATION_ADDRESS = bytearray([0x11])
MESSAGE = b'Ping'

def cb(events):
    if events & SX1262.RX_DONE:
        msg, err = sx.recv()
        # Check if address is correct
        if msg[0] == DEVICE_ADDRESS[0]:
            error = SX1262.STATUS[err]
            print('Receive: {}, {}'.format(msg[1:], error))
    elif events & SX1262.TX_DONE:
        print('TX done.')

sx = SX1262(spi_bus=1, clk=10, mosi=11, miso=12, cs=3, irq=20, rst=15, gpio=2)

sx.begin(freq=923, bw=500.0, sf=12, cr=8, syncWord=0x12,
         power=-5, currentLimit=60.0, preambleLength=8,
         implicit=False, implicitLen=0xFF,
         crcOn=True, txIq=False, rxIq=False,
         tcxoVoltage=1.7, useRegulatorLDO=False, blocking=True)

sx.setBlockingCallback(False, cb)

while True:
    # Add destination address to the packet
    sx.send(DESTINATION_ADDRESS + MESSAGE)
    time.sleep(10)
# Device 2
from sx1262 import SX1262
import time

DEVICE_ADDRESS = bytearray([0x11])
DESTINATION_ADDRESS = bytearray([0x10])
MESSAGE = b'Pong'

def cb(events):
    if events & SX1262.RX_DONE:
        msg, err = sx.recv()
        # Check if address is correct
        if msg[0] == DEVICE_ADDRESS[0] and msg[1:] == b'Ping':
            error = SX1262.STATUS[err]
            print('Receive: {}, {}'.format(msg[1:], error))
            # Add destination address to the packet
            sx.send(DESTINATION_ADDRESS + MESSAGE)
    elif events & SX1262.TX_DONE:
        print('TX done.')

sx = SX1262(spi_bus=1, clk=10, mosi=11, miso=12, cs=3, irq=20, rst=15, gpio=2)

sx.begin(freq=923, bw=500.0, sf=12, cr=8, syncWord=0x12,
         power=-5, currentLimit=60.0, preambleLength=8,
         implicit=False, implicitLen=0xFF,
         crcOn=True, txIq=False, rxIq=False,
         tcxoVoltage=1.7, useRegulatorLDO=False, blocking=True)

sx.setBlockingCallback(False, cb)
KievWolf commented 6 months ago

Thank you very much!! All its works!

KievWolf commented 6 months ago

Maybe you can give me some more advice? How can I have the recipient's address selected by the operator from the list? I'm interested in one-way transmission - remote activation of the relay. There is no need for a return message. When I accept an address variable from user input, the program is executed only 2 times and ends.

ehong-tl commented 6 months ago

Each of your end devices has their own hardcoded unique address. When the operator sends a message with the targeted address, all of the end devices will do a check to see if the message is intended for them based on the address. If it is, it will execute your command, else will just ignore the message. I'm not sure if this is what you are asking for, hope it can help you.

KievWolf commented 6 months ago

Tnx!