Quectel BC95-G: How to update firmware

Playing around with the built-in CoAP protocol stack in the Quectel BC95-G module I found out that I need to update the firmware, because it was not possible to me to include the payload in a CoAP request, which is a rather crucial feature ūüôā

Development board

I purchased a NB-IOT Module BC95 NBIOT Development Board Small System Board NB101 at aliexpress.com for about 17 Euros. Please note that you want to purchase a development board with a BC95-G on it, because only the “-G” product can be used with more than one NB-IoT RF band.


I use a FTDI cable to connect the development board to my PC via USB. Having the appropriate FTDI drivers installed, there is an additional COM port. I use the application PuTTY to open a serial connection to this COM port at 9600 Baud.

Firmware revision

Use the AT command ATI to find out the firmware revision:



After the firmware update:


Firmware update

For updating the firmware, you need two things:

  • The Quectel Upgrade Tool QFlash (I used version 4.13)
  • The firmware update package (I used a package named BC95GJBR01A07.fwpkg)

The Quectel support pages will help you to get these things.


Unfortunately, things get a little tricky here. The reason may be this particular development board I am using. May be other development boards behave in a different way:

  • Don’t use a baud rate of 9600 (like if you want to send AT commands), but instead use a baud rate of 115200, where the boot loader is listening for your commands when booting up.
  • When the QFlash application says “RESET” at the beginning of the update progress, you need to manually reset the BC95-G module. I simply turned off the power supply of the development board by plugging off the black Ground cable and then boot up the module by plugging it in again.

The QFlash application writes a log file log.txt in subdirectory Release\NB-IoT\1 that can help you to analyse any issues.

And now – have fun with your updated firmware!

Espruino on RAK8212: Digital Twin in Bosch IoT Suite

A few weeks ago, I wrote a blog post how to connect a Espruino powered RAK8212 device with AWS IoT. In this posting, I would like to showcase how to connect a RAK8212 device to the¬†Bosch IoT Suite¬†Platform using the¬†Quectel BG96’s¬†built-in MQTT stack.

The example will be a simple data logger, periodically sending sensor values using NB-IoT connectivity.

You can find the source code and other material on the following github repository:

The RAK8212 has quite a few sensors on board:

  • Temperature
  • Humidity
  • Barometeric Pressure
  • Ambient Light
  • Accelerometer
  • Magnetometer
  • Location (GNSS)


You are already familiar with the RAK 8212 and how to program it using Espruino.


This example uses the Asset Communication package of the Bosch IoT Suite. There are quite a few things to configure before you can start, but there is an excellent tutorial that describes the steps in detail:


What you need to do (steps described in the tutorial):

  • Create a Bosch IoT Suite account
  • Subscribe to the Bosch IoT Suite Asset Communications package
  • Configure a namespace for your things (digital twins)
  • Create and configure a technical OAuth2.0 client
  • Generate a test token to access the APIs of the Bosch IoT Suite

About Vorto Information Models

