[{"data":1,"prerenderedAt":807},["ShallowReactive",2],{"blog-\u002Fblog\u002F2025\u002F09\u002Fintegrating-lorawan-with-flowfuse-node-red":3},{"id":4,"title":5,"body":6,"description":12,"extension":797,"meta":798,"navigation":656,"path":803,"seo":804,"stem":805,"__hash__":806},"blog\u002Fblog\u002F2025\u002F09\u002Fintegrating-lorawan-with-flowfuse-node-red.md","Integrating LoRaWAN with FlowFuse",{"type":7,"value":8,"toc":784},"minimark",[9,13,16,21,24,27,40,50,53,57,60,65,68,83,92,96,99,103,140,151,155,158,205,208,332,336,347,368,374,435,440,457,466,469,519,522,530,534,537,545,687,692,712,731,734,742,746,749,764,767,780],[10,11,12],"p",{},"LoRaWAN (Long Range Wide Area Network) is a low-power wireless protocol designed for IoT devices that need to transmit small amounts of data over long distances. FlowFuse is a platform that provides a visual programming interface for connecting IoT devices and services.",[10,14,15],{},"By combining LoRaWAN with FlowFuse, you can easily collect data from remote sensors, process it, and integrate it with other systems or dashboards—all without writing complex code. In this article, we will guide you through setting up the integration and creating your first data processing flows.",[17,18,20],"h2",{"id":19},"what-is-lorawan-and-how-does-it-work?","What is LoRaWAN and How Does It Work?",[10,22,23],{},"LoRaWAN is designed for devices that need to send small amounts of data over long distances while using very little battery power. Your sensors can communicate up to 15 kilometers away and run for years on a single battery.",[10,25,26],{},"The system has three main parts:",[28,29,30,34,37],"ul",{},[31,32,33],"li",{},"End devices - Your sensors that collect and send data",[31,35,36],{},"Gateways - These receive data from your sensors and pass it along",[31,38,39],{},"Network server - Manages everything and sends your data to applications",[10,41,42,49],{},[43,44,48],"a",{"href":45,"rel":46},"https:\u002F\u002Fwww.thethingsnetwork.org\u002F",[47],"nofollow","The Things Network (TTN)"," is a free, global LoRaWAN network with thousands of gateways around the world. It's perfect for getting started with LoRaWAN projects and provides easy-to-use tools for managing your devices.",[10,51,52],{},"We'll show you how to connect TTN to FlowFuse for monitoring sensor data and building scalable industrial applications.",[17,54,56],{"id":55},"getting-started","Getting Started",[10,58,59],{},"Now that we understand the basics of LoRaWAN, let's set up the integration with FlowFuse.",[61,62,64],"h3",{"id":63},"prerequisites","Prerequisites",[10,66,67],{},"Before we begin, make sure you have the following components ready:",[69,70,71,80],"ol",{},[31,72,73,74,79],{},"Node-RED instance – Ensure you have a running Node-RED instance. The quickest way to set one up is through FlowFuse. ",[43,75,78],{"href":76,"rel":77},"https:\u002F\u002Fapp.flowfuse.com\u002Faccount\u002Fcreate",[47],"Sign up",", create your instance, and you will be able to manage, deploy, scale, and secure your flows with ease. FlowFuse also provides enterprise-ready features out of the box.",[31,81,82],{},"LoRaWAN device and gateway registered on TTN – You need a sensor or device connected to TTN and a gateway that can receive its uplinks.",[10,84,85,86,91],{},"If you do not have a LoRaWAN device, you can simulate one using available tools. For this article, I am using the ",[43,87,90],{"href":88,"rel":89},"https:\u002F\u002Fgithub.com\u002FUniCT-ARSLab\u002FLWN-Simulator",[47],"LWN-Simulator",".",[17,93,95],{"id":94},"setting-up-ttn-mqtt-connection","Setting Up TTN MQTT Connection",[10,97,98],{},"TTN provides MQTT integration that allows external applications to receive uplink messages from your devices. We'll use this to connect TTN with FlowFuse.",[61,100,102],{"id":101},"getting-ttn-connection-details","Getting TTN Connection Details",[69,104,105,113,116,119],{},[31,106,107,108,112],{},"Log into your TTN Console (",[43,109,110],{"href":110,"rel":111},"https:\u002F\u002Fconsole.thethingsnetwork.org",[47],")",[31,114,115],{},"Navigate to your application",[31,117,118],{},"Go to the Other Integrations tab and select MQTT",[31,120,121,122],{},"Note down the following connection details:\n",[28,123,124,131,134,137],{},[31,125,126,127],{},"Server Address: Depends on your cluster, for example: ",[128,129,130],"code",{},"nam1.cloud.thethings.network",[31,132,133],{},"Port: 1883 (for non-TLS) or 8883 (for TLS)",[31,135,136],{},"Username: Your application ID",[31,138,139],{},"Password: Your API key",[10,141,142,148],{},[143,144],"img",{"alt":145,"dataZoomable":146,"src":147},"Screenshot of TTN console showing MQTT integration details including server address, port, username, and API key","","\u002Fblog\u002F2025\u002F09\u002Fimages\u002Fmqtt-connection-details.png",[149,150,145],"em",{},[61,152,154],{"id":153},"configure-mqtt-node-and-receiving-uplink-messages","Configure MQTT Node and Receiving Uplink Messages",[10,156,157],{},"Uplink messages are data transmissions sent from your LoRaWAN sensors and devices to Network and then forwarded to your applications. These messages contain sensor readings, status updates, or any other data your devices collect. Let's configure FlowFuse to receive these uplink messages.",[69,159,160,163,166,193,196,199,202],{},[31,161,162],{},"Open your FlowFuse instance Editor.",[31,164,165],{},"Drag an MQTT In node from the palette onto your workspace",[31,167,168,169],{},"Double-click the node to configure it:\n",[28,170,171,174,177,180,183,186],{},[31,172,173],{},"Server: Add a new MQTT broker configuration",[31,175,176],{},"Host: Enter your TTN server address (e.g., nam1.cloud.thethings.network)",[31,178,179],{},"Port: 1883 or 8883 (if using TLS)",[31,181,182],{},"Username: Your TTN application ID",[31,184,185],{},"Password: Your TTN API key",[31,187,188,189,192],{},"Topic: ",[128,190,191],{},"v3\u002F{application-id}\u002Fdevices\u002F{device-id}\u002Fup"," (replace with your actual application and device IDs)",[31,194,195],{},"Click Done to save the configuration",[31,197,198],{},"Connect a Debug node to the output of your MQTT In node",[31,200,201],{},"Deploy the flow by clicking the Deploy button",[31,203,204],{},"Open the Debug panel to see incoming messages from your LoRaWAN device",[10,206,207],{},"The messages you receive will be in JSON format and contain various fields as following:",[209,210,211,224],"table",{},[212,213,214],"thead",{},[215,216,217,221],"tr",{},[218,219,220],"th",{},"Field",[218,222,223],{},"Description",[225,226,227,236,244,252,260,268,276,284,292,300,308,316,324],"tbody",{},[215,228,229,233],{},[230,231,232],"td",{},"end_device_ids.device_id",[230,234,235],{},"Unique identifier of the device in TTN",[215,237,238,241],{},[230,239,240],{},"end_device_ids.dev_eui",[230,242,243],{},"Globally unique hardware identifier (EUI) of the device",[215,245,246,249],{},[230,247,248],{},"end_device_ids.join_eui",[230,250,251],{},"Identifier used during device activation (JoinEUI\u002FAppEUI)",[215,253,254,257],{},[230,255,256],{},"end_device_ids.dev_addr",[230,258,259],{},"Device address assigned by the network",[215,261,262,265],{},[230,263,264],{},"received_at",[230,266,267],{},"Timestamp when TTN received the message",[215,269,270,273],{},[230,271,272],{},"uplink_message.f_port",[230,274,275],{},"LoRaWAN port number (used to separate types of payloads)",[215,277,278,281],{},[230,279,280],{},"uplink_message.f_cnt",[230,282,283],{},"Frame counter for tracking uplinks",[215,285,286,289],{},[230,287,288],{},"uplink_message.frm_payload",[230,290,291],{},"Raw payload",[215,293,294,297],{},[230,295,296],{},"uplink_message.decoded_payload",[230,298,299],{},"Decoded values (requires a payload formatter in TTN)",[215,301,302,305],{},[230,303,304],{},"uplink_message.rx_metadata",[230,306,307],{},"Metadata per gateway (includes RSSI, SNR, gateway ID, etc.)",[215,309,310,313],{},[230,311,312],{},"uplink_message.settings",[230,314,315],{},"Radio parameters (frequency, data rate, spreading factor, etc.)",[215,317,318,321],{},[230,319,320],{},"uplink_message.received_at",[230,322,323],{},"Timestamp when TTN processed the uplink",[215,325,326,329],{},[230,327,328],{},"correlation_ids",[230,330,331],{},"IDs used internally to correlate events across the TTN stack",[17,333,335],{"id":334},"processing-data","Processing Data",[10,337,338,339,342,343,346],{},"Let's add some processing to extract and format the received data. This approach uses community-contributed nodes and requires minimal coding. Install the ",[128,340,341],{},"node-red-node-base64"," and ",[128,344,345],{},"node-red-contrib-buffer-parser"," nodes.",[69,348,349,359,362,365],{},[31,350,351,352,355,356],{},"Drag a Change node and set ",[128,353,354],{},"msg.payload"," to ",[128,357,358],{},"msg.payload.uplink_message.frm_payload",[31,360,361],{},"Drag a base64 node and set the action to \"Decode\" (converts Base64 string to Buffer)",[31,363,364],{},"Drag the buffer parser node and configure elements based on your data format",[31,366,367],{},"Click the \"+\" button to add each element and fill in the following fields for each data point you want to extract:",[10,369,370],{},[371,372,373],"strong",{},"Example Configuration for Temperature\u002FHumidity Sensor:",[209,375,376,398],{},[212,377,378],{},[215,379,380,383,386,389,392,395],{},[218,381,382],{},"Element",[218,384,385],{},"Type",[218,387,388],{},"Name",[218,390,391],{},"Length",[218,393,394],{},"Offset",[218,396,397],{},"Scale",[225,399,400,420],{},[215,401,402,405,408,411,414,417],{},[230,403,404],{},"1",[230,406,407],{},"int16be",[230,409,410],{},"temperature",[230,412,413],{},"2",[230,415,416],{},"0",[230,418,419],{},"0.01",[215,421,422,424,426,429,431,433],{},[230,423,413],{},[230,425,407],{},[230,427,428],{},"humidity",[230,430,413],{},[230,432,413],{},[230,434,419],{},[10,436,437],{},[371,438,439],{},"Quick Parameter Guide:",[28,441,442,445,448,451,454],{},[31,443,444],{},"Type: How to read the bytes (int16be = 2-byte big-endian signed integer, uint8 = 1-byte unsigned integer)",[31,446,447],{},"Name: What to call it in your output (becomes msg.payload.temperature)",[31,449,450],{},"Length: Number of bytes to read (2 for int16be, 1 for uint8)",[31,452,453],{},"Offset: Where to start reading (0 = first byte, 2 = third byte, etc.)",[31,455,456],{},"Scale: Math to apply (0.01 = divide by 100, 1 = no scaling)",[69,458,460,463],{"start":459},5,[31,461,462],{},"Connect the MQTT in node to the input of change node, change node output to base64 node and base64 node output to the input of buffer parser and add the debug node at the end to see the output.",[31,464,465],{},"Deploy the flow.",[10,467,468],{},"Now you will see the object with the parsed sensor data in the debug panel. The output will show something like:",[470,471,475],"pre",{"className":472,"code":473,"language":474,"meta":146,"style":146},"language-json shiki shiki-themes github-light github-dark","{\n  \"temperature\": 21.5,\n  \"humidity\": 57.2\n}\n","json",[128,476,477,486,502,513],{"__ignoreMap":146},[478,479,482],"span",{"class":480,"line":481},"line",1,[478,483,485],{"class":484},"sVt8B","{\n",[478,487,489,493,496,499],{"class":480,"line":488},2,[478,490,492],{"class":491},"sj4cs","  \"temperature\"",[478,494,495],{"class":484},": ",[478,497,498],{"class":491},"21.5",[478,500,501],{"class":484},",\n",[478,503,505,508,510],{"class":480,"line":504},3,[478,506,507],{"class":491},"  \"humidity\"",[478,509,495],{"class":484},[478,511,512],{"class":491},"57.2\n",[478,514,516],{"class":480,"line":515},4,[478,517,518],{"class":484},"}\n",[10,520,521],{},"As you can see in the image below, TTN console shows live data with uplink message on the left side, and FlowFuse successfully reads and processes it on the right side.",[10,523,524,528],{},[143,525],{"alt":526,"dataZoomable":146,"src":527},"Image showing TTN console with live uplink messages on the left and FlowFuse debug panel with processed sensor data on the right","\u002Fblog\u002F2025\u002F09\u002Fimages\u002Flive-data-ttn-ff1.gif",[149,529,526],{},[17,531,533],{"id":532},"sending-commands-to-devices-(downlink)","Sending Commands to Devices (Downlink)",[10,535,536],{},"Downlink messages are commands sent from your application back to LoRaWAN devices through the network. These messages allow you to remotely control your devices, update their configuration, trigger specific actions, or send firmware updates. LoRaWAN devices can only receive downlink messages during their receive windows after sending an uplink, making this communication asynchronous but highly power-efficient.",[69,538,539,542],{},[31,540,541],{},"Drag the Inject node onto the canvas.",[31,543,544],{},"Drag a Function node and add JavaScript to format the downlink message with the data you want to send. Alternatively, you can use a Change node with a Base64 node for a low-code approach.",[470,546,550],{"className":547,"code":548,"language":549,"meta":146,"style":146},"language-javascript shiki shiki-themes github-light github-dark","\u002F\u002F Example: Send a command to turn on LED or change sensor interval\nconst downlinkMessage = {\n    downlinks: [{\n        f_port: 1, \u002F\u002F Port number (1-223)\n        frm_payload: Buffer.from([0x01, 0x0A]).toString('base64'), \u002F\u002F Command bytes\n        priority: \"NORMAL\"\n    }]\n};\n\nmsg.payload = JSON.stringify(downlinkMessage);\nreturn msg;\n","javascript",[128,551,552,558,573,578,591,630,639,645,651,658,678],{"__ignoreMap":146},[478,553,554],{"class":480,"line":481},[478,555,557],{"class":556},"sJ8bj","\u002F\u002F Example: Send a command to turn on LED or change sensor interval\n",[478,559,560,564,567,570],{"class":480,"line":488},[478,561,563],{"class":562},"szBVR","const",[478,565,566],{"class":491}," downlinkMessage",[478,568,569],{"class":562}," =",[478,571,572],{"class":484}," {\n",[478,574,575],{"class":480,"line":504},[478,576,577],{"class":484},"    downlinks: [{\n",[478,579,580,583,585,588],{"class":480,"line":515},[478,581,582],{"class":484},"        f_port: ",[478,584,404],{"class":491},[478,586,587],{"class":484},", ",[478,589,590],{"class":556},"\u002F\u002F Port number (1-223)\n",[478,592,593,596,600,603,606,608,611,614,617,620,624,627],{"class":480,"line":459},[478,594,595],{"class":484},"        frm_payload: Buffer.",[478,597,599],{"class":598},"sScJk","from",[478,601,602],{"class":484},"([",[478,604,605],{"class":491},"0x01",[478,607,587],{"class":484},[478,609,610],{"class":491},"0x0A",[478,612,613],{"class":484},"]).",[478,615,616],{"class":598},"toString",[478,618,619],{"class":484},"(",[478,621,623],{"class":622},"sZZnC","'base64'",[478,625,626],{"class":484},"), ",[478,628,629],{"class":556},"\u002F\u002F Command bytes\n",[478,631,633,636],{"class":480,"line":632},6,[478,634,635],{"class":484},"        priority: ",[478,637,638],{"class":622},"\"NORMAL\"\n",[478,640,642],{"class":480,"line":641},7,[478,643,644],{"class":484},"    }]\n",[478,646,648],{"class":480,"line":647},8,[478,649,650],{"class":484},"};\n",[478,652,654],{"class":480,"line":653},9,[478,655,657],{"emptyLinePlaceholder":656},true,"\n",[478,659,661,664,667,670,672,675],{"class":480,"line":660},10,[478,662,663],{"class":484},"msg.payload ",[478,665,666],{"class":562},"=",[478,668,669],{"class":491}," JSON",[478,671,91],{"class":484},[478,673,674],{"class":598},"stringify",[478,676,677],{"class":484},"(downlinkMessage);\n",[478,679,681,684],{"class":480,"line":680},11,[478,682,683],{"class":562},"return",[478,685,686],{"class":484}," msg;\n",[10,688,689],{},[371,690,691],{},"Downlink Properties Explanation:",[28,693,694,700,706],{},[31,695,696,699],{},[128,697,698],{},"f_port",": The LoRaWAN port number (1-223) used to differentiate message types",[31,701,702,705],{},[128,703,704],{},"frm_payload",": Your command data encoded as Base64 string",[31,707,708,711],{},[128,709,710],{},"priority",": Message priority (\"LOWEST\", \"LOW\", \"BELOW_NORMAL\", \"NORMAL\", \"ABOVE_NORMAL\", \"HIGH\", \"HIGHEST\")",[69,713,714,717,720,726,729],{"start":504},[31,715,716],{},"Add an MQTT Out node to your workspace",[31,718,719],{},"Configure it with the same TTN broker settings as your MQTT In node",[31,721,722,723,192],{},"Set the topic to: ",[128,724,725],{},"v3\u002F{application-id}\u002Fdevices\u002F{device-id}\u002Fdown\u002Fpush",[31,727,728],{},"Connect the Inject node to Function node and Function node to MQTT out node.",[31,730,465],{},[10,732,733],{},"In the image below, you can see FlowFuse sending and processing the downlink message, while TTN console displays the live data on the left.",[10,735,736,740],{},[143,737],{"alt":738,"dataZoomable":146,"src":739},"Image showing TTN console with live Downlink messages on the left and FlowFuse debug panel with processed sensor data on the right","\u002Fblog\u002F2025\u002F09\u002Fimages\u002Flive-data-ttn-downlink.gif",[149,741,738],{},[17,743,745],{"id":744},"next-steps","Next Steps",[10,747,748],{},"Next, you can store this data in a database. With FlowFuse, a managed PostgreSQL database is already provided—so you do not need to install or configure one manually. FlowFuse also offers a Query node that is automatically configured for your instance. Inside the Query node, you can use FlowFuse Expert, which allows you to write natural language prompts instead of SQL queries. The assistant will generate SQL automatically based on your table schema.",[10,750,751,752,757,758,763],{},"For a complete guide on storing and visualizing data, see the article on ",[43,753,756],{"href":754,"rel":755},"https:\u002F\u002Fflowfuse.com\u002Fblog\u002F2025\u002F08\u002Ftime-series-dashboard-flowfuse-postgresql\u002F",[47],"Building Historical Data Dashboards with FlowFuse Tables",". It also includes step-by-step instructions for creating dashboards using ",[43,759,762],{"href":760,"rel":761},"https:\u002F\u002Fdashboard.flowfuse.com\u002F",[47],"FlowFuse Dashboard","—a low-code way to build powerful industrial dashboards that also allows you to send downlink data to devices interactively.",[10,765,766],{},"With FlowFuse, you get a complete enterprise-grade platform built around visual programming—perfect for production-ready IoT deployments. It adds powerful capabilities like centralized management of Node-RED instances, DevOps tools, snapshots, real-time team collaboration, audit logs, RBAC, SSO, Built mqtt broker and database service and more—all designed to help you scale and manage your applications with ease.",[10,768,769,770,774,775,779],{},"If you're interested in exploring FlowFuse further for your industrial IoT applications, come visit us at our booth at upcoming TTN conferences to see live manufacturing demos. You can also ",[43,771,773],{"href":772},"\u002Fbook-demo\u002F","book a demo"," to see how FlowFuse can streamline your development and deployment workflows, or ",[43,776,778],{"href":76,"rel":777},[47],"start your free trial"," and build your first LoRaWAN-enabled dashboard today.",[781,782,783],"style",{},"html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}",{"title":146,"searchDepth":488,"depth":488,"links":785},[786,787,790,794,795,796],{"id":19,"depth":488,"text":20},{"id":55,"depth":488,"text":56,"children":788},[789],{"id":63,"depth":504,"text":64},{"id":94,"depth":488,"text":95,"children":791},[792,793],{"id":101,"depth":504,"text":102},{"id":153,"depth":504,"text":154},{"id":334,"depth":488,"text":335},{"id":532,"depth":488,"text":533},{"id":744,"depth":488,"text":745},"md",{"navTitle":5,"excerpt":799},{"type":7,"value":800},[801],[10,802,12],{},"\u002Fblog\u002F2025\u002F09\u002Fintegrating-lorawan-with-flowfuse-node-red",{"title":5,"description":12},"blog\u002F2025\u002F09\u002Fintegrating-lorawan-with-flowfuse-node-red","64WfBHOMcqaj88FR4kuO3MIYFfXRIksLT5-LMdWcGoM",1780132428327]