Before going in detail with the migration process, this section will give you a breakdown of differences between V2 and The Things Stack, along with some guidelines to make the migration process easier to manage.
Architecture
The Things Stack is made up of several components, which can be run redundantly and on distributed servers to improve scalability and robustness. See Components for a complete overview of the different components of The Things Stack.
LoRaWAN support
The Things Stack brings full support for all LoRaWAN® versions, as well as modes to support class B and class C capabilities.
The Things Stack requires the LoRaWAN version (MAC) and Regional Parameters version (LoRaWAN PHY version) to be set per end device. These default to LoRaWAN version MAC V1.0.2 and LoRaWAN Regional Parameters version PHY V1.0.2 Rev B for end devices imported from V2, because this configuration is the most commonly used one.
End devices also need to be set with a frequency plan. You will have to choose the frequency plan corresponding to your region. See Frequency Plans for a list of supported Frequency Plans and their respective IDs.
RX1 Delay
The RX1 delay is the time after which the first receive window (RX1) opens. In the receive window, the Network Server can schedule a downlink. The second receive window (RX2) opens exactly 1 second after the first one opens. In LoRaWAN, the RX1 delay can be between 1 and 15 seconds.
Devices imported from V2 are configured with an RX1 delay of 1 second. In all The Things Stack deployments, the recommended RX1 delay is 5 seconds to accommodate for high latency backhauls and/or peering with Packet Broker.
See the MAC settings guide for more information and instructions about configuring the RX1 delay.
MAC Commands
The Things Stack expects that all end devices comply with the LoRaWAN specification by default, which means that the end devices should respond to Network Server MAC command requests accordingly. If a device fails to answer a MAC Command in a timely manner, there may be disruptions to the device uplink or downlink traffic. As mentioned in the LoRaWAN specification, the Network Server of The Things Stack will always prioritize MAC commands over application payloads on downlink.
In case a device is not fully compliant with the LORaWAN specification, it can still work on The Things Stack, but it may require custom MAC settings configuration.
DevStatusReq
The DevStatusReq
MAC command is sent by the Network Server periodically to check the current status of the end device. Devices are expected to send a DevStatusAns
reply.
For end devices that ignore this MAC command, make sure to configure the StatusTimePeriodicity
(time duration after which a DevStatusReq
is issued by the Network Server) and StatusCountPeriodicity
(number of frames after which a DevStatusReq
is issued) of the device explicitly to 0
.
Note:
In the scope of Migrating from The Things Network Stack V2, devices exported with thettn-lw-migrate
tool have these MAC settings set to 0
by default.
See the MAC settings guide for more information.
Gateway Coverage
Packet Broker enables peering between networks, so traffic received by one network (The Things Network V2) but intended for a different network (The Things Stack) can be forwarded to and from that network. With Packet Broker enabled on both The Things Stack and The Things Network V2, you can receive traffic on The Things Stack without having to re-configure any of your gateways.
Packet Broker is already enabled on The Things Network V2 and The Things Stack Cloud. For The Things Stack Enterprise or The Things Stack Open Source, see how to Connect to Packet Broker.
For private The Things Stack deployments with Packet Broker disabled, you will need to re-configure your gateways to connect to The Things Stack, so that you can start receiving traffic from your end devices.
In order to connect a gateway to The Things Stack, first follow instructions for Adding Gateways,then reconfigure the gateway to connect to The Things Stack, and regenerate its API key (if required). See Gateways for instructions on configuring popular LoRaWAN gateways with The Things Stack.
Application Data
The Things Stack uses a different data format for uplink and downlink traffic than V2.
For details on the data format of V2, see the documentation from The Things Network.
For details on the data format of The Things Stack, see Data Formats section. It uses a different schema, different names, and has much richer metadata support.
Payload Formats
V2 has support for payload decoders, converters, validators (for uplink) and encoders (for downlink). These can be either CayenneLPP or Javascript functions.
The Things Stack has support for an uplink payload formatter (similar to the payload decoder) and a downlink payload formatter (similar to the payload encoder). These can be set per application, and can even be overridden per end device. CayenneLPP and Javascript functions are still supported, and now payload formatters can also be fetched from the Device Repository.
Migrating the V2 payload encoder and decoder to an uplink and downlink payload formatter should be straightforward.
See Payload Formatters for more details.
Integrations
Read the full documentation dedicated to Integrations supported by The Things Stack.
MQTT Traffic
The Things Stack has a new MQTT server address, so you will need to change this address in your application accordingly. You will also need to create API keys and update your MQTT credentials.
Read more in the MQTT Server section.
Webhooks
The HTTP Integration is now called HTTP Webhooks. The payload format, downlink endpoints, paths and security settings have changed.
Read more in the HTTP Webhooks section.
Storage Integration
The Things Stack supports a Storage Integration similar to V2.
Read details in the Storage Integration section.
API Comparison
The Things Stack provides multiple APIs. See the full API documentation.
For example, a comparison between The Things Industries V2 and The Things Stack MQTT API is given below.
MQTT Connection Details
Category/Type | The Things Industries V2 | The Things Stack |
---|---|---|
MQTT Public Address | {tenant_id}.thethings.industries:1883 |
https://thethings.example.com:1883 (replace with the URL of your deployment) |
MQTT Public TLS Address | {tenant_id}.thethings.industries:8883 (with using an appropriate TLS certificate) |
https://thethings.example.com:8883 |
Username | {application_id} |
{application_id}@{tenant_id} |
Password | Application Access Key (with default rights) | Application API Key (with Write downlink application traffic and Read application traffic (uplink and downlink) rights) |
Uplink topic (subscribe) | {application_id}/devices/{device_id}/up |
v3/{application id}@{tenant id}/devices/{device id}/up |
Downlink scheduling topic (pub) | {application_id}/devices/{device_id}/downSchedule (the downlink as the first or last item in a downlink queue using schedule key value in the payload) |
Push downlink - v3/{application id}@{tenant id}/devices/{device id}/down/push , Replace downlink queue - v3/{application id}@{tenant id}/devices/{device id}/down/replace |
Uplinks
Category/Type | The Things Industries V2 | The Things Stack |
---|---|---|
Overall Uplink Format | Show example{“app_id”: “my-app-id”, “dev_id”: “my-dev-id”, “hardware_serial”: “0102030405060708”, “port”: 1, “counter”: 2, “is_retry”: false, “confirmed”: false, “payload_raw”: “AQIDBA==”, “payload_fields”: { “temperature”: 1.0, “luminosity”: 0.64 },, “metadata”: { “airtime”: 46336000, “time”: “1970-01-01T00:00:00.000000000Z”, “frequency”: 868.1, “modulation”: “LORA”, “data_rate”: “SF7BW125”, “coding_rate”: “4/5”, “gateways”: [ { “gtw_id”: “ttn-herengracht-ams”, “timestamp”: 12345, “time”: “1970-01-01T00:00:00.000000000Z”, “channel”: 2, “rssi”: -25, “snr”: 5, “rf_chain”: 0, “latitude”: 52.1234, “longitude”: 6.1234, “altitude”: 6 }, //…more if received by more gateways… ], “latitude”: 52.2345, “longitude”: 6.2345, “altitude”: 2 } } |
Show example{“end_device_ids” : { “device_id” : “my-dev-id”, “application_ids” : { “application_id” : “my-app-id” }, “dev_eui” : “0102030405060708”, “join_eui” : “0102030405060708”, “dev_addr” : “01020304” }, “correlation_ids” : [ // … ], “received_at” : “1970-01-01T00:00:00.000000000Z”, “uplink_message” : { “session_key_id” : “AXA50tHUGUucuzS/bCGMNw==”, “f_cnt” : 1, “frm_payload” : “AQIDBA==”, “decoded_payload” : { “temperature”: 1.0, “luminosity”: 0.64 }, “rx_metadata” : [ { “gateway_ids” : { “gateway_id” : “ttn-herengracht-ams”, “eui” : “9C5C8E00001A05C4” }, “time” : “1970-01-01T00:00:00.000000000Z”, “timestamp” : 12345, “rssi” : -25, “channel_rssi” : -25, “snr” : 5, “uplink_token” : “ChIKEAoEZ3R3MRIInFyOAAAaBcQQ6L3Vlgk=”, “channel_index” : 2 } ], “settings” : { “data_rate” : { “lora” : { “bandwidth” : 125000, “spreading_factor” : 7 } }, “data_rate_index” : 5, “coding_rate” : “4/5”, “frequency” : “868100000”, “timestamp” : 12345, “time” : “1970-01-01T00:00:00.000000000Z” }, “received_at” : “1970-01-01T00:00:00.000000000Z” ,“consumed_airtime”: “0.051321s”, “locations”: { “user”: { “latitude”: 37.97155556731436, “longitude”: 23.72678801175413, “altitude”: 10, “source”: “SOURCE_REGISTRY” } },} } |
Gateway fields | metadata.gateways - This object includes gateway details |
uplink_message.rx_metadata - This object includes gateway details |
metadata.gateways.timestamp - Timestamp when the gateway received the message (microseconds) |
uplink_message.rx_metadata.timestamp - Gateway concentrator timestamp when the Rx finished (microseconds) |
|
metadata.gateways.time - Time when the gateway received the message |
uplink_message.rx_metadata.time - Time when the gateway received the message |
|
metadata.gateways.channel - Channel where the gateway received the message |
As an alternative channel_index is available.uplink_message.rx_metadata.channel_index - Index of the gateway channel that received the message |
|
metadata.gateways.rssi - Signal strength of the received message |
uplink_message.rx_metadata.rssi - Signal strength of the received message |
|
metadata.gateways.snr - Signal to noise ratio of the received message |
uplink_message.rx_metadata.snr - Signal to noise ratio of the received message |
|
metadata.gateways.rf_chain - RF chain where the gateway received the message |
Not available | |
metadata.gateways.latitude - Latitude of the gateway reported in its status updates |
Not available | |
metadata.gateways.longitude - Longitude of the gateway |
Not available | |
metadata.gateways.altitude - Altitude of the gateway |
Not available | |
Not available | uplink_message.rx_metadata.channel_rssi - Received signal strength indicator of the channel (dBm) |
|
Not available | uplink_message.rx_metadata.uplink_token - Uplink token injected by gateway, Gateway Server or Network Server |
|
Uplink Metadata | metadata - This object includes metadata |
uplink_message - This object includes metadata |
metadata.airtime |
uplink_message.consumed_airtime - Formatted as a string, with a suffix for the unit used (for example, "0.051321s" is 0.051321 seconds) |
|
metadata.time - Time when the server received the message |
uplink_message.received_at - Server time when the Application Server received the message |
|
metadata.frequency - Frequency at which the message was sent |
uplink_message.settings.frequency - Frequency (Hz) |
|
metadata.modulation - Modulation that was used (LoRa or FSK) |
Not available, but as an alternative the modulation can be derived from settings.data_rate |
|
metadata.data_rate - Data rate that was used (LoRa only) |
uplink_message.settings.data_rate - Data rate of LoRa or FSK |
|
metadata.bit_rate - Bit rate that was used (FSK only) |
uplink_message.settings.data_rate.fsk.bit_rate - Bit rate that was used (FSK only) |
|
metadata.coding_rate - Coding rate that was used |
uplink_message.settings.coding_rate - LoRa coding rate |
|
metadata.latitude |
uplink_message.locations.user.latitude - Latitude of the device |
|
metadata.longitude |
uplink_message.locations.user.longitude - Longitude of the device |
|
metadata.altitude |
uplink_message.locations.user.altitude - Altitude of the device |
|
Not available | uplink_message.locations.user.source - Location source |
|
metadata.data_rate_index - Not available |
uplink_message.data_rate_index - LoRaWAN data rate index |
|
metadata.payload_raw - Base64 encoded payload: [0x01, 0x02, 0x03, 0x04] |
uplink_message.frm_payload - Frame payload (Base64) |
|
port - LoRaWAN FPort |
uplink_message.f_port - LoRaWAN FPort |
|
counter - LoRaWAN frame counter |
uplink_message.f_cnt - LoRaWAN frame counter |
|
Not available | uplink_message.session_key_id - Join Server issued identifier for the session keys used by this uplink |
|
Common fields | app_id |
end_device_ids.application_ids.application_id |
dev_id |
end_device_ids.device_id |
|
hardware_serial - In case of LoRaWAN: the DevEUI |
end_device_ids.dev_eui |
|
confirmed - true if this message was a confirmed message |
Not available | |
Not available | end_device_ids.join_eui |
|
Not available | end_device_ids.dev_addr |
|
Uplink Payload fiedls | payload_fields - Object containing the results from the payload functions (left out when empty) |
uplink_message.decoded_payload |
Correlation IDs | Not available | correlation_ids |
Downlinks
Category/Type | The Things Industries V2 | The Things Stack |
---|---|---|
Downlink message overall format | Show example{“port”: 1, “confirmed”: false, “payload_raw”: “AQIDBA==”, “schedule”: “replace”, } or use payload_fields instead { “port”: 1, “confirmed”: false, “payload_fields”: { “led”: true }, “schedule”: “replace”, // allowed values: “replace” (default), “first”, “last”} |
Show example{“downlinks”: [{ “f_port”: 15, “frm_payload”: “vu8=”, “priority”: “HIGH”, “confirmed”: true, “correlation_ids”: [“my-correlation-id”] }] } |
Individual fields comparison | port |
f_port |
confirmed |
confirmed |
|
payload_raw |
frm_payload |
|
schedule |
Replace and push topics are available as an alternative | |
Not available | priority - You can specify LOWEST , LOW , BELOW_NORMAL , NORMAL , ABOVE_NORMAL , HIGH and HIGHEST (LOWEST is a default if not specified) |
|
Not available | correlation_ids - You can add multiple custom correlation IDs, for example to reference events or identifiers of your application |
|
payload_fields |
Not available |