pycom / pycom-micropython-sigfox

A fork of MicroPython with the ESP32 port customized to run on Pycom's IoT multi-network modules.
MIT License
196 stars 167 forks source link

Lorawan and ADR problem. #104

Open atoy40 opened 6 years ago

atoy40 commented 6 years ago

Hello

I'm using : (sysname='LoPy', nodename='LoPy', release='1.10.2.b1', version='v1.8.6-849-g0af003a4 on 2017-11-24', machine='LoPy with ESP32', lorawan='1.0.0')

I'm trying to use Lorawan with ADR. here is a piece of code :

lora = LoRa(mode=LoRa.LORAWAN, adr=True, public=True, tx_retries=1)
lora.power_mode(LoRa.ALWAYS_ON)
lora.callback(trigger=(LoRa.RX_PACKET_EVENT | LoRa.TX_PACKET_EVENT), handler=lora_cb)

# OTAA code not shown here

s = socket.socket(socket.AF_LORA, socket.SOCK_RAW)
s.bind(3)
# default rate to SF12
s.setsockopt(socket.SOL_LORA, socket.SO_DR, 0)
s.setsockopt(socket.SOL_LORA, socket.SO_CONFIRMED, True)

i = 0
while True:
    count = s.send(data)
    print('Sent %s bytes' % count)
    pycom.rgbled(green)
    time.sleep(0.1)
    pycom.rgbled(off)
    time.sleep(9.9 + os.urandom(1)[0]%5)
    i += 1

It seems to work "on the wire" because TX packet has ADR bit set, and RX packet (ack in my case) contains a mac command (LinkADRReq) telling the device to set DR4/SF8 (by default I've setup the socket to DR0/SF12)

The problem seems to be in the lora socket code (modlora.c), because it always ask the Semtech stack to send using the datarate defined in the socket, and it never check the current ChannelsDataRate value stored in the Semtech stack MIB after an ADR LinkADRReq is received.

Thanks for help. Anthony.

Juanma24- commented 6 years ago

Firstly, thanks for noticing this. I am having the same problem. I think you are right. In modlora.c,lora_socket_setsockoptandlora_socket_socket`set always data rate to a value selected by user in the first case and to DR_5 in the second, ignoring ADR. I think I could have solve it but I have not tested it yet. Here it is my workaround:

lora_socket_socket FUNCTION: Change -> LORAWAN_SOCKET_SET_DR(s->sock_base.u.sd, DR_5); BY ->

LoRaMacParams_t *LoRaMacParams = LoRaMacGetMacParams();
    if (lora_validate_data_rate(LoRaMacParams->ChannelsDatarate)) {
         LORAWAN_SOCKET_SET_DR(s->sock_base.u.sd, LoRaMacParams->ChannelsDatarate);
    }else{
         LORAWAN_SOCKET_SET_DR(s->sock_base.u.sd, DR_5);
    }

lora_socket_setsockopt FUNCTION: Change -> LORAWAN_SOCKET_SET_DR(s->sock_base.u.sd, *(uint8_t *)optval); By ->

LoRaMacParams_t *LoRaMacParams = LoRaMacGetMacParams();

        if (lora_validate_data_rate(LoRaMacParams->ChannelsDatarate)) {
                LORAWAN_SOCKET_SET_DR(s->sock_base.u.sd, LoRaMacParams->ChannelsDatarate);
        }else{
                LORAWAN_SOCKET_SET_DR(s->sock_base.u.sd, *(uint8_t *)optval);
        }

I repeate I have not tested it, but I think it has to be on the right way. If everything works fine, I will make a pull request.

JuanMa