Mengirim Data Sederhana ke Antares

Pada project ini Anda akan diarahkan untuk mengirim data sederhana dari board NB-LYNX-95 ke Antares IoT Platform menggunakan serangkaian AT Command dari modul BG95-M3.

Prasyarat

Material yang dibutuhkan mengikuti Prasyarat Umum pada laman sebelumnya. Jika Anda belum menyiapkan kebutuhan pada laman tersebut, maka Anda dapat mengunjungi laman berikut.

pagePrasyarat Umum NB-Lynx-95

Langkah Kerja

1. Setup Peralatan

Hal yang perlu Anda lakukan pertama kali adalah melakukan setup peralatan dengan cara menghubungkan board NB-LYNX-95 ke perangkat laptop/komputer Anda menggunakan kabel USB-C.

Pastikan Anda telah memasang antena pada port antena GSM sebelum menghubungkan board NB-LYNX-95 ke laptop/komputer.

Berikut adalah board NB-LYNX-95 yang sudah dihubungkan ke laptop/komputer.

2. Jalankan Aplikasi Arduino IDE

3. Menginputkan Kode Program

Untuk mengirim data ke Antares, Anda perlu menginputkan kode program di bawah pada Arduino IDE.

#include <Arduino.h>

// Configurable macros
#define APN "nb1internet"
#define APPNAME "YOUR-APP-NAME"
#define DEVNAME "YOUR-DEVICE-NAME"
#define ACCESSKEY "0000000000000000:0000000000000000"
#define PAYLOAD "{\\\"t\\\":\\\"25.5\\\",\\\"h\\\":\\\"60.35\\\"}"
#define BG96_POWER_KEY 27

const uint32_t interval = 10000; // 10 s interval to send message
uint32_t previousMillis = 0;     // will store last time message sent
uint32_t counter = 0;            // message counter

String sendCommand(String command, uint32_t timeout, char delimiter)
{
  while (Serial2.available())
    Serial2.read();

  uint32_t T = millis();
  String res = "";
  Serial.print("[SYS CMD] ");
  Serial.print(command);
  Serial.println("=========");
  Serial2.print(command);
  while ((millis() - T) < timeout)
  {
    while (Serial2.available())
    {
      res = Serial2.readStringUntil(delimiter);
      res.trim();
      if (res.length() > 0)
      {
        Serial.print("[SYS RES] ");
        Serial.println(res);
        return res;
      }
    }
  }
  return "TIMEOUT";
}

String receiveAddCommand(int32_t timeout)
{
  String res = "";
  uint32_t T = millis();
  while ((millis() - T) < timeout)
  {
    while (Serial2.available())
    {
      res = Serial2.readStringUntil('\0');
      res.trim();
      if (res.length() > 0)
      {
        Serial.print("[SYS RES] ");
        Serial.println(res);
        return res;
      }
    }
  }
  return res;
}

bool checkResponse(String response, String expected_response)
{
  if (response.indexOf(expected_response) != -1)
    return true;
  else
    return false;
}

bool bg96_L1()
{
  for (uint8_t i = 0; i < 2; i++)
  {
    if (checkResponse(sendCommand("AT\r\n", 300, '\0'), "OK"))
    {
      sendCommand("ATE0\r\n", 300, '\n');
      return true;
    }

    delay(1000);
  }
  
  pinMode(BG96_POWER_KEY, OUTPUT);
  delay(100);
  digitalWrite(BG96_POWER_KEY, HIGH);
  delay(700);
  digitalWrite(BG96_POWER_KEY, LOW);
  delay(5000);
  for (uint8_t i = 0; i < 5; i++)
  {
    if (checkResponse(sendCommand("AT\r\n", 300, '\0'), "OK"))
    {
      sendCommand("ATE0\r\n", 300, '\n');
      return true;
    }

    delay(1000);
  }
  return false;
}