The IoT Suite gives you full freedom how to model the Digital Twin of your physical devices. However, there is an open source project named “Eclipse Vorto” (https://vorto.eclipse.org) that allows you to compose an¬†Information Model¬†of your device from several so-called¬†Function Blocks. So, like with Lego Bricks, you can compose your device from other building blocks that can be shared by different devices.

Actually, to explain the full functionality behind that would go to far here …

The Information Model for the RAK8212 looks as follows:

vortolang 1.0
namespace org.klenk.connectivity.iot
version 1.0.0
displayname "RAK8212"
description "Information Model for RAK8212"

using com.bosch.iot.suite.example.octopussuiteedition.Humidity; 1.1.0
using org.eclipse.vorto.tutorial.Temperature; 1.0.0
using org.eclipse.vorto.Illuminance; 1.0.0
using com.bosch.iot.suite.example.octopussuiteedition.Magnetometer; 1.1.0
using org.eclipse.vorto.BarometricPressure; 1.0.0
using com.bosch.iot.suite.example.octopussuiteedition.Accelerometer; 1.1.0
using org.eclipse.vorto.Location; 1.0.0
infomodel RAK8212 {

	functionblocks {
		temperature as Temperature
		barometricPressure as BarometricPressure
		humidity as Humidity
		magnetometer as Magnetometer
		accelerometer as Accelerometer
		illuminance as Illuminance
		location as Location

One of the several advantages to model a device in an Information Model is that you now can generate code or other helpful things from it, like for instance the device provisioning script.

Again, this is out of scope for now, but the provisioning script generated from this Information Model is available in this repository (rak8212-device-provisioning-msg.json)

Have a look at this Youtube channel of Tim Grossmann for more inspiration about Eclipse Vorto. https://www.youtube.com/channel/UC9_Bk9247GgJ3k9O7yxctFg/featured

Device Provisioning

Again, the Bosch tutorial at https://www.bosch-iot-suite.com/tutorials/connecting-a-simple-device-to-the-bosch-iot-suite/#book-and-configure gives detailed instructions how to register your device with the Bosch IoT Suite.

But, as the RAK8212 has its own Information Model and provisioning script, use this one that is available in this repository:


  "id": "<your namespace>:rak8212",
  "hub": {
    "device": {
      "enabled": true
    "credentials": {
      "type": "hashed-password",
      "secrets": [
          "password": "<your-device-password>"
  "things": {
    "thing": {
      "attributes": {
        "thingName": "RAK8212",
        "definition": "org.klenk.connectivity.iot:RAK8212:1.0.0"
      "features": {
        "temperature": {
          "definition": [
          "properties": {
            "status": {
              "value": 0.0,
              "unit": ""

How to send telemetry data

To send telemetry data and in this way update the Digital Twin, you need to built up a Eclise Ditto message and publish it to topic telemetry.

    + JSON.stringify("telemetry"),
    '{' +
    '  "topic": "org.klenk.connectivity.iot/rak8212/things/twin/commands/modify",' +
    '  "headers": {},' +
    '  "path": "/features/temperature/properties",' +
    '  "value": {' +
    '    "status": {' +
    '      "value": ' + currentTemperature + ',' +
    '      "unit": "Degree Celsius"' +
    '    }' +
    '  }' +
     .then( ... )

Using the Quectal BG96 module’s command¬†AT+QMTPUB¬†to publish a message to a MQTT topic, this code section updates the feature “temperature” of the¬†Digital Twin.

How to subscribe to “modified” events of the Digital Twin

The built-in MQTT client of the Quectel BG96 makes it easy to subscribe to topics: You just need to use the AT+QMTSUB command to subscribe to topic command/+/+/req/#.

sendAtCommand('AT+QMTSUB=0,1,' + JSON.stringify("command/+/+/req/#") + ',1', 15000, '+QMTSUB:')
  .then( ... )

Now, whenever a message is received on this topic, the MQTT client creates an output line starting with +QMTRECV: , like the following one:

] "\r\n+QMTRECV: 0,3,\"command///req/2240e49bdde-57ad-4652-b557-70f2dcf7"
] "41c0replies/modified\",\"{\"topic\":\"org.klenk.connectivity.iot"
] "/rak8212/things/twin/events/modified\",\"headers\":{\"sec-fetch-mode\":\"cors\", 

You can see this output if you put the debug mode on. In case someone changed the device’s digital twin, we will receive a¬†Eclise Ditto¬†“modified” message like the following one:

  "topic": "org.klenk.connectivity.iot/rak8212/things/twin/events/modified",
  "headers": {
    "sec-fetch-mode": "cors",
    "referer": "https://apidocs.bosch-iot-suite.com/?urls.primaryName=Bosch%20IoT%20Things%20-%20API%20v2",
    "sec-fetch-site": "same-site",
    "accept-language": "de-DE, de;q=0.9, en-US;q=0.8, en;q=0.7",
    "correlation-id": "0e49bdde-57ad-4652-b557-70f2dcf741c0",
    "dnt": "1",
    "source": "iot-suite:service:iot-things-eu-1:50058525-a6ed-4401-9984-f678cd509323_things/full-access",
    "version": 2,
    "accept": "application/json",
    "host": "things.eu-1.bosch-iot-suite.com",
    "content-type": "application/vnd.eclipse.ditto+json",
    "accept-encoding": "gzip, deflate, br"
  "path": "/features/temperature/properties",
  "value": {
    "status": {
      "value": 21.61,
      "unit": "Degree Celsius"
  "revision": 525,
  "timestamp": "2019-09-22T10:58:49.666Z"

This one says that the feature “temperature” was modified.

In order to process this message, you just have to write a “handler” that deals with this incoming message.


As the Quectel BG96 module already has built in a MQTT stack, it is simple to communicate with the Bosch IoT Suite using this protocol. Using Espruino, one can efficiently build IoT prototypes without a big learning curve in regards to the programming of embedded devices.

However, it needs to be evaluated if MQTT in combination with this kind of verbose Eclise Ditto messages is actually a viable way for NB-IoT communication, where every transmitted byte counts to save energy and communication costs.

NB-IoT Explorer

Explore Narrowband IoT (NB-IoT) Radio Networks in a comfortable, user-friendly way.

Animated picture

In this project, two extremely powerful components come together:

The Espruino Pixl.js with its built-in JavaScript interpreter is easy to program. The (native) Espruino Web IDE lets you transfer the code to the device using Bluetooth LE, so there isn’t even a USB cable needed to connect the computer with the device. The Espruino Pixl.js device has a large LCD display with 128×64 pixels, and four buttons on each corner of the display allow highly interactive applications.

The Quectel BG96 module module on the NB-IoT Shield provides multi-band support, so it can be used in many different radio networks all around the world. The NB-IoT Shield provides direct access to the serial interface of the BG96 module, so you also can try things out using a FTDI cable, which can be useful if you want to do firmware updates. The BG96 module provides a wide range of AT commands for a lot of purposes, and even provides high-level protocol implementations like HTTPS and MQTT, which can be very useful for IoT applications. Additionally, it provides geo-positioning by its embedded GNSS chip.


  • Espruino Pixl.js – Bluetooth microcontroller programmable in JavaScript with built-in LCD display and Arduino footprint.
  • Dragino Nb-IoT Shield QG96 – Arduino shield that hosts a Quectel BG96 module. This module supports multiple bands for NB-IoT. Except NB-IoT, It also support LTE Cat M1 and EGPRS.
  • A SIM card from a network provider supporting NB-IoT.
  • Micro USB cable for power supply
  • Optional: GNSS Active Patch Antenna
  • Bluetooth Low Energy Dongle for your computer, if it not already supports BLE natively.


  • Get yourself familiar how to connect the (native) Espruino Web IDE with the Espruino Pixel.js board via Bluetooth LE.
  • Play around with the code examples for the Pixl.js.
  • The 5v pin on the on the Pixl.js will be used to power the NB-IoT shield. There is a solder jumper near the LCD connector labelled “3.3 5V Vin”. Short Vin to 5v – the 5v pin will be connected to 5v (when connected via USB) or whatever the voltage provided on Vin is. Read more about shield power at https://www.espruino.com/Pixl.js#shield-power. (Using the 3.3v at the output of the power regulator does not provide enough power when the BG96 starts to transmit).
  • If you are good in soldering, you can consider to physically remove the big square socket connector at the reverse side of the NB-IoT shield, because it is in the way when the Pixl.js and NB-IoT shield are connected.
  • Connect the Pixl.js with the NB-IoT shield by its Arduino connectors.
  • Optionally: Attach the GNSS Patch Antenna.
  • Get yourself a SIM card suitable for NB-IoT and insert it into the SIM card holder of the NB-IoT shield. Note: The cut corner of the SIM card has to point in your direction when inserting it. If you don’t take attention, then there is a chance that you insert the SIM card in the wrong orientation.
  • Load the JavaScript code from https://github.com/wklenk/nb-iot-explorer into the (native) Espruino Web IDE.
  • Check for the JSON structure named connection_options and provide the appropriate settings for the NB-IoT network provider of your choice.var connection_options = { band: “B8”, apn: “iot.1nce.net”, operator: “26201” };
  • Turn on Minification in Settings -> Minification. Choose Closure (online) – Simple optimizations.
  • Send the application to the Pixl.js.
  • If you want to keep the application in the Pixel.js even after re-booting the Pixl.js, then save it to flash by typingsave();
     ____                 _
    |  __|___ ___ ___ _ _|_|___ ___
    |  __|_ -| . |  _| | | |   | . |
    |____|___|  _|_| |___|_|_|_|___|
             |_| espruino.com
     2v01 (c) 2018 G.Williams
    Compacting Flash...
    Calculating Size...
    Compressed 40000 bytes to 20601
    Running onInit()...
    Press RESET button on NB-IoT shield if onInit() was called interactively.
  • To connect to the NB-IoT network, press the RESET button on the NB-IoT shield now. This is not necessary when you boot the device. In this case, the NB-IoT shield will reset by its own. When the application detects that the BG96 module is ready for operation, it will flicker the background light of the LCD display 5 times.
  • Now it is time to wait, as it may take seconds to a few minutes now for the BG96 module to manually register at the NB-IoT radio network. The activity LED should flash in the rhythm “on-off-off-off” periodically to indicate network search.
  • Once the BG96 module is connected, the splash screen on the LCD display will disappear, and other screens will appear. Use the two buttons on the corners of the right side of the display to cycle up/down trough these screens.


The button on the left top corner can be used to toggle the backlight of the LCD display. Use the two buttons on the corners of the right side of the display to cycle up/down trough the following screens.

When taking the screenshots, a NB-IoT SIM card of provider 1nce.com was used.

Screen: Registered Network

Registered Network

Displays the name of the registered network. The “Registered Public Land Mobile Network” (RPLMN) is identified by a globally unique PLMN code, which consists of a MCC (Mobile Country Code) and MNC (Mobile Network Code). The screenshot shows MCC 262 for Germany and MNC 01 for Deutsche Telekom.

Screen: Registration Status

Registration Status

Displays the Network Registration Status and the received signal strength (RSSI). On successful connection to the radio network, the status should be Registered Home Network or Registered Roaming.

Screen: Cell Information

Cell Information

Displays the two-byte tracking area code (TAC) in hexadecimal format, the 3 1/2 byte (28 bit) E-UTRAN cell ID in hexadecimal format, the eNB ID in decimal format (E-UTRAN cell id without 8 bit sector information) and the sector of the base station antenna.

This information can be used to look up the position of the base station tower in a map, with a service like https://www.cellmapper.net:

  • Enter Provider. The input field behaves a little bit strange. If RPLMN for example is “26201”, then you may need to enter “2621”.
  • Enter Network “4G – LTE”
  • In Input Area “Tower Search”, enter eNB ID and press Return


Screen: Network Information

Cell Information

Displays network information such as the access technology selected, the selected band and the Channel ID.

Screen: IP Address

IP Address

Displays the IP address assigned to the BG96 module in the address space applicable to the PDP.

Screen: Geo Position

Geo Position

Displays the current geo position including Longitude, Latitude and Elevation, and the number of satellites received.

Screen: Date and Time

Date and Time

Displays the current date and time in UTC.

Espruino on RAK8212: Create a Digital Twin in AWS IoT

You need a fast, simple and inexpensive way to prototype your IoT use cases?

This article describes how you can achieve this using

In this example, the RAK8212 device is used as a sensor that periodically sends temperature values to its digital twin in AWS IoT Core. For communication with AWS it uses the MQTT protocol over Narrowband IoT (NB-Iot). The state of a LED on the RAK8212 can be controlled by setting it on the digital twin in AWS IoT.

Setting up the thing in AWS Iot Core

Get yourself an account on AWS, navigate to “AWS IoT” and “Create a single thing”. Describing all the steps would go too far in this article, and AWS has good online documentation. So please follow the steps given in the AWS documentation.

In the end, you should have an IoT object (=thing), identified by a name, and a certificate for this object (e.g. 133c075337.cert.pem), a public key (e.g. 133c075337.public.key) and a private key (e.g. 133c075337.private.key). You need to download these three files and activate the certificate.

In the navigation menu of the AWS console, go to “Manage -> Things” and you will see all your things. Select the thing of your choice and, in the navigation menu of the thing, go to “interact”. Note the server address displayed as “Update your Thing Shadow using this Rest API Endpoint”. We will use this as the address of the MQTT server later.

Example Address: a136ivuau4uklv-ats.iot.eu-central-1.amazonaws.com

Also notice the MQTT topics below. They all contain the name of your thing:

Example MQTT Topic: $aws/things/klenk-iot-device/shadow/update

This shows that the name of my thing is “klenk-iot-device”.

Setting up the example code for RAK8212

The example code is hosted at github:


Find the JavaScript object that holds the configuration for the NB-IoT radio network connection, e.g.

// NB1 connectivity settings for Vodafone Germany
‚Ä©var connection_options = {‚Ä©  
  band: "B20",‚Ä©  
  apn: "vgesace.nb.iot",‚Ä©  
  operator: "26202",
‚Ä©  debug: false // Print communication with BG96 module to console.

Adapt this to fit to your NB-IoT network of choice.

Find the JavaScript object that holds the configuration for the MQTT connection to AWS IoT:

var mqtt_options = {‚Ä©
  // AWS IoT‚Ä©
  server: 'a136ivuau4uklv-ats.iot.eu-central-1.amazonaws.com',
‚Ä©  port: 8883,
‚Ä©  client_id: "klenk-iot-device"

Adapt the MQTT server (same as address of API endpoint noted down above) and client_id (name of the thing).

Upload the cryptographical material to the BG96 module

There is still one step missing: As AWS IoT uses bidirectional authentication of the MQTT connection, you need to transfer the thing’s certificate, the private key and the file of trusted root CA certificates to the BG96 module.
This is described in depth in this blog post: Espruino on RAK8212: Uploading cryptographic material to Quectel BG96 https://wolfgangklenk.wordpress.com/2019/03/26/espruino-on-rak8212-uploading-cryptographic-material-to-quectel-bg96/

To code expects the files uploaded to have the following names:

  • cert.pem – The certificate of the thing
  • key.pem – The private key of the thing
  • cacert.pem – The file holding the trusted root CA certificates

Starting the example code on the RAK8212

Using the Espruino IDE, connect to the RAK8212 via Bluetooth LE, send the JavaScript code to the RAK8212 device, and execute function onInit();

 ____                 _
|  __|___ ___ ___ _ _|_|___ ___
|  __|_ -| . |  _| | | |   | . |
|____|___|  _|_| |___|_|_|_|___|
         |_| espruino.com
 1v99 (c) 2018 G.Williams
Espruino is Open Source. Our work is supported
only by sales of official boards and donations:
Entering State Setup External Hardware
External modules connected.
BME280 wiring set up.
Entering State Configure Modem
Entering State Register To Network
Entering State Open MQTT Network
Entering State Connect To Server
Entering State Get Current State
Entering State Subscribe To Delta Updates
Entering State Publish Telemetry Data
Current temperature:  27.42
Entering State Sleep
Entering State Publish Telemetry Data
Current temperature:  27.52
Entering State Sleep
Entering State Publish Telemetry Data
Current temperature:  27.78
Entering State Sleep

The code is using a Finite State Machine, that transitions from state to state and can easily be extended (take care of memory limitations!). In case of a failure, the BG96 module is shut down, and the state machine is restarted.

The Digital Twin representation at AWS IoT

In the AWS IoT console’s navigation menu, go to “Manage -> Things” and you will see all your things. Select the thing of your choice and in the navigation menu of the thing, go to “shadow”.

Example Shadow State:

‚Ä©  "desired": {
‚Ä©    "led": "on"‚Ä©
‚Ä©  "reported": {‚Ä©
    "temperature": "27.57",
‚Ä©    "led": "on"‚Ä©

The code on the RAK8212 device will periodically update the temperature value every 60 seconds, and will also report the current state of the (blue) LED on the RAK8212.

Switching on/off the LED using the Digital Twin

You can switch on/off the (blue) LED on the RAK8212 by changing the LED’s desired state in the Digital Twin representation.

On the AWS IoT console, the is a page called “MQTT Client” that can be used to subscribe to or to publish to a arbitrary MQTT topic.

For switching the LED on and off, we need to public the desired state to the topic $aws/things/klenk-iot-device/shadow/update

Send a JSON object like this:

  "state" : {
‚Ä©    "desired" : {‚Ä©
      "led" : "off"‚Ä©
‚Ä©  }‚Ä©

The RAK8212 should output a line like these on the console and switch on/off the (blue) LED accordingly

+QMTRECV reports message on topic:
 ‚Ä©  "$aws/things/klenk-iot-device/shadow/update/delta"
 ‚Ä©  with payload:
 ‚Ä©  {"version":6981,"timestamp":1554561624,‚Ä©
‚Ä©  "metadata":{"led":{"timestamp":1554561624}}}"


Espruino on RAK8212: Uploading cryptographic material to Quectel BG96

Some IoT platforms like AWS IoT require you to authenicate with X.509 client certificates when using MQTT as communication protocol for your devices.

The Quectel BG96 module on the RAK8212 already has an embedded MQTT stack, so there is no need for using a MQTT library on the device’s MCU.

The BG96 module supports client and server side authentication using X.509 certificates. The following files must be provided:

  • The MQTT client’s client certificate (e.g. 3a34634a38-certificate.pem.crt on AWS IoT)
  • The private key of the client (e.g. 3a34634a38-private.pem.key)
  • The trusted root CA certificates

The challenge is: How can these files be transfered to the BG96 module’s file system?

Having Espruino installed on the RAK8212, this is not a complicated task. Check my github account at


for the JavaScript file upload-ssl-certs-to-bg96.js

All three files have to be provided in PEM format. As this format is in ASCII, you can just cut and paste the contents to the JavaScript source code.

Then transfer the code to the device (using the Espruino IDE) and call function


The files will be saved to the device as cert.pem, key.pem and cacert.pem and can be used in a later step to configure the SSL connection options for the embedded MQTT stack.

 ____                 _
|  __|___ ___ ___ _ _|_|___ ___
|  __|_ -| . |  _| | | |   | . |
|____|___|  _|_| |___|_|_|_|___|
         |_| espruino.com
 1v99 (c) 2018 G.Williams
Espruino is Open Source. Our work is supported
only by sales of official boards and donations:
Connecting Cellular Modem ...
Cellular Modem connected.
Files in file system: +QFLST: "cacert.pem",1187
+QFLST: "cert.pem",1224
+QFLST: "key.pem",1679
+QFUPL line: +QFUPL: 1224,380d Uploaded cert.pem
+QFUPL line: +QFUPL: 345,1203 Uploaded key.pem
+QFUPL line: +QFUPL: 1187,2d19 Uploaded cacert.pem
Successfully uploaded SSL certificates to BG96 module.

Espruino on RAK8212: Accessing the NB-IoT (NB1) modem

This blog post ist about how to communicate with the NB-IoT (NB1) modem on the Quectel BG96 module, and play around with some interesting AT commands, revealing information about the NB-IoT radio network and the provider.

The Nordic nRF52832 microcontroller on the RAK8212 board only has one hardware UART, which is many cases (like this case) is used to create a serial connection with components on the BG96 module. For this reason, you should not interface with the RAK8212 board using a serial connection over the USB cable, because if you do, your serial connection will go away as soon as the nRF52’s (single) UART is switched to establish this board-internal serial communication. However, the Espruino firmware is able to emulate a serial port over Bluetooth Low Enery (BLE) by software. Either your notebook or PC is already equipped with BLE communication, our you can get yourself a small BLE dongle for the USB port.

Please check the section “Requirements” on this Espruino page for more information about BLE:

I am using the Native Espruino IDE.

You can find some initial code for modem testing here:

We will use a slightly adapted code:

/* Example how to interface the modem using the "iTracker" and "AT" module. */

var at;
console.log("Connecting Cellular Modem ...");
require("iTracker").setCellOn(true, function (usart) {
  console.log("Cellular Modem connected.");
  at = require("AT").connect(usart);


function sendAtCommand(command) {
  var data = "";
  at.cmd(command + "\r\n", 1000, function cb(d) {
    if (d === undefined || d == "ERROR") {
      console.log("Error:", d);
    } else if (d == "OK") {
    else {
      data += (data ? "\n" : "") + d;
      return cb;

In the Espruino IDE, just connect to your RAK8212 module via Bluetooth LE, copy and paste this code to the right side of the IDE, and press the “Send to Espruino” button to transfer this JavaScript code to the RAM of the module.

What does this code do?

  • It internally “wires up” the nRF52’s UART with the UART of the BG96 module. For this, it uses a method of an Espruino module named “iTracker”.
  • It loads a utility module named “AT” that deals with non-blocking sending and receiving AT commands to modem-like devices over a serial line and tells this module which serial interface to use (“Serial1” on RAK8212).
  • It sends the “AT+GMR” command using the AT module and asynchronously collects the answer from the modem.

When uploading, the code will start to execute immediately and output something like

 ____                 _
|  __|___ ___ ___ _ _|_|___ ___
|  __|_ -| . |  _| | | |   | . |
|____|___|  _|_| |___|_|_|_|___|
         |_| espruino.com
1v99 (c) 2018 G.Williams
Espruino is Open Source. Our work is supported
only by sales of official boards and donations:
>Connecting Cellular Modem ...
Cellular Modem connected.

The AT command sent via the nRF52’s UART to the modem was “AT+GMR”.
The firmware version returned was BG96MAR02A05M1G.

A full list of AT commands of the Quectel BG96 module is publicly available. Just search for it on Quectel’s website.

One of the key advantages of Espruino is that we can use the JavaScript interpreter on the device interactively, so now let’s play around and try out some other AT commands:

Let’s use the JavaScript function sendAtCommand() to send some further AT commands:

Display Product Identification Information

Revision: BG96MAR02A05M1G



Creating a NB-IoT (NB1) connection

If you have a SIM card that allows to create NB-IoT (NB1) connections, the following sequence of AT commands can be used to check if you actually can use NB1 communication:

This example should work in Germany for Vodafone (values for 1NCE (Germany) in comment):

>sendAtCommand('AT+QCFG="band",0,0,80000,1'); // LTE Band 20 (1NCE: 80 for Band 8)
>sendAtCommand('AT+CGDCONT=1,"IP","vgesace.nb.iot"'); // "iot.1nce.net" for 1NCE
>sendAtCommand('AT+COPS=1,2,"26202",9'); // 26201 for 1NCE

It may take some minutes now for the modem to manually register at the network provider.
The modem LED should flash on-off-off-off periodically to indicate network search

With AT+CEREG?, you can check the current network registration status:

+CEREG: 2,5,"BB12","98","118F666",9

Status code 5 means that the modem has registered itself to the network in “roaming” modus. Check the specification of BG96 AT Commands for details about other status codes.
Two-byte tracking area code is “BB12”,
Four-byte E-UTRAN cell ID is “118F666”,
Access technology is LTE Cat NB1 (9).

Query some network information

+QNWINFO: "CAT-NB1","26202","LTE BAND 20",6290

So it acutally seems we have a NB1 connection using LTE Band 20.

Query the name of the registered network

+QSPN: "Vodafone.de","Vodafone","DATA ONLY",0,"26202"

Query signal strength


+QCSQ: "CAT-NB1",80,-85,134,-6

LTE NB-IoT: Send and receive a UDP message with Quectel BC66

Now that the firmware was updated to revision BC66NAR01A03_BETA0808 I managed to find out how to send a UDP message and receive a response message indication. The Quectel support informed that the “BC66 is not finally released” and there are a lot of hints about features being “preliminary” in the documentation. So, in the end, I had to collect information from different resources, which is currently really a pain point in my opinion.

Again, I used the terminal application “putty” on channel A at a baud rate of 115200 bps.
You have to press the on/off button to wake the module from sleeping.

A note to the NB-IoT SIM card provided by 1NCE: There is a 6-digit pin printed on the backside of the credit card sized SIM card holder. This is a little bit confusing, because I never got error messages regarding that the SIM card is locked. The 1NCE support stated:

“Wir haben Ihre SIM-Karte bereits vorab aktiviert. Eine Eingabe ihrer SIM-Pin ist in keinem Fall notwendig”

Good to know that ūüôā

Following you find a list of AT commands that I used to send and receive a UDP message. On a PC visible to the internet I started a small UDP echo server written in Python. A good example can be found here: https://pythontic.com/modules/socket/udp-client-server-example

Enable full functionality


Set default APN for PDP (only required once, is stored in NVRAM)
Provider: 1NCE


Set to automatically report network registration status, when the module is
registered on the network, a URC will be reported.


Reset the module now to make the APN settings effective

F1: 0000 0000
V0: 0000 0000 [0001]
00: 0006 000C
01: 0000 0000
U0: 0000 0001 [0000]
T0: 0000 00B4
Leaving the BROM

If the module has not registered with the network before, this process can actually take minutes. You can check with

+CEREG: 0,2

The “2” means, that the module is currently trying to attach or searching an operator to register to. “1” means registered to “home network” and “5” means the module is registered in a “roaming network”

+CEREG: 0,5

Once registered, it should only take some seconds to get an IP address from the network


This IP actually matches the IP address reported in the 1NCE customer portal at https://portal.1nce.com/portal/customer/sims


Create a UDP socket



Create a UDP socket connection to, port 20001


Send the string “0123456789”


If the UDP message manages to get to the UDP server and back (UDP messages may get lost), you should get the following “unsolicited result code” (URC), indicating that 16 bytes were received by the module.


That’s an issue and possibly a bug. I would have expected something like


Disconnect the UDP socket


Close the UDP socket


Some furtherAT commands of interest:

Query the available mobile network operators

+COPS: 0,2,"26201",9
           |       +-- NB-IoT 
           +---------- Operator is MCC=262/MNC=01 --> T-Mobile/Telekom


Query current network status

+QENG: 0,3740,0,156,"1D6E105",-78,-4,-74,15,8,"D325",0,
                    |                       | +-- Tracking Area Code (?)
                    |                       +---- Serving cell band
                    +---------------------------- Serving cell (hex) 


  • This module currently seems to be immature. The documentation is a mess, and it isn’t even possible to send and receive a UDP message in a communication round trip.
  • T-Mobile’s IoT Network is available, even though I don’t live in an area of high population density.
  • Would be interesting if someone is able to locate this network cell “1D6E105”. I couldn’t find it.
  • With Quectel OpenCPU, it is possible to write a small application and flash it directly into the module. So there is no longer the need to have a separate MCU. This seems very innovative for me. I will probably try out if I can write such a custom application that reads an external sensor and periodically sends the sensor values via NB-IoT.
  • Please leave me a comment if you like to give feedback or share insight.

LTE NB-IoT: First steps with Quectel BC66

Narrowband IoT (NB-IoT) is a Low Power Wide Area Network (LPWAN) radio technology.
NB-IoT focuses specifically on indoor coverage (deep penetration), low cost, long battery life, and high connection density. NB-IoT uses a subset of the LTE standard, but limits the bandwidth to a single narrow-band of 200kHz.

With the Quectel BC66, I decided to try out one of the radio modules that clearly focuses on NB-IoT and does not provide any other 2.5G standards. I purchased a BC66-DVK development kit at https://www.tekmodul.de/produkt/bc66-dvk/ for about ‚ā¨35. As this company is located in Germany, the development kit arrived just a few days after ordering.


From the “new” narrowband IoT carrier 1nce¬†I got two NB-IoT SIM cards for free.

As described in the BC66-TE-B User Guide, I connected the development kit via a Micro USB cable to the PC and configured the terminal application “putty” to a baud rate of 115200 bps. After pressing the on/off button, the module actually woke up from sleep:

F1: 0000 0000
V0: 0000 0000 [0001]
00: 0006 000C
01: 0000 0000
U0: 0000 0001 [0000]
T0: 0000 00B4
Leaving the BROM


+CFUN: 0


Time to get some information about the module. There is a preliminary “BC66 AT Commands Manual” (2018-04-23) that provides information on that (ask Quectel Customer Support for it).

Display Product Identification Information

Revision: BC66NAR01A01


Request Manufacturer Identification

Revision: MTK_2625


Request Manufacturer Revision

Revision: BC66NAR01A01


After having some issues with verifying the PIN code on the SIM card I contacted the Quectel support staff, and they recommended to do a firmware update, as the BC66 is still in development process and I possibly had a rather outdated firmware on my module. The support sent me a link to an update program and gave instructions.


Firmware update was successful, firmware revision is now BC66NAR01A03_BETA0808

Revision: BC66NAR01A03_BETA0808


Check the next blog posts to find out how the story goes on …