How to run a virtual LoraWAN end node(for testing)

Getting hardware to cooperate is hard. So if you want to test a LoRaWAN integration, its best to simulate an end node purely in software. In this tutorial, I will be showing you how to simulate an end node purely in software, and forward packets to the Helium network such that it appears on the console. The helium network project has developed a number of useful tools, two of which I will be using in this tutorial.

In this tutorial, I will be using the Helium Network’s Virtual Lorawan device, which integrates an end node simulator and Semtech gateway forwarder, and the gateway-rs , a forwarder that passes the messages to the Helium network servers. These 2 programs are meant to run on a single linux based gateway, but can also run on an Ubuntu machine.

Requirements

You will need an Ubuntu machine. I use a Lenovo P51 laptop running Ubuntu 20.01.

Running the virtual device

These are the steps for getting it to work:
Get the gateway-rs repo on your local machine:

git clone https://github.com/helium/gateway-rs.git

Then create a file settings.toml in the config folder. In this, put in the following overrides:

listen_addr = "127.0.0.1:1689"
region = "US915"

[log]
method = "stdio"
level = "debug"
timestamp = true

[update]
platform = "x86_64"

It will compile to run on x86 machine, and will be listening on 127.0.0.1:1689. I had to assign a different port from the default because for some reason, the default port(1690) was in use.

Now prepare the Virtual Lorawan device. Clone the repo:

git clone https://github.com/helium/virtual-lorawan-device.git

Then in the settings folder, create settings.toml. In there, put in the following overrides. You must get the dev_eui,app_eui and app_key from a registered device on the helium console:

# Optionally override host IP
[packet_forwarder.default]
host = "127.0.0.1:1689" # gateway-rs listening port


[device.one.credentials]
# Must register an OTAA device on the things network to get app_eui, dev_eui and app_key
dev_eui = "AABBCCDDEEFF11"   # replace with values from helium console
app_eui = "AABBCCDDEEFF11"   # replace with values from helium console
app_key = "29836423874632847632487632ABCD12"  # replace with values from helium console

Now its time to build and run both gateway-rs and the virtual device.

Running gateway-rs

Now its time to build and run this server. This server will receive all packets from a Semtech gateway forwarder(listening on 127.0.0.1:1689) and pass it on to the Helium Network servers. Instructions are shown below for building with rust the server. It is derived from the original repo readme.

  1. Install rust
    shell curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
  2. Install cargo cross, cargo-make, and, if needed, cargo-deb. The cross command allows for cross compiling to hardware targets using docker images, while the cargo-make command is used to package up. If creating a deb package, cargo-deb is also needed.
   cargo install cross
   cargo install cargo-make
   cargo install cargo-deb
  1. Build server.
  cross build --target x86_64-unknown-linux-gnu --release

Then run it:

sudo  ./target/x86_64-unknown-linux-gnu/release/helium_gateway -c config server

The server should be up and running.

Running the virtual device

Go to the root of the virtual lorawan device repo, and run:

cargo run

Now you should start seeing packets appearing on your Helium network console, as well in the logs for both the virtual device and gateway-rs. Packets are sent every few seconds.

WARNING: Each packet sent will consume datacredits. Keep that in mind.

View of the Helium console while packets come in

image
A view on the console when packets come through

Output logs for reference

The output log on gateway-rs will look like this:

medad@medad-ThinkPad-P51:~/Documents/GitHub/gateway-rs$ ./target/x86_64-unknown-linux-gnu/release/helium_gateway -c config server
Oct 01 11:33:06.693 INFO starting server, key: 138fSo8HLFAMXvkuEuG51qQwKpBJTmGEub43YWi3dm9tCpACq3W, version: 1.0.0-alpha.18
Oct 01 11:33:06.693 INFO starting, module: gateway
Oct 01 11:33:06.693 INFO starting, module: dispatcher
Oct 01 11:33:06.693 INFO default router, uri: http://54.176.88.149:8080/, public_key: 1124CJ9yJaHq4D6ugyPCDnSBzQik61C1BqD9VMh1vsUmjwt16HNB, module: dispatcher
Oct 01 11:33:06.693 INFO using gateway, uri: http://35.84.173.125:8080/, public_key: 11pUovhssQdXzrfcYMTUrNNTQossgny8WqhfdbprrAVFyHcmvAN, module: dispatcher
Oct 01 11:33:06.693 INFO starting, module: updater
Oct 01 11:33:06.693 DEBG connecting to 35.84.173.125:8080 
Oct 01 11:33:06.837 DEBG connected to 35.84.173.125:8080 
Oct 01 11:33:06.837 DEBG binding client connection 
Oct 01 11:33:06.837 DEBG client connection bound 
Oct 01 11:33:06.837 DEBG send frame=Settings { flags: (0x0), enable_push: 0, initial_window_size: 2097152, max_frame_size: 16384 } 
Oct 01 11:33:06.837 DEBG Connection; peer=Client
Oct 01 11:33:06.837 DEBG send frame=WindowUpdate { stream_id: StreamId(0), size_increment: 5177345 } 
Oct 01 11:33:06.837 DEBG service.ready=true processing request 
Oct 01 11:33:06.837 DEBG send frame=Headers { stream_id: StreamId(1), flags: (0x4: END_HEADERS) } 
Oct 01 11:33:06.837 DEBG send frame=Data { stream_id: StreamId(1) } 
Oct 01 11:33:06.837 DEBG send frame=Data { stream_id: StreamId(1), flags: (0x1: END_STREAM) } 
Oct 01 11:33:06.978 DEBG received frame=Settings { flags: (0x0) } 
Oct 01 11:33:06.979 DEBG send frame=Settings { flags: (0x1: ACK) } 
Oct 01 11:33:06.987 DEBG received frame=Settings { flags: (0x1: ACK) } 
Oct 01 11:33:06.988 DEBG received settings ACK; applying Settings { flags: (0x0), enable_push: 0, initial_window_size: 2097152, max_frame_size: 16384 } 
Oct 01 11:33:06.988 DEBG received frame=WindowUpdate { stream_id: StreamId(1), size_increment: 5 } 
Oct 01 11:33:06.988 DEBG received frame=WindowUpdate { stream_id: StreamId(0), size_increment: 5 } 
Oct 01 11:33:06.988 DEBG received frame=Headers { stream_id: StreamId(1), flags: (0x4: END_HEADERS) } 
Oct 01 11:33:07.082 INFO no update found, module: updater
Oct 01 11:33:07.129 DEBG received frame=Data { stream_id: StreamId(1) } 
Oct 01 11:33:07.208 DEBG received frame=Data { stream_id: StreamId(1) } 
Oct 01 11:33:07.270 DEBG received frame=Data { stream_id: StreamId(1) } 
Oct 01 11:33:07.348 DEBG received frame=Data { stream_id: StreamId(1) } 
Oct 01 11:33:07.357 INFO updated routing to height 1034613, module: dispatcher
Oct 01 11:33:07.357 INFO starting, oui: 13, uri: http://46.246.38.248:8080/, public_key: 115ZS5of9wsV3M5sH3mePp9NVnKayUXG7qT2W7Sn4KJLMzd3eMr, module: router
Oct 01 11:33:07.357 INFO starting, oui: 12, uri: http://54.219.236.122:8080/, public_key: 112ewJNEUfSg3Jvo276tMjzFC2JzmmZcJJ32CWz2fzYqbyCMMTe1, module: router
Oct 01 11:33:07.357 INFO starting, oui: 9, uri: http://13.37.13.24:8080/, public_key: 11afuQSrmk52mgxLu91AdtDXbJ9wmqWBUxC3hvjejoXkxEZfPvY, module: router
Oct 01 11:33:07.357 INFO starting, oui: 9, uri: http://44.238.156.97:8080/, public_key: 11w77YQLhgUt8HUJrMtntGGr97RyXmot1ofs5Ct2ELTmbFoYsQa, module: router
Oct 01 11:33:07.357 INFO starting, oui: 6, uri: http://185.34.141.6:8080/, public_key: 11awcuSbVURPkXX3FbKC7KF6bgEPRZqqPzv1FTEYABMLttUr13E, module: router
Oct 01 11:33:07.357 INFO starting, oui: 4, uri: http://54.193.165.228:8080/, public_key: 11263KvqW3GZPAvag5sQYtBJSjb25azSTSwoi5Tza9kboaLRxcsv, module: router
Oct 01 11:33:07.358 INFO starting, oui: 2, uri: http://54.176.88.149:8080/, public_key: 1124CJ9yJaHq4D6ugyPCDnSBzQik61C1BqD9VMh1vsUmjwt16HNB, module: router
Oct 01 11:33:07.358 INFO starting, oui: 1, uri: http://52.8.80.146:8080/, public_key: 112qB3YaH5bZkCnKA5uRH7tBtGNv2Y5B4smv1jsmvGUzgKT71QpE, module: router
Oct 01 11:36:48.287 INFO new packet forwarder client: MacAddress(01:02:03:04:05:06:08), 127.0.0.1:58198, module: gateway
Oct 01 11:36:48.287 INFO uplink @2910 us, 905.10 MHz, Ok(DataRate(SF10, BW125)), snr: 5.5, len: 23 from MacAddress(01:02:03:04:05:06:08), module: gateway
Oct 01 11:36:48.287 DEBG connecting to 52.8.80.146:8080 
Oct 01 11:36:48.432 DEBG connected to 52.8.80.146:8080 
Oct 01 11:36:48.432 DEBG binding client connection 
Oct 01 11:36:48.432 DEBG client connection bound 
Oct 01 11:36:48.432 DEBG send frame=Settings { flags: (0x0), enable_push: 0, initial_window_size: 2097152, max_frame_size: 16384 } 
Oct 01 11:36:48.432 DEBG Connection; peer=Client
Oct 01 11:36:48.432 DEBG send frame=WindowUpdate { stream_id: StreamId(0), size_increment: 5177345 } 
Oct 01 11:36:48.432 DEBG service.ready=true processing request 
Oct 01 11:36:48.432 DEBG send frame=Headers { stream_id: StreamId(1), flags: (0x4: END_HEADERS) } 
Oct 01 11:36:48.576 DEBG received frame=Settings { flags: (0x0) } 
Oct 01 11:36:48.576 DEBG send frame=Settings { flags: (0x1: ACK) } 
Oct 01 11:36:48.580 DEBG received frame=Settings { flags: (0x1: ACK) } 
Oct 01 11:36:48.580 DEBG received settings ACK; applying Settings { flags: (0x0), enable_push: 0, initial_window_size: 2097152, max_frame_size: 16384 } 
Oct 01 11:36:48.598 DEBG received frame=Headers { stream_id: StreamId(1), flags: (0x4: END_HEADERS) } 
Oct 01 11:36:48.599 DEBG send frame=Data { stream_id: StreamId(1) } 
Oct 01 11:36:48.741 DEBG received frame=Data { stream_id: StreamId(1) } 
Oct 01 11:36:48.745 DEBG received frame=Data { stream_id: StreamId(1) } 
Oct 01 11:36:48.867 DEBG received frame=Data { stream_id: StreamId(1) } 
Oct 01 11:36:48.888 DEBG received frame=Data { stream_id: StreamId(1) } 
Oct 01 11:36:48.889 DEBG received frame=Data { stream_id: StreamId(1) } 
Oct 01 11:36:48.889 DEBG received frame=Data { stream_id: StreamId(1) } 
Oct 01 11:36:48.889 DEBG received frame=WindowUpdate { stream_id: StreamId(1), size_increment: 191 } 
Oct 01 11:36:48.889 DEBG received frame=WindowUpdate { stream_id: StreamId(0), size_increment: 191 } 
Oct 01 11:36:48.890 DEBG service.ready=true processing request 
Oct 01 11:36:48.890 DEBG send frame=Headers { stream_id: StreamId(3), flags: (0x4: END_HEADERS) } 
Oct 01 11:36:48.890 DEBG send frame=Data { stream_id: StreamId(3) } 
Oct 01 11:36:48.890 DEBG send frame=Data { stream_id: StreamId(3), flags: (0x1: END_STREAM) } 
Oct 01 11:36:49.040 DEBG received frame=WindowUpdate { stream_id: StreamId(3), size_increment: 74 } 
Oct 01 11:36:49.040 DEBG received frame=WindowUpdate { stream_id: StreamId(0), size_increment: 74 } 
Oct 01 11:36:49.040 DEBG received frame=Headers { stream_id: StreamId(3), flags: (0x4: END_HEADERS) } 
Oct 01 11:36:49.042 DEBG received frame=Data { stream_id: StreamId(3) } 
Oct 01 11:36:49.042 DEBG received frame=Headers { stream_id: StreamId(3), flags: (0x5: END_HEADERS | END_STREAM) } 
Oct 01 11:36:49.044 INFO received banner, sc_id: BAmQOEjHv-D1ssEHq8YpV_3319Gm-yTpm9n6DhFA53k, oui: 1, uri: http://52.8.80.146:8080/, public_key: 112qB3YaH5bZkCnKA5uRH7tBtGNv2Y5B4smv1jsmvGUzgKT71QpE, module: router
Oct 01 11:36:50.747 DEBG received frame=Data { stream_id: StreamId(1) } 
Oct 01 11:36:50.747 INFO rx1 downlink @5002910 us, 926.90 MHz, DataRate(SF10, BW500), len: 17 via MacAddress(01:02:03:04:05:06:08), module: gateway
Oct 01 11:36:53.340 INFO uplink @5055474 us, 903.90 MHz, Ok(DataRate(SF10, BW125)), snr: 5.5, len: 17 from MacAddress(01:02:03:04:05:06:08), module: gateway
Oct 01 11:36:53.340 DEBG send frame=Data { stream_id: StreamId(1) } 
Oct 01 11:36:53.485 DEBG received frame=WindowUpdate { stream_id: StreamId(1), size_increment: 171 } 
Oct 01 11:36:53.485 DEBG received frame=WindowUpdate { stream_id: StreamId(0), size_increment: 171 } 
Oct 01 11:36:53.886 DEBG received frame=Data { stream_id: StreamId(1) } 
Oct 01 11:36:53.886 INFO rx1 downlink @6055474 us, 923.30 MHz, DataRate(SF10, BW500), len: 22 via MacAddress(01:02:03:04:05:06:08), module: gateway
Oct 01 11:36:54.392 INFO uplink @6107096 us, 904.50 MHz, Ok(DataRate(SF10, BW125)), snr: 5.5, len: 21 from MacAddress(01:02:03:04:05:06:08), module: gateway
Oct 01 11:36:54.392 DEBG send frame=Data { stream_id: StreamId(1) } 
Oct 01 11:36:54.539 DEBG received frame=WindowUpdate { stream_id: StreamId(1), size_increment: 175 } 
Oct 01 11:36:54.539 DEBG received frame=WindowUpdate { stream_id: StreamId(0), size_increment: 175 } 
Oct 01 11:36:54.941 DEBG received frame=Data { stream_id: StreamId(1) } 
Oct 01 11:36:54.941 INFO rx1 downlink @7107096 us, 925.10 MHz, DataRate(SF10, BW500), len: 12 via MacAddress(01:02:03:04:05:06:08), module: gateway
Oct 01 11:36:55.444 INFO uplink @7159350 us, 904.30 MHz, Ok(DataRate(SF10, BW125)), snr: 5.5, len: 17 from MacAddress(01:02:03:04:05:06:08), module: gateway
Oct 01 11:36:55.444 DEBG send frame=Data { stream_id: StreamId(1) } 
Oct 01 11:36:55.589 DEBG received frame=WindowUpdate { stream_id: StreamId(1), size_increment: 171 } 
Oct 01 11:36:55.589 DEBG received frame=WindowUpdate { stream_id: StreamId(0), size_increment: 171 } 
Oct 01 11:36:55.990 DEBG received frame=Data { stream_id: StreamId(1) } 
Oct 01 11:36:55.991 INFO rx1 downlink @8159350 us, 924.50 MHz, DataRate(SF10, BW500), len: 12 via MacAddress(01:02:03:04:05:06:08), module: gateway
Oct 01 11:36:56.495 INFO uplink @8210922 us, 904.30 MHz, Ok(DataRate(SF10, BW125)), snr: 5.5, len: 17 from MacAddress(01:02:03:04:05:06:08), module: gateway
Oct 01 11:36:56.495 DEBG send frame=Data { stream_id: StreamId(1) } 
Oct 01 11:36:56.641 DEBG received frame=WindowUpdate { stream_id: StreamId(1), size_increment: 171 } 
Oct 01 11:36:56.641 DEBG received frame=WindowUpdate { stream_id: StreamId(0), size_increment: 171 } 
Oct 01 11:36:57.042 DEBG received frame=Data { stream_id: StreamId(1) } 
Oct 01 11:36:57.042 INFO rx1 downlink @9210922 us, 924.50 MHz, DataRate(SF10, BW500), len: 12 via MacAddress(01:02:03:04:05:06:08), module: gateway
Oct 01 11:36:57.548 INFO uplink @9263212 us, 903.90 MHz, Ok(DataRate(SF10, BW125)), snr: 5.5, len: 17 from MacAddress(01:02:03:04:05:06:08), module: gateway
Oct 01 11:36:57.548 DEBG send frame=Data { stream_id: StreamId(1) } 
Oct 01 11:36:57.693 DEBG received frame=WindowUpdate { stream_id: StreamId(1), size_increment: 171 } 
Oct 01 11:36:57.693 DEBG received frame=WindowUpdate { stream_id: StreamId(0), size_increment: 171 } 
Oct 01 11:36:58.115 DEBG received frame=Data { stream_id: StreamId(1) } 
Oct 01 11:36:58.115 INFO rx1 downlink @10263212 us, 923.30 MHz, DataRate(SF10, BW500), len: 12 via MacAddress(01:02:03:04:05:06:08), module: gateway
Oct 01 11:36:58.599 INFO uplink @10314982 us, 904.10 MHz, Ok(DataRate(SF10, BW125)), snr: 5.5, len: 17 from MacAddress(01:02:03:04:05:06:08), module: gateway
Oct 01 11:36:58.600 DEBG send frame=Data { stream_id: StreamId(1) } 
Oct 01 11:36:58.833 DEBG received frame=WindowUpdate { stream_id: StreamId(1), size_increment: 171 } 
Oct 01 11:36:58.833 DEBG received frame=WindowUpdate { stream_id: StreamId(0), size_increment: 171 } 
Oct 01 11:36:59.146 DEBG received frame=Data { stream_id: StreamId(1) } 
Oct 01 11:36:59.146 INFO rx1 downlink @11314982 us, 923.90 MHz, DataRate(SF10, BW500), len: 12 via MacAddress(01:02:03:04:05:06:08), module: gateway
Oct 01 11:36:59.651 INFO uplink @11366424 us, 905.30 MHz, Ok(DataRate(SF10, BW125)), snr: 5.5, len: 17 from MacAddress(01:02:03:04:05:06:08), module: gateway
Oct 01 11:36:59.651 DEBG send frame=Data { stream_id: StreamId(1) } 
Oct 01 11:36:59.795 DEBG received frame=WindowUpdate { stream_id: StreamId(1), size_increment: 171 } 
Oct 01 11:36:59.795 DEBG received frame=WindowUpdate { stream_id: StreamId(0), size_increment: 171 } 
Oct 01 11:37:00.198 DEBG received frame=Data { stream_id: StreamId(1) } 
Oct 01 11:37:00.198 INFO rx1 downlink @12366424 us, 927.50 MHz, DataRate(SF10, BW500), len: 12 via MacAddress(01:02:03:04:05:06:08), module: gateway
Oct 01 11:37:00.702 INFO uplink @12417995 us, 904.30 MHz, Ok(DataRate(SF10, BW125)), snr: 5.5, len: 17 from MacAddress(01:02:03:04:05:06:08), module: gateway