bool bg96_L2()
{
  if (!checkResponse(sendCommand("AT+QCFG=\"nwscanseq\",03,1\r\n", 300, '\0'), "OK"))
    return false;
  if (!checkResponse(sendCommand("AT+QCFG=\"nwscanmode\",3,1\r\n", 300, '\0'), "OK"))
    return false;
  if (!checkResponse(sendCommand("AT+QCFG=\"iotopmode\",1,1\r\n", 300, '\0'), "OK"))
    return false;
  if (!checkResponse(sendCommand("AT+QCFG=\"band\",3,80,80,1\r\n", 300, '\0'), "OK"))
    return false;
  if (!checkResponse(sendCommand("AT+QCFG=\"servicedomain\",1,1\r\n", 300, '\0'), "OK"))
    return false;

  return true;
}

bool bg96_L3(uint8_t stage)
{
  switch (stage)
  {
  case 0:
    if (!checkResponse(sendCommand("AT+QIDEACT=1\r\n", 40000, '\n'), "OK"))
      return false;

  case 1:
    if (!checkResponse(sendCommand("AT+QICSGP=1,1,\"" + String(APN) + "\",\"\",\"\",0\r\n", 300, '\n'), "OK"))
      return false;

  default:
    if (!checkResponse(sendCommand("AT+QIACT=1\r\n", 60000, '\n'), "OK"))
      return false;
  }

  return true;
}

bool bg96_L3_check()
{
  String response = sendCommand("AT+QIACT?\r\n", 300, '\0');
  if (checkResponse(response, "OK"))
  {
    response.replace("+QIACT:","");
    int firstCommaIndex = response.indexOf(",");
    int secondCommaIndex = response.indexOf(",", firstCommaIndex+1);
    String ctx_id = response.substring(0, firstCommaIndex);
    String ctx_state = response.substring(firstCommaIndex + 1, secondCommaIndex);

    if (checkResponse(ctx_state, "0"))
      return bg96_L3(0);
    else
      return true;
  }
  else
    return bg96_L3(0);
}

void bg96_send()
{
  String httpBody = "{\"m2m:cin\": {\"con\": \"%1\"}}";
  httpBody.replace("%1", PAYLOAD);

  String response = sendCommand("AT+QIOPEN=1,0,\"TCP\",\"platform.antares.id\",8080\r\n", 300, '\n');
  Serial.println("Response : " + response);
  if (checkResponse(response, "OK"))
  {
    response = receiveAddCommand(60000);
    Serial.println("Response1 : " + response);
    if (checkResponse(response, "QIOPEN"))
    {
      response.replace("+QIOPEN: ","");
      response.trim();
      Serial.println("Response2 : " + response);
      String socketResult = response.substring(response.indexOf(",") + 1, response.length());
      Serial.println("socketResult : " + socketResult);
      if (socketResult.toInt() > 0)
      {
        sendCommand("AT+QICLOSE=0\r\n", 10000, '\n');
        return;
      }
    }
    else
    {
      sendCommand("AT+QICLOSE=0\r\n", 10000, '\n');
      return;
    }

    Serial.print("POST /~/antares-cse/antares-id/" + String(APPNAME) + "/" + String(DEVNAME) + " HTTP/1.1\r\n");
    Serial.print("Host: platform.antares.id:8080\r\n");
    Serial.print("Accept: application/json\r\n");
    Serial.print("Content-Type: application/json;ty=4\r\n");
    Serial.print("X-M2M-Origin: " + String(ACCESSKEY) + "\r\n");
    Serial.print("Content-Length: " + String(httpBody.length()) + "\r\n\r\n");
    Serial.println(httpBody);

    sendCommand("AT+QISEND=0\r\n", 300, '\0');
    Serial2.print("POST /~/antares-cse/antares-id/" + String(APPNAME) + "/" + String(DEVNAME) + " HTTP/1.1\r\n");
    Serial2.print("Host: platform.antares.id:8080\r\n");
    Serial2.print("Accept: application/json\r\n");
    Serial2.print("Content-Type: application/json;ty=4\r\n");
    Serial2.print("X-M2M-Origin: " + String(ACCESSKEY) + "\r\n");
    Serial2.print("Content-Length: " + String(httpBody.length()) + "\r\n\r\n");
    Serial2.print(httpBody);
    Serial2.write(0x1A);

    String response2 = receiveAddCommand(60000);
    Serial.print("Response2 : ");
    Serial.println(response2);
    
  }
  
  sendCommand("AT+QICLOSE=0\r\n", 10000, '\n');
}

