mcci-catena / arduino-lmic

LoraWAN-MAC-in-C library, adapted to run under the Arduino environment
https://forum.mcci.io/c/device-software/arduino-lmic/
MIT License
629 stars 207 forks source link

Problem with Class B downlink. #921

Open akapong-tkc opened 1 year ago

akapong-tkc commented 1 year ago

I've some problem with Class B device downlink.

Point: I want to make my custom board to Control Board that connect to LoRaWan and always waiting for downlink., Noted: Node device always connect with power supply so didn't have issue with power.
Actually I want my node device into Class C but this library didn't support and can't find another one compatible with SX1276 radio..

Issue that I've found is when device online and joined already
In Chirpstack always show join request and join accept In Serial port show joined but after that always show EV_SCAN_TIMEOUT every 2 minutes even though I published MQTT to device.

So anyone have a solution or have any example with Class B ?

** My node device is custom board that use ESP32 and LoRa SX1276 Environment

In Chirpstack: I've setting Class B already. as the image below image

In Firmware I've add LMIC_enableTracking(0); at setup section and LMIC_setPingable(1); after joined already and remove uplink because my device didn't need to send anything. as code show below.

#include <lmic.h>
#include <hal/hal.h>
#include <SPI.h>   
// LoRaWan
static const u1_t PROGMEM APPEUI[8]={ ******************** };
void os_getArtEui (u1_t* buf) { memcpy_P(buf, APPEUI, 8);}
static const u1_t PROGMEM DEVEUI[8]={ ******************** };
void os_getDevEui (u1_t* buf) { memcpy_P(buf, DEVEUI, 8);}
static const u1_t PROGMEM APPKEY[16] = { ******************** };
void os_getDevKey (u1_t* buf) {  memcpy_P(buf, APPKEY, 16);}
const lmic_pinmap lmic_pins = {
    .nss = 18,
    .rxtx = LMIC_UNUSED_PIN,
    .rst = 14,
    .dio = {2, 21, 4}, 
};
void printHex2(unsigned v) {
    v &= 0xff;
    if (v < 16)
        Serial.print('0');
    Serial.print(v, HEX);
}
void onEvent (ev_t ev) {
    Serial.print(os_getTime());
    Serial.print(": ");
    switch(ev) {
        case EV_SCAN_TIMEOUT:
            Serial.println(F("EV_SCAN_TIMEOUT"));
            LMIC_setPingable(1); 
            break;
        case EV_BEACON_FOUND:
            Serial.println(F("EV_BEACON_FOUND"));
            break;
        case EV_BEACON_MISSED:
            Serial.println(F("EV_BEACON_MISSED"));
            break;
        case EV_BEACON_TRACKED:
            Serial.println(F("EV_BEACON_TRACKED"));
            break;
        case EV_JOINING:
            Serial.println(F("EV_JOINING"));
            break;
        case EV_JOINED:
            Serial.println(F("EV_JOINED"));
            {
              u4_t netid = 0;
              devaddr_t devaddr = 0;
              u1_t nwkKey[16];
              u1_t artKey[16];
              LMIC_getSessionKeys(&netid, &devaddr, nwkKey, artKey);
              Serial.print("netid: ");
              Serial.println(netid, DEC);
              Serial.print("devaddr: ");
              Serial.println(devaddr, HEX);
              Serial.print("AppSKey: ");
              for (size_t i=0; i<sizeof(artKey); ++i) {
                if (i != 0)
                  Serial.print("-");
                printHex2(artKey[i]);
              }
              Serial.println("");
              Serial.print("NwkSKey: ");
              for (size_t i=0; i<sizeof(nwkKey); ++i) {
                      if (i != 0)
                              Serial.print("-");
                      printHex2(nwkKey[i]);
              }
              Serial.println();
            } 
            LMIC_setLinkCheckMode(0);        
            LMIC_setPingable(1); 
            break; 
        case EV_JOIN_FAILED:
            Serial.println(F("EV_JOIN_FAILED"));
            break;
        case EV_REJOIN_FAILED:
            Serial.println(F("EV_REJOIN_FAILED"));
            break;
        case EV_TXCOMPLETE:
            Serial.println(F("EV_TXCOMPLETE (includes waiting for RX windows)"));
            if (LMIC.txrxFlags & TXRX_ACK)
              Serial.println(F("Received ack"));
            if (LMIC.dataLen) { 
              Serial.print(F("Data Received: ")); 
              // Control Relay Code  
            } 
            break;
        case EV_LOST_TSYNC:
            Serial.println(F("EV_LOST_TSYNC")); 
            break;
        case EV_RESET:
            Serial.println(F("EV_RESET"));
            break;
        case EV_RXCOMPLETE: 
            Serial.println(F("EV_RXCOMPLETE"));
            break;
        case EV_LINK_DEAD:
            Serial.println(F("EV_LINK_DEAD"));
            break;
        case EV_LINK_ALIVE:
            Serial.println(F("EV_LINK_ALIVE"));
            break; 
        case EV_TXSTART:
            Serial.println(F("EV_TXSTART"));
            break;
        case EV_TXCANCELED:
            Serial.println(F("EV_TXCANCELED"));
            break;
        case EV_RXSTART:
            /* do not print anything -- it wrecks timing */
            break;
        case EV_JOIN_TXCOMPLETE:
            Serial.println(F("EV_JOIN_TXCOMPLETE: no JoinAccept"));
            break; 
        default:
            Serial.print(F("Unknown event: "));
            Serial.println((unsigned) ev);
            break;
    }
}
void setup() {
    Serial.begin(9600);
    Serial.println(F("Starting"));  
    os_init();
    LMIC_reset(); 
    LMIC_enableTracking(0);
    LMIC_startJoining();  
}
void loop() {
    os_runloop_once();
}
kadirozdinc commented 1 year ago

I also try to make class b example work but I could not so far. It would be better if there is an example of how we configure devices for class b operation

A-Emile commented 11 months ago

Have you found something?

terrillmoore commented 11 months ago

We don't have an example with Class B. For class C, I did a lot of work on a branch, but ran into problems and got called off onto another project. The last person who tested class B (a few years ago) reported that there were problems. Unfortunately, it's a little hard to debug. #481 has some fixes that might be relevant.

kadirozdinc commented 11 months ago

I just want ta add that If you want to test Class B operation, Gateway used should support Class B mode. Every gateway doesn't support B, it needs to have GPS on it.

If Class C works for you (if there is no energy-convervation issue), you can try another libraries.