The debug log on the virtual device will look like this:

medad@medad-ThinkPad-P51:~/Documents/GitHub/virtual-lorawan-device$ cargo run
[2021-10-01T10:36:48Z INFO  virtual_lorawan_device::metrics] Prometheus Server listening on http://127.0.0.1:9898
[2021-10-01T10:36:48Z INFO  virtual_lorawan_device] Creating packet forwarder default connecting to 127.0.0.1:1689 from 0.0.0.0:0
[2021-10-01T10:36:53Z INFO  virtual_lorawan_device::virtual_device] one      join success, time remaining: 2539 ms, SessionKeys { NewSKey: AES128([188, 246, 65, 156, 83, 56, 179, 229, 61, 111, 89, 249, 229, 237, 163, 11]), AppsSKey: AES128([32, 37, 175, 4, 36, 53, 148, 235, 227, 193, 138, 150, 68, 41, 10, 79]), DevAddr 12010048}
[2021-10-01T10:36:53Z INFO  virtual_lorawan_device::virtual_device] one      sending packet fcnt = 0 on fport 208
[2021-10-01T10:36:54Z INFO  virtual_lorawan_device::virtual_device] one      downlink received with fcnt = 0, time remaining:  452 ms
[2021-10-01T10:36:54Z INFO  virtual_lorawan_device::virtual_device] one      sending packet fcnt = 1 on fport 146
[2021-10-01T10:36:55Z INFO  virtual_lorawan_device::virtual_device] one      downlink received with fcnt = 1, time remaining:  449 ms
[2021-10-01T10:36:55Z INFO  virtual_lorawan_device::virtual_device] one      sending packet fcnt = 2 on fport 250
[2021-10-01T10:36:56Z INFO  virtual_lorawan_device::virtual_device] one      downlink received with fcnt = 2, time remaining:  452 ms
[2021-10-01T10:36:56Z INFO  virtual_lorawan_device::virtual_device] one      sending packet fcnt = 3 on fport 12
[2021-10-01T10:36:57Z INFO  virtual_lorawan_device::virtual_device] one      downlink received with fcnt = 3, time remaining:  452 ms
[2021-10-01T10:36:57Z INFO  virtual_lorawan_device::virtual_device] one      sending packet fcnt = 4 on fport 67

Leave a Reply

Your email address will not be published. Required fields are marked *