bool nbSetup()
{
  Serial2.begin(115200);
  Serial.println("[BG96] Turning ON...");
  if (bg96_L1())
    Serial.println("Success");
  else
  {
    Serial.println("Failed");
    return false;
  }

  Serial.println("[BG96] Set NB Mode... ");
  if (bg96_L2())
    Serial.println("Success");
  else
  {
    Serial.println("Failed");
    return false;
  }

  Serial.println("[BG96] Start IP Connection...");
  bg96_L3(0);

  return true;
}

void setup()
{
  Serial.begin(115200);
  if (!nbSetup())
  {
    while (1)
      delay(1000);
  }
}

void loop()
{
  // Check interval overflow
  if (millis() - previousMillis > interval)
  {
    previousMillis = millis();

    if (bg96_L3_check())
    {
      char message[50];
      sprintf(message, "Sending frame : %d", counter);
      Serial.println(message);
      bg96_send();
      counter++;
    }
  }
}

```

Jangan lupa untuk menggganti APPNAME dengan nama aplikasi yang Anda buat di platform Antares, DEVNAME dengan nama device yang dibuat pada platform Antares, dan ACCESSKEY dengan access-key akun Anda.

Setelah menginputkan kode program, jangan lupa untuk menyimpan kode program tersebut dengan memilih File > Save As. Berikut adalah tampilan pada Arduino IDE ketika Anda sudah menginputkan kodenya.

4. Penjelasan Kode Program

Supaya board NB-LYNX-95 dapat berkomunikasi dengan platform Antares, digunakan modul BG95-M3. BG95-M3 merupakan modul komunikasi seluler yang dikembangkan oleh Quectel. Modul ini menerapkan beberapa protokol yang memungkinkan perangkat untuk terhubung ke jaringan internet menggunakan AT command. Berikut dijelaskan beberapa AT command yang digunakan pada kode program.

AT<CR><LF>

Pada kode program terdapat command "AT\r\n" yang dikirimkan sebagai starting point atau tahap inisialisasi modul SIM7000. \r merupakan carriage return , sedangkan \n merupakan line feed. Command ini dikirimkan untuk mendapatkan respons “OK”.

ATE0<CR><LF>

Pada kode program terdapat command "ATE0\r\n" yang dikirimkan setelah mendapatkan respons “OK”. Command ini digunakan untuk menonaktifkan echo mode yang menandakan bahwa inisialisasi telah berhasil.

AT+QCFG="nwscanseq”[,<scanseq>[,effect]]<CR><LF>

Pada kode program terdapat command “AT+QCFG="nwscanseq",03,1\r\n” yang dikirimkan untuk mengatur urutan pencarian RAT (Radio Access Technology). Pada command tersebut tedapat parameter “03” yang merupakan <scanseq> sebagai urutan pencarian untuk NB-IoT, sedangkan parameter “1” merupakan <effect> supaya konfigurasi segera berlaku.

Berikut parameter <scanseq> lain yang dapat digunakan

  • 00 = Otomatis (eMTC --> NB-IoT --> GSM)

  • 01 = GSM

  • 02 = eMTC

  • 03 = NB-IoT

Berikut parameter <effect> lain yang dapat digunakan

  • 0 = Konfigurasi berlaku ketika UE (user equipment) di-restart

  • 1 = Konfigurasi akan segera berlaku

AT+QCFG="nwscanmode”[,<scanmode>[,effect]]<CR><LF>

Pada kode program terdapat command “AT+QCFG="nwscanmode",3,1\r\n” yang dikirimkan untuk menentukan RAT yang boleh dicari. Parameter “3” merupakan <scanmode> untuk melakukan pencarian pada LTE saja, sedangkan parameter “1” merupakan supaya konfigurasi segera berlaku.

Berikut parameter lengkap <scanmode> yang dapat digunakan

  • 0 = Otomatis

  • 1 = GSM saja

  • 3 = LTE saja

AT+QCFG="iotopmode”[,<mode>[,effect]]<CR><LF>

Pada kode program terdapat command “AT+QCFG="iotopmode",1,1\r\n” yang dikirimkan untuk menentukan kategori jaringan yang akan dicari di bawah LTE RAT. Parameter “1” merupakan untuk mencari kategori jaringan berupa NB-IoT, sedangkan parameter “1” berikutnya merupakan <effect> supaya konfigurasi segera berlaku.

Berikut parameter lengkap <mode> yang dapat digunakan

  • 0 = eMTC

  • 1 = NB-IoT

  • 2 = eMTC dan NB-IoT

AT+QCFG="band”[,<gsmbandval>,<emtcbandval>,<nbiotbandval>[,effect]]<CR><LF>

Pada kode program terdapat command “AT+QCFG="band",3,80,80,1\r\n” yang dikirimkan untuk menentukan pita frekuensi yang diperbolehkan untuk dicari. Parameter “3” merupakan <gsmbandval> untuk mengatur frekuensi GSM di Indonesia yang berada pada 900 MHz dan 1800 MHz, parameter “80” merupakan <emtcbandval> untuk mengatur frekuensi pada LTE B8, sedangkan parameter “80” berikutnya merupakan <nbiotbandval> untuk mengatur frekuensi NB-IoT pada LTE B8, kemudian parameter “1” merupakan <effect> supaya konfigurasi segera berlaku.

AT+QCFG="servicedomain”[,<service>[,effect]]<CR><LF>

Pada kode program terdapat command “AT+QCFG="servicedomain",1,1\r\n” yang dikirimkan untuk menentukan domain service yang terdaftar. Parameter “1” merupakan <service> untuk menentukan domain service sebagai PS (Packet Swithced) saja, sedangkan parameter “1” berikutnya merupakan <effect> supaya konfigurasi segera berlaku.

Berikut parameter lengkap <service> yang dapat digunakan

  • 1 = PS (Packet Swithced ) saja

  • 2 = CS (Circuit Switched) dan PS (Packet Swithced)

AT+QIDEACT=<contextID><CR><LF>

Pada kode program terdapat command “AT+QIDEACT=1\r\n” yang dikirimkan untuk menonaktifkan PDP context, dalam hal ini diatur pada parameter <contextID> dengan nilai “1”, dan menutup semua koneksi TCP/IP.

AT+QICSGP=<contextID>[,<context_type>,<APN>,[,<username>,<password>[,<authentication>]]]<CR><LF>

Pada kode program terdapat command “AT+QICSGP=1,1,"" + String(APN) + "","","",0\r\n” untuk mengatur parameter TCP/IP context <APN>, <username>, <password>, dan <authentication>. Parameter “1” menunjukkan nilai <contextID>, sedangkan parameter “1” berikutnya menunjukkan nilai <context_type> untuk mengatur protokol yang digunakan berupa IPv4.

Pada command tersebut parameter <APN> yang diatur dengan String(APN) sesuai dengan yang sudah didefinisikan pada awal program dengan value "nb1internet". Untuk parameter lain seperti <username> dan <password> dibiarkan kosong pada command ini, sedangkan untuk parameter <authentication> diatur sebagai “0” yang menandakan tidak ada metode autentikasi yang digunakan

Berikut parameter lengkap <context_type> yang dapat digunakan

  • 1 = IPv4

  • 2 = IPv6

  • 3 = IPv4v6

Berikut parameter lengkap <authentication> yang dapat digunakan

  • 0 = Tidak ada autentikasi

  • 1 = PAP

  • 2 = CHAP

  • 3 = PAP atau CHAP

AT+QIACT=<contextID><CR><LF>

Pada kode program terdapat command “AT+QIACT=1\r\n” yang dikirimkan untuk mengaktifkan PDP context dengan nilai <contextID> adalah “1”.

AT+QIACT?<CR><LF>

Pada kode program terdapat command “AT+QIACT?\r\n” yang dikirimkan untuk menampilkan PDP context yang aktif beserta dengan IP address.

AT+QIOPEN=<contextID>,<connectID>,<service_type>,<IP_address>/<domain_name>,<remote_port><CR><LF>

Pada kode program terdapat command “AT+QIOPEN=1,0,"TCP","platform.antares.id",8080\r\n” yang dikirimkan untuk membuka socket service, dalam hal ini adalah Antares IoT Platform. Parameter “1” merupakan <contextID>, sedangkan parameter “0” merupakan <connectID>. Selanjutnya didefinisikan juga parameter “TCP” sebagai <service_type>, “platform.antares.id” sebagai <domain_name> dari Antares IoT Platform, sedangkan parameter “8080” sebagai <remote_port> dari remote server.

AT+QISEND=<connectID><CR><LF>

Pada kode program terdapat command “AT+QISEND=0\r\n” yang dikirimkan untuk mengirimkan data pada socket service yang telah diatur sebelumnya. Parameter “0” merupakan nilai dari <connectID>.

AT+QICLOSE=<connectID><CR><LF>

Pada kode program terdapat command “AT+QICLOSE=0\r\n” yang dikirimkan untuk menutup socket service yang sedang berjalan. Parameter “0” merupakan nilai dari <connectID>.

5. Upload Program ke Board NB-LYNX-7000

Pertama. Anda harus mengatur board yang digunakan dengan memilih ESP32 Dev Module pada bagian Tools > Board > esp32.

Setelah itu, Anda perlu mengatur port yang digunakan dengan membuka Tools > Port > COM(X). Nilai X menyesuaikan dengan nomor port yang digunakan oleh board NB-LYNX-7000.

Setelah Anda mempersiapkan kode program, selanjutnya Anda dapat meng-upload kode program tersebut dengan menekan tombol upload seperti ditunjukkan pada gambar di bawah.

Jika kode program sudah berhasil di-upload, Anda dapat membuka Serial Monitor dengan menekan icon seperti ditunjukkan pada gambar di bawah. Icon tersebut dapat Anda temukan pada bagian atas sebelah kanan.

Anda perlu mengatur baud rate Serial Monitor menjadi 115200 supaya output-nya dapat terbaca.

Tampilan Serial Monitor akan menjadi seperti pada gambar di bawah yang menandakan proses inisiasi modul BG95-M3.

Selanjutnya proses yang akan terjadi pada serial monitor adalah pengaturan mode menjadi NB-IoT dengan jaringan LTE. Berikut tampilan yang muncul pada serial monitor.

Setelah berhasil, proses yang bekerja adalah pengaturan konektivitas jaringan dengan memulai koneksi IP. Berikut adalah tampilan yang muncul pada serial monitor.

Setelah IP berhasil didapatkan, modul NB-LYNX-95 telah siap untuk mengirimkan data ke Antares IoT Platform. Proses pengiriman data ditandai dengan tulisan "Sending frame" yang dimulai dari frame 0. Kemudian modul tersebut akan mengakses server Antares dengan koneksi TCP untuk mengirimkan data. Berikut adalah tampilan pada serial monitor.

Pada gambar di atas, modul NB-LYNX-95 telah berhasil mengirimkan satu data pada Antares IoT Platform. Kode program dirancang untuk terus menerus mengirimkan data ke Antares IoT Platform yang ditandai dengan hitungan frame. Berikut adalah tampilan pada serial monitor ketika mengirimkan data berikutnya.

6. Periksa Data pada Antares IoT Platform

Untuk memastikan bahwa data telah terkirim dengan benar dari modul NB-LYNX-95 ke Antares IoT Platform, Anda dapat membuka URL device Anda. Gambar berikut menunjukkan tampilan pada Antares IoT Platform yang sudah menerima data dari NB-LYNX-7000.