Problem with Class B downlink

I’ve some problem with Class B device downlink.

Point
I want to make node device like control board that connect to LoRaWAN and always waiting for downlink. When have command from others platform, LoRa Server (Chirpstack) will be send downlink to node and do what ever its command.

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 have show frame join request and join accepted already.
In Serial port show joined but after that always show EV_SCAN_TIMEOUT every 2 minutes even though I published MQTT to node 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

  • Version of LMIC: 4.1.1
  • Version of Arduino IDE: 2.0
  • Network provider: ChirpStack
  • Region: AS923
  • Board: TTGO LoRa32-OLED V1
  • Radio: SX1276

In Chirpstack
I’ve setting Class B already and setting only ping-slot periodicity to every 8 seconds, others are 0 (default).

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();
}