FlowFuse2024-03-28T00:00:00Zhttps://flowfuse.com/bloghttps://flowfuse.com/blog/2024/03/flowfuse-gallarus-strategic-partnership-to-accelerate-industry-4-adoption/FlowFuse and Gallarus Announce Strategic Partnership to Accelerate Industry 4.0 AdoptionStrategic partnership to empower businesses with low-code development for Industry 4.0 Transformation2024-03-28T00:00:00Z<p>FlowFuse, a leading provider of the low-code end-to-end development platform for industrial applications, and Gallarus Industry Solutions Limited, the leading industry 4.0 integrator in Europe dedicated to digital transformation through the deployment of the Unified Namespace (UNS) digital architecture, today announced an exciting strategic partnership. This collaboration aims to empower businesses with advanced solutions for Industry 4.0 transformation and optimized operational efficiency.</p>
<!--more-->
<p>Powered by Node-RED, FlowFuse enables teams of all sizes to harness low-code capabilities to build robust applications with unparalleled scalability, and security. FlowFuse’s collaborative environment and scalable architecture ensure that teams can build securely and together for continuous development and operational success. Gallarus, with its extensive experience in digital transformation projects and industrial technology integration, will leverage its expertise in high-quality project implementation, support, and maintenance. Together, they offer a comprehensive solution for businesses seeking to digitally transform their operations.</p>
<p>“We are pleased to announce this strategic alliance with Gallarus,” said Zeger-Jan van de Weg, CEO at FlowFuse. “This partnership signifies a significant step forward in providing businesses with the tools they need to excel in the current digital landscape. By combining our expertise, we are confident in delivering exceptional value to our customers.”
“This partnership with FlowFuse perfectly aligns with our mission to empower businesses with transformative industry 4.0 solutions,” said Patrick Mc Carthy, COO at Gallarus Industry Solutions Limited. “FlowFuse's low-code development platform, combined with our expertise in UNS architecture and integration, will provide a powerful solution for organizations of all sizes to move away from an Industry 3.0 mentality and embrace Industry 4.0, streamlining operations to unlock new levels of efficiency not seen before.”</p>
<p>This combined expertise will address the complexities of digital transformation for businesses by:</p>
<ul>
<li>Facilitating data access, transformation, and visualization across any protocol.</li>
<li>Breakdown data silos enabling organization-wide data availability via the UNS.</li>
<li>Enable citizen developers to build extremely useful industrial applications.</li>
</ul>
<p>For more information about FlowFuse and Gallarus Industry Solutions Limited, please visit their respective websites at <a href="http://flowfuse.com/">flowfuse.com</a> and <a href="http://gis.ie/">gis.ie.</a></p>
https://flowfuse.com/blog/2024/03/dashboard-getting-started/Getting Started with Node-RED Dashboard 2.0New to Node-RED? New to Dashboard 2.0? This guide will help you get started.2024-03-27T00:00:00ZJoe Pavitt<p>With our latest release of Node-RED Dashboard 2.0, we've made some big improvements to the onboarding experience.</p>
<p>We're seeing over 2,000 people download Dashboard 2.0 per week, and are seeing a great buzz in the community of brand new Node-RED users, experienced Node-RED users that haven't explored a UI solution previously and existing users migrating from Dashboard 1.0.</p>
<p>So, with that in mind, we wanted to offer a new "Getting Started" guide that will help you get up and running with building custom user interfaces and data visualizations in Node-RED.</p>
<!--more-->
<h2 id="how-to-install-node-red-dashboard-2.0" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/dashboard-getting-started/#how-to-install-node-red-dashboard-2.0"># </a> How to Install Node-RED Dashboard 2.0</h2>
<h3 id="step-1%3A-%22manage-palette%22" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/dashboard-getting-started/#step-1%3A-%22manage-palette%22"># </a> Step 1: "Manage Palette"</h3>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/dashboard-getting-started-manage-palette-xMbApteq_f-1920.avif 1920w" sizes="(min-device-pixel-ratio: 1.25) 3840px, (min-resolution: 120dpi) 3840px, 1920px" /><source type="image/webp" srcset="https://flowfuse.com/img/dashboard-getting-started-manage-palette-xMbApteq_f-1920.webp 1920w" sizes="(min-device-pixel-ratio: 1.25) 3840px, (min-resolution: 120dpi) 3840px, 1920px" /><img data-zoomable="" alt="Screenshot to show where to find the "Manage Palette" option in Node-RED" loading="lazy" decoding="async" src="https://flowfuse.com/img/dashboard-getting-started-manage-palette-xMbApteq_f-1920.jpeg" width="1920" height="1102" /></picture></p>
<figcaption>Screenshot to show where to find the "Manage Palette" option in Node-RED</figcaption>
<ol>
<li>Click the Node-RED Settings (top-right)</li>
<li>Click "Manage Palette"</li>
</ol>
<h3 id="step-2%3A-search-%26-%22install%22" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/dashboard-getting-started/#step-2%3A-search-%26-%22install%22"># </a> Step 2: Search & "Install"</h3>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/dashboard-getting-started-search-install-nhnZ52tZ_L-1920.avif 1920w" sizes="(min-device-pixel-ratio: 1.25) 3840px, (min-resolution: 120dpi) 3840px, 1920px" /><source type="image/webp" srcset="https://flowfuse.com/img/dashboard-getting-started-search-install-nhnZ52tZ_L-1920.webp 1920w" sizes="(min-device-pixel-ratio: 1.25) 3840px, (min-resolution: 120dpi) 3840px, 1920px" /><img data-zoomable="" alt="Screenshot to show where to find the "Install" tab, and how to find @flowfuse/node-red-dashboard" loading="lazy" decoding="async" src="https://flowfuse.com/img/dashboard-getting-started-search-install-nhnZ52tZ_L-1920.jpeg" width="1920" height="1102" /></picture></p>
<figcaption>Screenshot to show where to find the "Install" tab, and how to find @flowfuse/node-red-dashboard</figcaption>
<ol>
<li>Switch to the "Install" tab</li>
<li>Search for <em>"@flowfuse/node-red-dashboard"</em></li>
<li>Click "Install"</li>
</ol>
<h2 id="adding-your-first-widgets" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/dashboard-getting-started/#adding-your-first-widgets"># </a> Adding your first widgets</h2>
<p>With the nodes installed, getting started is as easy as choosing a node from the Palette (the left-hand side list of nodes) in Node-RED, and dropping it onto your canvas.</p>
<p><picture><source type="image/gif" srcset="https://flowfuse.com/img/dashboard-getting-started-add-widget-95NyxoNYz7-800.gif 800w" sizes="(min-device-pixel-ratio: 1.25) 3840px, (min-resolution: 120dpi) 3840px, 1920px" /><img data-zoomable="" alt="Screen recording to show how easy it is to deploy your first Dashboard 2.0 application." loading="lazy" decoding="async" src="https://flowfuse.com/img/dashboard-getting-started-add-widget-95NyxoNYz7-800.webp" width="800" height="460" /></picture></p>
<figcaption>Screen recording to show how easy it is to deploy your first Dashboard 2.0 application.</figcaption>
<p>In this case, we drop in a <code>ui-button</code>, click "Deploy" and then can see the button running live in our user interface.</p>
<p>Notice too that Dashboard will automatically setup some underlying configurations for you (visible in the right-side menu):</p>
<ul>
<li><code>ui-base</code>: Each instance of Node-RED that uses Dashboard 2.0 must have a single <code>ui-base</code> element (we're hoping to add support for multiple in the future). This element contains all of the global settings for your Dashboard instance.</li>
<li><code>ui-page</code>: A single Dashboard (<code>ui-base</code>) can consist of multiple pages, and can be navigated to using the left-side sidebar. Each page is then responsible for displaying a collection of <code>ui-group</code> elements.</li>
<li><code>ui-group</code>: Each group contains a collection of widgets, and can be used to organize your Dashboard into logical sections.</li>
<li><code>ui-theme</code>: Each <code>ui-page</code> can be assigned a given theme. Your "Themes" provide control over the aesthetic of your Dashboard like color, padding and margins.</li>
</ul>
<h2 id="configuring-your-layout" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/dashboard-getting-started/#configuring-your-layout"># </a> Configuring your layout</h2>
<p>Dashboard 2.0 adds a dedicated sidebar to Node-RED to provide a centralized view of your pages, groups and widgets. From here you can add new pages and groups, modify existing settings, and re-order content to your liking.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/dashboard-getting-started-sidebar-s6ArRRciML-1920.avif 1920w" sizes="(min-device-pixel-ratio: 1.25) 3840px, (min-resolution: 120dpi) 3840px, 1920px" /><source type="image/webp" srcset="https://flowfuse.com/img/dashboard-getting-started-sidebar-s6ArRRciML-1920.webp 1920w" sizes="(min-device-pixel-ratio: 1.25) 3840px, (min-resolution: 120dpi) 3840px, 1920px" /><img data-zoomable="" alt="Screenshot showing the Dashboard 2.0 sidebar in the Node-RED Editor." loading="lazy" decoding="async" src="https://flowfuse.com/img/dashboard-getting-started-sidebar-s6ArRRciML-1920.jpeg" width="1920" height="1102" /></picture></p>
<figcaption>Screenshot showing the Dashboard 2.0 sidebar in the Node-RED Editor.</figcaption>
<p>When defining your layout options, we break the choice into two sections:</p>
<ul>
<li><strong>Page Layout:</strong> Controls how the <code>ui-groups</code>'s are presented on a given page in your application.</li>
<li><strong>Navigation Sidebar:</strong> Defines the left-side navigation style, defined at the <code>ui-base</code> level.</li>
</ul>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/dashboard-getting-started-layout-pROZ0TkQTa-1920.avif 1920w" sizes="(min-device-pixel-ratio: 1.25) 3840px, (min-resolution: 120dpi) 3840px, 1920px" /><source type="image/webp" srcset="https://flowfuse.com/img/dashboard-getting-started-layout-pROZ0TkQTa-1920.webp 1920w" sizes="(min-device-pixel-ratio: 1.25) 3840px, (min-resolution: 120dpi) 3840px, 1920px" /><img data-zoomable="" alt="Example of a "Grid" page layout, with "Collapsing" sidebar navigation." loading="lazy" decoding="async" src="https://flowfuse.com/img/dashboard-getting-started-layout-pROZ0TkQTa-1920.jpeg" width="1920" height="1110" /></picture></p>
<figcaption>Example of the "Grid" page layout, with "Collapsing" sidebar navigation.</figcaption>
<h3 id="page-layout" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/dashboard-getting-started/#page-layout"># </a> Page Layout</h3>
<p>Currently, we have three different options for page layout:</p>
<ul>
<li><strong>Grid:</strong> (<a href="https://dashboard.flowfuse.com/layouts/types/grid.html">docs</a>) This is the default layout for a page, and uses a 12-column grid system to layout your <code>ui-groups</code>. Widths of groups and widgets define the number of columns they will render in. So, a "width" of 6" would render to 50% of the screen. Grid layouts are entirely responsive, and will adjust to the size of the screen.</li>
<li><strong>Fixed:</strong> (<a href="https://dashboard.flowfuse.com/layouts/types/fixed.html">docs</a>) Each component will render at a <em>fixed</em> width, no matter what the screen size is. The "width" property is converted a fixed pixel value (multiples of 48px by default).</li>
<li><strong>Notebook:</strong> (<a href="https://dashboard.flowfuse.com/layouts/types/notebook.html">docs</a>) This layout will stretch to 100% width, up to a maximum width of 1024px, and will centrally align. It's particularly useful for storytelling (e.g. articles/blogs) or analysis type user interfaces (e.g. Jupyter Notebooks), where you want the user to digest content in a particular order through scrolling.</li>
</ul>
<h3 id="navigation-sidebar" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/dashboard-getting-started/#navigation-sidebar"># </a> Navigation Sidebar</h3>
<p>Dashboard 2.0 offers various options on the appearance of the navigation sidebar:</p>
<ul>
<li><strong>Collapsing:</strong> When the sidebar is opened the page content will adjust with the width of the sidebar.</li>
<li><strong>Fixed:</strong> The full sidebar will always be visible, and the page content will adjust to the width of the sidebar.</li>
<li><strong>Collapse to Icons:</strong> When minimized, users can still navigate between pages by clicking on the icons representing each page in the sidebar.</li>
<li><strong>Appear over Content:</strong> When the sidebar is opened, the page is given an overlay, and the sidebar sits on top.</li>
<li><strong>Always Hide:</strong> The sidebar will never show, and navigation between pages can instead be driven by <a href="https://dashboard.flowfuse.com/nodes/widgets/ui-control.html"><code>ui-control</code></a>.</li>
</ul>
<h3 id="define-your-layout" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/dashboard-getting-started/#define-your-layout"># </a> Define Your Layout</h3>
<p>In our example, we're going to switch to a "Notebook" layout, with a "Collapse to Icons" sidebar:</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/dashboard-getting-started-example-4OZNSC6E9z-1920.avif 1920w" sizes="(min-device-pixel-ratio: 1.25) 3840px, (min-resolution: 120dpi) 3840px, 1920px" /><source type="image/webp" srcset="https://flowfuse.com/img/dashboard-getting-started-example-4OZNSC6E9z-1920.webp 1920w" sizes="(min-device-pixel-ratio: 1.25) 3840px, (min-resolution: 120dpi) 3840px, 1920px" /><img data-zoomable="" alt="Example of the "Notebook" layout and "Collapse to icons" sidebar" loading="lazy" decoding="async" src="https://flowfuse.com/img/dashboard-getting-started-example-4OZNSC6E9z-1920.jpeg" width="1920" height="1112" /></picture></p>
<figcaption>Example of the "Notebook" layout, with "Collapse to Icons" sidebar navigation.</figcaption>
<h2 id="adding-more-widgets" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/dashboard-getting-started/#adding-more-widgets"># </a> Adding More Widgets</h2>
<p>Now, we're going to build a quick example to demonstrate how we can wire nodes together, and visualize the output from a <code>ui-slider</code> onto a <code>ui-chart</code>.</p>
<h3 id="adding-a-group" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/dashboard-getting-started/#adding-a-group"># </a> Adding a Group</h3>
<p>In the Node-RED Editor's Dashboard 2.0 sidebar, we're going to then do the following things:</p>
<ol>
<li>Edit "My Group" and rename it to "Controls"</li>
<li>Create a new "Group" in your existing page called "Data Visualization"</li>
</ol>
<p>You'll now see the two groups listed under "Page 1". "Controls" with a single <code>ui-button</code> and "Data Visualization" with no widgets.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/dashboard-getting-started-new-group-AHNnsSIu4I-1586.avif 1586w" sizes="(min-device-pixel-ratio: 1.25) 3840px, (min-resolution: 120dpi) 3840px, 1920px" /><source type="image/webp" srcset="https://flowfuse.com/img/dashboard-getting-started-new-group-AHNnsSIu4I-1586.webp 1586w" sizes="(min-device-pixel-ratio: 1.25) 3840px, (min-resolution: 120dpi) 3840px, 1920px" /><img data-zoomable="" alt="Screenshot of the modified and newly added groups" loading="lazy" decoding="async" src="https://flowfuse.com/img/dashboard-getting-started-new-group-AHNnsSIu4I-1586.jpeg" width="1586" height="972" /></picture></p>
<figcaption>Screenshot of the modified and newly added groups</figcaption>
<h3 id="connecting-new-nodes" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/dashboard-getting-started/#connecting-new-nodes"># </a> Connecting New Nodes</h3>
<p>Then, we're going to add two new widgets:</p>
<ul>
<li>UI Chart</li>
<li>UI Slider</li>
</ul>
<p>Which we can do by dropping them from the left-side Palette and onto our canvas.</p>
<p>We'll need to double-click each new node and confirm which "Group" we want to add this node to. In this case, we'll add the <code>ui-slider</code> to the "Controls" group, and the <code>ui-chart</code> to the "Data Visualization" group.</p>
<p>We're also going to connect the output from both the <code>ui-slider</code> and <code>ui-button</code> to the input of the <code>ui-chart</code>:</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/dashboard-getting-started-flow-lz1mTarEt6-1920.avif 1920w" sizes="(min-device-pixel-ratio: 1.25) 3840px, (min-resolution: 120dpi) 3840px, 1920px" /><source type="image/webp" srcset="https://flowfuse.com/img/dashboard-getting-started-flow-lz1mTarEt6-1920.webp 1920w" sizes="(min-device-pixel-ratio: 1.25) 3840px, (min-resolution: 120dpi) 3840px, 1920px" /><img data-zoomable="" alt="Screenshot of the Node-RED Editor, showing the ui-slider and ui-button connected to our ui-chart" loading="lazy" decoding="async" src="https://flowfuse.com/img/dashboard-getting-started-flow-lz1mTarEt6-1920.jpeg" width="1920" height="1101" /></picture></p>
<figcaption>Screenshot of the Node-RED Editor, showing the ui-slider and ui-button connected to our ui-chart</figcaption>
<p>Now, when we view our Dashboard, we can see the <code>ui-slider</code> output is def straight into our <code>ui-chart</code>:</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/dashboard-getting-started-final-QAE6kfCc3P-1920.avif 1920w" sizes="(min-device-pixel-ratio: 1.25) 3840px, (min-resolution: 120dpi) 3840px, 1920px" /><source type="image/webp" srcset="https://flowfuse.com/img/dashboard-getting-started-final-QAE6kfCc3P-1920.webp 1920w" sizes="(min-device-pixel-ratio: 1.25) 3840px, (min-resolution: 120dpi) 3840px, 1920px" /><img data-zoomable="" alt="Screenshot of the Dashboard with all three widgets rendered" loading="lazy" decoding="async" src="https://flowfuse.com/img/dashboard-getting-started-final-QAE6kfCc3P-1920.jpeg" width="1920" height="1112" /></picture></p>
<figcaption>Screenshot of the Dashboard with all three widgets rendered</figcaption>
<p>The final step we're going to make is to modify our <code>ui-button</code>. We're going to rename it to "Clear", and configure it's "Payload" option to send a JSON payload of <code>[]</code>, which, when sent to the <code>ui-chart</code> will clear the chart of all data.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/dashboard-getting-started-btn-config-udwduPdQw9-1920.avif 1920w" sizes="(min-device-pixel-ratio: 1.25) 3840px, (min-resolution: 120dpi) 3840px, 1920px" /><source type="image/webp" srcset="https://flowfuse.com/img/dashboard-getting-started-btn-config-udwduPdQw9-1920.webp 1920w" sizes="(min-device-pixel-ratio: 1.25) 3840px, (min-resolution: 120dpi) 3840px, 1920px" /><img data-zoomable="" alt="The ui-button configuration after setting it's payload and label" loading="lazy" decoding="async" src="https://flowfuse.com/img/dashboard-getting-started-btn-config-udwduPdQw9-1920.jpeg" width="1920" height="950" /></picture></p>
<figcaption>The ui-button configuration after setting it's payload and label</figcaption>
<p>With all of this together, we have the following functional Dashboard:</p>
<p><picture><source type="image/gif" srcset="https://flowfuse.com/img/dashboard-getting-started-final-ycsdL19nfh-800.gif 800w" sizes="(min-device-pixel-ratio: 1.25) 3840px, (min-resolution: 120dpi) 3840px, 1920px" /><img data-zoomable="" alt="Short animation showing the final functional dashboard" loading="lazy" decoding="async" src="https://flowfuse.com/img/dashboard-getting-started-final-ycsdL19nfh-800.webp" width="800" height="450" /></picture></p>
<figcaption>Short animation showing the final functional dashboard.</figcaption>
<h2 id="next-steps" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/dashboard-getting-started/#next-steps"># </a> Next Steps</h2>
<p>Whilst this is just a simple introduction of Node-RED Dashboard 2.0, we do have many other articles and documentation that can help you get started with more advanced features.</p>
<ul>
<li><a href="https://flowfuse.com/blog/dashboard/">FlowFuse Dashboard Articles</a> - Collection of examples and guides written by FlowFuse.</li>
<li><a href="https://dashboard.flowfuse.com/">Node-RED Dashboard 2.0 Documentation</a> - Detailed information for each of the nodes available in Dashboard 2.0, as well as useful guides on building custom nodes and widgets of your own.</li>
<li><a href="https://discourse.nodered.org/tag/dashboard-2">Node-RED Forums - Dashboard 2.0</a> - The Node-RED forums is a great place to ask questions, share your projects and get help from the community.</li>
<li><a href="https://flowfuse.com/ebooks/beginner-guide-to-a-professional-nodered/">Beginner Guide to a Professional Node-RED</a> - A free guide to an enterprise-ready Node-RED. Learn all about Node-RED history, securing your flows and dashboard data visualization.</li>
<li><a href="https://flowfuse.com/contact-us">FlowFuse - Book a Demo</a> - FlowFuse provides a complete platform to scale your production Node-RED applications, increase developer velocity, and enhance security in order to accelerate innovation.</li>
</ul>
<h2 id="follow-our-progress" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/dashboard-getting-started/#follow-our-progress"># </a> Follow our Progress</h2>
<p>New features and improvements are coming to Node-RED Dashboard 2.0 every week, if you're interested in what we have lined up, or want to contribute yourself, then you can track the work we have lined up on our GitHub Projects:</p>
<ul>
<li><a href="https://github.com/orgs/FlowFuse/projects/15/views/1">Dashboard 2.0 Activity Tracker</a></li>
<li><a href="https://github.com/orgs/FlowFuse/projects/15/views/4">Dashboard 2.0 Planning Board</a></li>
<li><a href="https://github.com/orgs/FlowFuse/projects/15/views/5">Dashboard 1.0 Feature Parity Tracker</a></li>
</ul>
<p>If you have any feature requests, bugs/complaints or general feedback, please do reach out, and raise issues on our relevant <a href="https://github.com/FlowFuse/node-red-dashboard">GitHub repository</a>.</p>
https://flowfuse.com/blog/2024/03/http-authentication-node-red-with-flowfuse/Securing HTTP Traffic for Node-RED with FlowFuseChoosing the right form of authentication for your Node-RED integration is important.2024-03-26T00:00:00ZGrey Dziuba<p>Citizen development empowers employees to create digital solutions. However, it requires guardrails to ensure data security, operational stability, and compliance. These guardrails are what FlowFuse provides to the Node-RED community to level up their deployments. FlowFuse offers many different security measures for authentication and authorization, which all apply to different scenarios.</p>
<p>In this post we’ll take a look at most of them, specifically for HTTP traffic. We’ll discuss the trade-offs for auditabliltiy, convenience to use as either machine or human, among other factors.</p>
<!--more-->
<h2 id="http-basic-authentication%3A-a-simple-approach" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/http-authentication-node-red-with-flowfuse/#http-basic-authentication%3A-a-simple-approach"># </a> HTTP Basic Authentication: A Simple Approach</h2>
<p>HTTP Basic Authentication is widely supported and straightforward to implement, making it a popular choice for securing APIs. It requires users to provide a username and password before accessing the Node-RED instance. While this method is easy to use, it's important to note that the username and password are shared and transmitted in plain text, making it vulnerable to interception if the connection doesn't leverage SSL/TLS. FlowFuse by default ensures SSL/TLS is deployed.</p>
<h2 id="personal-access-tokens%3A-knowing-who-accessed-the-node-red" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/http-authentication-node-red-with-flowfuse/#personal-access-tokens%3A-knowing-who-accessed-the-node-red"># </a> Personal access tokens: Knowing who accessed the Node-RED</h2>
<p>Personal access tokens (PATs) are an essential component of FlowFuse, allowing users to securely access their accounts without sharing their passwords. These tokens are generated by the user and can be used to authenticate to the SaaS product's API or other services. PATs provide a more secure alternative to traditional username/password authentication, as they can be revoked or regenerated at any time, limiting the potential impact of a compromised token.</p>
<h2 id="flowfuse-authentication%3A-seamless-integration" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/http-authentication-node-red-with-flowfuse/#flowfuse-authentication%3A-seamless-integration"># </a> FlowFuse Authentication: Seamless Integration</h2>
<p>FlowFuse authentication offers a seamless and secure way for users to access dashboards and other resources that are typically accessed through a browser. It leverages single sign-on (SSO) and SAML 2.0, reducing the management burden for organizations.</p>
<p>For users this is convenient as they can access multiple applications and resources using a single set of credentials, eliminating the need to remember and manage multiple passwords.</p>
<p>For organizations, SSO enhances security by centralizing authentication and authorization, reducing the risk of unauthorized access. By leveraging SSO and SAML 2.0, FlowFuse takes care of user management, freeing up customers from the administrative burden of managing user accounts and passwords. FlowFuse authentication adheres to industry-standard security protocols, ensuring compliance with regulatory requirements.</p>
<p>This method of authentication is however impractical for API access by other services, to programmatically transfer data between them.</p>
<h2 id="bearer-authentication%3A-a-token-based-approach" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/http-authentication-node-red-with-flowfuse/#bearer-authentication%3A-a-token-based-approach"># </a> Bearer Authentication: A Token-Based Approach</h2>
<p>Bearer Authentication offers a more secure and flexible alternative to traditional username/password authentication. Users will generate the token through the FlowFuse platform with each instance generating its own token. These tokens can be designed to have limited lifespans, reducing the risk if compromised. In the case the token then becomes compromised only the instance in which the token is generated can become subject to malicious behaviors. In the case that this does occur, simply deleting the token will elevate any unwanted access.</p>
<p>Compared to FlowFuse Authentication, this method is very well suited for API access and programmatic access to FlowFuse.</p>
<h2 id="choosing-the-right-authentication-strategy" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/http-authentication-node-red-with-flowfuse/#choosing-the-right-authentication-strategy"># </a> Choosing the Right Authentication Strategy</h2>
<p>FlowFuse provides multiple authentication mechanisms to cater to various aspects of security and user experience. When designing your Node-RED applications, consider the specific requirements of your project and the patterns of user interaction to select the most appropriate authentication strategy. By doing so, you can ensure both a high level of security and an optimal user experience for your web development projects with API calls through Node-RED.</p>
<p>In conclusion, understanding and utilizing these different types of authentication in FlowFuse empowers citizen developers like you to create more secure and efficient applications for diverse use cases.</p>
https://flowfuse.com/blog/2024/03/scaling-node-red-devices-vs-flowfuse-instance/Scaling Node-RED with FlowFuse: Differences between a FlowFuse Instance and a Device InstanceManaging your Node-RED instances is easier with FlowFuse.2024-03-25T00:00:00ZGrey Dziuba<p>FlowFuse is a Software as a Service (SaaS) platform designed to enhance the experience and capabilities of Node-RED for its users. By focusing on scalability, security, and Dev Ops, FlowFuse aims to remove some of the technical barriers associated with using Node-RED, making it easier for citizen developers to automate tasks, process data, and create applications. In this blog post, we will discuss the differences between a FlowFuse instance and a FlowFuse device instance while highlighting how FlowFuse addresses scalability challenges in Node-RED deployments.</p>
<!--more-->
<h2 id="scalability-challenges-with-traditional-node-red-deployments" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/scaling-node-red-devices-vs-flowfuse-instance/#scalability-challenges-with-traditional-node-red-deployments"># </a> Scalability Challenges with Traditional Node-RED Deployments</h2>
<p>While deploying Node-Red is quite simple, managing multiple instances across different environments can become complex and time-consuming. As the number of devices and use cases grow, users face difficulties in scaling their Node-RED applications efficiently to handle increased load without compromising performance or security. This is where FlowFuse comes into play.</p>
<h2 id="the-role-of-flowfuse-as-an-orchestration-tool" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/scaling-node-red-devices-vs-flowfuse-instance/#the-role-of-flowfuse-as-an-orchestration-tool"># </a> The Role of FlowFuse as an Orchestration Tool</h2>
<p>FlowFuse functions as an orchestration tool that allows the deployment and management of all your Node-Red instances at scale, addressing scalability challenges head-on. By leveraging its platform, users can quickly deploy and manage multiple Node-RED instances while ensuring optimal performance and security. This enables them to connect with a wide range of devices, from PLCs and sensors to legacy software, without worrying about the complexities of managing their Node-RED deployment.</p>
<h2 id="deploying-node-red-next-to-devices" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/scaling-node-red-devices-vs-flowfuse-instance/#deploying-node-red-next-to-devices"># </a> Deploying Node-RED Next to Devices</h2>
<p>One common issue in IoT deployments is that device instances of Node-RED often communicate with unsecure devices or networks. To mitigate security risks and ensure data protection, it's common to deploy Node-RED in close proximity to these devices. The FlowFuse platform uses <a href="https://flowfuse.com/docs/device-agent/introduction/">device agents</a> that communicate back to the platform via a reverse tunnel over port 443. This setup requires only one firewall rule: allowing outbound connections from the <a href="https://flowfuse.com/docs/device-agent/introduction/">device agent</a> running Node-RED to the FlowFuse platform, significantly minimizing security risks while enabling remote monitoring, flow editing, and configuration deployment at scale.</p>
<h2 id="deploying-node-red-instances-within-the-flowfuse-platform" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/scaling-node-red-devices-vs-flowfuse-instance/#deploying-node-red-instances-within-the-flowfuse-platform"># </a> Deploying Node-Red Instances Within the FlowFuse Platform</h2>
<p>Not all instances of Node-RED need to be deployed at the edge and can be deployed anywhere. FlowFuse offers this flexibility in cases where users prefer or require deploying their Node-RED instances within the platform itself. This capability allows users to focus on developing and managing their applications without worrying about the underlying infrastructure.</p>
<h2 id="conclusion" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/scaling-node-red-devices-vs-flowfuse-instance/#conclusion"># </a> Conclusion</h2>
<p>FlowFuse addresses scalability challenges in Node-RED deployments by providing an easy-to-use platform that enables users to manage multiple instances at scale while maintaining security and performance. By understanding the differences between a FlowFuse instance and a device instance, you can make informed decisions about your deployment strategy and leverage the full potential of Node-RED for your applications. Stay tuned for our upcoming blogs where we will dive deeper into the areas of security, dev ops, and backup solutions provided by FlowFuse.</p>
https://flowfuse.com/blog/2024/03/using_kafka_in_manufacturing/How Kafka is applied in manufacturingAn overview of Kafka -- How it's applied for industrial applications, and how it works2024-03-15T00:00:00Z<p>Have you ever wondered how manufacturing and automotive industries can effectively manage the vast amount of real-time data generated by sensors and systems throughout the production process? A few years back, these industries faced major obstacles in handling the large volume of real-time data produced by sensors placed across the production line. Even today many industries continue to grapple with similar challenges. Traditional data management systems struggle to process and analyze this data in real-time, leading to inefficiencies in operational activities and decision-making. To address these challenges, various manufacturing and automobile plants have embraced technologies like Apache Kafka.</p>
<!--more-->
<p>Kafka provides a distributed streaming platform that enables the efficient handling of real-time data streams. By leveraging Kafka, we can aggregate, process, and analyze data in real-time seamlessly. This guide provides a high-level overview of Kafka, covering its definition, components, functionality, applications, and limitations.</p>
<h2 id="what-is-kafka%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/using_kafka_in_manufacturing/#what-is-kafka%3F"># </a> What is Kafka?</h2>
<p>Apache Kafka is a platform for distributed data streaming that allows for the publishing, subscribing, storing, and processing of streams of records in real-time. It is intended to handle data streams from multiple sources and to deliver them to multiple consumers. In essence, it can move large quantities of data in real-time from any source to any destination, simultaneously.</p>
<p>Kafka is also a very good <a href="https://flowfuse.com/blog/2024/01/unified-namespace-what-broker/">broker for UNS architecture</a>.</p>
<h2 id="understanding-kafka's-architecture" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/using_kafka_in_manufacturing/#understanding-kafka's-architecture"># </a> Understanding Kafka's Architecture</h2>
<p>Kafka architecture is designed to provide a scalable and fault-tolerant platform for handling real-time data streams. The architecture consists of several key components, each component serves a specific purpose in the data processing pipeline. In this section, we will take an overview of Kafka's architecture and its key components.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/using-kafka-with-node-red-architecture-v-c7g889LaEF-1600.avif 1600w" sizes="(min-device-pixel-ratio: 1.25) 3840px, (min-resolution: 120dpi) 3840px, 1920px" /><source type="image/webp" srcset="https://flowfuse.com/img/using-kafka-with-node-red-architecture-v-c7g889LaEF-1600.webp 1600w" sizes="(min-device-pixel-ratio: 1.25) 3840px, (min-resolution: 120dpi) 3840px, 1920px" /><img data-zoomable="" title="Architecture of Kafka" alt=""Architecture of Kafka"" loading="lazy" decoding="async" src="https://flowfuse.com/img/using-kafka-with-node-red-architecture-v-c7g889LaEF-1600.jpeg" width="1600" height="1519" /></picture></p>
<p><strong>1. Topics and Partitions</strong></p>
<ul>
<li>Topics: Imagine topics as folders for organizing data – they act as distinct categories. Kafka arranges information into these topics for systematic storage.</li>
<li>Partitions: Think of partitions as subdivisions within topics. They enable parallel processing across multiple servers, enhancing fault tolerance and throughput.</li>
</ul>
<p><strong>2. Producers:</strong></p>
<ul>
<li>Producers: Producers are like architects of data flow. They decide where to send records within a topic. This decision can be balanced using a round-robin or directed by a record key for specific purposes, such as maintaining order.</li>
</ul>
<p><strong>3. Brokers:</strong></p>
<ul>
<li>Definition: Brokers are the backbone servers in a Kafka cluster.</li>
<li>Tasks: Brokers store data, handle requests from both producers and consumers, and maintain the integrity and persistence of data. They also manage the critical task of tracking offsets, which determine the position of consumers within partitions.</li>
</ul>
<p><strong>4. Consumers and Consumer Groups:</strong></p>
<ul>
<li>Consumers: These entities read data from brokers. They subscribe to one or more topics and pull data from the specific partitions they are interested in.</li>
<li>Consumer Groups: Consumers collaborate in groups to scale data processing. Kafka dynamically assigns each consumer in a group a set of partitions from the subscribed topics, ensuring that each partition is processed by only one consumer within the group.</li>
</ul>
<p><strong>5. Offsets</strong></p>
<ul>
<li>Definition: Offsets act as unique identifiers for records within a partition. They denote the position of a consumer in the partition.</li>
<li>Function: As consumers read records, they increment their offset. This allows them to resume processing from where they left off, which is crucial for handling failures or restarts. Kafka stores offset information in a specialized topic for easy recovery.</li>
</ul>
<p><strong>6. Replication</strong></p>
<ul>
<li>Mechanism: Kafka ensures data durability by replicating partitions across multiple brokers.</li>
<li>Replication Factor: This configurable setting determines the number of copies of a partition in the cluster. If one broker fails, another can seamlessly take over, guaranteeing high availability.</li>
</ul>
<h2 id="features-of-kafka" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/using_kafka_in_manufacturing/#features-of-kafka"># </a> Features of Kafka</h2>
<p>Now that we've gained a foundational understanding of Kafka, let's explore the key features that make it a preferred choice for many organizations. These features highlight why Kafka transcends being just another data processing tool and why it merits consideration for various use cases.</p>
<ul>
<li><strong>High Throughput and Scalability:</strong> Kafka can handle thousands of messages per second and can scale horizontally and vertically to meet growing data demands without compromising performance.</li>
<li><strong>Fault Tolerance and Reliability:</strong> Built to ensure reliability, Kafka guarantees fault tolerance through replication, safeguarding data against loss in the event of a broker failure. Data redundancy ensures data safety even during hardware failures.</li>
<li><strong>Real-Time Processing and Low Latency:</strong> Kafka's real-time processing ensures low latency for instant data analysis, which is critical for real-time decision-making.</li>
</ul>
<h2 id="applications-of-kafka" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/using_kafka_in_manufacturing/#applications-of-kafka"># </a> Applications of Kafka</h2>
<p>As we explore the capabilities of Kafka, we realize that it goes beyond being just a regular data processing tool. Kafka is a strategic powerhouse that influences decision-making, operational efficiency, and overall effectiveness in various industries. In this section, we will discuss specific, practical applications of Kafka in different industries, demonstrating how its adaptability can solve unique challenges.</p>
<p><strong>1. Manufacturing Operations Optimization:</strong></p>
<ul>
<li>Real-time Production Monitoring: Kafka is used in manufacturing for continuous monitoring of production lines, equipment status, and inventory levels. This real-time visibility aids in optimizing production efficiency, reducing downtime, and enhancing overall supply chain management.</li>
<li>Quality Assurance and Yield Management: Companies utilize Kafka to monitor quality control metrics in real-time, enabling proactive measures to maintain product quality standards, minimize defects, and optimize production yield.</li>
</ul>
<p><strong>2. Predictive Maintenance:</strong> Organizations use Kafka to collect and analyze sensor data from machinery and equipment to predict potential failures. This helps them optimize scheduled maintenance tasks to prevent costly downtime and disruptions</p>
<p><strong>3. Supply Chain Management:</strong> Kafka provides real-time visibility into supply chain operations. This enables companies to track shipments, monitor inventory levels, and coordinate with suppliers and distributors for efficient supply chain management.</p>
<p><strong>4. Logistics and Transportation:</strong> Companies use Kafka to track vehicle and shipment locations in real-time, optimizing routes through the processing of streams of GPS data.</p>
<p><strong>5. Telecommunications:</strong> Telecom operators utilize Kafka to monitor network performance metrics in real-time. This allows swift responses to outages or service degradations, ensuring a seamless communication network.</p>
<p><strong>6. Financial Services:</strong> Banks leverage Kafka to process transactions in real-time, enabling immediate fraud detection by analyzing patterns in transaction data as they occur. This enhances overall security and compliance in financial operations.</p>
<h2 id="challenges-and-considerations" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/using_kafka_in_manufacturing/#challenges-and-considerations"># </a> Challenges and Considerations</h2>
<p>As beneficial as Kafka is in various industries, it also presents certain limitations and challenges that must be considered before deciding to use Kafka for your applications.</p>
<ol>
<li>
<p>Performance: Kafka both receives and transmits data. When the flow of data is compressed or decompressed, the performance is affected. For example, if the data is decompressed it will eventually drain the node memory. As a result, it affects both throughput and performance.</p>
</li>
<li>
<p>Complexity: As we all know Kafka is an excellent platform for streamlining messages. However, in the case of migration projects that transform data, Apache Kafka gets more complex. Hence, to interact with both data producers and consumers you need to create data pipelines.</p>
</li>
<li>
<p>Tool Support: There is always a concern for startup companies to use Kafka over other options. Especially, if it remains in the long run. This is because a full set of management and monitoring tools are absent in Kafka.</p>
</li>
<li>
<p>Message Tweaking: Kafka uses system calls before delivering a message. Therefore, the messages are sensitive to modifications. Tweaking messages reduces the performance of Kafka to a greater extent. The performance is not impacted only under the condition of not changing the message.</p>
</li>
<li>
<p>Data Storage: Apache Kafka is not a recommended option for storing large sets of data. If the data is stored for a long period, the redundant copies of it are also stored. When this happens, the app must be ready to compromise its performance. For this reason, only use Kafka if there is a need to store data for a short period.</p>
</li>
</ol>
<h2 id="conclusion" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/using_kafka_in_manufacturing/#conclusion"># </a> Conclusion</h2>
<p>This guide provides a high-level overview of Apache Kafka, including its definition, architecture, features, and applications in various industries and the challenges or limitations of using Kafka. Kafka's versatility in real-time data processing, decision-making, and operational efficiency is highlighted, with applications ranging from manufacturing to finance. The overview aims to provide a clear understanding of Kafka's role in handling data challenges and fostering innovation across sectors.</p>
https://flowfuse.com/blog/2024/03/flowfuse-self-hosted-starter-resource-limits/FlowFuse Open Source Starter Tier Resource LimitsThe first 5 Node-RED runtimes are part of the starter package going forward2024-03-14T00:00:00ZZJ van de Weg<p>Today, with the latest FlowFuse release, an important change was made that
updates the resource limits for our open-source, self-managed FlowFuse server
tier. This change does not affect FlowFuse Cloud users in any way.</p>
<!--more-->
<h2 id="new-starter-tier-resource-limits" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/flowfuse-self-hosted-starter-resource-limits/#new-starter-tier-resource-limits"># </a> New Starter Tier Resource Limits</h2>
<p>The new limit for the number of Node-RED runtimes on the Starter tier is 5.
These 5 instances can be distributed across a maximum of 5 teams. This revised
structure allows for the development of your initial FlowFuse and Node-RED
solutions, providing a clear understanding of how FlowFuse can enhance your
organization's workflows. Upgrading to a Team or Enterprise tier license unlocks
the full potential of FlowFuse and grants access to our dedicated support team.</p>
<h2 id="why-the-change%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/flowfuse-self-hosted-starter-resource-limits/#why-the-change%3F"># </a> Why the Change?</h2>
<p>Here at FlowFuse, we're committed to providing a great experience for all our
users, including those utilizing our free, open-source Starter tier. We
initially designed this tier to offer a platform for small organizations and
larger teams to explore FlowFuse's capabilities without needing our direct
involvement. However, we've observed instances where the Starter tier's free
limits were being used to run very large deployments and even entire sites.</p>
<p>While support is a key benefit we offer to paying customers, we believe everyone
deserves a positive FlowFuse experience. As such, we're adjusting the resource
limits to better align with the Starter tier's intended purpose and allow the
company to continue to invest in the Starter tier.</p>
<h2 id="transitioning-users" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/flowfuse-self-hosted-starter-resource-limits/#transitioning-users"># </a> Transitioning Users</h2>
<p>If you're currently impacted by these resource limit changes, we want to ensure
a smooth transition. We're offering a complimentary 1-year Enterprise license to
affected users. To claim your license, simply email support@flowfuse.com with
the IP address your server has used to send telemetry data (if available) and a
screenshot of your admin panel so we can match the currently usage with the new
license.</p>
<p>We appreciate your understanding and continued support. If you have any
questions regarding this update, please don't hesitate to reach out to our team
at support@flowfuse.com.</p>
https://flowfuse.com/blog/2024/03/low-code-is-better/Why Low-Code is BetterStop coding in High-Code when it can be done in Low-Code2024-03-13T00:00:00ZGrey Dziuba<p>There are two common reasons why new languages come about. They provide a feature missing in the existing programming languages, or it is a tool that is easier to learn and use. The latter often functions like a swiss army knife with each iteration including more and more tools. The journey of low-code is like a swiss army knife, the perfect tool for the Citizen Developer.</p>
<!--more-->
<h2 id="a-typical-coding-evolution" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/low-code-is-better/#a-typical-coding-evolution"># </a> A Typical Coding Evolution</h2>
<p>Every decade seems to introduce something that simplifies coding. For me, in college, it was Python. A classmate was excited about this new programming language that was all about simplicity and readability, especially with its indentation-based syntax. It seemed too simple at first. Yet, over time, Python became a staple in my programming toolbox.</p>
<p>During this time in our education, our coursework was filled with languages like C++, which felt distant from the future of programming we imagined. We joked about "outdated" languages, not yet realizing the breadth of what programming could encompass.</p>
<p>After finishing college in 2010, I started working during the tail end of the housing crisis in the U.S. My first role was as a Controls System Integrator at Logical System Inc., where I was introduced to programming PLCs with Ladder Logic. Despite my initial reservations—viewing it as barely a programming language—this experience was my first step towards appreciating the diversity and utility of programming languages beyond the conventional.</p>
<p>Later on in my career, I worked as a Corporate Automation and Controls Engineer where I worked on and enforced standards for partner System Integrators and OEMs. One of these important standards was making sure applications written in the control process were written in Ladder Logic within the PLCs. There were exceptions, of course, but the rule was to apply a visually appealing coding language, Ladder Logic, over a text-like language often called Structured Text.</p>
<h2 id="programming-languages-as-specialized-tools" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/low-code-is-better/#programming-languages-as-specialized-tools"># </a> Programming Languages as Specialized Tools</h2>
<p>Programming languages are typically optimized for certain tasks. For instance, Matlab and R excel in complex numerical computations thanks to their extensive libraries designed specifically for mathematical operations. While Python might not replace Matlab or R for their core functionalities, it can broaden the applicability of numerical analyses into various other contexts. In another example, VB.net is the go-to for standalone applications in Windows environments. However, for applications that need to run across different operating systems (excluding web applications), Java might be a better choice due to its platform independence. Each programming language has its niche, along with inherent complexities and constraints.</p>
<p>There are situations, however, where the specific strengths of a programming language become less critical. In cases where the application is straightforward, the choice of language might simply come down to personal preference or familiarity. But an important consideration arises when thinking about the future of the project: "Will someone else need to edit or view this code later?" If the answer is yes, and especially if the project aims to involve citizen developers, opting for a low-code solution becomes highly advantageous. Low-code platforms are designed with accessibility in mind, making them ideal for projects that benefit from collaboration and ease of maintenance.</p>
<h2 id="the-purpose-of-citizen-development" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/low-code-is-better/#the-purpose-of-citizen-development"># </a> The Purpose of Citizen Development</h2>
<p>The idea behind Citizen Development is simple, make programming accessible to more people. This is what low-code platforms aim to do. They lower the entry barrier, making programming more inclusive. Insisting on complex, traditional programming languages when there are simpler, equally powerful alternatives seems counterproductive. We should be looking towards making programming more accessible to everyone.</p>
<p>If we want to drive meaningful change within our organizations, embracing tools that broaden participation is key. The aim of adopting new standards and tools is to simplify, not complicate. It's about finding better, more accessible ways to work that can accommodate a wider range of skill sets.</p>
<h2 id="simplification" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/low-code-is-better/#simplification"># </a> Simplification</h2>
<p>This discussion isn't about the mechanics of coding, it's about opening up the field to more diverse contributions. Low-code platforms represent a step towards a more inclusive, collaborative future in technology. By lowering barriers to entry, we're not just simplifying coding, we're inviting a broader community to engage, innovate, and drive progress. I look forward to seeing how we can all contribute to this evolving landscape.</p>
<h2 id="how-flowfuse-helps" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/low-code-is-better/#how-flowfuse-helps"># </a> How FlowFuse Helps</h2>
<p>Our goal here at FlowFuse is to keep expanding on the Swiss army knife, Node-RED. We strive to elevate Node-RED for professionals by providing the tools needed to deploy Node-RED in a safe and secure way. For example by default, the editor for Node-RED is protected using your FlowFuse user credentials. You can also use SSO to further protect your user accounts and give access to Node-RED to your team members. All traffic to FlowFuse and your Node-RED instances is protected by HTTPS. FlowFuse has set up the domain name and manages the certificates so you can spend time on your flows rather than configuring security.</p>
<p>We believe that Low-Code is the future and strive to make Citizen Development a reality. To learn more <a href="https://flowfuse.com/free-consultation/">schedule a call with one of our experts. </a></p>
https://flowfuse.com/blog/2024/03/looking-towards-node-red-4/Looking towards Node-RED 4.0 and beyondA look at what is coming in Node-RED 4.02024-03-07T00:00:00ZNick O'Leary<p>With Node-RED 4.0 coming soon, I wanted to take a look at what users can expect to see with the new release,
as well as some of the new features we're working on.</p>
<!--more-->
<p>The Node-RED project <a href="https://nodered.org/about/releases/">schedules its releases</a> around a yearly major release that coincides with when a Node.js version
reaches its end-of-support. This lets us drop support for that node.js version and update the default version of node used
in the docker containers we publish. We treat this as a major change because it might require actions on the end-users part to update any additional modules they have installed.</p>
<p>With Node-RED 4.0, we will be dropping support for anything earlier than Node 18 - with Node 20 the currently recommended version to use. That will give users almost 2 full years before needing to consider another Node.js upgrade.</p>
<p>Now, talking about Node.js versions is not that exciting. What is more exciting is to look at what new features are coming to Node-RED.</p>
<p>There are a few things already merged and ready to be released in the first beta release, and more landing each week.</p>
<h3 id="more-auto-complete" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/looking-towards-node-red-4/#more-auto-complete"># </a> More auto-complete</h3>
<p>Node-RED already has simple auto-complete on <code>msg</code> fields in the editor. We've now extended that to also work with <code>flow</code>/<code>global</code> context inputs as well as the <code>env</code> type for accessing environment variables.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/nr4-auto-complete-14i7D5DBpC-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/nr4-auto-complete-14i7D5DBpC-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Node-RED editor autocompleting properties" alt="Node-RED editor autocompleting properties" loading="lazy" decoding="async" src="https://flowfuse.com/img/nr4-auto-complete-14i7D5DBpC-650.jpeg" width="650" height="184" /></picture></p>
<p>This makes it so much easier to work with these types of properties - being sure you're using something that exists rather than having to switch between different views in the editor to get the names right.</p>
<p>In the case of env vars, it also shows you where the value was set - useful when you have nested groups and subflows which might be overriding a particular value.</p>
<p>The <code>msg</code> auto-complete is still based on a built-in list of common message properties used by the core nodes. There is interest in enabling this to pull completions from 'live' messages seen by the node in question - but that's not currently in the plan for 4.0.</p>
<h3 id="timestamp-formatting" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/looking-towards-node-red-4/#timestamp-formatting"># </a> Timestamp formatting</h3>
<p>The Inject node has provided the ability to inject a timestamp since the very early days of Node-RED. The value it actually sets is the number of milliseconds since epoch (aka January 1st, 1970). If you're used to working with JavaScript, then this is a perfectly normal way to pass times around. However, it isn't always what is needed and flows end up using a Function node to reformat it in some way.</p>
<p>With 4.0 we've added options to pick what format the timestamp is generated in at the start. Now, formatting times and dates can be a big can of worms of options. So, for this initial release, we've kept it simple by offering three options:</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/nr4-timestamp-formatting-1QFHkE6yLW-582.avif 582w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/nr4-timestamp-formatting-1QFHkE6yLW-582.webp 582w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Format options for Node-RED timestamp" alt=""Format options for Node-RED timestamp"" loading="lazy" decoding="async" src="https://flowfuse.com/img/nr4-timestamp-formatting-1QFHkE6yLW-582.jpeg" width="582" height="272" /></picture></p>
<ul>
<li><em>milliseconds since epoch</em> - the existing option, just more explicitly labelled for what it is</li>
<li><em>YYYY-MM-DDTHH:mm:ss.sssZ</em> - also known as ISO 8601</li>
<li><em>JavaScript Date Object</em> - the standard Date object</li>
</ul>
<p>There is scope to allow custom format strings to be set in the node - but we'll see what the feedback is on these new options first.</p>
<h3 id="a-better-csv-node" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/looking-towards-node-red-4/#a-better-csv-node"># </a> A better CSV node</h3>
<p>The CSV node has had a big overhaul to make it more standards compliant. It turns out CSV has a whole bunch of tricky edge cases that most users don't hit - but if you did hit them you would be stuck.</p>
<p>The new node follows the <a href="https://www.ietf.org/rfc/rfc4180.txt">RFC4180</a> standard and is also faster - wins all around.</p>
<p>For those flows that rely on some of the non-standard edge case behaviour of the existing node, we've kept a legacy mode in place to keep those flows working.</p>
<h3 id="customising-config-nodes-in-subflows" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/looking-towards-node-red-4/#customising-config-nodes-in-subflows"># </a> Customising config nodes in Subflows</h3>
<p>This one needs a bit of explaining. Subflows are a way Node-RED lets you create a flow and add multiple reusable instances of it within your flows. For example, a subflow may connect to an MQTT broker and do some standard processing on the messages it received before sending them on. The Subflow can then expose a set of properties that can be customised for each instance. In our example, that could be the topic the MQTT node subscribes to.</p>
<p>However, in that example, the MQTT node's broker configuration would be locked to the same broker config node in every instance - and that's something we're solving in Node-RED 4.0.</p>
<p>We're making it possible to expose the choice of a configuration node in the Subflow properties - so each instance can be customised even further.</p>
<p>Another common use for this will be with Node-RED Dashboard - which uses config nodes to set the location of a widget. With Node-RED today, you cannot really use dashboard nodes inside subflows as you end up with multiple copies of the widgets all packed into the same group. With this update, you'll be able to configure the subflow instance with exactly what dashboard group to place its contents into.</p>
<h3 id="updated-jsonata" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/looking-towards-node-red-4/#updated-jsonata"># </a> Updated JSONata</h3>
<p>The JSONata library is used to provide the <code>expression</code> types in Node-RED - a really powerful way of working with JSON objects. With this release we've updated to the new major release of JSONata that comes with a bunch of performance improvements.</p>
<h3 id="and-many-more-minor-changes" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/looking-towards-node-red-4/#and-many-more-minor-changes"># </a> And many more minor changes</h3>
<p>I'll hold off listing them all out here, but there are plenty of other smaller changes scattered through the editor and the core nodes. Be sure to check the beta release notes when it arrives to see what else has been done.</p>
<h2 id="looking-further-ahead" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/looking-towards-node-red-4/#looking-further-ahead"># </a> Looking further ahead</h2>
<p>Whilst all of these are great incremental improvements to Node-RED, there are some bigger items we're looking at that will really improve the overall Node-RED experience.</p>
<p>I wrote recently about improving how users can <a href="https://flowfuse.com/blog/2024/02/software-development-in-node-red/#testing">test their flows</a>. This remains something I think we really help make Node-RED stand apart from other low-code solutions. It won't be in the imminent 4.0 release, but it is definitely still on the roadmap for a future release.</p>
<h3 id="concurrent-editing" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/looking-towards-node-red-4/#concurrent-editing"># </a> Concurrent editing</h3>
<p>Another area we want to improve is the collaboration experience within Node-RED. Working on flows as a team is a key feature of FlowFuse, and we want to make it even easier to do.</p>
<p>One of the common complaints is how Node-RED currently handles multiple users editing flows at the same time. Whilst it's better than it used to be, it still makes for a very jarring experience when you have to keep merging other users' changes into your own.</p>
<p>Our goal is to make collaboration as simple and natural as possible.</p>
<p>There are a wide range of approaches we could take here. For example, a small improvement would be to merge other users' changes in the background without interrupting what you're doing. But I think we do better than that.</p>
<p>What if the editing experience was more like Google Docs - knowing that other users have the editor open, and being able to see their changes in real time. This would make for a truely collaborative editing experience.</p>
<p>There are some difficult problems to solve before we can get there, but I think this will be one of the more transformational changes to Node-RED we've had for some time.</p>
<h2 id="beta-releases" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/looking-towards-node-red-4/#beta-releases"># </a> Beta releases</h2>
<p>The <a href="https://nodered.org/about/releases/">release plan</a> has Node-RED 4.0 coming around the end of April. As mentioned, we'll be doing a series of beta releases between now and then to start getting early feedback from the community.</p>
<p>Keep an eye on the <a href="https://discourse.nodered.org/c/news/9">community forum</a> for release announcements as they come.</p>
https://flowfuse.com/blog/2024/03/installing-operating-node-red-behind-firewall/Installing and operating Node-RED behind a firewallFlowFuse was built to empower Node-RED to run everywhere, even behind a firewall2024-03-06T00:00:00ZZJ van de Weg<p>Practitioners using Node-RED often find themselves in a situation where a firewall
is deployed in their organization. This network configuration is a fact of life and is generally not controlled by the same people using Node-RED. Given security reigns supreme in Industrial IoT (IIoT), and a firewall offers a lot of benefits, we anticipate it will be deployed more often in the future, and as such it’s good to understand how you can get the most out of Node-RED when deployed behind a firewall.</p>
<!--more-->
<h2 id="node-red-installation-with-a-firewall" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/installing-operating-node-red-behind-firewall/#node-red-installation-with-a-firewall"># </a> Node-RED installation with a firewall</h2>
<p>Generally, the standard install procedure for Node-RED requires a connection to the NPM servers that host the package. Due to NPM’s unaudited nature, IT is unlikely to agree to a permanent exception to the firewall to allow access to it. However, there are a couple of actions one can take to install Node-RED anyway.</p>
<p>First, ask for a temporary exception. Node-RED is installed in a few minutes, so if there’s a set time schedule an exception can be made there’s a regular method available again through collaboration with the network administrator. The second option is leveraging vendor specific package managers. As these are vetted repositories, it’s not uncommon that these gates in the firewall have been created and opened to you. Some vendors supply repositories for major package managers like <code>apt-get</code> on Debian/Ubuntu-based systems, or there’s a marketplace approach to install Node-RED like for example the <a href="https://developer.community.boschrexroth.com/t5/Store-and-How-to/FlowFuse-Node-RED/ba-p/82135">Rexroth CtrlX with Node-RED in it</a>. Lastly, you could consider downloading the NPM package beforehand and transferring it to your machine within the network. NPM allows the installation of local packages, which in turn allows you to create applications with Node-RED. This is generally a shadow IT action, and not recommended unless it’s approved.</p>
<h2 id="flowfuse-and-your-firewall" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/installing-operating-node-red-behind-firewall/#flowfuse-and-your-firewall"># </a> FlowFuse and your firewall</h2>
<p>As FlowFuse can be installed in a VPN behind a firewall, there’s no requirement to open up a ‘gate’ in your firewall to FlowFuse servers. The safe perimeter provided remains to the outside world. The security aspect remains, though as a Node-RED developer, there are still everyday tasks you’ll need access to the outside world.</p>
<p>Consider installing third party nodes to connect your Node-RED instance to virtually any protocol or digital service. There are over 5000 of these nodes available, and as an organization it’s challenging to keep on top of. Your firewall provides one layer of security so that the data you’re accessing remains safe. FlowFuse provides a second layer of protection; we’ve introduced a <a href="https://flowfuse.com/certified-nodes/">“Certified Nodes” catalog</a>. These nodes have gone through automated and manual inspection to prevent malicious code from making it onto your production systems.</p>
<p>Installing these packages would typically still require you to obtain files from NPM. With FlowFuse however, a cache can be built with only vetted nodes – All other nodes remain unavailable.</p>
<p>Once Node-RED is installed and the initial development has been completed, FlowFuse aims to reduce the maintenance burden on both IT and OT teams too. In the same package cache aforementioned, Node-RED versions can be added. Updating Node-RED to the latest version becomes a job of just a few clicks. Updating your Node-RED instances, even behind a firewall, is imperative, as virtually all breaches are the result of daisy-chaining multiple security vulnerabilities into a high to critical event.</p>
<h2 id="wrap-up" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/installing-operating-node-red-behind-firewall/#wrap-up"># </a> Wrap up</h2>
<p>FlowFuse founding engineers have decades of experience running Node-RED wherever it is valuable. Our product is the culmination of that, and we’re excited to help you become successful in your digitization efforts – even when a firewall is in play.</p>
https://flowfuse.com/blog/2024/03/flowfuse-on-siemens-iot2050/Run FlowFuse on Siemens IoT2050How to install FlowFuse Device Agent on Siemens IoT20502024-03-04T00:00:00ZGrey Dziuba<p>Siemens <a href="https://press.siemens.com/global/en/pressrelease/new-siemens-gateway-between-cloud-company-it-and-production">announced</a> the IoT2000 series in March of 2020. With this tool many have been using it to function as a gateway between their plant operations and cloud infrastructure. Onboard it came with Node-RED pre-installed. To manage Node-RED as an organization the FlowFuse agent is recommended, this guide shows you how to do so.</p>
<!--more-->
<div style="background-color: #fff4b9; border:1px solid #ffc400; color: #a27110; padding: 12px; border-radius: 6px; font-style: italic;">Warning: Later in the guide we will be updating Node.js. This will break <a href="https://www.npmjs.com/package/mraa">MRAA</a> library. This will prevent communication to the GPIO of the device.</div>
<h2 id="goal" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/flowfuse-on-siemens-iot2050/#goal"># </a> Goal</h2>
<p>The goal of this blog is to guide the user through the installation process of getting FlowFuse Device agent installed on an IoT2050. The IoT2050 comes pre-installed with version 12.22.x Node.js on the <a href="https://support.industry.siemens.com/cs/document/109741799/downloads-for-simatic-iot20x0?dti=0&lc=en-GB">IOT2050_Example_Image_V1.3.1</a> image. A requirement to install FlowFuse Device Agent, Node.js needs to be upgraded to version 18 minimum. We will be going through that process.</p>
<h2 id="prerequisites" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/flowfuse-on-siemens-iot2050/#prerequisites"># </a> Prerequisites</h2>
<p>We will be working with the IoT2050 Advanced, <em>6ES7 647-0BA00-1YA2</em>. The device has been <a href="https://support.industry.siemens.com/cs/attachments/109741799/IOT2050_How_To_Firmware_Update_V1.3.pdf">upgraded</a> to the latest firmware at the time of writing this article of v1.3.1. We will be leveraging the IOT2050_Example_Image_V1.3.1.zip image which is a Debian base OS. To complete this guide, knowledge of Linux-based cli is necessary. Documentation to complete these requirements can be found <a href="https://support.industry.siemens.com/cs/document/109741799/downloads-for-simatic-iot20x0?dti=0&lc=en-GB">here</a>.</p>
<h2 id="step-by-step-guide" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/flowfuse-on-siemens-iot2050/#step-by-step-guide"># </a> Step by Step Guide</h2>
<ol>
<li>First we need to run the standard updates.</li>
</ol>
<div style="position: relative">
<pre class="language-shell"><code id="code-27" class="language-shell"><span class="token function">apt-get</span> update<br /><span class="token function">apt-get</span> upgrade</code></pre>
<button class="code-copy " data-clipboard-target="#code-27" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<ol start="2">
<li>If you need to migrate your existing Node-RED follow these <a href="https://flowfuse.com/docs/migration">instructions</a> to backup your existing progress. From there we will need to remove the existing service that autostarts Node-RED by running the following command and rebooting:</li>
</ol>
<div style="position: relative">
<pre class="language-shell"><code id="code-35" class="language-shell">systemctl disable node-red.service<br /><span class="token function">reboot</span> <span class="token parameter variable">-h</span> now</code></pre>
<button class="code-copy " data-clipboard-target="#code-35" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<ol start="3">
<li>Confirm that your Node-RED instance is no longer running.</li>
</ol>
<div style="position: relative">
<pre class="language-shell"><code id="code-43" class="language-shell">systemctl status node-red</code></pre>
<button class="code-copy " data-clipboard-target="#code-43" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>In the output look for the text that signifies the service has been stopped.</p>
<blockquote>
<p>iot2050-debian systemd[1]: Stopped Node-RED.</p>
</blockquote>
<ol start="4">
<li>Now it is time to upgrade your Node.js version. To check the version before we get started run <code>node -v</code>.</li>
</ol>
<p>You should see an output like this:</p>
<blockquote>
<p>v12.22.5</p>
</blockquote>
<div style="background-color: #fff4b9; border:1px solid #ffc400; color: #a27110; padding: 12px; border-radius: 6px; font-style: italic;">Warning: updating Node.js will break the <a href="https://www.npmjs.com/package/mraa">MRAA</a> library. This will prevent communication to the GPIO of the device. Details can be found <a href="https://support.industry.siemens.com/forum/WW/en/posts/iot2050-node-js-versions/297170">here</a>.</div>
<p>Then, install a tool called <em>n</em> that will allow you to change your versions of Node.js with the following command.</p>
<div style="position: relative">
<pre class="language-shell"><code id="code-71" class="language-shell"><span class="token function">npm</span> <span class="token function">install</span> n <span class="token parameter variable">-g</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-71" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<ol start="5">
<li>Next we will install the version 18.17.x (LTS) of Node.js.</li>
</ol>
<div style="position: relative">
<pre class="language-shell"><code id="code-79" class="language-shell">n v18.17</code></pre>
<button class="code-copy " data-clipboard-target="#code-79" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>Now run <code>node -v</code> again to confirm the installation. You should see the latest version now installed.</p>
<blockquote>
<p>v18.17.1</p>
</blockquote>
<ol start="6">
<li>
<p>Now that we have Node.js installed, we can proceed with the standard installation process. First <a href="https://flowfuse.com/docs/device-agent/install/">install</a> the FlowFuse Device agent. Then, to connect your FlowFuse Device Agent, follow these <a href="https://flowfuse.com/docs/device-agent/register/">instructions</a>.</p>
</li>
<li>
<p>Lastly, if you want your device to run on boot. Follow these <a href="https://flowfuse.com/blog/2023/05/device-agent-as-a-service/">instructions</a>.</p>
</li>
</ol>
<h2 id="switching-between-versions-of-node.js" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/flowfuse-on-siemens-iot2050/#switching-between-versions-of-node.js"># </a> Switching between versions of Node.js</h2>
<p>Switching between versions of Node.js can now be completed by leveraging <em>n</em> command that was installed in step 4. To do so simply run the following to switch back.</p>
<div style="position: relative">
<pre class="language-shell"><code id="code-106" class="language-shell">n v12.22.5</code></pre>
<button class="code-copy " data-clipboard-target="#code-106" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<h2 id="more-on-mraa" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/flowfuse-on-siemens-iot2050/#more-on-mraa"># </a> More on MRAA</h2>
<p>The MRAA library is a "Low Level Skeleton Library for Communication on GNU/Linux platform." It has been key for various solutions to communicate to hardware boards GPIO, General Purpose Input Output. The MRAA library only supports version 6.x.x of Node.js, but Siemens put in the effort to patch their deployment up to version 12.22.x of Node.js.</p>
https://flowfuse.com/blog/2024/03/using_webcam_with_node-red/Using a webcam with Node-REDGuide to integrating webcam features into Node-RED applications.2024-03-01T00:00:00Z<p>Dashboard 2.0 just got its first third-party webcam widget that simplifies integrating webcam features with Node-RED applications. In this guide, we will show you how you can use the ui-webcam widget in your Node-RED applications.</p>
<!--more-->
<p>Additionally, if you are willing to develop your own third-party widget, we have our <a href="https://github.com/FlowFuse/node-red-dashboard-2-ui-example">example widget</a> which helps you develop your widget. Additionally for a detailed step-by-step guide refer to <a href="https://dashboard.flowfuse.com/contributing/widgets/third-party.html">Building Third Party Widgets</a>.</p>
<h2 id="installing-dashboard-2.0" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/using_webcam_with_node-red/#installing-dashboard-2.0"># </a> Installing Dashboard 2.0</h2>
<p>Before we start integrating the webcam, make sure you have installed Dashboard 2.0, if not follow the below steps.</p>
<ol>
<li>Install Node-RED Dashboard 2.0. Follow these <a href="https://dashboard.flowfuse.com/getting-started.html">instructions</a> to install.</li>
<li>Create your first group, page, theme, and base.</li>
</ol>
<h2 id="using-a-webcam-custom-widget" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/using_webcam_with_node-red/#using-a-webcam-custom-widget"># </a> Using a webcam custom widget</h2>
<p>Once Dashboard 2.0 is installed, proceed to install the ui-webcam widget:</p>
<ol>
<li>Install <code>@sumit_shinde_84/node-red-dashboard-2-ui-webcam</code> by the palette manager.</li>
<li>Select a created group for the ui-webcam widget in which it will render.</li>
<li>Deploy the flow by clicking on the top-right red deploy button.</li>
</ol>
<h2 id="inner-workings-of-the-webcam-widget" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/using_webcam_with_node-red/#inner-workings-of-the-webcam-widget"># </a> Inner Workings of the Webcam Widget</h2>
<p>In this section, we will take a closer look at the inner workings of the webcam widget. The widget is built using Vue.js and provides a highly engaging and interactive user interface that follows Node-RED and Dashboard 2.0 standards. To enable webcam functionality, the widget makes use of the <a href="https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia">MediaDevices API</a>, which facilitates access to connected media input devices like cameras and microphones.</p>
<h2 id="capturing-images-using-controls" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/using_webcam_with_node-red/#capturing-images-using-controls"># </a> Capturing images using controls</h2>
<p>This webcam widget offers nice interactive controls that will allow you to interact with the webcam easily.</p>
<ol>
<li>Navigate to the dashboard by accessing <code>https://<your-instance-name>.flowfuse.cloud/dashboard</code>.</li>
<li>Initially, you'll see a black interface with a power button on the dashboard. Clicking this button will activate the webcam. Ensure that you grant permission to the dashboard to access your webcam.</li>
<li>Once the webcam is active, you can capture images by clicking the button with the camera icon located at the bottom center of the webcam interface.</li>
<li>The widget returns a Base64 string containing the captured image in PNG format.</li>
</ol>
<p><picture><source type="image/gif" srcset="https://flowfuse.com/img/using_webcam_with_node-red_capturing_images_by_control-q_ST9ypPux-442.gif 442w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="capturing images using webcam widget controls" alt=""capturing images using webcam widget controls"" loading="lazy" decoding="async" src="https://flowfuse.com/img/using_webcam_with_node-red_capturing_images_by_control-q_ST9ypPux-442.webp" width="442" height="450" /></picture></p>
<h2 id="capturing-images-by-passing-payload" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/using_webcam_with_node-red/#capturing-images-by-passing-payload"># </a> Capturing images by passing payload</h2>
<ol>
<li>Drag an inject node onto the canvas.</li>
<li>Set <code>msg.payload</code> to <code>capture</code> as string. You can also set an interval time to automatically send the message after a specific interval, or you can keep it unchanged to manually send the payload by clicking the inject button.</li>
<li>Connect the output of the inject node to the input of the webcam widget.</li>
<li>Deploy the flow.</li>
</ol>
<p>By passing the "capture" string as payload, the webcam widget will activate (if it's off) and capture images automatically, without requiring user interaction. This method is commonly used in industrial applications which depend on automated actions.</p>
<p><picture><source type="image/gif" srcset="https://flowfuse.com/img/using_webcam_with_node-red_capturing_images_by_passing_payload-U3F52J1Y1z-600.gif 600w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="capturing images by passing payload" alt=""capturing images by passing payload"" loading="lazy" decoding="async" src="https://flowfuse.com/img/using_webcam_with_node-red_capturing_images_by_passing_payload-U3F52J1Y1z-600.webp" width="600" height="291" /></picture></p>
<h2 id="selecting-different-camera-devices" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/using_webcam_with_node-red/#selecting-different-camera-devices"># </a> Selecting different camera devices</h2>
<p>The webcam widget also allows you to select different camera devices connected to your system:</p>
<ol>
<li>Click on the ellipsis icon located at the top-right corner of the webcam interface.</li>
<li>A dropdown menu will display the connected cameras. Select your preferred camera to use. Additionally, you can turn off the camera by selecting the "Turn camera off" option.</li>
</ol>
<p><picture><source type="image/gif" srcset="https://flowfuse.com/img/using_webcam_with_node-red_selecting_different_camera-t0Z06w7WWF-600.gif 600w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="selecting different camera" alt=""selecting different camera"" loading="lazy" decoding="async" src="https://flowfuse.com/img/using_webcam_with_node-red_selecting_different_camera-t0Z06w7WWF-600.webp" width="600" height="606" /></picture></p>
<h2 id="browser-support-and-privacy" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/using_webcam_with_node-red/#browser-support-and-privacy"># </a> Browser support and privacy</h2>
<ul>
<li>Browser Compatibility: The webcam widget is compatible with all modern browsers, except Internet Explorer. Whether you're using Chrome, Firefox, Safari, or Edge, you can seamlessly integrate webcam features into your Node-RED applications.</li>
<li>Control Limitation: It's important to note that this widget is designed to interact with webcams directly accessible to the system running Node-RED. For example, if the webcam is connected to a different device or network and not directly accessible to the Node-RED running system, the video stream from that webcam won't be displayed on a dashboard using this widget.</li>
<li>HTTPS Requirement: When accessing Dashboard 2.0 remotely (not via <code>localhost</code>), it's crucial to use HTTPS. Failure to do so may result in the browser blocking access to the webcam.</li>
<li>User Permission: Before the webcam can be activated, the browser will prompt the user for permission to access the webcam device. This ensures user privacy and consent before any image capture occurs. The widget cannot capture images until the user has given their permission.</li>
</ul>
<h2 id="conclusion" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/03/using_webcam_with_node-red/#conclusion"># </a> Conclusion</h2>
<p>In this guide, we have guided you through the steps of integrating the webcam feature into Node-RED applications. Additionally, we have discussed the inner workings, privacy considerations, and browser compatibility of the webcam widget that we will use to integrate the webcam feature in Node-RED applications.</p>
https://flowfuse.com/blog/2024/02/history-of-nodered/History of Node-REDHow it all started as told by Node-RED creator Nick O'Leary2024-02-28T00:00:00ZNick O'Leary<p>In January 2013, I could have never foreseen that my fun little proof-of-concept project would become Node-RED, an open source low-code environment with millions of deployments in IoT and automation.</p>
<!--more-->
<p>Long before IoT became the ubiquitous term it is today, I was working in IBM’s Emerging Technology Group playing around with capturing data from devices and doing interesting things with it. The team focused on very fast-paced, short, proof-of-concept projects and was afforded time to learn new skills, innovate and work on side projects.</p>
<p>My background working with the MQTT protocol space before it was known outside of IBM led me to a side project: I wanted some way to visualize mapping messages on an MQTT infrastructure to see how they come in on one topic and get sent out on another.</p>
<p>Using it as an excuse to also start playing the relatively new Node.js runtime, I spent a day or two putting together a little demo of an application that would connect to an MQTT broker and visualize the topic mappings in a web browser.</p>
<p>Showing it to my colleague, Dave Conway-Jones, I mentioned it wouldn't take much to make it more interactive; to let you draw the mappings and apply them. He sent me on my way to do just that and, 24 hours later, I had a simple browser-based application that could define and apply mappings between MQTT topics.</p>
<p>It very quickly became useful.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/history-nr-screenshot-suha6UufnL-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/history-nr-screenshot-suha6UufnL-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="" loading="lazy" decoding="async" src="https://flowfuse.com/img/history-nr-screenshot-suha6UufnL-650.jpeg" width="650" height="495" /></picture></p>
<p class="italic" style="font-size: 0.9em; margin-top: -1rem;">An early screenshot of Node-RED</p>
<p>The projects Dave and I were working on became rich sources of requirements; each project needing to access data from some other source such as a device plugged into a serial port, or being able to modify the data with a bit of JavaScript code.</p>
<p>I spent a few days redesigning the code to make it easier to write in new nodes, unlocking the ability to quickly add in the function node, change node, and switch node, which became the basic building blocks of the tool.</p>
<p>The utility of the application was clear, and more colleagues started making use of it - all grounded in real client projects. But it was still a tool largely known only to our team.</p>
<h3 id="going-open-source" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/history-of-nodered/#going-open-source"># </a> Going Open Source</h3>
<p>As we considered how best to move the project forward, we essentially had two choices; keep it to ourselves and see if we could get an IBM product group to back turning it into a fully-fledged product, or to go the open source route. In my mind, the OSS route was the natural fit and that is what we ultimately chose to do, getting it published in late 2013.</p>
<p>I demoed Node-RED in late 2013 at a London IoT meetup and word spread among my peers in that community. A week later, I was at an open source hardware conference and attended a workshop on home automation. I was surprised to see Node-RED on everyone’s screens! The facilitator had seen Node-RED and reworked his workshop so that people didn’t have to worry about writing lines of code and were able to do useful things much more quickly.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/history-ibm-lab-P2wH0a6IKn-650.avif 650w, https://flowfuse.com/img/history-ibm-lab-P2wH0a6IKn-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/history-ibm-lab-P2wH0a6IKn-650.webp 650w, https://flowfuse.com/img/history-ibm-lab-P2wH0a6IKn-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/history-ibm-lab-P2wH0a6IKn-650.jpeg 650w, https://flowfuse.com/img/history-ibm-lab-P2wH0a6IKn-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="" loading="lazy" decoding="async" src="https://flowfuse.com/img/history-ibm-lab-P2wH0a6IKn-650.jpeg" width="1300" height="975" /></picture></p>
<p class="italic" style="font-size: 0.9em; margin-top: -1rem;">The IBM Emerging Technology Demo Lab - many of the demos were built on Node-RED</p>
<h3 id="building-an-audience" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/history-of-nodered/#building-an-audience"># </a> Building an audience</h3>
<p>A key step forward was when IBM was preparing to launch its new IBM Cloud service. In the months before the launch, they were looking for innovative ideas that could help expand the offering. We put forward a proposal to use this tool we'd created as a way to visualise the mapping of web services within the cloud.</p>
<p>This generated some great interest from a wider audience within the company, and whilst that concept didn't ultimately come to anything, we had gotten our project noticed.</p>
<p>Over time, we started seeing Node-RED being picked up by more than just the OSS community. Companies started using it with their own hardware devices and online services.</p>
<p>By this time, IBM Cloud had launched, and from our previous conversations with them, we got Node-RED included as one of the 'starter applications' in the catalogue that gave users a one-click option for getting Node-RED running in the cloud.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/history-cloud-catalog-ya8a2Mbcsr-650.avif 650w, https://flowfuse.com/img/history-cloud-catalog-ya8a2Mbcsr-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/history-cloud-catalog-ya8a2Mbcsr-650.webp 650w, https://flowfuse.com/img/history-cloud-catalog-ya8a2Mbcsr-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/history-cloud-catalog-ya8a2Mbcsr-650.jpeg 650w, https://flowfuse.com/img/history-cloud-catalog-ya8a2Mbcsr-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="" loading="lazy" decoding="async" src="https://flowfuse.com/img/history-cloud-catalog-ya8a2Mbcsr-650.jpeg" width="1300" height="454" /></picture></p>
<p class="italic" style="font-size: 0.9em; margin-top: -1rem;">Node-RED in the original IBM Cloud catalog</p>
<h3 id="moving-to-a-foundation" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/history-of-nodered/#moving-to-a-foundation"># </a> Moving to a Foundation</h3>
<p>As we saw the project grow, discussions were had around the longer-term future of the project. Some companies voiced a concern about it being a single-vendor open source project. This also came at a time when IBM was actively working with the Node.js project to help relaunch the Node Foundation (which has since become the OpenJS Foundation). This culminated in Node-RED joining the foundation as one of its founding projects, alongside other well-established projects such as Node.js itself, jQuery and many others.</p>
<p>Having an independent governance structure around the project gave companies more confidence to get involved, knowing they had an equal voice in its development. Hitachi became big supporters of the project and had a team dedicated to working on it.</p>
<p>For software developers, time spent writing boilerplate code is not time adding value to the application they’re building. With low-code, Node-RED abstracts all that boilerplate so they can focus on the business problem.</p>
<p>Device manufacturers paid attention when Node-RED was installed on the Raspberry Pi image, with its low-code accessibility attracting a broad range of people from systems engineers building automations to IoT hobbyists.</p>
<p>Now with millions of deployments, Node-RED continues to collect, transform, and integrate data through visualized dashboards. And, as this open source community grows it remains rooted in the two pillars of its low-code user experience, and its extensibility.</p>
https://flowfuse.com/blog/2024/02/why-citizen-development-platforms/Citizen Development: Unleashing Domain ExpertsWhy you should encourage domain experts to build applications2024-02-26T00:00:00ZGrey Dziuba<p>Citizen development has taken the spotlight recently, but the concept itself isn't entirely new. Remember the era of "hackers"? They weren't malicious actors, but individuals who tinkered with technology, pushing boundaries and creating solutions. Today, these same problem-solving personas have evolved into "<a href="https://www.gartner.com/en/information-technology/glossary/citizen-developer">citizen developers</a>" – business users empowered to build applications without relying solely on professional coders.</p>
<!--more-->
<h2 id="why-now%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/why-citizen-development-platforms/#why-now%3F"># </a> Why Now?</h2>
<p>While the drive for user-friendliness has always been present in programming languages, several factors have converged to push citizen development to the forefront:</p>
<ul>
<li>Democratization of Technology: Cloud computing and advancements in low-code/no-code platforms have lowered the barrier to entry, making development tools accessible to individuals with minimal technical expertise.</li>
<li>Business Agility: The need for rapid innovation necessitates solutions that bypass lengthy IT backlogs. Citizen developers can bridge the gap, creating applications and internal tools quickly and efficiently.</li>
<li>Domain Expertise: Business users possess deep insights into specific processes and challenges. By giving them the tools to build solutions, organizations can tap into a new knowledge source by putting domain experts into the driver's seat.</li>
</ul>
<h3 id="beyond-spreadsheets%3A-platforms-of-empowerment" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/why-citizen-development-platforms/#beyond-spreadsheets%3A-platforms-of-empowerment"># </a> Beyond Spreadsheets: Platforms of Empowerment</h3>
<p>Reports and Dashboards are often created by a BI teams that have to take information from specialists to create custom visualizations that may or may not come out to be exactly what they asked for. Queue old faiful, spreadsheets, where a domain expert can create their own reports that suit their needs. Spreadsheets are powerful for analysis, but they often lack the real-time secure connectivity needed for enterprise applications. Transform the knowledge created in a spreadsheet into a personalized real-time visualization. To do that, you must first select a citizen development platform and those platforms should offer:</p>
<ul>
<li>Visual Interfaces: Drag-and-drop functionality and pre-built components eliminate the need for complex coding, allowing users to focus on logic and functionality.</li>
<li>Integration Capabilities: Seamless connection with existing data sources and systems ensures that citizen-built applications integrate seamlessly into the overall workflow. Plus, the ability to create custom integrations.</li>
<li>Governance and Security: IT governance establishes guardrails while empowering users, ensuring data security and application stability through features like Role Based Access Control and SSO integration.</li>
<li>Collaboration Tools: Built-in collaboration features enable teams to share ideas, iterate on solutions, and ensure knowledge transfer.</li>
<li>Reseliency: Backup management.</li>
</ul>
<h3 id="citizen-developers%3A-not-rube-goldberg-machines%2C-but-value-creators" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/why-citizen-development-platforms/#citizen-developers%3A-not-rube-goldberg-machines%2C-but-value-creators"># </a> Citizen Developers: Not Rube Goldberg Machines, But Value Creators</h3>
<p>The key to successful citizen development lies in empowerment, not abdication. By providing the right tools, training, and governance, organizations can avoid creating complex, fragile solutions. Instead, citizen developers become powerful problem-solvers, building value-driven applications that address specific needs and contribute to overall business goals.</p>
<h2 id="lean-in" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/why-citizen-development-platforms/#lean-in"># </a> Lean In</h2>
<p>Remember, citizen development isn't about replacing professional developers. It's about creating a collaborative environment where everyone can contribute their unique skills and perspectives. By removing the coding barrier, we unleash a wider pool of innovators, accelerating progress and driving organizational success.</p>
https://flowfuse.com/blog/2024/02/postgresql-with-node-red/Using PostgreSQL with Node-REDGuide to integrating PostgreSQL database into Node-RED Applications for Storing, Updating, and Querying Data2024-02-23T00:00:00Z<p>A few months back, we shared a blog on <a href="https://flowfuse.com/blog/2023/07/connect-node-red-to-influxdb/">integrating InfluxDB with Node-RED</a> to handle time-series data effectively. However, applications typically involve more than just time-series data, they often include various data types that can be efficiently managed with SQL-based databases. In this guide, we will walk you through building a simple inventory management system with Node-RED and PostgreSQL to demonstrate how to integrate PostgreSQL with
Node-RED.</p>
<!--more-->
<h1 id="what-exactly-is-postgresql%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/postgresql-with-node-red/#what-exactly-is-postgresql%3F"># </a> What exactly is PostgreSQL?</h1>
<p>PostgreSQL is a highly reliable open-source relational database known for its extensive features. It supports diverse data types, robust SQL, and ACID compliance, allowing high-performance systems. Over the years, it has demonstrated reliability, security, and compatibility, which makes it a popular choice of businesses worldwide.</p>
<h2 id="using-postgresql-with-node-red" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/postgresql-with-node-red/#using-postgresql-with-node-red"># </a> Using PostgreSQL with Node-RED</h2>
<p>The first thing we need to do to get things started is to install the PostgreSQL custom node and gain an understanding of PostgreSQL configuration details.</p>
<ol>
<li>Install <code>node-red-contrib-postgresql</code> by the pallet manager. You can choose other nodes too, but we chose this node because it is part of the <a href="https://flowfuse.com/certified-nodes/">certified node catalogue by FlowFuse</a> which assures that the node is robust, secure, and developed with high-quality.</li>
<li>Before connecting to your PostgreSQL database, ensure you have the following information ready and environment variables set up as discussed below in <code>Adding environment variable</code> section:</li>
</ol>
<ul>
<li>Host: IP address or hostname of your PostgreSQL server.</li>
<li>Port: By default, PostgreSQL uses port 5432. Ensure this matches your PostgreSQL server configuration.</li>
<li>Database: The name of the PostgreSQL database you want to connect to.</li>
<li>User: Username with the necessary privileges to access the specified database.</li>
<li>Password: Corresponding password for the username.</li>
</ul>
<ol start="3">
<li>Drag the PostgreSQL node onto the canvas, click on that node and click on the edit icon next to the server input field to configure it.</li>
</ol>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/postgresql_with_node-red_pgconfig1-wzmy2maA3Y-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/postgresql_with_node-red_pgconfig1-wzmy2maA3Y-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Configuring PostgreSQL Connection" alt=""Configuring PostgreSQL Connection"" loading="lazy" decoding="async" src="https://flowfuse.com/img/postgresql_with_node-red_pgconfig1-wzmy2maA3Y-650.jpeg" width="650" height="570" /></picture></p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/postgresql_with_node-red_pgconfig2-jpmKyw0F1f-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/postgresql_with_node-red_pgconfig2-jpmKyw0F1f-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Configuring PostgreSQL Security" alt=""Configuring PostgreSQL Security"" loading="lazy" decoding="async" src="https://flowfuse.com/img/postgresql_with_node-red_pgconfig2-jpmKyw0F1f-650.jpeg" width="650" height="663" /></picture></p>
<h1 id="adding-environment-variables" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/postgresql-with-node-red/#adding-environment-variables"># </a> Adding environment variables</h1>
<p>We have discussed many times in previous blogs that using environment variables is a best practice that prevents revealing confidential configuration details such as API keys, passwords, secret keys, etc directly in the flow. Therefore, In this section, we will add environment variables for PostgreSQL configuration details, for more details see <a href="https://flowfuse.com/blog/2023/02/environment-variables-in-node-red/">Using Environment Variables in Node-RED</a>.</p>
<ol>
<li>Navigate to the instance's setting and then go to the environment section.</li>
<li>Click on the <code>add variable</code> button and add variables for each of the configuration data that we discussed in the above section.</li>
<li>Click on the save button and restart the instance by clicking on the top right <code>Action</code> button and selecting the restart option.</li>
</ol>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/postgresql_with_nodred_environment_variable-RwoUwE9897-650.avif 650w, https://flowfuse.com/img/postgresql_with_nodred_environment_variable-RwoUwE9897-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/postgresql_with_nodred_environment_variable-RwoUwE9897-650.webp 650w, https://flowfuse.com/img/postgresql_with_nodred_environment_variable-RwoUwE9897-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/postgresql_with_nodred_environment_variable-RwoUwE9897-650.jpeg 650w, https://flowfuse.com/img/postgresql_with_nodred_environment_variable-RwoUwE9897-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Adding environment variables" alt=""Adding environment variables"" loading="lazy" decoding="async" src="https://flowfuse.com/img/postgresql_with_nodred_environment_variable-RwoUwE9897-650.jpeg" width="1300" height="632" /></picture></p>
<h1 id="creating-table" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/postgresql-with-node-red/#creating-table"># </a> Creating Table</h1>
<p>In this section, we will create a table in our database to store product data.</p>
<ol>
<li>Drag an Inject node onto canvas, and keep it unchanged.</li>
<li>Click on the PostgreSQL node we added previously and paste the following SQL command into the query input field. (I have added comments for your understanding of SQL commands)</li>
</ol>
<div style="position: relative">
<pre class="language-sql"><code id="code-112" class="language-sql"><span class="token comment">-- Create a table named product_data if it does not already exist</span><br /><span class="token keyword">CREATE</span> <span class="token keyword">TABLE</span> <span class="token keyword">IF</span> <span class="token operator">NOT</span> <span class="token keyword">EXISTS</span> product_data <span class="token punctuation">(</span><br /> <span class="token comment">-- Define a column named id as a SERIAL type, which serves as the primary key</span><br /> id <span class="token keyword">SERIAL</span> <span class="token keyword">PRIMARY</span> <span class="token keyword">KEY</span><span class="token punctuation">,</span> <span class="token comment">-- SERIAL data type automatically generates unique integer values for each row inserted into the table</span><br /> <br /> <span class="token comment">-- Define a column named name to store product names as variable-length character strings with a maximum length of 100 characters, ensuring it's not null</span><br /> name <span class="token keyword">varchar</span><span class="token punctuation">(</span><span class="token number">100</span><span class="token punctuation">)</span> <span class="token operator">NOT</span> <span class="token boolean">NULL</span><span class="token punctuation">,</span><br /> <br /> <span class="token comment">-- Define a column named price to store product prices, ensuring it's not null</span><br /> price <span class="token keyword">int</span> <span class="token operator">NOT</span> <span class="token boolean">NULL</span><span class="token punctuation">,</span><br /> <br /> <span class="token comment">-- Define a column named stock to store product stock levels, ensuring it's not null</span><br /> stock <span class="token keyword">int</span> <span class="token operator">NOT</span> <span class="token boolean">NULL</span><br /><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-112" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/postgresql_with_nodered_create_table-4kGUcZTOa9-586.avif 586w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/postgresql_with_nodered_create_table-4kGUcZTOa9-586.webp 586w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Creating table for product data" alt=""Creating table for product data"" loading="lazy" decoding="async" src="https://flowfuse.com/img/postgresql_with_nodered_create_table-4kGUcZTOa9-586.jpeg" width="586" height="665" /></picture></p>
<ol start="3">
<li>Connect the inject node’s output to the PostgreSQL node’s input.</li>
</ol>
<h1 id="installing-dashboard-2.0" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/postgresql-with-node-red/#installing-dashboard-2.0"># </a> Installing Dashboard 2.0</h1>
<ol>
<li>Install Dashboard 2.0. Follow these <a href="https://dashboard.flowfuse.com/getting-started.html">instructions</a> to install.</li>
<li>Create your first group, page, theme, and base.</li>
</ol>
<h1 id="inserting-product-data-into-the-database" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/postgresql-with-node-red/#inserting-product-data-into-the-database"># </a> Inserting Product Data into the Database</h1>
<p>In this section, we will add a Form interface that will enable us to obtain product data that we need to insert into the database. Moreover, we will use the PostgreSQL node to interact with the database.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/postgresql_with_node-red_form1-Oq-iabkMnx-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/postgresql_with_node-red_form1-Oq-iabkMnx-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Adding form to insert data" alt=""Adding form to insert data"" loading="lazy" decoding="async" src="https://flowfuse.com/img/postgresql_with_node-red_form1-Oq-iabkMnx-650.jpeg" width="650" height="449" /></picture></p>
<ol>
<li>Drag a ui-form widget onto the canvas and select the created ui-group.</li>
<li>Add an element for all required input data in the form widget and give it a name, label, and select type, I have selected 'number' as a type for 'price' and 'stock', and 'text' for 'name', but feel free to adjust according to your preference and data requirements.</li>
<li>Drag the function node onto Canvas and paste the following script.</li>
</ol>
<div style="position: relative">
<pre class="language-javascript"><code id="code-164" class="language-javascript"><span class="token comment">// Destructure the properties from msg.payload (obtained data by using form)</span><br /><span class="token keyword">const</span> <span class="token punctuation">{</span>name<span class="token punctuation">,</span> price<span class="token punctuation">,</span> stock <span class="token punctuation">}</span> <span class="token operator">=</span> msg<span class="token punctuation">.</span>payload<span class="token punctuation">;</span><br /><span class="token comment">// Create an array containing name, price, and stock</span><br /><span class="token comment">// The order of the array items in msg.params will correspond to the placeholders in the SQL query</span><br /><span class="token comment">// For example, $1 will be replaced by the value of name, $2 will be replaced by the value of price, and so on</span><br />msg<span class="token punctuation">.</span>params <span class="token operator">=</span> <span class="token punctuation">[</span>name<span class="token punctuation">,</span> price<span class="token punctuation">,</span> stock<span class="token punctuation">]</span><span class="token punctuation">;</span><br /><span class="token keyword">return</span> msg<span class="token punctuation">;</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-164" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<ol start="4">
<li>Drag a PostgreSQL node onto the Canvas and click on that node and paste the following SQL command into the query input field</li>
</ol>
<div style="position: relative">
<pre class="language-sql"><code id="code-172" class="language-sql"><span class="token comment">-- This is an SQL INSERT statement used to add data into the product_data table.</span><br /><span class="token keyword">INSERT</span> <span class="token keyword">INTO</span> product_data <span class="token punctuation">(</span> name<span class="token punctuation">,</span> price<span class="token punctuation">,</span> stock<span class="token punctuation">)</span><br /><span class="token comment">-- This line specifies the columns into which data will be inserted. The columns are name, price, and stock.</span><br /><span class="token comment">-- It's important to match the columns in the same order as the values in the next line.</span><br /><span class="token keyword">VALUES</span> <span class="token punctuation">(</span>$<span class="token number">1</span><span class="token punctuation">,</span> $<span class="token number">2</span><span class="token punctuation">,</span> $<span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-172" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/postgresql_with_node-red_insert_data-fm1NRi4oC9-579.avif 579w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/postgresql_with_node-red_insert_data-fm1NRi4oC9-579.webp 579w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Inserting data into database" alt=""Inserting data into database"" loading="lazy" decoding="async" src="https://flowfuse.com/img/postgresql_with_node-red_insert_data-fm1NRi4oC9-579.jpeg" width="579" height="651" /></picture></p>
<ol start="5">
<li>Connect ui-form’s output to the function node’s input and the function node's output to the PostgreSQL node’s input.</li>
</ol>
<h1 id="displaying-product-data-on-dashboard-2.0" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/postgresql-with-node-red/#displaying-product-data-on-dashboard-2.0"># </a> Displaying product data on Dashboard 2.0</h1>
<p>In this section, we will retrieve all data from our database table and display it on Dashboard 2.0 using the ui-table widget.</p>
<ol>
<li>Drag an Inject node onto the canvas.</li>
<li>Drag a PostgreSQL node onto the Canvas and click on that node and paste the following SQL command into the query input field.</li>
<li>Drag a ui-table widget onto the canvas and create a new ui-group for it.</li>
<li>Connect the inject node's output to the PostgreSQL node’s input and the PostgreSQL node's output to the ui-table's input.</li>
</ol>
<div style="position: relative">
<pre class="language-sql"><code id="code-211" class="language-sql"><span class="token comment">-- Retrieve all data from the product_data table</span><br /><span class="token keyword">SELECT</span> <span class="token operator">*</span> <span class="token keyword">FROM</span> product_data<span class="token punctuation">;</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-211" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/postgresql_with_node-red_retrive_data-29gzbNPpKL-588.avif 588w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/postgresql_with_node-red_retrive_data-29gzbNPpKL-588.webp 588w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Retriving all product data from database" alt=""Retriving all product data from database"" loading="lazy" decoding="async" src="https://flowfuse.com/img/postgresql_with_node-red_retrive_data-29gzbNPpKL-588.jpeg" width="588" height="530" /></picture></p>
<h1 id="updating-product-data-to-the-database" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/postgresql-with-node-red/#updating-product-data-to-the-database"># </a> Updating product data to the Database</h1>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/postgresql_with_node-red_form2-TLrtEmJF2P-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/postgresql_with_node-red_form2-TLrtEmJF2P-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="adding form to update product data" alt=""Adding form to update product data"" loading="lazy" decoding="async" src="https://flowfuse.com/img/postgresql_with_node-red_form2-TLrtEmJF2P-650.jpeg" width="650" height="464" /></picture></p>
<p>In this section, we will add a form interface to collect the product ID and the new stock value for the update process. Feel free to select other data fields that you need to update. To achieve this, we will add a form interface using Dashboard 2.0. Additionally, we will interact with the database using the same PostgreSQL node that we have used so far in this guide.</p>
<ol>
<li>Drag a ui-form widget onto the canvas and create a new ui-group for it.</li>
<li>Add elements for product id and stock in the form widget and give it a name, label, and select type.</li>
<li>Drag a function node onto Canvas and paste the following script.</li>
</ol>
<div style="position: relative">
<pre class="language-javascript"><code id="code-241" class="language-javascript"><span class="token comment">// Destructure the properties from msg.payload</span><br /><span class="token keyword">const</span> <span class="token punctuation">{</span> id<span class="token punctuation">,</span> stock <span class="token punctuation">}</span> <span class="token operator">=</span> msg<span class="token punctuation">.</span>payload<span class="token punctuation">;</span><br /><span class="token comment">// Create an array containing id and stock</span><br /><span class="token comment">// The order of the array items in msg.params will correspond to the placeholders in the SQL query</span><br /><span class="token comment">// For example, $1 will be replaced by the value of id, $2 will be replaced by the value of stock</span><br />msg<span class="token punctuation">.</span>params <span class="token operator">=</span> <span class="token punctuation">[</span>id<span class="token punctuation">,</span> stock<span class="token punctuation">]</span><span class="token punctuation">;</span><br /><span class="token keyword">return</span> msg<span class="token punctuation">;</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-241" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<ol start="4">
<li>Drag a PostgreSQL node on canvas, click on that node and paste the following SQL command into the query input field.</li>
</ol>
<div style="position: relative">
<pre class="language-sql"><code id="code-249" class="language-sql"><span class="token comment">-- UPDATE statement to modify data in the product_data table</span><br /><br /><span class="token keyword">UPDATE</span> product_data <br /><span class="token comment">-- Specifies the table to be updated (product_data)</span><br /><br /><span class="token keyword">SET</span> <br /> stock <span class="token operator">=</span> $<span class="token number">2</span><br /><span class="token comment">-- Sets the value of the "stock" column to the value represented by the parameter $2.</span><br /><span class="token comment">-- The value to be set is typically provided externally, In our context, we get this parameter by "msg.params"</span><br /><br /><span class="token keyword">WHERE</span> id <span class="token operator">=</span> $<span class="token number">1</span><span class="token punctuation">;</span><br /><span class="token comment">-- Specifies the condition that must be met for the update to occur.</span><br /><span class="token comment">-- In this case, it updates rows where the "id" column matches the value represented by the parameter $1.</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-249" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/postgresql_with_node-red_update_data-T4f9j66uXf-592.avif 592w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/postgresql_with_node-red_update_data-T4f9j66uXf-592.webp 592w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Updating product data to the database" alt=""Updating product data to the database"" loading="lazy" decoding="async" src="https://flowfuse.com/img/postgresql_with_node-red_update_data-T4f9j66uXf-592.jpeg" width="592" height="620" /></picture></p>
<ol start="5">
<li>Connect ui-form’s output to the function node’s input and the function node's output to the PostgreSQL node’s input.</li>
</ol>
<h1 id="deleting-product-data-from-the-database" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/postgresql-with-node-red/#deleting-product-data-from-the-database"># </a> Deleting product data from the database</h1>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/postgresql_with_node-red_form3-ISvh_wSeX9-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/postgresql_with_node-red_form3-ISvh_wSeX9-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Deleting product data to the database" alt=""Deleting product data to the database"" loading="lazy" decoding="async" src="https://flowfuse.com/img/postgresql_with_node-red_form3-ISvh_wSeX9-650.jpeg" width="650" height="506" /></picture></p>
<p>In this section, we'll cover how to delete product data from the database. We will use Dashboard 2.0's form interface to collect essential information like the product id and name. While the product id alone is sufficient to delete a product from the database, we include the product name as an additional precaution to prevent accidental deletion of product data.</p>
<ol>
<li>Drag a ui-form widget onto the canvas and create a new ui-group for it.</li>
<li>Add elements for product id and name in the form widget and give it a name, label, and select type.</li>
<li>Drag a function node onto Canvas and paste the following script.</li>
</ol>
<div style="position: relative">
<pre class="language-javascript"><code id="code-286" class="language-javascript"><span class="token comment">// Destructure the properties from msg.payload</span><br /><span class="token keyword">const</span> <span class="token punctuation">{</span> id<span class="token punctuation">,</span> name <span class="token punctuation">}</span> <span class="token operator">=</span> msg<span class="token punctuation">.</span>payload<span class="token punctuation">;</span><br /><span class="token comment">// Create an array containing id and name</span><br /><span class="token comment">// The order of the array items in msg.params will correspond to the placeholders in the SQL query</span><br /><span class="token comment">// For example, $1 will be replaced by the value of id, $2 will be replaced by the value of name</span><br />msg<span class="token punctuation">.</span>params <span class="token operator">=</span> <span class="token punctuation">[</span>id<span class="token punctuation">,</span> name <span class="token punctuation">]</span><span class="token punctuation">;</span><br /><span class="token keyword">return</span> msg<span class="token punctuation">;</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-286" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<ol start="4">
<li>Drag a PostgreSQL node on canvas, click on that node and paste the following SQL command into the query input field.</li>
</ol>
<div style="position: relative">
<pre class="language-sql"><code id="code-294" class="language-sql"><span class="token comment">-- Deletes rows from the "product_data" table where both "id" and "name" match the given parameters</span><br /><span class="token keyword">DELETE</span> <span class="token keyword">FROM</span> product_data <br /><span class="token comment">-- Specifies the conditions for deletion</span><br /><span class="token keyword">WHERE</span> id <span class="token operator">=</span> $<span class="token number">1</span> <span class="token operator">AND</span> name <span class="token operator">=</span> $<span class="token number">2</span><span class="token punctuation">;</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-294" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/postgresql_with_node-red_delete_data-migvUk6ERT-588.avif 588w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/postgresql_with_node-red_delete_data-migvUk6ERT-588.webp 588w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Deleting product data to the database" alt=""Deleting product data to the database"" loading="lazy" decoding="async" src="https://flowfuse.com/img/postgresql_with_node-red_delete_data-migvUk6ERT-588.jpeg" width="588" height="566" /></picture></p>
<ol start="5">
<li>Connect ui-form’s output to the function node’s input and the function node's output to PostgreSQL node’s input.</li>
</ol>
<h1 id="dropping-table" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/postgresql-with-node-red/#dropping-table"># </a> Dropping Table</h1>
<p>This section will explain how to drop ( delete ) tables from the database.</p>
<ol>
<li>Drag an Inject node onto the canvas.</li>
<li>Drag a PostgreSQL node onto canvas and paste the following SQL command into the query input field.</li>
</ol>
<div style="position: relative">
<pre class="language-sql"><code id="code-323" class="language-sql"><span class="token comment">-- Drop the table 'product_data' if it exists to avoid conflicts.</span><br /><span class="token keyword">DROP</span> <span class="token keyword">TABLE</span> <span class="token keyword">IF</span> <span class="token keyword">EXISTS</span> product_data<span class="token punctuation">;</span><br /><br /><span class="token comment">-- Note: 'IF EXISTS' is used to check if the table exists in the database before attempting to drop it.</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-323" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/postgresql_with_node-red_drop_tables-WYjzw-OsrT-588.avif 588w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/postgresql_with_node-red_drop_tables-WYjzw-OsrT-588.webp 588w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Droping product_data from the database" alt=""Droping product_data from the database"" loading="lazy" decoding="async" src="https://flowfuse.com/img/postgresql_with_node-red_drop_tables-WYjzw-OsrT-588.jpeg" width="588" height="604" /></picture></p>
<h1 id="deploying-flow" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/postgresql-with-node-red/#deploying-flow"># </a> Deploying Flow</h1>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/postgresql_with_nodred_environment_variable_ff_editor-5Oq_92oTCI-650.avif 650w, https://flowfuse.com/img/postgresql_with_nodred_environment_variable_ff_editor-5Oq_92oTCI-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/postgresql_with_nodred_environment_variable_ff_editor-5Oq_92oTCI-650.webp 650w, https://flowfuse.com/img/postgresql_with_nodred_environment_variable_ff_editor-5Oq_92oTCI-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/postgresql_with_nodred_environment_variable_ff_editor-5Oq_92oTCI-650.jpeg 650w, https://flowfuse.com/img/postgresql_with_nodred_environment_variable_ff_editor-5Oq_92oTCI-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Deploying Inventory management system's flow" alt=""Deploying Inventory management system's flow"" loading="lazy" decoding="async" src="https://flowfuse.com/img/postgresql_with_nodred_environment_variable_ff_editor-5Oq_92oTCI-650.jpeg" width="1300" height="610" /></picture></p>
<p>Our Inventory Management System is now complete and ready for deployment. To initiate the deployment process, locate the red 'Deploy' button positioned in the top right corner. To create, drop tables, and retrieve table data, click on the 'Inject Node' button. For product data insertion, updates, and deletions, navigate to <code>https://<your-instance-name>.flowfuse.cloud/dashboard</code>.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/postgresql_with_node-red_Inventory_management_system-8F0AYW4nTB-650.avif 650w, https://flowfuse.com/img/postgresql_with_node-red_Inventory_management_system-8F0AYW4nTB-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/postgresql_with_node-red_Inventory_management_system-8F0AYW4nTB-650.webp 650w, https://flowfuse.com/img/postgresql_with_node-red_Inventory_management_system-8F0AYW4nTB-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/postgresql_with_node-red_Inventory_management_system-8F0AYW4nTB-650.jpeg 650w, https://flowfuse.com/img/postgresql_with_node-red_Inventory_management_system-8F0AYW4nTB-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Inventory management system" alt=""Inventory management system"" loading="lazy" decoding="async" src="https://flowfuse.com/img/postgresql_with_node-red_Inventory_management_system-8F0AYW4nTB-650.jpeg" width="1300" height="614" /></picture></p>
<h2 id="best-practices-to-follow" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/postgresql-with-node-red/#best-practices-to-follow"># </a> Best practices to follow</h2>
<p>Throughout this guide, we have followed some best practices that we think need to be discussed separately. In this section, we'll discuss some best practices that need to be followed while using the PostgreSQL database.</p>
<ol>
<li>
<p>Connection Pooling: Implementing connection pooling can significantly enhance the performance of PostgreSQL. It allows multiple clients to reuse database connections, reducing the overhead of establishing new connections for each query. By configuring PostgreSQL to use connection pooling, you can optimize resource usage and improve overall system performance. In this guide, we have configured our PostgreSQL to use connection pooling via the Postgres Config node/tab.</p>
</li>
<li>
<p>Environment Variables: The <a href="https://12factor.net/">Twelve Factors</a> emphasize the importance of separating configuration details from the code (flow) to ensure better security. Storing database credentials within the codebase can pose a security risk. Instead, expose the configuration details, as environment variables. This ensures that sensitive information remains secure and can be managed separately from the codebase.</p>
</li>
<li>
<p>Credential Rotation: Regularly rotating database credentials is essential for maintaining robust security practices. This includes changing login information for managed databases and other database access points. Implementing a scheduled credential rotation process, such as quarterly 'rotation days,' streamlines the task and reduces the risk of unauthorized access.</p>
</li>
</ol>
<h1 id="conclusion" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/postgresql-with-node-red/#conclusion"># </a> Conclusion</h1>
<p>This guide has demonstrated the integration of PostgreSQL with Node-RED. Throughout this article, we've built an inventory management system with data stored in a database. You've learned to create and drop tables and perform operations like inserting, updating, and deleting data. Also, we have highlighted best practices, such as utilizing environment variables and selecting certified nodes to ensure security.</p>
https://flowfuse.com/blog/2024/02/taking-it-further-with-node-red/Storing Data: Getting Started with Node-REDNode-RED is one of the easiest ways to program ever created but everyone needs a little help2024-02-19T00:00:00ZRob Marcer<p>It's quite straightforward to pass plenty of useful data with each message (msg) in your flows. Not only can you store information in msg.payload, but you can also place information in any other named object, for instance, msg.store.</p>
<!--more-->
<p>In this article, we will explore some of the better solutions for storing and retrieving transactional information in your flows.</p>
<h4 id="storing-data-outside-of-msg.payload" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/taking-it-further-with-node-red/#storing-data-outside-of-msg.payload"># </a> Storing data outside of msg.payload</h4>
<p>In this example, we have data in msg.payload as well as in msg.later.</p>
<p><picture><source type="image/gif" srcset="https://flowfuse.com/img/data-outside-msg-payload-SMjDhqJt-E-650.gif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Storing data outside of msg.payload" alt="Storing data outside of msg.payload" loading="lazy" decoding="async" src="https://flowfuse.com/img/data-outside-msg-payload-SMjDhqJt-E-650.webp" width="650" height="226" /></picture></p>
<p>If you want your debug to display the full content of the message, change the output to 'complete message object' as shown above.</p>
<p>You can import the flow using this code.</p>
<div style="position: relative">
<pre class="language-json"><code id="code-22" class="language-json"><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"aaa1e17e5f158004"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"67746003c844dbc4"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Inject the message"</span><span class="token punctuation">,</span><span class="token property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"later"</span><span class="token punctuation">,</span><span class="token property">"v"</span><span class="token operator">:</span><span class="token string">"A string I want to be able to use later in my flow"</span><span class="token punctuation">,</span><span class="token property">"vt"</span><span class="token operator">:</span><span class="token string">"str"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"repeat"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"once"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"onceDelay"</span><span class="token operator">:</span><span class="token number">0.1</span><span class="token punctuation">,</span><span class="token property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"payload"</span><span class="token operator">:</span><span class="token string">"Hello World"</span><span class="token punctuation">,</span><span class="token property">"payloadType"</span><span class="token operator">:</span><span class="token string">"str"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">690</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">140</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"bce1bf09736125b7"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"bce1bf09736125b7"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"debug"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"67746003c844dbc4"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"debug 1"</span><span class="token punctuation">,</span><span class="token property">"active"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"tosidebar"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"console"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"tostatus"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"complete"</span><span class="token operator">:</span><span class="token string">"true"</span><span class="token punctuation">,</span><span class="token property">"targetType"</span><span class="token operator">:</span><span class="token string">"full"</span><span class="token punctuation">,</span><span class="token property">"statusVal"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"statusType"</span><span class="token operator">:</span><span class="token string">"auto"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">880</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">140</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">]</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-22" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>Storing data outside of msg.payload can be very useful when you need access to that data later in your flow. You may notice that many nodes overwrite the content of msg.payload, so putting your data elsewhere is essential otherwise, it will be overwritten and lost.</p>
<h4 id="tidying-your-messages" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/taking-it-further-with-node-red/#tidying-your-messages"># </a> Tidying your messages</h4>
<p>You may also want to remove data you don't need from your messages to optimize the speed of your flows.</p>
<p>It's easy enough to remove data you don't need, wherever it sits within your messages using the Change Node. In this example, we are going to delete the content of msg.other while leaving the rest of the message to be passed to the next Node.</p>
<p><picture><source type="image/gif" srcset="https://flowfuse.com/img/delete-other-N0V0b_jWnm-650.gif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Deleting data from msg.other" alt="Deleting data from msg.other" loading="lazy" decoding="async" src="https://flowfuse.com/img/delete-other-N0V0b_jWnm-650.webp" width="650" height="196" /></picture></p>
<p>The Change Node is configured as follows.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/delete-EbnbfRJ_27-561.avif 561w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/delete-EbnbfRJ_27-561.webp 561w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Change Node configuration" alt="Change Node configuration" loading="lazy" decoding="async" src="https://flowfuse.com/img/delete-EbnbfRJ_27-561.jpeg" width="561" height="290" /></picture></p>
<p>You can import the flow using this code.</p>
<div style="position: relative">
<pre class="language-json"><code id="code-47" class="language-json"><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"1ac51e71153f7c1f"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"67746003c844dbc4"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Inject the message"</span><span class="token punctuation">,</span><span class="token property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"other"</span><span class="token punctuation">,</span><span class="token property">"v"</span><span class="token operator">:</span><span class="token string">"We don't need this string anymore"</span><span class="token punctuation">,</span><span class="token property">"vt"</span><span class="token operator">:</span><span class="token string">"str"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"repeat"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"once"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"onceDelay"</span><span class="token operator">:</span><span class="token number">0.1</span><span class="token punctuation">,</span><span class="token property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"payload"</span><span class="token operator">:</span><span class="token string">"Hello World"</span><span class="token punctuation">,</span><span class="token property">"payloadType"</span><span class="token operator">:</span><span class="token string">"str"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">530</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">100</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"5d3a978ad9eab443"</span><span class="token punctuation">,</span><span class="token string">"cd7609101328caa2"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"5d3a978ad9eab443"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"debug"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"67746003c844dbc4"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"debug 2"</span><span class="token punctuation">,</span><span class="token property">"active"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"tosidebar"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"console"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"tostatus"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"complete"</span><span class="token operator">:</span><span class="token string">"true"</span><span class="token punctuation">,</span><span class="token property">"targetType"</span><span class="token operator">:</span><span class="token string">"full"</span><span class="token punctuation">,</span><span class="token property">"statusVal"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"statusType"</span><span class="token operator">:</span><span class="token string">"auto"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">700</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">60</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"cd7609101328caa2"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"67746003c844dbc4"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"t"</span><span class="token operator">:</span><span class="token string">"delete"</span><span class="token punctuation">,</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"other"</span><span class="token punctuation">,</span><span class="token property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">730</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">100</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"be2f7f68dee570be"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"be2f7f68dee570be"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"debug"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"67746003c844dbc4"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"debug 3"</span><span class="token punctuation">,</span><span class="token property">"active"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"tosidebar"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"console"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"tostatus"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"complete"</span><span class="token operator">:</span><span class="token string">"true"</span><span class="token punctuation">,</span><span class="token property">"targetType"</span><span class="token operator">:</span><span class="token string">"full"</span><span class="token punctuation">,</span><span class="token property">"statusVal"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"statusType"</span><span class="token operator">:</span><span class="token string">"auto"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">900</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">100</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">]</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-47" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<h4 id="storing-data-outside-of-msg.payload-so-you-can-access-it-later-in-your-flows" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/taking-it-further-with-node-red/#storing-data-outside-of-msg.payload-so-you-can-access-it-later-in-your-flows"># </a> Storing data outside of msg.payload so you can access it later in your flows</h4>
<p>Storing data outside of msg.payload allows you to access it later in your flows. In this example, we inject geographical coordinates and use an API to get the sunset time for each location. We can then output the result as a sentence.</p>
<p>As the HTTP Node, which we are using to interact with the weather API, overwrites msg.payload with the response, we will store the submitted city name and coordinates in msg.store for later use.</p>
<p>You can see the flow working below.</p>
<p><picture><source type="image/gif" srcset="https://flowfuse.com/img/sunset-example-jsDwOaJQKU-650.gif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Example flow which gets the sunset time for a given location" alt="Example flow which gets the sunset time for a given location" loading="lazy" decoding="async" src="https://flowfuse.com/img/sunset-example-jsDwOaJQKU-650.webp" width="650" height="254" /></picture></p>
<p>You can import the flow using this code.</p>
<div style="position: relative">
<pre class="language-json"><code id="code-66" class="language-json"><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"809cc8f4678767b7"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"67746003c844dbc4"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"London"</span><span class="token punctuation">,</span><span class="token property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"payload.city"</span><span class="token punctuation">,</span><span class="token property">"v"</span><span class="token operator">:</span><span class="token string">"London"</span><span class="token punctuation">,</span><span class="token property">"vt"</span><span class="token operator">:</span><span class="token string">"str"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"payload.lat"</span><span class="token punctuation">,</span><span class="token property">"v"</span><span class="token operator">:</span><span class="token string">"51.5072"</span><span class="token punctuation">,</span><span class="token property">"vt"</span><span class="token operator">:</span><span class="token string">"str"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"payload.lng"</span><span class="token punctuation">,</span><span class="token property">"v"</span><span class="token operator">:</span><span class="token string">"0.1276"</span><span class="token punctuation">,</span><span class="token property">"vt"</span><span class="token operator">:</span><span class="token string">"str"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"repeat"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"once"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"onceDelay"</span><span class="token operator">:</span><span class="token number">0.1</span><span class="token punctuation">,</span><span class="token property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">170</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">80</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"6b5a6a2ef7a64f1a"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"b86d2d558eebbd7e"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"67746003c844dbc4"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Washington DC"</span><span class="token punctuation">,</span><span class="token property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"payload.city"</span><span class="token punctuation">,</span><span class="token property">"v"</span><span class="token operator">:</span><span class="token string">"Washington DC"</span><span class="token punctuation">,</span><span class="token property">"vt"</span><span class="token operator">:</span><span class="token string">"str"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"payload.lat"</span><span class="token punctuation">,</span><span class="token property">"v"</span><span class="token operator">:</span><span class="token string">"38.9072"</span><span class="token punctuation">,</span><span class="token property">"vt"</span><span class="token operator">:</span><span class="token string">"str"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"payload.lng"</span><span class="token punctuation">,</span><span class="token property">"v"</span><span class="token operator">:</span><span class="token string">"77.0369"</span><span class="token punctuation">,</span><span class="token property">"vt"</span><span class="token operator">:</span><span class="token string">"str"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"repeat"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"once"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"onceDelay"</span><span class="token operator">:</span><span class="token number">0.1</span><span class="token punctuation">,</span><span class="token property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">140</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">160</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"6b5a6a2ef7a64f1a"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"aaecc81a2de233d6"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"debug"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"67746003c844dbc4"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"debug 4"</span><span class="token punctuation">,</span><span class="token property">"active"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"tosidebar"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"console"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"tostatus"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"complete"</span><span class="token operator">:</span><span class="token string">"false"</span><span class="token punctuation">,</span><span class="token property">"statusVal"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"statusType"</span><span class="token operator">:</span><span class="token string">"auto"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">820</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">160</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"6b5a6a2ef7a64f1a"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"67746003c844dbc4"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"store"</span><span class="token punctuation">,</span><span class="token property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">320</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">120</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"273ee743f8d1a5f1"</span><span class="token punctuation">,</span><span class="token string">"af43cea5866e11f5"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"273ee743f8d1a5f1"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"template"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"67746003c844dbc4"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"create the URL"</span><span class="token punctuation">,</span><span class="token property">"field"</span><span class="token operator">:</span><span class="token string">"url"</span><span class="token punctuation">,</span><span class="token property">"fieldType"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"format"</span><span class="token operator">:</span><span class="token string">"handlebars"</span><span class="token punctuation">,</span><span class="token property">"syntax"</span><span class="token operator">:</span><span class="token string">"mustache"</span><span class="token punctuation">,</span><span class="token property">"template"</span><span class="token operator">:</span><span class="token string">"https://api.sunrisesunset.io/json?lat=&lng="</span><span class="token punctuation">,</span><span class="token property">"output"</span><span class="token operator">:</span><span class="token string">"str"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">500</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">120</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"52e8913233f379eb"</span><span class="token punctuation">,</span><span class="token string">"1d94053c790791ee"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"af43cea5866e11f5"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"debug"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"67746003c844dbc4"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"debug 5"</span><span class="token punctuation">,</span><span class="token property">"active"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"tosidebar"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"console"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"tostatus"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"complete"</span><span class="token operator">:</span><span class="token string">"true"</span><span class="token punctuation">,</span><span class="token property">"targetType"</span><span class="token operator">:</span><span class="token string">"full"</span><span class="token punctuation">,</span><span class="token property">"statusVal"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"statusType"</span><span class="token operator">:</span><span class="token string">"auto"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">480</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">160</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"52e8913233f379eb"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"http request"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"67746003c844dbc4"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"method"</span><span class="token operator">:</span><span class="token string">"GET"</span><span class="token punctuation">,</span><span class="token property">"ret"</span><span class="token operator">:</span><span class="token string">"obj"</span><span class="token punctuation">,</span><span class="token property">"paytoqs"</span><span class="token operator">:</span><span class="token string">"ignore"</span><span class="token punctuation">,</span><span class="token property">"url"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"tls"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"persist"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"proxy"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"insecureHTTPParser"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"authType"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"senderr"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"headers"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">670</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">120</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"aaecc81a2de233d6"</span><span class="token punctuation">,</span><span class="token string">"a245b322ade3a7e9"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"1d94053c790791ee"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"debug"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"67746003c844dbc4"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"debug 6"</span><span class="token punctuation">,</span><span class="token property">"active"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"tosidebar"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"console"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"tostatus"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"complete"</span><span class="token operator">:</span><span class="token string">"true"</span><span class="token punctuation">,</span><span class="token property">"targetType"</span><span class="token operator">:</span><span class="token string">"full"</span><span class="token punctuation">,</span><span class="token property">"statusVal"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"statusType"</span><span class="token operator">:</span><span class="token string">"auto"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">660</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">80</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"a245b322ade3a7e9"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"template"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"67746003c844dbc4"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Create the sentence"</span><span class="token punctuation">,</span><span class="token property">"field"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"fieldType"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"format"</span><span class="token operator">:</span><span class="token string">"handlebars"</span><span class="token punctuation">,</span><span class="token property">"syntax"</span><span class="token operator">:</span><span class="token string">"mustache"</span><span class="token punctuation">,</span><span class="token property">"template"</span><span class="token operator">:</span><span class="token string">"The sun will set at in ."</span><span class="token punctuation">,</span><span class="token property">"output"</span><span class="token operator">:</span><span class="token string">"str"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">860</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">120</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"3e4b2d3644845f91"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"3e4b2d3644845f91"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"debug"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"67746003c844dbc4"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"debug 7"</span><span class="token punctuation">,</span><span class="token property">"active"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"tosidebar"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"console"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"tostatus"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"complete"</span><span class="token operator">:</span><span class="token string">"false"</span><span class="token punctuation">,</span><span class="token property">"statusVal"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"statusType"</span><span class="token operator">:</span><span class="token string">"auto"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">1040</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">120</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">]</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-66" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>Using this technique, we can build the content of message.store (or any other name you'd like to use) and then output the content at the end of a flow, even if you use msg.payload to interact with APIs and other custom nodes.</p>
<h4 id="why-not-store-the-values-in-context%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/taking-it-further-with-node-red/#why-not-store-the-values-in-context%3F"># </a> Why not store the values in context?</h4>
<p>Where possible, it's more robust to store all the information related to a particular message within the message rather than saving it to context and retrieving it later. Using context risks a <a href="https://en.wikipedia.org/wiki/Race_condition#:~:text=A%20race%20condition%20or%20race,to%20unexpected%20or%20inconsistent%20results">race condition</a> within your flow that could result in data corruption.</p>
<p>In this example, we simulate how a race condition can make context a bad choice for transactional data storage. The flow passes in the name and age of two people then moves the age to context. The flow then adds a random delay for each message so that, in some cases, the messages do not reach the debug in the order they were created. After the delay, the age is pulled back from context and added to each msg.payload.</p>
<p><picture><source type="image/gif" srcset="https://flowfuse.com/img/race-condition-YyJKcqFYsf-650.gif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Example of how a race condition can make context a bad place to cache data" alt="Example of how a race condition can make context a bad place to cache data" loading="lazy" decoding="async" src="https://flowfuse.com/img/race-condition-YyJKcqFYsf-650.webp" width="650" height="222" /></picture></p>
<p>If there is a race condition in play, we should intermittently see Rob and John's stored ages being assigned to the wrong person. We can see in the image above that Rob is showing the incorrect age.</p>
<p>You can import the flow using this code.</p>
<div style="position: relative">
<pre class="language-json"><code id="code-88" class="language-json"><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"7ac4e7165d99f041"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"67746003c844dbc4"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Rob"</span><span class="token punctuation">,</span><span class="token property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"payload.name"</span><span class="token punctuation">,</span><span class="token property">"v"</span><span class="token operator">:</span><span class="token string">"Rob"</span><span class="token punctuation">,</span><span class="token property">"vt"</span><span class="token operator">:</span><span class="token string">"str"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"payload.age"</span><span class="token punctuation">,</span><span class="token property">"v"</span><span class="token operator">:</span><span class="token string">"46"</span><span class="token punctuation">,</span><span class="token property">"vt"</span><span class="token operator">:</span><span class="token string">"str"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"repeat"</span><span class="token operator">:</span><span class="token string">"2"</span><span class="token punctuation">,</span><span class="token property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"once"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"onceDelay"</span><span class="token operator">:</span><span class="token number">0.1</span><span class="token punctuation">,</span><span class="token property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">570</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">840</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"1e0575bd662f9277"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"e9c0baba4f50b0b2"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"67746003c844dbc4"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"John"</span><span class="token punctuation">,</span><span class="token property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"payload.name"</span><span class="token punctuation">,</span><span class="token property">"v"</span><span class="token operator">:</span><span class="token string">"John"</span><span class="token punctuation">,</span><span class="token property">"vt"</span><span class="token operator">:</span><span class="token string">"str"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"payload.age"</span><span class="token punctuation">,</span><span class="token property">"v"</span><span class="token operator">:</span><span class="token string">"29"</span><span class="token punctuation">,</span><span class="token property">"vt"</span><span class="token operator">:</span><span class="token string">"str"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"repeat"</span><span class="token operator">:</span><span class="token string">"2"</span><span class="token punctuation">,</span><span class="token property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"once"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"onceDelay"</span><span class="token operator">:</span><span class="token number">0.1</span><span class="token punctuation">,</span><span class="token property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">570</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">880</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"1e0575bd662f9277"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"d5f688682206d316"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"67746003c844dbc4"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"age"</span><span class="token punctuation">,</span><span class="token property">"pt"</span><span class="token operator">:</span><span class="token string">"flow"</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">"payload.age"</span><span class="token punctuation">,</span><span class="token property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">850</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">860</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"d56225e59bde93cf"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"d56225e59bde93cf"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"67746003c844dbc4"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"t"</span><span class="token operator">:</span><span class="token string">"delete"</span><span class="token punctuation">,</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"payload.age"</span><span class="token punctuation">,</span><span class="token property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">1050</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">860</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"d5a119b311bf8377"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"e3ec11b4e038e564"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"debug"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"67746003c844dbc4"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"debug 8"</span><span class="token punctuation">,</span><span class="token property">"active"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"tosidebar"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"console"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"tostatus"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"complete"</span><span class="token operator">:</span><span class="token string">"false"</span><span class="token punctuation">,</span><span class="token property">"statusVal"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"statusType"</span><span class="token operator">:</span><span class="token string">"auto"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">1080</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">940</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"d5a119b311bf8377"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"delay"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"67746003c844dbc4"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"pauseType"</span><span class="token operator">:</span><span class="token string">"random"</span><span class="token punctuation">,</span><span class="token property">"timeout"</span><span class="token operator">:</span><span class="token string">"5"</span><span class="token punctuation">,</span><span class="token property">"timeoutUnits"</span><span class="token operator">:</span><span class="token string">"seconds"</span><span class="token punctuation">,</span><span class="token property">"rate"</span><span class="token operator">:</span><span class="token string">"1"</span><span class="token punctuation">,</span><span class="token property">"nbRateUnits"</span><span class="token operator">:</span><span class="token string">"1"</span><span class="token punctuation">,</span><span class="token property">"rateUnits"</span><span class="token operator">:</span><span class="token string">"second"</span><span class="token punctuation">,</span><span class="token property">"randomFirst"</span><span class="token operator">:</span><span class="token string">"0"</span><span class="token punctuation">,</span><span class="token property">"randomLast"</span><span class="token operator">:</span><span class="token string">"5"</span><span class="token punctuation">,</span><span class="token property">"randomUnits"</span><span class="token operator">:</span><span class="token string">"seconds"</span><span class="token punctuation">,</span><span class="token property">"drop"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"allowrate"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"outputs"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">720</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">940</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"b329d7f2685d0ed6"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"b329d7f2685d0ed6"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"67746003c844dbc4"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"payload.age"</span><span class="token punctuation">,</span><span class="token property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">"age"</span><span class="token punctuation">,</span><span class="token property">"tot"</span><span class="token operator">:</span><span class="token string">"flow"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">900</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">940</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"e3ec11b4e038e564"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"1e0575bd662f9277"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"delay"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"67746003c844dbc4"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"pauseType"</span><span class="token operator">:</span><span class="token string">"random"</span><span class="token punctuation">,</span><span class="token property">"timeout"</span><span class="token operator">:</span><span class="token string">"5"</span><span class="token punctuation">,</span><span class="token property">"timeoutUnits"</span><span class="token operator">:</span><span class="token string">"seconds"</span><span class="token punctuation">,</span><span class="token property">"rate"</span><span class="token operator">:</span><span class="token string">"1"</span><span class="token punctuation">,</span><span class="token property">"nbRateUnits"</span><span class="token operator">:</span><span class="token string">"1"</span><span class="token punctuation">,</span><span class="token property">"rateUnits"</span><span class="token operator">:</span><span class="token string">"second"</span><span class="token punctuation">,</span><span class="token property">"randomFirst"</span><span class="token operator">:</span><span class="token string">"0"</span><span class="token punctuation">,</span><span class="token property">"randomLast"</span><span class="token operator">:</span><span class="token string">"1"</span><span class="token punctuation">,</span><span class="token property">"randomUnits"</span><span class="token operator">:</span><span class="token string">"seconds"</span><span class="token punctuation">,</span><span class="token property">"drop"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"allowrate"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"outputs"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">700</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">860</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"d5f688682206d316"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">]</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-88" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<h4 id="conclusion" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/taking-it-further-with-node-red/#conclusion"># </a> Conclusion</h4>
<p>Storing transactional data in msg rather than context in Node-RED offers advantages in modularity, scalability, simplicity, and also helps prevent race conditions. By using msg, data transfer between nodes becomes more seamless, allowing for independent node reuse across flows without additional configuration. This approach ensures scalability by avoiding the imposition of large datasets on the global context. Moreover, storing data outside of msg.payload within the msg object enhances flexibility. It separates metadata and other relevant information from the main payload, promoting a cleaner and more organized structure. This practice not only aligns with Node-RED's visual programming paradigm but also improves code readability. Steering clear of context for transactional data, while also organizing it within the msg object, provides a comprehensive and reliable solution within the Node-RED framework.</p>
<p>Thanks to <a href="https://sunrisesunset.io/">SunriseSunset</a> for creating the useful API we've used in this article.</p>
https://flowfuse.com/blog/2024/02/node-red-unified-namespace-architecture/Node-RED in a Unified Namespace ArchitectureHow does Node-RED elevate a Unified Namespace Architecture?2024-02-14T00:00:00ZMarian Demme<p>As we embark on the journey toward a more interconnected industrial environment, the emergence of a Unified Namespace (UNS) as the fundamental framework for facilitating communication among various systems and devices has become a focal point of discussion. I've often been queried about the role of Node-RED in a UNS architecture. To illuminate this, let's delve into an exemplary UNS architecture, underlining the classic use cases for Node-RED within this framework.</p>
<!--more-->
<p>In this Article: <a href="https://flowfuse.com/blog/2024/02/node-red-perfect-adapter-middleware-uns/">Node-RED: The perfect adapter and middleware for your UNS</a>, where classic use cases for Node-RED are delineated. Building upon that foundation, this discussion aims to present a tangible architectural example, showcasing the practical implementation of these use cases.</p>
<h2 id="simplifying-complexity%3A-the-two-layered-approach" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/node-red-unified-namespace-architecture/#simplifying-complexity%3A-the-two-layered-approach"># </a> Simplifying Complexity: The Two-Layered Approach</h2>
<p>For ease of understanding, consider the architecture split into two principal layers: the Shopfloor layer and the Service layer.</p>
<p><strong>The Shopfloor Layer</strong>
This is where the physical assets dwell, requiring connectivity through a network layer, which in our example, is the UNS. It acts as the foundation for data flow from the operational technology (OT) on the shop floor to the information technology (IT) in the Service layer.</p>
<p><strong>The Service Layer</strong>
Here resides the applications and software that analyze data, transforming raw metrics into actionable insights. It's where the data becomes meaningful through analytics, dashboards, and decision-support tools.</p>
<h2 id="the-roles-in-uns-architecture" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/node-red-unified-namespace-architecture/#the-roles-in-uns-architecture"># </a> The Roles in UNS Architecture</h2>
<p>Within this bifurcated architecture, we have two general categories of actors: Indirect Consumer/Producers and Direct Consumer/Producers.</p>
<p><strong>Indirect Consumer/Producers</strong>:
These actors cannot natively communicate with our UNS broker. The communication barrier could be due to protocol differences, such as not using MQTT, or payload structures incompatible with your UNS's schema. This is a common challenge in manufacturing, especially in "brownfield" scenarios where legacy machines and equipment from various eras must be integrated.</p>
<p>In such cases, Node-RED shines as a middleware for protocol conversion and data contextualization. Take, for example, the topic hierarchy in UNS based on location for context. A raw sensor reading might lack necessary details like measurement units or message versions. Node-RED steps in to enrich this data, ensuring compatibility with the UNS. In our <a href="https://flowfuse.com/blog/2023/12/unified-namespace-data-modelling/">concrete architecture example</a>, we have an indirect PLC producer. With Node-RED, we can convert and contextualize the data from this PLC for the UNS, ensuring smooth communication and effective integration.</p>
<p><strong>Direct Consumer/Producers</strong>:
Contrastingly, direct actors can interact with the UNS out of the box. Modern industrial equipment usually falls into this category, equipped to speak the language of the UNS directly. However, the challenge remains not just in protocol communication but also in data contextualization. Merely speaking the same language is not enough; the data must also carry the correct context to be fully understood and utilized.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/unified-namespace-architecture-hUxpOvAc1R-650.avif 650w, https://flowfuse.com/img/unified-namespace-architecture-hUxpOvAc1R-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/unified-namespace-architecture-hUxpOvAc1R-650.webp 650w, https://flowfuse.com/img/unified-namespace-architecture-hUxpOvAc1R-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/unified-namespace-architecture-hUxpOvAc1R-650.jpeg 650w, https://flowfuse.com/img/unified-namespace-architecture-hUxpOvAc1R-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Example Architecture" loading="lazy" decoding="async" src="https://flowfuse.com/img/unified-namespace-architecture-hUxpOvAc1R-650.jpeg" width="1300" height="731" /></picture></p>
<h2 id="harnessing-node-red-for-actionable-insights" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/node-red-unified-namespace-architecture/#harnessing-node-red-for-actionable-insights"># </a> Harnessing Node-RED for Actionable Insights</h2>
<p>Node-RED's prowess extends beyond middleware capabilities; it can also derive actionable insights. Our example architecture includes Dashboards for both the Human Machine Interface on the Shopfloor and an OEE Dashboard in the Service Layer. These dashboards engage with the UNS, calculating KPIs directly within Node-RED. For manufacturing applications, our <a href="https://flowfuse.com/blueprints/">Blueprint Library</a> serves as a robust starting point, offering one-click deployment to your Node-RED managed instance.
Node-RED emerges not just as a translator between machines and UNS but as an interpreter and analyst, generating real-time insights that drive decision-making and operational efficiency. The role of Node-RED in UNS architecture, therefore, is not ancillary; it is central to realizing the vision of a connected, intelligent industrial ecosystem.</p>
<p><img alt="Andon Live Dashboard" loading="lazy" decoding="async" src="https://flowfuse.com/img/ANDON-Screenshot-D4DBvWieJZ-650.avif" width="undefined" height="undefined" /></p>
https://flowfuse.com/blog/2024/02/connect-node-red-to-kepware-opc/Connect Node-RED to KepserverEX OPC server.Step by step guide to connect to PTC's Kepware OPC server.2024-02-12T00:00:00ZGrey Dziuba<p>KepserverEX, often referred to as Kepware, is an OPC server that has been the important tool many manufacturing companies have used on their digital transformation journey. It plays an important role for many to extract data from PLCs, Programmable Logic Controllers, without having to directly interact with them.</p>
<!--more-->
<h1 id="ptc's-kepserverex" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/connect-node-red-to-kepware-opc/#ptc's-kepserverex"># </a> PTC's KepserverEX</h1>
<p>PTC's <a href="https://www.ptc.com/en/products/kepware/kepserverex-ppc">KEPServerEX</a> is a versatile connectivity platform designed to securely manage, monitor, and control diverse automation devices and software applications. Central to its functionality is the OPC standard, which enables universal communication across industrial hardware and software, facilitating data exchange. This makes KEPServerEX particularly valuable in a variety of use cases, such as real-time data monitoring, machine-to-machine (M2M) communication, and industrial Internet of Things (IIoT) applications. It serves as a critical bridge in the automation and controls engineering space, offering a robust solution for integrating disparate systems, thereby enhancing operational efficiency and enabling data-driven decision-making. Integrating KEPServerEX with Node-RED extends this functionality, by allowing bidirectional communication for sending, storing, and or manipulating data.</p>
<h2 id="scope" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/connect-node-red-to-kepware-opc/#scope"># </a> Scope</h2>
<p>The goal of this blog is for a quick start guide on the configuration for collecting data from a KepserverEX OPC server. We are going to be leveraging the <a href="https://flows.nodered.org/node/node-red-contrib-opcua">node-red-contrib-opcua</a> node. We will assume that you already have <a href="https://www.ptc.com/en/products/kepware/kepserverex-ppc">KepserverEX</a> install and ready for the integration. We will be using Basic256Sha256 security in this guide with anonymous authentication. Assumptions of the installation include allowing Default configuration of the installation of KepserverEX 6.15 and allowing dynamic tag addressing.</p>
<h2 id="configure-connection-from-node-red-to-kepserver" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/connect-node-red-to-kepware-opc/#configure-connection-from-node-red-to-kepserver"># </a> Configure Connection from Node-RED to Kepserver</h2>
<h3 id="step-1%3A-kepserverex" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/connect-node-red-to-kepware-opc/#step-1%3A-kepserverex"># </a> Step 1: KepserverEX</h3>
<p>The first thing we need to do is check our <strong>OPC UA Configuration Manager</strong> for the security requirements for our environment. In the tray at the bottom, click on the KepserverEX symbol and select <strong>OPC UA Configuration</strong></p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/kepserverex-tray-QqmK2jUgGh-219.avif 219w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/kepserverex-tray-QqmK2jUgGh-219.webp 219w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="kepware tray" loading="lazy" decoding="async" src="https://flowfuse.com/img/kepserverex-tray-QqmK2jUgGh-219.jpeg" width="219" height="326" /></picture></p>
<p>If your Node-RED instance lives on the same server that your KepserverEX is on, pick accordingly or click add if you need to define by ip address. This is for setting different credential requirements for localhost vs remote host access. Also note, that if you have multiple network adapters, make sure to select the adapter that is in use.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/kep-endpoint-definition-MV8GQdyozv-543.avif 543w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/kep-endpoint-definition-MV8GQdyozv-543.webp 543w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="kepware endpoint definition" loading="lazy" decoding="async" src="https://flowfuse.com/img/kep-endpoint-definition-MV8GQdyozv-543.jpeg" width="543" height="347" /></picture></p>
<p>We are testing locally on the server, so we will use the one selected for loopback addressing. We will be leaving the OPC server port as default and select <strong>Basic256Sha256</strong> with <strong>Sign and Encrypt</strong>.</p>
<p>Click <strong>OK</strong>.</p>
<h3 id="step-2%3A-node-red" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/connect-node-red-to-kepware-opc/#step-2%3A-node-red"># </a> Step 2: Node-RED</h3>
<p>Next, navigate to your Node-RED instance and install the <a href="https://flows.nodered.org/node/node-red-contrib-opcua">node-red-contrib-opcua</a> node if you haven't already done so.</p>
<p>Import the flow below into your Node-RED environment.</p>
<iframe width="100%" height="225px" src="https://flows.nodered.org/flow/04a84fe5b0db7cda9e74ba811e7b0ca5/share?height=250" allow="clipboard-read; clipboard-write" style="border: none;"></iframe>
<p>Next, let's configure the <strong>OPC UA Client</strong>. Click the <strong>pencil</strong> to add a new OPCUA-Endpoint.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/opcua-endpoint-node-red-encrypted-pnhgwT-Uka-510.avif 510w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/opcua-endpoint-node-red-encrypted-pnhgwT-Uka-510.webp 510w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="kepware node-red encrypted opc ua node" loading="lazy" decoding="async" src="https://flowfuse.com/img/opcua-endpoint-node-red-encrypted-pnhgwT-Uka-510.jpeg" width="510" height="425" /></picture></p>
<p>For the endpoint, <strong>copy</strong> the endpoint definition from the KepserverEX OPC UA Configuration Manager. In our example, it is <code>opc.tcp://127.0.0.1:49320</code>, and paste it into the Endpoint. For SecurityPolicy select <strong>Basic256Sha256</strong>. For SecurityMode, select <strong>Sign&Encrypt</strong>. Lastly, we will be selecting <strong>Anonymous</strong>. Click <strong>Update</strong>, then <strong>Deploy</strong>.</p>
<p>Trigger the flow by <strong>clicking</strong> on the inject node. The server may not connect at this time, and it is expected.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/node-red-opc-ua-invalid-endpoint-t5uZPH6xlb-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/node-red-opc-ua-invalid-endpoint-t5uZPH6xlb-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="kepware node-red invalid endpoint" loading="lazy" decoding="async" src="https://flowfuse.com/img/node-red-opc-ua-invalid-endpoint-t5uZPH6xlb-650.jpeg" width="650" height="91" /></picture></p>
<h3 id="step-3%3A-kepserverex" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/connect-node-red-to-kepware-opc/#step-3%3A-kepserverex"># </a> Step 3: KepserverEX</h3>
<p>Moving back over to KepserverEX, Click on the tray again in the bottom of the screen and select <strong>Configuration</strong>, then select <strong>Edit</strong> from the file menu, then <strong>Properties</strong>. Next, Select <strong>OPC UA</strong> and ensure that <strong>Allow Anonymous login</strong> is set to <strong>Yes</strong>. Click <strong>OK</strong>.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/node-red-kepware-anonymous-login-3B-EJsJH6O-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/node-red-kepware-anonymous-login-3B-EJsJH6O-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="kepware node-red anonymous login" loading="lazy" decoding="async" src="https://flowfuse.com/img/node-red-kepware-anonymous-login-3B-EJsJH6O-650.jpeg" width="650" height="385" /></picture></p>
<p>Select the tray at the bottom of the screen again, and select <strong>OPC UA Configuration</strong>. Select the <strong>Trusted Clients</strong> tab.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/kepserverex-trusted-client-before-pVmF0OD14u-618.avif 618w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/kepserverex-trusted-client-before-pVmF0OD14u-618.webp 618w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="kepware node-red trusted client before" loading="lazy" decoding="async" src="https://flowfuse.com/img/kepserverex-trusted-client-before-pVmF0OD14u-618.jpeg" width="618" height="456" /></picture></p>
<p>Now select the <strong>NodeOPCUA-Client</strong> and then <strong>click</strong> Trust. <em><strong>If you don't have the client option, trigger the inject node again from the Node-RED flow and check the logs</strong></em></p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/kepserverex-trusted-client-after-C9-aKvQ9hf-621.avif 621w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/kepserverex-trusted-client-after-C9-aKvQ9hf-621.webp 621w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="kepware node-red trusted client after" loading="lazy" decoding="async" src="https://flowfuse.com/img/kepserverex-trusted-client-after-C9-aKvQ9hf-621.jpeg" width="621" height="463" /></picture></p>
<h3 id="step-4%3A-node-red" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/connect-node-red-to-kepware-opc/#step-4%3A-node-red"># </a> Step 4: Node-RED</h3>
<p>Lastly, Navigate back to Node-RED and <strong>trigger</strong> the inject node. This node will now browse the project from the KepserverEX and display all of the existing tags.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/kepware-opc-browsed-tags-node-red-9I-AK21K3k-460.avif 460w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/kepware-opc-browsed-tags-node-red-9I-AK21K3k-460.webp 460w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="kepware node-red browsed tags" loading="lazy" decoding="async" src="https://flowfuse.com/img/kepware-opc-browsed-tags-node-red-9I-AK21K3k-460.jpeg" width="460" height="596" /></picture></p>
<h2 id="read-tags" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/connect-node-red-to-kepware-opc/#read-tags"># </a> Read Tags</h2>
<p>We will be leveraging the default Simulated Examples for reading tags from KepserverEX. Let's move on to the next set of flows.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/node-red-kepware-read-tag-5xMr3AhvM7-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/node-red-kepware-read-tag-5xMr3AhvM7-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="kepware node-red read tags" loading="lazy" decoding="async" src="https://flowfuse.com/img/node-red-kepware-read-tag-5xMr3AhvM7-650.jpeg" width="650" height="61" /></picture></p>
<p>Edit the OPCUa-Item node and note the item.</p>
<pre><code>ns=2;s=Simulation Examples.Functions.Ramp1
</code></pre>
<p>Let's break down the syntax, ns stands for namespace that will coincide with the project. In this case, it is namespace 2. Once the namespace has been selected, we are use <strong>Dynamic Addressing</strong> to select the tag through the variable <strong>s</strong>, which stands for string type of NodeId. <strong>Click</strong> Done. Now let's <strong>trigger</strong> the Read inject node and view the debug output.</p>
<p>The debug node is set to show a complete msg object. Note the payload as the value of the variable.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/node-red-debug-output-opc-uiECBwJsXC-473.avif 473w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/node-red-debug-output-opc-uiECBwJsXC-473.webp 473w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="kepware node-red read tags output" loading="lazy" decoding="async" src="https://flowfuse.com/img/node-red-debug-output-opc-uiECBwJsXC-473.jpeg" width="473" height="278" /></picture></p>
<h2 id="write-tag" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/connect-node-red-to-kepware-opc/#write-tag"># </a> Write Tag</h2>
<p>Writing a tag is a similar process. The only difference is that a variable is set in the <strong>OPCUa-Item</strong> node and the <strong>OPCUa-Client</strong> action is set to Write.</p>
<p>In this example, we created a new variable in KepserverEX under <strong>Simulation Examples > Functions</strong> called myInt of Date Type Long.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/node-red-kepware-write-tag-cg08zZsS9T-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/node-red-kepware-write-tag-cg08zZsS9T-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="kepware node-red write tags" loading="lazy" decoding="async" src="https://flowfuse.com/img/node-red-kepware-write-tag-cg08zZsS9T-650.jpeg" width="650" height="69" /></picture></p>
<p>View the OPCUa-Item node and note the item.</p>
<pre><code>ns=2;s=Simulation Examples.Functions.myInt
</code></pre>
<p><strong>Click</strong> Done and <strong>Deploy</strong></p>
<p>Open up the <strong>Quick Client</strong> within KepserverEX and navigate to the address of <strong>Simulation Examples.Functions</strong> and look for myInt. It should by default, be 0. <strong>Trigger</strong> the inject node within Node-RED to see the Value change within the Quick Client.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/node-red-debug-output-write-opc-1-Tfg-UK3T-485.avif 485w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/node-red-debug-output-write-opc-1-Tfg-UK3T-485.webp 485w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="kepware node-red write tags output" loading="lazy" decoding="async" src="https://flowfuse.com/img/node-red-debug-output-write-opc-1-Tfg-UK3T-485.jpeg" width="485" height="321" /></picture>
<picture><source type="image/avif" srcset="https://flowfuse.com/img/kepware-quick-client-lh5PnZay82-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/kepware-quick-client-lh5PnZay82-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="kepware node-red quick client" loading="lazy" decoding="async" src="https://flowfuse.com/img/kepware-quick-client-lh5PnZay82-650.jpeg" width="650" height="214" /></picture></p>
<h2 id="conclusion" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/connect-node-red-to-kepware-opc/#conclusion"># </a> Conclusion</h2>
<p>This guide was designed to help you easily connect your Node-RED instance to KepserverEX with security. For more examples of how to do more advanced configuration, please watch the past <a href="https://flowfuse.com/webinars/2023/getting-started-opcua-node-red/">webinar</a> going over these <a href="https://github.com/mikakaraila/node-red-contrib-opcua/tree/master/examples">examples</a> in detail.</p>
https://flowfuse.com/blog/2024/02/software-development-in-node-red/Bringing Software Development practices to Node-REDApplying lessons from traditional development to the low-code space.2024-02-06T00:00:00ZNick O'Leary<p>I'm always thinking about how we can continue to improve the Node-RED experience. One area I like to explore is to make sure we learn the right lessons from the Software Development world.</p>
<p>In this post, I'm going to look at some of the common practices in modern Software Development and show how they translate to the Node-RED world.</p>
<!--more-->
<h3 id="linting" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/software-development-in-node-red/#linting"># </a> Linting</h3>
<p>Linting is a way of examining some code and automatically spotting things that need attention. This can range from stylistic errors ("Use tabs, not spaces") to real bugs that will prevent the code from working as intended.</p>
<p>This is all about spotting problems <em>before</em> the code runs. It also helps ensure consistency when you have multiple people contributing to the code.</p>
<p>Having code that is consistently formatted and free of syntactic mistakes makes it much easier to maintain.</p>
<p>Applying this concept to Node-RED, we have the <a href="https://github.com/node-red/nrlint"><code>nrlint</code> tool</a>. This is a linting tool that can run either on the command-line or within the editor directly to spot potential problems with the flows.</p>
<p>On the stylistic side, for example, it can highlight nodes that aren't properly aligned to the grid. Whilst this doesn't have any bearing on the runtime operation of the flow, it encourages keeping the flows tidy and orderly.</p>
<p>It can help identify potential infinite loops in flows, and highlight Debug nodes without a name set.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/node-red-linter-AIfk_2k73f-650.avif 650w, https://flowfuse.com/img/node-red-linter-AIfk_2k73f-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/node-red-linter-AIfk_2k73f-650.webp 650w, https://flowfuse.com/img/node-red-linter-AIfk_2k73f-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/node-red-linter-AIfk_2k73f-650.jpeg 650w, https://flowfuse.com/img/node-red-linter-AIfk_2k73f-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="" loading="lazy" decoding="async" src="https://flowfuse.com/img/node-red-linter-AIfk_2k73f-650.jpeg" width="1300" height="367" /></picture></p>
<h3 id="debugging" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/software-development-in-node-red/#debugging"># </a> Debugging</h3>
<p>Whether you are writing lines of code or not, eventually you will need to figure out why your application isn't doing what you think it should.</p>
<p>In Software Engineering there are two typical approaches. One is to add debug statements through the code to print out bits of information as the program runs. Then, depending on what output you got, you'd move the debug statements around, add some more, print out different bits of information - all until you'd nailed down the problem. This is the Debug node approach in Node-RED; adding nodes at different points of your flow to capture some piece of information and then iterating as you go.</p>
<p>This is probably how most Node-RED users go about it today. The downside is you end up leaving the Debug nodes in place, capturing information long after it is needed.</p>
<p>The alternative approach is Step-by-Step debugging. This is why you are able to pause the program and then step it forward one statement at a time - examining the state at each point. But what's the equivalent for low-code? Pretty much exactly that when you have the <a href="https://flows.nodered.org/node/node-red-debugger">Node-RED Debugger plugin</a> installed.</p>
<p>This allows you to set 'breakpoints' on any node input or output that are triggered when a message arrives at that point of the flow. The Debugger will then pause the whole runtime and shows you all of the queued up messages in the flow.</p>
<p>You can then examine those messages and tell the Debugger to 'release' them one at a time - seeing how the flow progresses.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/node-red-debugger-D38_PJq6FA-650.avif 650w, https://flowfuse.com/img/node-red-debugger-D38_PJq6FA-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/node-red-debugger-D38_PJq6FA-650.webp 650w, https://flowfuse.com/img/node-red-debugger-D38_PJq6FA-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/node-red-debugger-D38_PJq6FA-650.jpeg 650w, https://flowfuse.com/img/node-red-debugger-D38_PJq6FA-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="" loading="lazy" decoding="async" src="https://flowfuse.com/img/node-red-debugger-D38_PJq6FA-650.jpeg" width="1300" height="695" /></picture></p>
<h3 id="testing" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/software-development-in-node-red/#testing"># </a> Testing</h3>
<p>Testing code is a critical part of developing software. You want to make sure it does what you want. But it's more than just manually testing it once and then letting it go; you want to have tests you can run regularly, whenever you make changes, to ensure you don't break something that was working previously.</p>
<p>In the Software Development world, there are all sorts of testing methodologies and techniques; unit testing individual components, system testing larger sections, stubbing out components to simulate different conditions, integrating test suites into the whole development process.</p>
<p>They each have their own place in the process of software development. The question is, how does this apply to Node-RED?</p>
<p>Most Node-RED users today will of course be testing their flows whilst developing them - iterating until the flow does what is needed. It's far less common to have a set of repeatable tests including the flows.</p>
<p>That is certainly achievable with Node-RED today, albeit with some limitations. For example, a typical test will be to verify that, given a set of particular inputs, the outputs look correct. This can be done using Inject nodes to quickly trigger messages with different values, and use Debug nodes to examine the results.</p>
<p>That isn't ideal as you end up littering your flows with these extra Inject nodes, and it still requires manually verifying the results. It also doesn't work well if your flows need to interact with external systems - such as saving values to a database. You don't want to pollute your system with test data.</p>
<p>So what would be the ideal workflow? This is something the project has spent some time exploring in the past, and the start of a design was put together.</p>
<p>The concept would be to introduce a Testing sidebar to the editor. Within that, you can define a set of test cases. Then for each test case, you can customise the behaviours of individual nodes. For example, a test case may disable an MQTT node at the start of a flow, and tell the runtime to inject a message in its place. For each subsequent node in the flow, the test case would then be able to either to bypass it (to avoid interacting with external systems), or to add checks on what the node outputs. Each test case would then define some criteria for what it means to pass the test.</p>
<p>As with the Debugger plugin, the Test Runner would be disabled by default - so the 'production' flows aren't modified in anyway. When the Test Runner is enabled, it would then take care of running each test in return and reporting back the results.</p>
<p>The main challenge is providing a user experience that makes it easy to create these tests in a way that is consistent with the low-code nature of Node-RED.</p>
<p>Whilst this is very much a future roadmap item for Node-RED, it is one I hope we can start moving forward soon. Having a good, repeatable, testing strategy in Node-RED will make it stand-out from many of the other low-code tools and platforms available today.</p>
<h3 id="low-code-vs-lines-of-code" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/software-development-in-node-red/#low-code-vs-lines-of-code"># </a> Low-Code vs Lines-of-Code</h3>
<p>The low-code nature of Node-RED means it is easily accessible to a wide range of users. You don't need to be a seasoned software engineer to get started.</p>
<p>If you have a task to solve, and understand it well enough to break it into the right set of steps, translating that into a Node-RED flow can be much easier than having to write all of the corresponding code from scratch.</p>
<p>Just because you aren't writing code in Node-RED, it doesn't mean you shouldn't be able to benefit from ways of working that are proven to improve the end result - whilst keeping true to the low-code nature of the project.</p>
<h3 id="flowfuse-cloud" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/software-development-in-node-red/#flowfuse-cloud"># </a> FlowFuse Cloud</h3>
<p>Both <code>nrlint</code> and Node-RED Debugger are already pre-installed in all <a href="https://app.flowfuse.com/">FlowFuse Cloud</a> hosted instances. You can start using them today via the sidebar menu.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/node-red-sidebar---eVf1YJ7O-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/node-red-sidebar---eVf1YJ7O-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="" loading="lazy" decoding="async" src="https://flowfuse.com/img/node-red-sidebar---eVf1YJ7O-650.jpeg" width="650" height="648" /></picture></p>
https://flowfuse.com/blog/2024/02/node-red-perfect-adapter-middleware-uns/Node-RED: The perfect adapter and middleware for your UNSHow Node-RED Enhances Connectivity and Efficiency in Unified Namespace Environments.2024-02-06T00:00:00ZZJ van de WegMarian Demme<p>Digitalization is at the inflection point where it’s been adopted enough that the additional investments provided better and better ROIs for organizations. The next bump in ROI will be achieved through the UNS. A torrent of information is more useful when structured and adapted for new use-cases. Either a <a href="https://flowfuse.com/blueprints/manufacturing/performance-overview/">performance dashboard</a>, Artificial Intelligence, or station metrics – each is built faster when the data is readily available and well structured? As a company started around Node-RED, we’ve not spoken a lot where FlowFuse fits into the picture, which is what this post is about.</p>
<!--more-->
<h3 id="adapting-legacy-machines-to-the-uns" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/node-red-perfect-adapter-middleware-uns/#adapting-legacy-machines-to-the-uns"># </a> Adapting legacy machines to the UNS</h3>
<p>The digitalization effort in traditional industries like manufacturing, agriculture, and beyond, has additional challenges due to the high capex assets that need to join in the effort. As these assets will not be replaced, the only way is to adapt them. Adaptation will require tooling that can interact with sensor data regardless of the protocol, data format, and data structures.</p>
<p>Node-RED bridges the gap between analog and digital data acquisition by seamlessly integrating with a vast array of protocols including serial bus support, Modbus, MQTT, and OPC-UA. Its format agnostic nature allows it to handle diverse data formats, from parsing binary data, to JSON, Protobuf (Sparkplug B), making it a versatile tool for extracting and manipulating data from various sources. With its widespread adoption, Node-RED ensures compatibility with almost every protocol, enabling users to connect and process data from a wide range of devices and applications.</p>
<h3 id="contextualisation-of-the-data" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/node-red-perfect-adapter-middleware-uns/#contextualisation-of-the-data"># </a> Contextualisation of the data</h3>
<p>When data is captured and parsed, it needs to be contextualized. For example; in a UNS the topic hierarchy on which to publish and subscribe to is based on location – that is; context. Furthermore, a raw sensor reading might miss details like the unit of measurement, what message version is required, or doesn’t supply the information in a proper type. All these minor niggles are actual blocking issues for adopting all sensors to the UNS. In some cases makes and models of the sensor might influence the tolerances of readings, it’s a good idea in those cases to include that information in the message.</p>
<h3 id="filtering-and-preprocessing" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/node-red-perfect-adapter-middleware-uns/#filtering-and-preprocessing"># </a> Filtering and preprocessing</h3>
<p>Not all messages are created equal, which was discussed in <a href="https://flowfuse.com/blog/2024/01/unified-namespace-when-not-to-use/">an earlier post</a>. In two of the three examples provided in that post, Node-RED can preprocess or filter information before sending it to the UNS. In the case of big files or binary data, Node-RED can store it in S3 or a network attached storage layer, or even store it locally through a REST interface. The distribution of the event that created the binary data is still published through the UNS though.</p>
<p>Filtering of data is also a great use-case for Node-RED, generally just a <code>change</code> node and the data is ready to be published. The flexibility to do virtually anything with captured data is what makes Node-RED such a strong partner for your UNS.</p>
<h3 id="continuous-improvement" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/node-red-perfect-adapter-middleware-uns/#continuous-improvement"># </a> Continuous improvement</h3>
<p>While it would be ideal if data schemas were stable, changes are frequent and unpredictable. It’s a non-obvious requirement for your UNS edge to be adaptable. Message structures can change, to add or remove data from them. Though also the format, from JSON to Sparkplug B, or maybe to XML. Not to say that standardization of messages will continuously require updates to leverage the UNS for higher business value.</p>
<p>A swiss-army knife as both data sender and receiver is not just a nice-to-have, it’s a requirement.</p>
<h3 id="scalable-operations" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/node-red-perfect-adapter-middleware-uns/#scalable-operations"># </a> Scalable operations</h3>
<p>While there are other tools available that can adapt to a few protocols, or parse a handful of data formats, there’s no alternative for Node-REDs breadth and depth of integration level. This is why many organizations have already adopted Node-RED for their edge cases, which their current standard solution doesn’t handle.</p>
<p>There’s no situation where a vendor provided, off-the-shelf solution handles protocols and formats across vendors, modern and legacy OT, that also satisfies the IT requirements unless the extensibility is handled through an Open-Source community, with compliance and security controls from a professional entity surrounding the open source project.</p>
https://flowfuse.com/blog/2024/02/professional-services-for-node-red/Should You Invest in Professional Services for Your Node-RED Development?Professional Services for Node-RED, When and Why?2024-02-05T00:00:00ZGrey Dziuba<p>Professional services come in many different forms. Anything from setup and configuration, flow development, to node development. In this article, we will cover a few examples of how you can leverage professional services for your Node-RED applications.</p>
<!--more-->
<h1 id="should-you-invest-in-professional-services-for-your-node-red-development%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/professional-services-for-node-red/#should-you-invest-in-professional-services-for-your-node-red-development%3F"># </a> Should You Invest in Professional Services for Your Node-RED Development?</h1>
<p>Node-RED is multifaceted, and Professional Services (PS) can apply to many use cases. We will break it down into three categories that will help identify whether PS (Professional Services) is right for you. Those categories will be setup, flow development, and node development. Each takes a different skill set and has different levels of complexity.</p>
<p>Before we jump into things, we need to understand the value proposition of Node-RED. Why Node-RED? Node-RED is a tool that makes Citizen Development a reality. It should be treated that way throughout the development journey regardless of Professional Services or not. Following standard procedures that minimize complexity, for example: reducing the use of function nodes when other nodes would be more ideal. Don’t overcomplicate things that don’t need to be or better said by this quote.</p>
<blockquote>
<p>Easy things should be easy, and hard things should be possible.
-Larry Wall</p>
</blockquote>
<h2 id="setup" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/professional-services-for-node-red/#setup"># </a> Setup</h2>
<p>It is often recommended to use PS for the setup and installation of products,
and Node-RED and FlowFuse aren't different. This becomes especially true if you
desire to professionalize your Node-RED instance. The reason for this is that PS
teams focus on minimizing the risk of application failure, security compromise,
and data/ip loss. This is an area of PS that can easily be overlooked, mainly
there aren't any negative consequences in the short term. The work these teams focus on prevents catastrophic issues in the future. With Node-RED and FlowFuse, these teams will focus on installing FlowFuse based on system requirements and prerequisites, migrating existing Node-RED instances, securing your environment, and integrating with your existing ecosystem of applications.</p>
<h2 id="flow-development" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/professional-services-for-node-red/#flow-development"># </a> Flow development</h2>
<p>Oftentimes, many think of Flow development when they think of PS for Node-RED. There will be a process flow that needs to be accomplished, but it is leveraging standard nodes built within the Node-RED platform. Occasionally, there will be a need to install a custom node from the pallet manager, but the complexities in the development are adhering to a process and or visualization. There may be complex data translation, but for the most part, access to the command line of the Node-RED instance is unnecessary. Professional services may be used in situations like this where knowledge of specific systems that Node-RED is integrating into is complex. For example, a complex backend database for specific industry-wide used applications.</p>
<h2 id="node-development" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/professional-services-for-node-red/#node-development"># </a> Node Development</h2>
<p>At the core of some integration projects lies a critical requirement: the need for specific integrations that align precisely with your application's demands. This is where Node-RED's open-source nature becomes its most significant asset. Node-RED allows for the development of custom nodes, catering to specialized protocols unique to your organization or to serve niche applications. Such node development isn't just another feature; it represents the foundational element of Node-RED, embodying the platform's core value proposition.</p>
<p>Whether addressing the need for custom integration with internal systems or expanding functionality to include less common applications, node development stands as the pivotal mechanism for enabling these capabilities. This critical development can be undertaken in-house, leveraging your team's expertise, or through PS specialized in node development.</p>
<h3 id="conflating-flow-and-node-development" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/professional-services-for-node-red/#conflating-flow-and-node-development"># </a> Conflating Flow and Node Development</h3>
<p>It is important when scoping out a project to identify all of the potential nodes needed and identify any potential missing ones. The skills for developing Nodes and Flow development, while similar, are often different skill sets. Having these identified will help prevent scope creep and setting expectations on timelines.</p>
<h2 id="conclusion" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/02/professional-services-for-node-red/#conclusion"># </a> Conclusion</h2>
<p>As we've explored throughout this article, Professional Services for Node-RED can significantly enhance the efficiency, security, and scalability of your automation and integration projects. From the initial setup and configuration to the intricacies of flow and node development, the expertise PS teams offer can be invaluable. The decision to engage with Professional Services should be informed by your project's specific needs, internal capabilities, and strategic priorities. Whether it's leveraging PS for the foundational setup of your Node-RED instance, outsourcing flow development to expedite project timelines, or seeking expert assistance for node development, the goal is the same: create a coding environment that is conducive to citizen development.</p>
<p>If you are interested in professional services or consultation, <a href="https://flowfuse.com/professional-services/">please reach out</a>.</p>
https://flowfuse.com/blog/2024/01/unified-namespace-when-not-to-use/Unified Namespace: When to Use It, and When to Choose Something ElseData isn't created equal, some data doesn't fit the UNS2024-01-31T00:00:00ZZJ van de Weg<p>At FlowFuse, we're convinced of the Unified Namespace (UNS) architecture for IoT cases. It's a powerful tool that can make information much more readily available and easy to consume. However, as with any architecture, there are times when it's not the best choice. In this blog post, we'll discuss when to use the UNS and when to consider other options.</p>
<!--more-->
<h3 id="latency-sensitivity" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/unified-namespace-when-not-to-use/#latency-sensitivity"># </a> Latency sensitivity</h3>
<p>When automating strictly digital tasks, there's generally no or very lenient requirements on latency. Requesting APIs from another server, normalizing data, and sending it towards another service takes very little time, though it hardly matters if you’re 100ms later than usual. In industrial automation or other cases where physical safety is safeguarded, there’s a requirement for low latency to ensure that data is transmitted and processed quickly enough to maintain real-time control of processes.</p>
<p>Extending this beyond the UNS – For controlled use cases, use specialized software and do not rely on third parties to broker the information correctly.</p>
<p>However, while control was used as an example here, the general case here is not the UNS for real-time, low-latency communication.</p>
<h3 id="large-files-or-binary-data" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/unified-namespace-when-not-to-use/#large-files-or-binary-data"># </a> Large files or binary data</h3>
<p>Sending large blobs of binary data, such as pictures and archives, through UNS is not recommended due to several drawbacks. First, UNS is optimized for small, mostly text-based communication, and sending binary data through it can significantly increase message size and processing overhead. As the sender of the data, there’s also generally no control over the number of receivers of the data, so if you send a large file to the broker once, it might need to be copied many times for every receiver.</p>
<p>To overcome these limitations, it is more efficient and practical to store binary data elsewhere, such as on a shared storage location or a cloud service. Once the data is stored externally, a reference to its location can be sent through UNS.</p>
<h3 id="data-security-and-data-access" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/unified-namespace-when-not-to-use/#data-security-and-data-access"># </a> Data security and data access</h3>
<p>The UNS becomes more useful the more hubs are connected, and it stands to reason that better business outcomes are achieved when everything is connected. Not just the sensor data (Level 1 of the <a href="https://flowfuse.com/blog/2023/08/isa-95-automation-pyramid-to-unified-namespace/#automation-pyramid---visualization">automation pyramid</a> <em>except actuators</em>), but also the customer-facing systems like your ERP (Level 4 or the automation pyramid), and even your CRM, Customer Relationship Management. This would allow better insight and communication with the customer when, for example, their car is done with production and will be shipped to them. The CRM contains personal details about the customer. Publishing what a customer ordered might thus disclose personally identifiable information (PII).</p>
<p>Connecting a CRM is certainly possible, and could streamline the supply chain, but PII shouldn’t be published. Consider if there’s a unique ID for the customer instead to use. Does your CRM, for example, keep a customer ID? If not, mask the information instead. Use strong hashing algorithms like SHA-512 to hash their email addresses. This way, other systems can cross reference messages received in the UNS, without ever knowing the customer PII. Another venue to explore is topic-based authentication for data receivers, which most data brokers provide. However, stripping and masking PII is still highly recommended either way.</p>
<h3 id="in-conclusion" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/unified-namespace-when-not-to-use/#in-conclusion"># </a> In Conclusion</h3>
<p>The Unified Namespace is a powerful architecture that can make IoT data more accessible and easier to consume. However, it's not always the best choice for all applications. When considering whether to use the UNS, be sure to weigh the benefits against the potential risks. If you need low latency, strong data security, or fine-grained control over data access, you may need to adjust your architecture pattern or instantiate point-to-point connections through REST or other interfaces.</p>
https://flowfuse.com/blog/2024/01/revolutionizing-manufacturing-impact-ai-chatgpt-technologies/AI and ChatGPT - Revolutionizing the Manufacturing IndustryHow AI and Conversational Technologies are Transforming Industrial Processes2024-01-31T00:00:00Z<p>The application of artificial intelligence (AI) in various industries, particularly in manufacturing, is a topic of growing interest. The evolution of technologies like ChatGPT is driving significant changes in this sector. For a more nuanced understanding, we reference four informative blog posts from our team members. The first post, <a href="https://flowfuse.com/blog/2023/12/ai-use-cases/">"AI Use Cases that are shaping the next manufacturing frontier"</a>, offers an insightful overview of AI's role in diverse areas. Following this, <a href="https://flowfuse.com/blog/2023/11/ai-assistant/">"ChatGPT AI Assistants with Node-RED"</a> examines the specific impact of AI assistants. The third article, <a href="https://flowfuse.com/blog/2023/11/chatgpt-gpt/">"Node-Red Builder a ChatGPT GPT"</a>, discusses the capabilities of generative pre-trained transformers like ChatGPT. Lastly, <a href="https://flowfuse.com/blog/2023/09/chatgpt-for-node-red-developers/">"How ChatGPT improves Node-RED Developer Experience"</a> explores ChatGPT's application in Node-Red development, an important aspect for many in manufacturing.</p>
<!--more-->
<h2 id="how-ai-and-chatgpt-are-impacting-manufacturing" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/revolutionizing-manufacturing-impact-ai-chatgpt-technologies/#how-ai-and-chatgpt-are-impacting-manufacturing"># </a> How AI and ChatGPT are Impacting Manufacturing</h2>
<p>AI and ChatGPT's integration into manufacturing indicates a shift in production process management. Here are some key impacts:</p>
<h3 id="boosting-efficiency-and-productivity" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/revolutionizing-manufacturing-impact-ai-chatgpt-technologies/#boosting-efficiency-and-productivity"># </a> Boosting Efficiency and Productivity</h3>
<p>AI, especially ChatGPT, enhances manufacturing efficiency by analyzing data to improve production lines, predict maintenance, and aid in design and development.</p>
<h3 id="automating-routine-tasks" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/revolutionizing-manufacturing-impact-ai-chatgpt-technologies/#automating-routine-tasks"># </a> Automating Routine Tasks</h3>
<p>AI is adept at handling repetitive tasks, speeding up manufacturing and allowing human workers to engage in more complex production aspects.</p>
<h3 id="elevating-quality-control" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/revolutionizing-manufacturing-impact-ai-chatgpt-technologies/#elevating-quality-control"># </a> Elevating Quality Control</h3>
<p>AI algorithms consistently ensure high-quality standards, quickly identifying and fixing product defects or deviations.</p>
<h3 id="enabling-customization-and-flexibility" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/revolutionizing-manufacturing-impact-ai-chatgpt-technologies/#enabling-customization-and-flexibility"># </a> Enabling Customization and Flexibility</h3>
<p>AI's learning and adaptability make it suitable for customizing production, allowing manufacturers to meet specific customer demands more efficiently.</p>
<h3 id="transforming-the-workforce" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/revolutionizing-manufacturing-impact-ai-chatgpt-technologies/#transforming-the-workforce"># </a> Transforming the Workforce</h3>
<p>AI in manufacturing necessitates skilled workers to operate and maintain these systems, altering job roles and responsibilities.</p>
<h2 id="pros-and-cons-of-ai-and-chatgpt-in-manufacturing" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/revolutionizing-manufacturing-impact-ai-chatgpt-technologies/#pros-and-cons-of-ai-and-chatgpt-in-manufacturing"># </a> Pros and Cons of AI and ChatGPT in Manufacturing</h2>
<h3 id="pros" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/revolutionizing-manufacturing-impact-ai-chatgpt-technologies/#pros"># </a> Pros</h3>
<ol>
<li>Boosted Productivity: AI-driven automation increases production efficiency.</li>
<li>Consistent Quality Assurance: AI ensures ongoing product quality.</li>
<li>Reduced Costs: AI optimizes resource use and minimizes waste.</li>
<li>Encouraging Innovation: AI facilitates new manufacturing methods and products.</li>
<li>Enhancing Safety: AI reduces human exposure to hazardous manufacturing conditions.</li>
</ol>
<h3 id="cons" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/revolutionizing-manufacturing-impact-ai-chatgpt-technologies/#cons"># </a> Cons</h3>
<ol>
<li>Initial Investment Costs: AI technology implementation can be expensive.</li>
<li>Need for Skilled Labor: Demand for workers proficient in AI technologies is growing.</li>
<li>Job Role Changes: Automation might decrease the need for certain labor roles.</li>
<li>Security Concerns: AI systems can be susceptible to cyber threats.</li>
<li>Technological Dependence: Excessive reliance on AI could limit problem-solving abilities in workers.</li>
</ol>
<h2 id="frequently-asked-questions-(faqs)" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/revolutionizing-manufacturing-impact-ai-chatgpt-technologies/#frequently-asked-questions-(faqs)"># </a> Frequently Asked Questions (FAQs)</h2>
<details>
<summary>1. How is AI changing manufacturing?</summary>
<br />
<strong>AI is altering manufacturing through automation, optimizing efficiency, and fostering production innovations.</strong>
</details>
<details>
<summary>2. What is ChatGPT's role in manufacturing?</summary>
<br />
<strong>ChatGPT aids in data analysis, automates processes, and improves communication and documentation in manufacturing.</strong>
</details>
<details>
<summary>3. Are manufacturing jobs at risk due to AI?</summary>
<br />
<strong>While AI may automate some repetitive jobs, it also creates opportunities for skilled labor in technology management and development.</strong>
</details>
<details>
<summary>4. Can AI enhance manufacturing product quality?</summary>
<br />
<strong>Yes, AI's continuous monitoring and analysis significantly boost quality control.</strong>
</details>
<details>
<summary>5. What are the main challenges of integrating AI in manufacturing?</summary>
<br />
<strong>Challenges include high implementation costs, the need for skilled labor, and transitioning to automated processes.</strong>
</details>
<details>
<summary>6. Is AI cost-effective in manufacturing?</summary>
<br />
<strong>Despite high initial costs, AI can lead to long-term savings through improved efficiency and waste reduction.</strong>
</details>
<details>
<summary>7. How does AI affect manufacturing worker safety?</summary>
<br />
<strong>AI reduces risk by taking over hazardous tasks, improving overall workplace safety.</strong>
</details>
<details>
<summary>8. Can small manufacturers benefit from AI?</summary>
<br />
<strong>Yes, AI solutions are increasingly accessible for small-scale manufacturers.</strong>
</details>
<details>
<summary>9. What training is required for AI-enabled manufacturing workers?</summary>
<br />
<strong>Training in AI system operation, data analysis, and potentially programming skills is needed.</strong>
</details>
<details>
<summary>10. What does the future hold for AI in manufacturing?</summary>
<br />
<strong>The future suggests more integrated, intelligent, and adaptable manufacturing processes driven by AI advancements.</strong>
</details>
https://flowfuse.com/blog/2024/01/how-to-deploy-node-red-with-flowfuse-to-balenacloud/Step-by-Step Guide to Deploying Node-RED with FlowFuse in balenaCloudFleet management made easier with FlowFuse and balena.2024-01-30T00:00:00ZGrey Dziuba<p>In a <a href="https://flowfuse.com/webinars/2024/balena/">recent webinar with balena</a>, we explored the dynamic capabilities of deploying FlowFuse to a fleet of devices using <a href="https://www.balena.io/cloud">balenaCloud</a>. This blog post serves as a practical guide to replicate that process, specifically tailored for those aiming to streamline their deployment of FlowFuse in an efficient and user-friendly manner.</p>
<!--more-->
<h1 id="how-to-implement-flowfuse-with-balenacloud-on-a-fleet-of-devices" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/how-to-deploy-node-red-with-flowfuse-to-balenacloud/#how-to-implement-flowfuse-with-balenacloud-on-a-fleet-of-devices"># </a> How to Implement FlowFuse with balenaCloud on a Fleet of devices</h1>
<p><a href="https://www.youtube.com/watch?v=cKFu1ljUlKE" title="Deploying Node-RED with FlowFuse in balenaCloud"><img alt="Deploying Node-RED with FlowFuse in balenaCloud" loading="lazy" decoding="async" src="https://i.ytimg.com/vi/cKFu1ljUlKE/hqdefault.jpg" width="undefined" height="undefined" /></a></p>
<h2 id="preparation-steps" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/how-to-deploy-node-red-with-flowfuse-to-balenacloud/#preparation-steps"># </a> Preparation Steps</h2>
<p>Before diving into the deployment process, it's crucial to familiarize yourself with key resources. We recommend reviewing our previous <a href="https://flowfuse.com/blog/2023/11/device-agent-balena/">blog post</a> on deploying the FlowFuse Device Agent via balena. This post contains a vital link to the GitHub repository, essential for deploying FlowFuse with balena, laying the groundwork for the steps ahead.</p>
<h2 id="creating-a-new-fleet-in-balenacloud" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/how-to-deploy-node-red-with-flowfuse-to-balenacloud/#creating-a-new-fleet-in-balenacloud"># </a> Creating a New Fleet in balenaCloud</h2>
<ol>
<li>Navigate to the <a href="https://github.com/FlowFuse/balena-device-agent">FlowFuse git</a> repository. Click on the <strong>Deploy with balena</strong> button.</li>
<li>Name your fleet.</li>
<li>Select your default device.</li>
<li>Click <strong>Create and Deploy</strong>.</li>
</ol>
<h2 id="adding-devices-to-the-fleet" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/how-to-deploy-node-red-with-flowfuse-to-balenacloud/#adding-devices-to-the-fleet"># </a> Adding Devices to the Fleet</h2>
<p>Once your fleet is created, the next step is to add devices. To add a device to your fleet, follow these <a href="https://docs.balena.io/learn/getting-started/var-som-mx6/rust/#add-a-device-and-download-os">instructions</a>.</p>
<h2 id="setting-up-flowfuse" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/how-to-deploy-node-red-with-flowfuse-to-balenacloud/#setting-up-flowfuse"># </a> Setting Up FlowFuse</h2>
<p>Setting up FlowFuse correctly is essential for seamless operation:</p>
<ol>
<li>Create a new instance within FlowFuse or use an existing one if you prefer. Follow these <a href="https://flowfuse.com/docs/user/introduction/#creating-a-node-red-instance">instructions</a> to create a new instance.</li>
<li>Create a <strong>Device Provisioning Token</strong> by following these <a href="https://flowfuse.com/docs/device-agent/register/#generating-%22provisioning-configuration%22">instructions</a>.</li>
<li>Ensure you add the FlowFuse Node-RED application you want the devices to provision. If left at default, devices will need to be manually added to applications.</li>
</ol>
<h2 id="using-the-device-provisioning-token" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/how-to-deploy-node-red-with-flowfuse-to-balenacloud/#using-the-device-provisioning-token"># </a> Using the Device Provisioning Token</h2>
<ol>
<li>First, convert the contents of the Device Provisioning Token to base64. Follow these <a href="https://flowfuse.com/blog/2023/11/device-agent-balena/#environment-variable">instructions</a> to convert the file to base64.</li>
<li>Once converted, import this string into balena as a <strong>Fleet</strong> level variable, not a device level variable. Follow these <a href="https://docs.balena.io/learn/manage/variables/#fleet-wide-variables">instructions</a> to import the Fleet level variable with the Name <code>FF_DEVICE_YML</code>.</li>
<li>This action will provision any new device added to the fleet with the yaml file configuration, automatically adding the device to a FlowFuse instance.</li>
</ol>
<h2 id="deploying-and-testing-the-flowfuse-instance" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/how-to-deploy-node-red-with-flowfuse-to-balenacloud/#deploying-and-testing-the-flowfuse-instance"># </a> Deploying and Testing the FlowFuse Instance</h2>
<p>Deploying the FlowFuse instance brings everything together:</p>
<ol>
<li>Navigate to your FlowFuse application created earlier.</li>
<li>Go to your devices and you should now see your newly provisioned devices from balena.</li>
<li>If this is your first time setting up your fleet, the device will not have a snapshot. You will need to deploy a snapshot. Follow these <a href="https://flowfuse.com/docs/user/snapshots/#create-a-snapshot">instructions</a> to do so. Ensure that you select <strong>Set Target Snapshot</strong>.</li>
<li>Once complete, the FlowFuse instance will deploy to your device(s).</li>
</ol>
<h1 id="integrating-influxdb-(optional)" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/how-to-deploy-node-red-with-flowfuse-to-balenacloud/#integrating-influxdb-(optional)"># </a> Integrating InfluxDB (Optional)</h1>
<p>Integrating InfluxDB enables effective data storage and management:</p>
<ol>
<li>Similar to the previous steps, navigate to this <a href="https://github.com/mpous/flowfuse-agent-influx-balena/tree/main?tab=readme-ov-file">Github repository</a> and click <strong>Deploy with balena</strong>.</li>
<li>This time, instead of creating a new fleet, select <strong>Use an existing fleet instead</strong>.</li>
<li>Choose your fleet for deployment and select <strong>Deploy to fleet</strong>.</li>
</ol>
<h2 id="data-generation-and-management" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/how-to-deploy-node-red-with-flowfuse-to-balenacloud/#data-generation-and-management"># </a> Data Generation and Management</h2>
<p>For testing, we have created a flow to get you started. Follow this <a href="https://flows.nodered.org/flow/66f37bb739b6cdb0c7ad3a4e2edd68ef">link</a> and import it. There are four sets of flows for you to begin with. The first is for data generation. The second is a manual data generation flow. The third is key as it initiates the creation of a database, in this case, <strong>mydb</strong>. The last flow is a simple query that pulls data from InfluxDB.</p>
<ol>
<li>Import the flows into your FlowFuse instance of Node-RED and deploy. Follow these <a href="https://flowfuse.com/blog/2023/03/3-quick-node-red-tips-5/#2.-import-helpful-example-flows-provided-with-custom-nodes">instructions</a> for importing and exporting.</li>
<li>Return to Flowfuse, go to your instance, and create another <a href="https://flowfuse.com/docs/user/snapshots/#create-a-snapshot">snapshot</a>.</li>
<li>Ensure that you <strong>Set Target Snapshot</strong>.</li>
</ol>
<h2 id="finalizing-and-testing-the-setup" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/how-to-deploy-node-red-with-flowfuse-to-balenacloud/#finalizing-and-testing-the-setup"># </a> Finalizing and Testing the Setup</h2>
<p>The final steps ensure that your setup is fully operational:</p>
<ol>
<li>Once deployed, navigate to the device.</li>
<li><a href="https://flowfuse.com/docs/device-agent/deploy/#editing-the-node-red-flows-on-a-device-that-is-assigned-to-an-application">Enable Developer Mode</a>.</li>
<li>Next, click the newly revealed button, <strong>Open Editor</strong>, to access the deployed Flow.</li>
</ol>
<h2 id="conclusion" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/how-to-deploy-node-red-with-flowfuse-to-balenacloud/#conclusion"># </a> Conclusion</h2>
<p>Implementing FlowFuse with balenaCloud significantly enhances your device management and data processing capabilities. This guide provides a foundational approach, but don't hesitate to delve deeper into each step to tailor the setup to your specific needs.</p>
https://flowfuse.com/blog/2024/01/speech-driven-chatbot-with-node-red/Speech-Driven Chatbot System with Node-REDGuide to building speech-driven chatbot using Node-RED, speech recognition, and Dashboard 2.0.2024-01-29T00:00:00Z<p>Have you ever wanted to integrate speech recognition and synthesis into your Node-RED project and thought it was too complex? Often it has required external services or APIs. However, in this guide, we show you how you can use speech recognition and synthesis in your Node-RED projects without needing an external service or API.</p>
<p>In addition, we make things more interesting by building a system that can listen to us and respond like humans using the Chat-GPT API.
Let's get started!</p>
<!--more-->
<h1 id="what-exactly-is-speech-recognition-and-synthesis%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/speech-driven-chatbot-with-node-red/#what-exactly-is-speech-recognition-and-synthesis%3F"># </a> What exactly is speech recognition and synthesis?</h1>
<p>Speech recognition is a technology where a device captures spoken words through a microphone, checks against grammar rules and vocabulary, and returns recognized words as text. On the other hand, speech synthesis converts app text into speech and plays it through a device's speaker or audio output. There are many benefits and real-world applications of this technology.</p>
<ul>
<li><strong>Hands-Free Operation:</strong> Using speech recognition technology is often used today to perform tasks such as making calls, sending messages, or controlling smart home devices without the need for physical interaction.</li>
<li><strong>Accessibility:</strong> It allows individuals with visual impairments to access digital content through spoken words and as discussed above, to control devices without physical interaction.</li>
<li><strong>Efficient Content Consumption:</strong> It allows us to listen to information instead of reading. For example, in the audiobook industry by using speech synthesis technology they create audio versions of books which helps users to be more productive.</li>
</ul>
<h1 id="installing-dashboard-2.0" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/speech-driven-chatbot-with-node-red/#installing-dashboard-2.0"># </a> Installing Dashboard 2.0</h1>
<p>The first thing we need to do to get things started is installing Dashboard 2.0.</p>
<ol>
<li>Install Node-RED Dashboard 2.0. Follow these <a href="https://dashboard.flowfuse.com/getting-started.html">instructions</a> to install.</li>
<li>Create your first group, page, theme, and base.</li>
</ol>
<h1 id="building-speech-to-text-vue-component" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/speech-driven-chatbot-with-node-red/#building-speech-to-text-vue-component"># </a> Building Speech-to-Text Vue component</h1>
<p>In this section, we will build a Vue component that will perform a speech-to-text conversion operation using Web speech API, and display results on the dashboard. While we did say previously that we won't need any external API for speech recognition, this <a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Speech_API">Web Speech API</a> is not an external API.
This will process your speech locally as it is a JavaScript API that allows us to use speech-related functionalities, such as speech recognition and synthesis, in a web browser directly. It is widely present in modern browsers (except Firefox) which eliminates the need for external APIs to implement these features. Let's now start to build that component.</p>
<ol>
<li>Drag a ui template widget to canvas and select the created group.</li>
<li>Paste the below Vue snippets into the template widget step by step.</li>
</ol>
<p>If you are unfamiliar with Vue, we have added comments that will help you to understand the code better.</p>
<p>We are going to start by pasting a user interface’s snippet which will allow us to interact with our system. This snippet adds a button that triggers our system to listen, an Icon, and a paragraph to display speech recognition results on the dashboard.</p>
<div style="position: relative">
<pre class="language-html"><code id="code-72" class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>template</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token special-attr"><span class="token attr-name">style</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token value css language-css"><span class="token property">display</span><span class="token punctuation">:</span> flex<span class="token punctuation">;</span> <span class="token property">flex-direction</span><span class="token punctuation">:</span> column<span class="token punctuation">;</span> <span class="token property">justify-content</span><span class="token punctuation">:</span> center<span class="token punctuation">;</span> <span class="token property">align-items</span><span class="token punctuation">:</span> center<span class="token punctuation">;</span></span><span class="token punctuation">"</span></span></span><span class="token punctuation">></span></span><br /> <span class="token comment"><!-- Button triggers recording when clicked --></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>button</span> <span class="token attr-name">@click</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>startRecording<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token comment"><!-- Microphone icon inside the button --></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>img</span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Microphone<span class="token punctuation">"</span></span> <span class="token special-attr"><span class="token attr-name">style</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token value css language-css"><span class="token property">height</span><span class="token punctuation">:</span> 62px<span class="token punctuation">;</span> <span class="token property">width</span><span class="token punctuation">:</span> 62px</span><span class="token punctuation">"</span></span></span> <span class="token attr-name">:src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>microphoneIcon<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>button</span><span class="token punctuation">></span></span><br /> <span class="token comment"><!-- Displaying speech recognition results --></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>strong</span><span class="token punctuation">></span></span>You:<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>strong</span><span class="token punctuation">></span></span> {{ results }}<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>template</span><span class="token punctuation">></span></span></code></pre>
<button class="code-copy " data-clipboard-target="#code-72" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>Now paste the below script right after the HTML in the template widget, This script adds functionality of speech recognition in our system.</p>
<div style="position: relative">
<pre class="language-html"><code id="code-76" class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>script</span><span class="token punctuation">></span></span><span class="token script"><span class="token language-javascript"><br /><span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token punctuation">{</span><br /> <span class="token function">data</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">return</span> <span class="token punctuation">{</span><br /> <span class="token comment">// Initial data properties</span><br /> <span class="token literal-property property">buttonText</span><span class="token operator">:</span> <span class="token string">'Speak'</span><span class="token punctuation">,</span><br /> <span class="token literal-property property">microphoneIcon</span><span class="token operator">:</span> <span class="token string">'http://icons.iconarchive.com/icons/blackvariant/button-ui-requests-15/512/Microphone-icon.png'</span><span class="token punctuation">,</span><br /> <span class="token literal-property property">recognition</span><span class="token operator">:</span> <span class="token keyword">null</span><span class="token punctuation">,</span><br /> <span class="token literal-property property">results</span><span class="token operator">:</span> <span class="token string">''</span><span class="token punctuation">,</span><br /> <span class="token punctuation">}</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token literal-property property">methods</span><span class="token operator">:</span> <span class="token punctuation">{</span><br /> <span class="token comment">// Method to start recording</span><br /> <span class="token function">startRecording</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span>buttonText <span class="token operator">=</span> <span class="token string">'Recording'</span><span class="token punctuation">;</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span>recognition<span class="token punctuation">.</span><span class="token function">stop</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span>recognition<span class="token punctuation">.</span><span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token comment">// Method to process the speech recognition results</span><br /> <span class="token function">processSpeech</span><span class="token punctuation">(</span><span class="token parameter">event</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">let</span> results <span class="token operator">=</span> Array<span class="token punctuation">.</span><span class="token function">from</span><span class="token punctuation">(</span>event<span class="token punctuation">.</span>results<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token parameter">result</span> <span class="token operator">=></span> result<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>transcript<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">''</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span>results <span class="token operator">=</span> results<span class="token punctuation">;</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">$emit</span><span class="token punctuation">(</span><span class="token string">'speak'</span><span class="token punctuation">,</span> results<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token comment">//Sending result to next node as payload</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>results<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token comment">// Method to handle the start of recognition</span><br /> <span class="token function">handleRecognitionStart</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span>microphoneIcon <span class="token operator">=</span> <span class="token string">'https://upload.wikimedia.org/wikipedia/commons/0/06/Mic-Animation.gif'</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token comment">// Method to handle recognition errors</span><br /> <span class="token function">handleRecognitionError</span><span class="token punctuation">(</span><span class="token parameter">event</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span>microphoneIcon <span class="token operator">=</span> event<span class="token punctuation">.</span>error <span class="token operator">===</span> <span class="token string">'no-speech'</span> <span class="token operator">||</span> event<span class="token punctuation">.</span>error <span class="token operator">===</span> <span class="token string">'audio-capture'</span><br /> <span class="token operator">?</span> <span class="token string">'https://i.ytimg.com/vi/9YQU797Oy0Y/hqdefault.jpg'</span><br /> <span class="token operator">:</span> <span class="token keyword">this</span><span class="token punctuation">.</span>microphoneIcon<span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token comment">// Method to handle the end of recognition</span><br /> <span class="token function">handleRecognitionEnd</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span>microphoneIcon <span class="token operator">=</span> <span class="token string">'http://icons.iconarchive.com/icons/blackvariant/button-ui-requests-15/512/Microphone-icon.png'</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token comment">// Method to set up the SpeechRecognition object</span><br /> <span class="token function">setupRecognition</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span>recognition <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">webkitSpeechRecognition</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span>recognition<span class="token punctuation">.</span>continuous <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span>recognition<span class="token punctuation">.</span>interimResults <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span>recognition<span class="token punctuation">.</span>onresult <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>processSpeech<span class="token punctuation">;</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span>recognition<span class="token punctuation">.</span>onstart <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>handleRecognitionStart<span class="token punctuation">;</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span>recognition<span class="token punctuation">.</span>onerror <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>handleRecognitionError<span class="token punctuation">;</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span>recognition<span class="token punctuation">.</span>onend <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>handleRecognitionEnd<span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token function">mounted</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token comment">// Initialize SpeechRecognition when the component is mounted</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setupRecognition</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /><span class="token punctuation">}</span><span class="token punctuation">;</span><br /></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>script</span><span class="token punctuation">></span></span></code></pre>
<button class="code-copy " data-clipboard-target="#code-76" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<h1 id="adding-an-environment-variable" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/speech-driven-chatbot-with-node-red/#adding-an-environment-variable"># </a> Adding an Environment variable</h1>
<p>Why do we need to add an environment variable? In this guide, we will build a speech-driven chatbot that involves integrating the Chat-GPT AI model. For this we need openAi’s API key. An API key is a form of private data that needs to be protected from being exposed. That is why we need the environment variables. It provides a secure way to store and access the API key without revealing it directly in the flow. For more details see <a href="https://flowfuse.com/blog/2023/01/environment-variables-in-node-red/">Using Environment Variables in Node-RED</a></p>
<ol>
<li>Navigate to the instance's setting and then go to the environment section.</li>
<li>Click on the <code>add variable</code> button and add a variable for Chat-gpt API.</li>
</ol>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/speech-driven-chatbot-environment-section-byp_bdQ1f_-650.avif 650w, https://flowfuse.com/img/speech-driven-chatbot-environment-section-byp_bdQ1f_-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/speech-driven-chatbot-environment-section-byp_bdQ1f_-650.webp 650w, https://flowfuse.com/img/speech-driven-chatbot-environment-section-byp_bdQ1f_-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/speech-driven-chatbot-environment-section-byp_bdQ1f_-650.jpeg 650w, https://flowfuse.com/img/speech-driven-chatbot-environment-section-byp_bdQ1f_-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Setting environment variable for chat-gpt token" alt=""Setting environment variable for Chat-gpt token"" loading="lazy" decoding="async" src="https://flowfuse.com/img/speech-driven-chatbot-environment-section-byp_bdQ1f_-650.jpeg" width="1300" height="641" /></picture></p>
<h1 id="setting-msg-property" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/speech-driven-chatbot-with-node-red/#setting-msg-property"># </a> Setting msg property</h1>
<p>Now let’s set that added environment variables as msg's property.</p>
<ol>
<li>Add a change node to canvas.</li>
<li>Set environment variable to ms.token property.</li>
<li>Connect the change node’s input to the template widget’s output.</li>
</ol>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/speech-driven-chatbot-change-node-Yxl1FrDmYv-616.avif 616w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/speech-driven-chatbot-change-node-Yxl1FrDmYv-616.webp 616w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Setting msg's property for Chat-gpt token" alt=""Setting msg's property for Chat-gpt token"" loading="lazy" decoding="async" src="https://flowfuse.com/img/speech-driven-chatbot-change-node-Yxl1FrDmYv-616.jpeg" width="616" height="462" /></picture></p>
<h1 id="installing-and-configuring-custom-node" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/speech-driven-chatbot-with-node-red/#installing-and-configuring-custom-node"># </a> Installing and configuring custom node</h1>
<p>In this section, we will install a custom node that will allow us to interact with the Chat-gpt AI model.</p>
<ol>
<li>Install <code>@sumit_shinde_84/node-red-contrib-node-gpt</code> by pallet manager, you can use other nodes according to your preference.</li>
<li>Drag a ChatGPT node to canvas.</li>
<li>Connect the ChatGPT node’s input to the change node’s output.</li>
</ol>
<h1 id="building-text-to-speech-vue-component" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/speech-driven-chatbot-with-node-red/#building-text-to-speech-vue-component"># </a> Building Text-to-Speech Vue component</h1>
<p>We will build a Vue component that converts text received from ChatGPT into speech.</p>
<ol>
<li>Drag another template widget to canvas and select the added group, alternatively, you can create a separate group for this component according to your preference.</li>
<li>Paste the below Vue snippets into the template widget.</li>
<li>Connect the template widget’s input to the ChatGPT node’s output.</li>
</ol>
<p>Paste the below snippet in the template widget which displays chat-gpt response on the dashboard</p>
<div style="position: relative">
<pre class="language-html"><code id="code-173" class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>template</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>strong</span><span class="token punctuation">></span></span> Chat-gpt: <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>strong</span><span class="token punctuation">></span></span> {{textToSpeech}}<br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>template</span><span class="token punctuation">></span></span></code></pre>
<button class="code-copy " data-clipboard-target="#code-173" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>Paste the below snippet right after the HTML, This snippet adds the functionality of text-to-speech into our system, which triggers when msg received by the previous node.</p>
<div style="position: relative">
<pre class="language-html"><code id="code-177" class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>script</span><span class="token punctuation">></span></span><span class="token script"><span class="token language-javascript"><br /> <span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token punctuation">{</span><br /> <span class="token function">data</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">return</span> <span class="token punctuation">{</span><br /> <span class="token comment">// Data property to store the text to be spoken</span><br /> <span class="token literal-property property">textToSpeech</span><span class="token operator">:</span> <span class="token string">''</span><span class="token punctuation">,</span><br /> <span class="token punctuation">}</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token literal-property property">methods</span><span class="token operator">:</span> <span class="token punctuation">{</span><br /> <span class="token comment">// Method to trigger text-to-speech</span><br /> <span class="token function">speakText</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token comment">// Check if there is non-empty text to speech</span><br /> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>textToSpeech<span class="token punctuation">.</span><span class="token function">trim</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">!==</span> <span class="token string">''</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token comment">// Create a SpeechSynthesisUtterance with the text to be spoken</span><br /> <span class="token keyword">const</span> utterance <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">SpeechSynthesisUtterance</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>textToSpeech<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token comment">// Use the SpeechSynthesis API to speak the provided text</span><br /> window<span class="token punctuation">.</span>speechSynthesis<span class="token punctuation">.</span><span class="token function">speak</span><span class="token punctuation">(</span>utterance<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token function">mounted</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token comment">// Event listener for receiving messages </span><br /> <br /> <span class="token keyword">this</span><span class="token punctuation">.</span>$socket<span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">'msg-input:'</span> <span class="token operator">+</span> <span class="token keyword">this</span><span class="token punctuation">.</span>id<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">msg</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /><br /> <span class="token comment">// Update the textToSpeech property with the received message payload</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span>textToSpeech <span class="token operator">=</span> msg<span class="token punctuation">.</span>payload<span class="token punctuation">;</span><br /> <br /> <span class="token comment">// Trigger text-to-speech with the received message</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">speakText</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /><span class="token punctuation">}</span><span class="token punctuation">;</span><br /></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>script</span><span class="token punctuation">></span></span><br /><br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>style</span> <span class="token attr-name">scoped</span><span class="token punctuation">></span></span><span class="token style"><span class="token language-css"><br /> <span class="token selector">textarea</span> <span class="token punctuation">{</span><br /> <span class="token property">width</span><span class="token punctuation">:</span> 100%<span class="token punctuation">;</span><br /> <span class="token property">height</span><span class="token punctuation">:</span> 100px<span class="token punctuation">;</span><br /> <span class="token property">margin-bottom</span><span class="token punctuation">:</span> 10px<span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>style</span><span class="token punctuation">></span></span></code></pre>
<button class="code-copy " data-clipboard-target="#code-177" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>Your final flow should look like this:</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/speech-driven-chatbot-flow-dZRhFkXA0B-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/speech-driven-chatbot-flow-dZRhFkXA0B-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Speech Driven Chatbot system flow" alt=""Speech Driven Chatbot system flow"" loading="lazy" decoding="async" src="https://flowfuse.com/img/speech-driven-chatbot-flow-dZRhFkXA0B-650.jpeg" width="650" height="135" /></picture></p>
<h1 id="deploying-the-flow" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/speech-driven-chatbot-with-node-red/#deploying-the-flow"># </a> Deploying the Flow</h1>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/speech-driven-chatbot-flowfue-editor-lsVJ-mg72b-650.avif 650w, https://flowfuse.com/img/speech-driven-chatbot-flowfue-editor-lsVJ-mg72b-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/speech-driven-chatbot-flowfue-editor-lsVJ-mg72b-650.webp 650w, https://flowfuse.com/img/speech-driven-chatbot-flowfue-editor-lsVJ-mg72b-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/speech-driven-chatbot-flowfue-editor-lsVJ-mg72b-650.jpeg 650w, https://flowfuse.com/img/speech-driven-chatbot-flowfue-editor-lsVJ-mg72b-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Deploying Sentiment analysis Node-RED flow" alt=""Deploying Sentiment analysis Node-RED flow"" loading="lazy" decoding="async" src="https://flowfuse.com/img/speech-driven-chatbot-flowfue-editor-lsVJ-mg72b-650.jpeg" width="1300" height="615" /></picture></p>
<p>We have successfully built our Speech-Driven Chatbot System. Now it's time to deploy the flow, to do that click on the red deploy button which you can find in the top right corner. After that go to <code>https://<your-instance-name>.flowfuse.cloud/dashboard</code></p>
<p><picture><source type="image/gif" srcset="https://flowfuse.com/img/speech-driven-chatbot-system-8ga4czQg42-648.gif 648w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Speech Driven Chatbot using Node-RED Dashboard 2.0" alt=""Speech Driven Chatbot using Node-RED Dashboard 2.0"" loading="lazy" decoding="async" src="https://flowfuse.com/img/speech-driven-chatbot-system-8ga4czQg42-648.webp" width="648" height="400" /></picture></p>
<h1 id="conclusion" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/speech-driven-chatbot-with-node-red/#conclusion"># </a> Conclusion</h1>
<p>In this guide, we have built a Speech-Driven Chatbot System which allows us to understand how we can add speech recognition and synthesis features into our project without any external API or custom node. It also provides a brief overview of how we can integrate chat-gpt into our system.</p>
https://flowfuse.com/blog/2024/01/dashboard-2-multi-user/Personalised Multi-user Dashboards with Node-RED Dashboard 2.0!Explore how to build multi-user Dashboards, secured with FlowFuse Cloud!2024-01-24T00:00:00ZJoe Pavitt<p>This week has seen the release of the <a href="https://flowfuse.com/blog/2024/01/dashboard-2-ga">first major version of Node-RED Dashboard 2.0</a>, with it, we've made available a new FlowFuse-exclusive feature, personalised multi-user dashboards.</p>
<p>This new feature will allow you to build applications that provide unique data to each user, build admin-only views, and track user activity, to name but a few. We're really excited to see what the Node-RED Community and our FlowFuse customers can do with such a powerful and flexible framework.</p>
<!--more-->
<h2 id="personalised-multi-user-dashboards" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/dashboard-2-multi-user/#personalised-multi-user-dashboards"># </a> Personalised Multi User Dashboards</h2>
<p>The original Node-RED Dashboard was built with a "single source of truth", no matter how many users interacted with the dashboard, each user would always see the same data. This is great for prototyping, or hobby projects, but as you scale up your Node-RED usage, you'll want to be able to have unique dashboard experiences for each user.</p>
<h3 id="getting-started" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/dashboard-2-multi-user/#getting-started"># </a> Getting Started</h3>
<p>To enable personalised multi-user dashboards, you'll need to be using FlowFuse, and complete two steps:</p>
<h4 id="step-1%3A-enable-%22flowfuse-user-authentication%22" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/dashboard-2-multi-user/#step-1%3A-enable-%22flowfuse-user-authentication%22"># </a> Step 1: Enable "FlowFuse User Authentication"</h4>
<p>All instances on FlowFuse can be configured with <em>"FlowFuse User Authentication"</em> in the "Security" Settings. This option requires any user that wants access to your Editor or dashboard to be authorized by FlowFuse first.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/multi-user-dashboard-ffauth-0hagBkY4IT-1920.avif 1920w" sizes="(min-device-pixel-ratio: 1.25) 3840px, (min-resolution: 120dpi) 3840px, 1920px" /><source type="image/webp" srcset="https://flowfuse.com/img/multi-user-dashboard-ffauth-0hagBkY4IT-1920.webp 1920w" sizes="(min-device-pixel-ratio: 1.25) 3840px, (min-resolution: 120dpi) 3840px, 1920px" /><img data-zoomable="" title="Screenshot of the 'Security' settings available for any Instances running in FlowFuse" alt=""Screenshot of the 'Security' settings available for any Instances running in FlowFuse"" loading="lazy" decoding="async" src="https://flowfuse.com/img/multi-user-dashboard-ffauth-0hagBkY4IT-1920.jpeg" width="1920" height="1101" /></picture></p>
<figcaption class="-mt-6 mb-4 text-center"><b>"Screenshot of the 'Security' settings available for any Instances running in FlowFuse"</b></figcaption>
<h4 id="step-2%3A-install-flowfuse's-user-addon" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/dashboard-2-multi-user/#step-2%3A-install-flowfuse's-user-addon"># </a> Step 2: Install FlowFuse's User Addon</h4>
<h5 id="flowfuse-cloud" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/dashboard-2-multi-user/#flowfuse-cloud"># </a> FlowFuse Cloud</h5>
<p><em>Note: Every instance created from today onwards automatically comes with the necessary configuration. Already created instances need to be manually restarted.</em></p>
<p>The Personalised Multi-User Dashboard plugin, <code>@flowfuse/node-red-dashboard-2-user-addon</code>, is available in our <a href="https://flowfuse.com/certified-nodes/">Certified Nodes</a> catalogue, accessible to our Teams and Enterprise customers.</p>
<p>Once the "FlowFuse User Authentication" option has been enabled on your instance, you can then install our plugin, <code>@flowfuse/node-red-dashboard-2-user-addon</code>, through the "Manage Palette" option in the Node-RED Editor.</p>
<p>For your devices, we provide the necessary configuration and access token upon request, so that your Node-RED devices can also benefit from a Personalised Multi-user Dashboard.</p>
<h5 id="flowfuse-self-hosted" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/dashboard-2-multi-user/#flowfuse-self-hosted"># </a> FlowFuse Self-Hosted</h5>
<p>For all our Teams and Enterprise Self-Hosted customers who also want to use the Certified Nodes and the Multi-User Dashboard, we provide all necessary configurations upon request to get started.</p>
<p>Alternatively, if you're looking to elevate your Node-RED infrastructure, <a href="https://flowfuse.com/contact-us">book in a chat with us</a> to talk about how FlowFuse can help.</p>
<h3 id="using-the-plugin" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/dashboard-2-multi-user/#using-the-plugin"># </a> Using the Plugin</h3>
<p>Once enabled, any messages emitted by a Dashboard 2.0 node will contain a new <code>msg._client.user</code> object, e.g:</p>
<div style="position: relative">
<pre class="language-js"><code id="code-62" class="language-js"><span class="token punctuation">{</span><br /> <span class="token string-property property">"userId"</span><span class="token operator">:</span> <span class="token string">""</span><span class="token punctuation">,</span> <span class="token comment">// unique identifier for the user</span><br /> <span class="token string-property property">"username"</span><span class="token operator">:</span> <span class="token string">""</span><span class="token punctuation">,</span> <span class="token comment">// FlowFuse Username</span><br /> <span class="token string-property property">"email"</span><span class="token operator">:</span> <span class="token string">""</span><span class="token punctuation">,</span> <span class="token comment">// E-Mail Address connected to their FlowFuse account</span><br /> <span class="token string-property property">"name"</span><span class="token operator">:</span> <span class="token string">""</span><span class="token punctuation">,</span> <span class="token comment">// Full Name</span><br /> <span class="token string-property property">"image"</span><span class="token operator">:</span> <span class="token string">""</span> <span class="token comment">// User Avatar from FlowFuse</span><br /><span class="token punctuation">}</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-62" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>Then, when running Node-RED Dashboard 2.0 on FlowFuse, you'll have a new sidebar option in the Node-RED Editor, which allows you to control which node types allow for "client constraints".</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/multi-user-dashboard-ff-settings-Jf8rG8WpVt-1100.avif 1100w" sizes="(min-device-pixel-ratio: 1.25) 3840px, (min-resolution: 120dpi) 3840px, 1920px" /><source type="image/webp" srcset="https://flowfuse.com/img/multi-user-dashboard-ff-settings-Jf8rG8WpVt-1100.webp 1100w" sizes="(min-device-pixel-ratio: 1.25) 3840px, (min-resolution: 120dpi) 3840px, 1920px" /><img data-zoomable="" title="The new 'FF Auth' options available in Node-RED to allow for client constraints" alt="The new 'FF Auth' options available in Node-RED to allow for client constraints" loading="lazy" decoding="async" src="https://flowfuse.com/img/multi-user-dashboard-ff-settings-Jf8rG8WpVt-1100.jpeg" width="1100" height="1316" /></picture></p>
<figcaption class="-mt-6 mb-4 text-center"><b>A screenshot of the new 'FF Auth' options available in Node-RED to allow for client constraints on different node types.</b></figcaption>
<p>In the original Node-RED Dashboard, this was <em>always</em> enabled for the <code>ui-notification</code> and <code>ui-control</code> nodes, whereby you could include <code>msg.socket</code> data and it would only then send that message to the specified client. For Dashboard 2.0 we've extended this concept so that as a Node-RED Developer, you can now include <code>msg._client.user</code> data in any message sent to a Dashboard 2.0 node. Under the covers, our FlowFuse-exclusive plugin will then automatically filter messages to only send to the relevant user's connection.</p>
<p>Utilising this feature, below you can see an example where we send data to a <code>ui-template</code> to render a custom table for each user. Under the covers this is a <code>ui-event</code> node (triggered on a page view), which then uses the <code>msg._client.user</code> object to make a REST API call to retrieve a list of todo items for that specific user. We then wire the response into the <code>ui-template</code>, which has been configured to "Accept Client Constraints", and so only sends this data to User 2's dashboard.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/multi-user-dashboard-admin-tasks-OhvPu-0L5n-1920.avif 1920w" sizes="(min-device-pixel-ratio: 1.25) 3840px, (min-resolution: 120dpi) 3840px, 1920px" /><source type="image/webp" srcset="https://flowfuse.com/img/multi-user-dashboard-admin-tasks-OhvPu-0L5n-1920.webp 1920w" sizes="(min-device-pixel-ratio: 1.25) 3840px, (min-resolution: 120dpi) 3840px, 1920px" /><img data-zoomable="" title="Showing Admin Task View" alt="Showing Admin Task View" loading="lazy" decoding="async" src="https://flowfuse.com/img/multi-user-dashboard-admin-tasks-OhvPu-0L5n-1920.jpeg" width="1920" height="1111" /></picture></p>
<figcaption class="-mt-6 mb-4 text-center"><b>Example of a dashboard that displays user-specific content.</b></figcaption>
<p>Note too that we're also utilising the new <a href="https://dashboard.flowfuse.com/nodes/widgets/ui-template.html#teleports">Teleport</a> option available in a <code>ui-template</code> which allows us to define content to show in the top-right of the dashboard, in this case, a little <em>"Hi {username}"</em> message.</p>
<h3 id="examples" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/dashboard-2-multi-user/#examples"># </a> Examples</h3>
<h4 id="rendering-logged-in-user-data" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/dashboard-2-multi-user/#rendering-logged-in-user-data"># </a> Rendering Logged In User Data</h4>
<p>In the previous example, you may have noticed that we're also displaying a welcome to the authenticated user on our dashboard, this means that we have access to the full User object within any <code>ui-template</code> that we render too.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/multi-user-dashboard-user2-qTs1QLNtiv-1920.avif 1920w" sizes="(min-device-pixel-ratio: 1.25) 3840px, (min-resolution: 120dpi) 3840px, 1920px" /><source type="image/webp" srcset="https://flowfuse.com/img/multi-user-dashboard-user2-qTs1QLNtiv-1920.webp 1920w" sizes="(min-device-pixel-ratio: 1.25) 3840px, (min-resolution: 120dpi) 3840px, 1920px" /><img data-zoomable="" title="Showing User Unique Data" alt="Showing User Unique Data" loading="lazy" decoding="async" src="https://flowfuse.com/img/multi-user-dashboard-user2-qTs1QLNtiv-1920.jpeg" width="1920" height="1111" /></picture></p>
<figcaption class="-mt-6 mb-4 text-center"><b>The "Admin" view that is only made available to users registered as an "admin".</b></figcaption>
<p>Under the covers, we're appending our <code>user</code> object to the <code>msg</code> object, via the SocketIO <code>auth</code> option. We make the <code>socketio</code> object available via a computed <code>setup</code> variable, this means that we can access this data in any <code>ui-template</code> node, and render like so:</p>
<div style="position: relative">
<pre class="language-html"><code id="code-99" class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>template</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h1</span><span class="token punctuation">></span></span>Hi, {{ setup?.socketio?.auth?.user?.name }}!<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h1</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>template</span><span class="token punctuation">></span></span></code></pre>
<button class="code-copy " data-clipboard-target="#code-99" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>To enable custom user-by-user content in a <code>ui-template</code> though, we must allow it to "Accept Client Constraints". This means that if a <code>.msg._client.user</code> value is included in any messages sent to a <code>ui-template</code> node, then the underlying SocketIO message will be filtered to only send to the relevant user's connection, and no others.</p>
<h4 id="admin-only-views" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/dashboard-2-multi-user/#admin-only-views"># </a> Admin Only Views</h4>
<p>With this new functionality we can also now show/hide content based on the authenticated user.</p>
<p>We recently introduced the option to <a href="https://github.com/FlowFuse/node-red-dashboard/pull/484">set default visiblity & interaction states</a>. This was partly introduced because it's a good practice to set the default "Visibility" option for any admin-only pages to "Hidden", and then use a <code>ui-control</code> node to show the content only to the relevant admins.</p>
<iframe width="100%" height="100%" src="https://flows.nodered.org/flow/2fe8e6f1e7002f1ff6a9195ad1a153b6/share" allow="clipboard-read; clipboard-write" style="border: none; margin-bottom: 12px;"></iframe>
<p>Let's breakdown the above flow:</p>
<ol>
<li>We wire a <code>ui-event</code> node (which emits each time a user views a page) into a switch node</li>
<li>Our switch node checks the <code>user.username</code> against a known list of admin users and branches "admin:" and "non-admin" users</li>
<li>For admin users, the <code>change</code> node defines a message for our <code>ui-control</code> node to dynamically show content, in this case an "Admin" page, when appropriate.</li>
</ol>
<div style="position: relative">
<pre class="language-json"><code id="code-133" class="language-json"><span class="token punctuation">{</span><br /> <span class="token property">"pages"</span><span class="token operator">:</span><span class="token punctuation">{</span><br /> <span class="token property">"show"</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">"Admin View"</span><span class="token punctuation">]</span><br /> <span class="token punctuation">}</span><br /><span class="token punctuation">}</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-133" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>All events going into <code>ui-control</code> are automatically filtered based on the <code>msg._client.user</code> object, so only the Admin users will receive the message to show the "Admin View" page, resulting in:</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/multi-user-dashboard-admin-FyPHrtXpYw-1920.avif 1920w" sizes="(min-device-pixel-ratio: 1.25) 3840px, (min-resolution: 120dpi) 3840px, 1920px" /><source type="image/webp" srcset="https://flowfuse.com/img/multi-user-dashboard-admin-FyPHrtXpYw-1920.webp 1920w" sizes="(min-device-pixel-ratio: 1.25) 3840px, (min-resolution: 120dpi) 3840px, 1920px" /><img data-zoomable="" title="Showing Admin Only View" alt="Showing Admin Only View" loading="lazy" decoding="async" src="https://flowfuse.com/img/multi-user-dashboard-admin-FyPHrtXpYw-1920.jpeg" width="1920" height="1111" /></picture></p>
<figcaption class="-mt-6 mb-4 text-center"><b>The "Admin" view that is only made available to users registered as an "admin".</b></figcaption>
<p>Further extensions of this could also check <code>ui-event</code> in case a non-admin user tries to access the <code>/admin</code> page directly, in which case we can utilise <code>ui-control</code> to navigate the user away from the page immediately. See the <a href="https://dashboard.flowfuse.com/nodes/widgets/ui-control.html#navigation">ui-control documentation</a> for more details on this.</p>
<h2 id="upcoming-webinar" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/dashboard-2-multi-user/#upcoming-webinar"># </a> Upcoming Webinar</h2>
<p>If you're interested in learning more about Dashboard 2.0 and in particular multi-user Dashboards, we're hosting a webinar on Thursday, 29th February. You can find out more information <a href="https://flowfuse.com/webinars/2024/node-red-dashboard-multi-user/">here</a></p>
<h2 id="follow-our-progress" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/dashboard-2-multi-user/#follow-our-progress"># </a> Follow our Progress</h2>
<p>We aren't stopping here, we'll continue to push Dashboard 2.0 forward with future development, and you can track that progress on our GitHub Projects:</p>
<ul>
<li><a href="https://github.com/orgs/FlowFuse/projects/15/views/1">Dashboard 2.0 Activity Tracker</a></li>
<li><a href="https://github.com/orgs/FlowFuse/projects/15/views/4">Dashboard 2.0 Planning Board</a></li>
<li><a href="https://github.com/orgs/FlowFuse/projects/15/views/5">Dashboard 1.0 Feature Parity Tracker</a></li>
</ul>
<p>If you have any feature requests, bugs/complaints or general feedback, please do reach out, and raise issues on our relevant <a href="https://github.com/FlowFuse/node-red-dashboard">GitHub repository</a>.</p>
https://flowfuse.com/blog/2024/01/dashboard-2-ga/Node-RED Dashboard 2.0 is Generally Available!This week sees our first major version release of Node-RED Dashboard 2.0!2024-01-24T00:00:00ZJoe Pavitt<p>Back in <a href="https://flowfuse.com/blog/2023/06/dashboard-announcement/">June 2023</a> we announced that FlowFuse would be investing into building out the next generation of Node-RED Dashboard, the most popular UI framework for Node-RED.
We followed this up with the <a href="https://flowfuse.com/blog/2023/07/dashboard-0-1-release/">first release</a> (<code>0.0.1</code>) in July, just one month later, and today, we are pleased to announce that we have reached a major milestone in this journey, with the release of our first major version (<code>1.0.0</code>) of Node-RED Dashboard 2.0.</p>
<!--more-->
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/dashboard-ga-example-GdrlGHRgNj-650.avif 650w, https://flowfuse.com/img/dashboard-ga-example-GdrlGHRgNj-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/dashboard-ga-example-GdrlGHRgNj-650.webp 650w, https://flowfuse.com/img/dashboard-ga-example-GdrlGHRgNj-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/dashboard-ga-example-GdrlGHRgNj-650.jpeg 650w, https://flowfuse.com/img/dashboard-ga-example-GdrlGHRgNj-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Dashboard 2.0 Example showing weather data" loading="lazy" decoding="async" src="https://flowfuse.com/img/dashboard-ga-example-GdrlGHRgNj-650.jpeg" width="1300" height="886" /></picture></p>
<p>With our <code>1.0.0</code> release, you can now build your dashboards on a reliable and stable package, and we invite you to to start contributing your own third-party <a href="https://dashboard.flowfuse.com/contributing/widgets/third-party.html">widgets</a> and <a href="https://dashboard.flowfuse.com/contributing/plugins/">plugins</a>. We're excited to see what the community can contribute and build on top of this new Dashboard 2.0 framework, and we'll be continuing development to the core collection of widgets too.</p>
<p>With Node-RED Dashboard 2.0, we have re-built the original Node-RED Dashboard from the ground up. It is now extensible due to it being VueJS-based, completely responsive down to mobile, and we've made many quality of life improvements across the board to the existing widget collection, as well as adding a few new ones too.</p>
<h2 id="what's-new-in-dashboard-2.0%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/dashboard-2-ga/#what's-new-in-dashboard-2.0%3F"># </a> What's new in Dashboard 2.0?</h2>
<p>We've shared plenty of updates since we started, detailing the feature parity with the original Node-RED Dashboard, as well as some of the new widgets and features we've added to the new Dashboard, such as Markdown, Mermaid Charts and new Layout Options, you can read more about those here:</p>
<ul>
<li><a href="https://flowfuse.com/blog/2023/09/dashboard-notebook-layout/">Dynamic Markdown, Tables & Notebooks</a></li>
<li><a href="https://flowfuse.com/blog/2023/11/dashboard-0-7/">UI Chart Improvements</a></li>
<li><a href="https://flowfuse.com/blog/2023/12/dashboard-0-10-0/">Building a Custom Video Player</a></li>
</ul>
<p>Furthermore, the most requested feature for the legacy dashboard has been implemented in Dashboard 2.0, the ability to hide charts and forms based on the user that's viewing the dashboard.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/multi-user-dashboard-user2-qTs1QLNtiv-650.avif 650w, https://flowfuse.com/img/multi-user-dashboard-user2-qTs1QLNtiv-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/multi-user-dashboard-user2-qTs1QLNtiv-650.webp 650w, https://flowfuse.com/img/multi-user-dashboard-user2-qTs1QLNtiv-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/multi-user-dashboard-user2-qTs1QLNtiv-650.jpeg 650w, https://flowfuse.com/img/multi-user-dashboard-user2-qTs1QLNtiv-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Dashboard 2.0 Example showing personalised dashboard" loading="lazy" decoding="async" src="https://flowfuse.com/img/multi-user-dashboard-user2-qTs1QLNtiv-650.jpeg" width="1300" height="752" /></picture></p>
<p>Read more about it here:</p>
<ul>
<li><a href="https://flowfuse.com/blog/2024/01/dashboard-2-multi-user/">Personalised Multi User Dashboards</a></li>
</ul>
<p>If that wasn't enough, we also have <a href="https://dashboard.flowfuse.com/">rich documentation</a> for Dashboard 2.0 too, detailing all of the available nodes, details on how Dashboard 2.0 is built and how to contribute to the project too if you're that way inclined.</p>
<h2 id="upcoming-webinar" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/dashboard-2-ga/#upcoming-webinar"># </a> Upcoming Webinar</h2>
<p>If you're interested in learning more about Dashboard 2.0 and in particular, personalised multi-user dashboards, we're hosting a webinar on Thursday, 29th February. You can find out more information <a href="https://flowfuse.com/webinars/2024/node-red-dashboard-multi-user/">here</a></p>
<h2 id="follow-our-progress" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/dashboard-2-ga/#follow-our-progress"># </a> Follow our Progress</h2>
<p>We aren't stopping here, we'll continnue to push Dashboard 2.0 forward with future development, with a <a href="https://github.com/FlowFuse/node-red-dashboard/issues/12">new UI Gauge</a> next on the list. You can track that progress of that particular issue, and the rest of the work we have lined up on our GitHub Projects:</p>
<ul>
<li><a href="https://github.com/orgs/FlowFuse/projects/15/views/1">Dashboard 2.0 Activity Tracker</a></li>
<li><a href="https://github.com/orgs/FlowFuse/projects/15/views/4">Dashboard 2.0 Planning Board</a></li>
<li><a href="https://github.com/orgs/FlowFuse/projects/15/views/5">Dashboard 1.0 Feature Parity Tracker</a></li>
</ul>
<p>If you have any feature requests, bugs/complaints or general feedback, please do reach out, and raise issues on our relevant <a href="https://github.com/FlowFuse/node-red-dashboard">GitHub repository</a>.</p>
https://flowfuse.com/blog/2024/01/barcode-scanner-into-nodered/How to connect a barcode scanner to your Node-RED applicationA guide to connecting a barcode scanner to Node-RED.2024-01-24T00:00:00ZGrey Dziuba<p>Barcode scanners, functioning as Human Interface Devices (HID) similar to keyboards, offer versatile programming options. Variations of barcode scanners can be seen used from anything from checkout counters, logistics, and to manufacturing erp systems. In our case, we kept it basic and we used one to trigger a Node-RED flow, keeping the process straightforward and efficient. Don't let that limit your imagination though, with QR codes, you can store just about anything including recipes in a JSON structure.</p>
<!--more-->
<h2 id="configuring-the-scanner-and-scanning-barcodes" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/barcode-scanner-into-nodered/#configuring-the-scanner-and-scanning-barcodes"># </a> Configuring the scanner and scanning barcodes</h2>
<p>We revitalized an older project for this purpose, ensuring it's up-to-date. For Windows users, the setup is straightforward. Start by importing the project, <a href="https://flows.nodered.org/node/@gdziuba/node-red-usbhid">@gdziuba/node-red-usbhid</a>, via the palette manager. Import these <a href="https://flows.nodered.org/flow/3e08565bc0e024e81325dc028c5da792">flows</a> to get started. This initial flow identified as <strong>getHIDdevices</strong> will detect all devices connected to your Node-RED environment. Locate your barcode scanner in the debug output. You will see everything from your mouse and keyboard. If you have just recently added the barcode scanner to your computer, it will probably be found at the end. Once you find it note its <strong>Product ID</strong> and <strong>Vendor ID</strong>. For us, they would be identified as 1536 and 1504 respectively.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/usbhid-barcode-node-red-AQ6X4zk4GS-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/usbhid-barcode-node-red-AQ6X4zk4GS-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="USB HID Node-RED" loading="lazy" decoding="async" src="https://flowfuse.com/img/usbhid-barcode-node-red-AQ6X4zk4GS-650.jpeg" width="650" height="186" /></picture></p>
<p>Next, configure the <strong>HIDdevice</strong> node: replace the default <strong>PID</strong> with your scanner’s Product ID, and the <strong>VID</strong> with its Vendor ID.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/usbhid-config-node-red-lsaRM5Lp6t-516.avif 516w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/usbhid-config-node-red-lsaRM5Lp6t-516.webp 516w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="USB HID Config Node-RED" loading="lazy" decoding="async" src="https://flowfuse.com/img/usbhid-config-node-red-lsaRM5Lp6t-516.jpeg" width="516" height="305" /></picture></p>
<p>Test your barcode scanner against any barcode your scanner works with and you should observe an event being triggered in Node-RED and output to debug should be the contents of the barcode.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/usbhid-scanned-barcode-gotI6cZP22-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/usbhid-scanned-barcode-gotI6cZP22-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="USB HID Scanned Barcode in Node-RED" loading="lazy" decoding="async" src="https://flowfuse.com/img/usbhid-scanned-barcode-gotI6cZP22-650.jpeg" width="650" height="158" /></picture></p>
<p>You could even take it a step further and create a <a href="https://smalldev.tools/qr-code-generator-online">QR code</a> for your favorite pizza ingredients as seen here on the new <a href="https://dashboard.flowfuse.com/">Dashboard 2.0</a>.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/usbhid-qr-pizza-order-NEn39raWL7-645.avif 645w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/usbhid-qr-pizza-order-NEn39raWL7-645.webp 645w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="USB HID Scanned Barcode Pizza Ingredients" loading="lazy" decoding="async" src="https://flowfuse.com/img/usbhid-qr-pizza-order-NEn39raWL7-645.jpeg" width="645" height="231" /></picture></p>
<h2 id="linux-setup" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/barcode-scanner-into-nodered/#linux-setup"># </a> Linux Setup</h2>
<p>Linux users might face a slightly more complicated setup, as access to communication ports isn't always granted by default, and specific drivers are needed for optimal node functionality. This is due to the security around applications having access to specific devices connected to the system. For this, we recommend following the detailed instructions available in the project's <a href="https://github.com/gdziuba/node-red-contrib-usbhid">GitHub</a> repository.</p>
<h2 id="conclusion" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/barcode-scanner-into-nodered/#conclusion"># </a> Conclusion</h2>
<p>At first this project seemed like it was going to be overly complicated, but after updating the node, it became incredibly easy. The way Node-RED is supposed to make it. Simple.</p>
https://flowfuse.com/blog/2024/01/sentiment-analysis-with-node-red/Sentiment Analysis with Node-REDA guide to building a simple sentiment analysis system with Node-RED.2024-01-23T00:00:00Z<p>Have you ever built a sentiment analysis system to extract insights from text content? If yes then I don’t think you'll need an explanation of how complex it is to build. In this guide, we will build a sentiment analysis system with Node-RED using Dashboard 2.0 in a few easy steps.</p>
<!--more-->
<h1 id="what-exactly-is-sentiment-analysis%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/sentiment-analysis-with-node-red/#what-exactly-is-sentiment-analysis%3F"># </a> What exactly is sentiment analysis?</h1>
<p>Sentiment analysis is a context-mining technique used to understand emotions and opinions expressed in text, often classifying them as positive, neutral, or negative. There are many real-world applications of this technique.</p>
<ul>
<li><strong>Analysing Feedback:</strong> Customers, or other stakeholders like employees, are periodically requested to fill out a feedback form. Analysis of such feedback is the most widespread application of sentiment analysis.</li>
<li><strong>Campaign Monitoring:</strong> Another use case of sentiment analysis is a measure of influence which is crucial in any marketing campaign.</li>
<li><strong>Brand Monitoring:</strong> Brand monitoring is another great use case for sentiment analysis. Companies can use sentiment analysis to check the social media sentiments around their brand from their audience.</li>
</ul>
<h1 id="building-a-form-in-dashboard-2.0" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/sentiment-analysis-with-node-red/#building-a-form-in-dashboard-2.0"># </a> Building a Form in Dashboard 2.0</h1>
<p>In this system, we will analyse the sentiment of text content obtained from the user. For this we are going to build a user interface using Dashboard 2.0 and Node-RED.</p>
<ol>
<li>Install Node-RED Dashboard 2.0. Follow these <a href="https://dashboard.flowfuse.com/getting-started.html">instructions</a> to install.</li>
<li>Create your first group, page, theme, and base.</li>
<li>Drag a ui form widget to the canvas and select the created group.</li>
<li>Add an element in the form widget and give it a name and label, select the type as multiline, and set the number of rows according to your need.</li>
</ol>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/sentiment-analysis-form-szWddYyGjF-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/sentiment-analysis-form-szWddYyGjF-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Taking user input for Sentiment analysis using form" alt=""Taking user input for Sentiment analysis using form"" loading="lazy" decoding="async" src="https://flowfuse.com/img/sentiment-analysis-form-szWddYyGjF-650.jpeg" width="650" height="424" /></picture></p>
<h1 id="normalizing-the-data" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/sentiment-analysis-with-node-red/#normalizing-the-data"># </a> Normalizing the data</h1>
<p>We need to normalize the payload before sending it to the next node because the form widget always returns an object containing the property of values of form elements.</p>
<ol>
<li>Drag a change node to canvas.</li>
<li>Set <code>msg.payload.$FORM_ELEMENT_NAME</code> to <code>msg.payload</code>, replace the <code>$FORM_ELEMENT_NAME</code> with the name of the form element that you have added to the form to obtain user input.</li>
<li>Connect the UI form nodes output to the change node’s input.</li>
</ol>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/sentiment-anlaysis-change-node(1)-sGGRlgRdFg-598.avif 598w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/sentiment-anlaysis-change-node(1)-sGGRlgRdFg-598.webp 598w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Normalizing the payload using change node" alt=""Normalizing the payload using change node"" loading="lazy" decoding="async" src="https://flowfuse.com/img/sentiment-anlaysis-change-node(1)-sGGRlgRdFg-598.jpeg" width="598" height="390" /></picture></p>
<h1 id="installing-custom-node" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/sentiment-analysis-with-node-red/#installing-custom-node"># </a> Installing custom node</h1>
<p>Now it’s time to install a custom node that can perform sentiment analysis for us. In this guide, we will use the <code>node-red-node-sentiment</code> which is a Node-RED node that uses the AFINN-165 wordlists for sentiment analysis of words. It returns a sentiment object containing a score and other properties but we will only use the score property. Score property typically ranges from -5 to 5.</p>
<ol>
<li>Install the <code>node-red-node-sentiment</code> package by the node-red palette manager.</li>
<li>Drag a sentiment node to canvas.</li>
<li>Connect the change nodes output to sentiment node input.</li>
</ol>
<h1 id="calculating-percentage" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/sentiment-analysis-with-node-red/#calculating-percentage"># </a> Calculating percentage</h1>
<p>Why do we need to calculate the percentage? We will show the final result with the help of a circular progress bar and three different emojis. Ideally we should show the progress bar based on a percentage of score instead of negative values.</p>
<ol>
<li>Drag another change node to canvas.</li>
<li>set <code>msg.payload</code> to <code>((msg.sentiment.score - (-5)) / (5 - (-5))) * 100</code> as a JSONata expression, it will calculate the percentage of the score.</li>
</ol>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/sentiment-analysis-change-node(2)-fOUBxjaBfl-608.avif 608w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/sentiment-analysis-change-node(2)-fOUBxjaBfl-608.webp 608w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Calculating the percentage based on the score using the change node" alt=""Calculating the percentage based on the score using the change node"" loading="lazy" decoding="async" src="https://flowfuse.com/img/sentiment-analysis-change-node(2)-fOUBxjaBfl-608.jpeg" width="608" height="382" /></picture></p>
<h1 id="displaying-result-on-dashboard-2.0" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/sentiment-analysis-with-node-red/#displaying-result-on-dashboard-2.0"># </a> Displaying result on Dashboard 2.0</h1>
<p>Finally, we are going to display the result on Dashboard 2.0 with the help of the Vuetify circular progress bar and emojis. To do that we will build a Vue component by using our ui template widget.</p>
<ol>
<li>Drag a ui template widget to canvas and create another group for it.</li>
<li>Paste the below Vue component snippet into the template widget.</li>
</ol>
<p>We're aware that not everyone coming into Dashboard 2.0 will be familiar with VueJS. We have a more detailed guide <a href="https://dashboard.flowfuse.com/nodes/widgets/ui-template.html#building-full-vue-components">here</a>, but we'll also give a quick overview of the component that we'll use to display the result:</p>
<div style="position: relative">
<pre class="language-html"><code id="code-149" class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>template</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>v-progress-circular</span> <span class="token attr-name">:rotate</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>360<span class="token punctuation">"</span></span> <span class="token attr-name">:size</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>245<span class="token punctuation">"</span></span> <span class="token attr-name">width</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>20<span class="token punctuation">"</span></span> <span class="token attr-name">:width</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>15<span class="token punctuation">"</span></span> <span class="token attr-name">:model-value</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>msg.payload<span class="token punctuation">"</span></span> <span class="token attr-name">color</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>rgb(0,255,0)<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>img</span> <span class="token attr-name">v-if</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>msg.payload <= 33.33<span class="token punctuation">"</span></span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>https://i.ibb.co/VHKZ8sn/imgbin-smirk-emoji-face-emoticon-smile-png.png<span class="token punctuation">"</span></span> <span class="token attr-name">width</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>240<span class="token punctuation">"</span></span> <span class="token attr-name">height</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>240<span class="token punctuation">"</span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>sad emoji<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>img</span> <span class="token attr-name">v-else-if</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>msg.payload <= 66.66<span class="token punctuation">"</span></span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>https://i.ibb.co/nMnybLJ/imgbin-emoji-computer-icons-emoticon-smiley-png.png<span class="token punctuation">"</span></span> <span class="token attr-name">width</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>240<span class="token punctuation">"</span></span> <span class="token attr-name">height</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>240<span class="token punctuation">"</span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>neutral emoji<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>img</span> <span class="token attr-name">v-else</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>https://i.ibb.co/TK12RrH/Smile-Emoji-Face-PNG-Download-Image.png<span class="token punctuation">"</span></span> <span class="token attr-name">width</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>240<span class="token punctuation">"</span></span> <span class="token attr-name">height</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>240<span class="token punctuation">"</span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>happy emoji<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>v-progress-circular</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>template</span><span class="token punctuation">></span></span></code></pre>
<button class="code-copy " data-clipboard-target="#code-149" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<ul>
<li>v-progress-circular is a Vuetify component to display a circular progress bar, for a detailed guide refer to our blog on <a href="https://flowfuse.com/blog/2023/10/custom-vuetify-components-dashboard/">Custom Vuetify components for Dashboard 2.0</a>.</li>
<li><code>rotate</code> is an attribute that lets you specify the rotation angle of the progress bar.</li>
<li><code>size</code> and <code>width</code> allow you to set the size of the circular progress bar, and another <code>width</code> attribute allows you to set the stroke width of the circular progress bar.</li>
<li>v-if, v-else-if, and v-else, allow dynamic rendering of elements based on specified conditions, in this component we are rendering emojis based on percentages calculated by score.</li>
</ul>
<p>Your final flow should look like this:</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/sentiment-anlaysis-flow-VWfC9HkbQu-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/sentiment-anlaysis-flow-VWfC9HkbQu-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Node-RED flow to do sentiment analysis" alt=""Node-RED flow to do sentiment analysis"" loading="lazy" decoding="async" src="https://flowfuse.com/img/sentiment-anlaysis-flow-VWfC9HkbQu-650.jpeg" width="650" height="143" /></picture></p>
<h1 id="deploying-the-flow" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/sentiment-analysis-with-node-red/#deploying-the-flow"># </a> Deploying the Flow</h1>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/sentiement-analysis-flowfuse-editor-JDMftUY6jN-650.avif 650w, https://flowfuse.com/img/sentiement-analysis-flowfuse-editor-JDMftUY6jN-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/sentiement-analysis-flowfuse-editor-JDMftUY6jN-650.webp 650w, https://flowfuse.com/img/sentiement-analysis-flowfuse-editor-JDMftUY6jN-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/sentiement-analysis-flowfuse-editor-JDMftUY6jN-650.jpeg 650w, https://flowfuse.com/img/sentiement-analysis-flowfuse-editor-JDMftUY6jN-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Deploying Sentiment analysis Node-RED flow" alt=""Deploying Sentiment analysis Node-RED flow"" loading="lazy" decoding="async" src="https://flowfuse.com/img/sentiement-analysis-flowfuse-editor-JDMftUY6jN-650.jpeg" width="1300" height="616" /></picture></p>
<p>Finally, we have successfully built our sentiment analysis system. Now it's time to deploy the flow, to do that click on the red deploy button which you can find in the top right corner. After that go to <code>https://<your-instance-name>.flowfuse.cloud/dashboard</code></p>
<p><picture><source type="image/gif" srcset="https://flowfuse.com/img/sentiment-analysis-dashboard-gif-cioCkFeLOX-600.gif 600w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Sentiment analysis on Text using Node-RED Dashboard 2.0" alt=""Sentiment analysis on Text using Node-RED Dashboard 2.0"" loading="lazy" decoding="async" src="https://flowfuse.com/img/sentiment-analysis-dashboard-gif-cioCkFeLOX-600.webp" width="600" height="306" /></picture></p>
<h1 id="conclusion" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/sentiment-analysis-with-node-red/#conclusion"># </a> Conclusion</h1>
<p>In this post, a sentiment analysis system is built with Node-RED in which the user has a form field to paste text content. After submitting the form, it calculates the percentage based on the output score, which ranges from -5 to 5. The output will be displayed on dashboard 2.0 by a circular progress bar and three different emojis based on percentage.</p>
https://flowfuse.com/blog/2024/01/unified-namespace-what-broker/Selecting a broker for your Unified NamespaceThe broker is the data backbone for the unified namespace, which one is right for you?2024-01-19T00:00:00ZZJ van de Weg<p>When starting to roll out a new data distribution architecture for the unified namespace (UNS), one of the first questions you'll ask is, "What broker should I select for my UNS? The broker must implement a publish-subscribe (pub-sub) pattern, though that leaves plenty of options.</p>
<!--more-->
<h2 id="technology-selection" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/unified-namespace-what-broker/#technology-selection"># </a> Technology selection</h2>
<h3 id="two-protocols-frontrunners" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/unified-namespace-what-broker/#two-protocols-frontrunners"># </a> Two protocols frontrunners</h3>
<p>Currently, there are two protocols that are front runners for becoming the de facto data transfer choice in (industrial) IoT: MQTT or Kafka. They’ve been designed for different use cases and have different properties. At this time, MQTT is more often deployed as a broker in the unified namespace and is generally the best choice when starting to implement a unified namespace, it also features better support from hardware vendors.</p>
<p>First and foremost, MQTT has been designed to enable IoT use cases. The main design objectives were to be lightweight to enable low-bandwidth communication, enable low-power devices, and handle unreliable networks. MQTT enables a large number of data producers and consumers to collaborate.</p>
<p>Kafka is designed as an event streaming platform. Its initial adoption was mostly for data brokers between microservices all part of the same web backend for large sites like LinkedIn. When communicating data between servers or just a few data centers around the world, there’s less of a concern around the reliability of the connection or to enable constrained devices to participate in the shift towards a unified namespace.</p>
<p>Generally, MQTT is more often seen deployed in practice as data distribution architecture.</p>
<h3 id="the-cloud-route" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/unified-namespace-what-broker/#the-cloud-route"># </a> The Cloud route</h3>
<p>Cloud message queue brokers like AWS Kinesis and GCP Pub/Sub offer a high level of convenience. Scaling the infrastructure for real-time data processing and communication is their concern, the customer is mostly concerned about paying the bill. These brokers are fully managed, meaning they are maintained and updated by the cloud provider, reducing the burden on developers.</p>
<p>However, this convenience comes with the tradeoff of vendor lock-in. When selecting these brokers, the cloud vendor has usually adapted their technology to support many protocols, and these offerings are usually jack-of-all-trades solutions – master of none. It creates a situation where the unified namespace implementation will change in subtle ways to accommodate the vendor instead of the other way around. An organization might become so reliant on a particular vendor's products or services that they are unable to easily switch to another vendor or protocol that serves their business objectives better. The cost of changing is exacerbated by having to train personnel on new and open-source protocols.</p>
<p>In addition to vendor lock-in, cloud message queue brokers also introduce reliance on the network to the cloud providers. Network reliability for (industrial) IoT is a major concern due to the physically distributed nature, adding external dependencies creates more variability.</p>
<h3 id="exotic-options" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/unified-namespace-what-broker/#exotic-options"># </a> Exotic options</h3>
<p>RabbitMQ is a widely used open-source message broker that’s mostly used as an event message bus for web applications. It can also function as a hub in a unified namespace. The broker primarily supports the AMQP (Advanced Message Queuing Protocol), considered the industry standard for high-performance messaging systems. It also supports STOMP (Streaming Text Oriented Messaging Protocol) and MQTT (MQ Telemetry Transport), catering to various messaging needs.</p>
<p>NATS, short for Network Agnostic Messaging System, is another open-source message broker that is designed for simplicity and reliability. NATS implements its own protocols, making it harder to be interoperable with hardware and software previously purchased. NATS has requirements on message structure too, which creates another barrier to adoption for IoT use cases.</p>
<h2 id="conclusion" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/unified-namespace-what-broker/#conclusion"># </a> Conclusion</h2>
<p>An MQTT broker is currently recommended as a broker solution for your unified namespace. There are many different implementations of the protocol available. At FlowFuse, we’re using <a href="https://mosquitto.org/">Mosquitto</a>, due to its efficiency on resources and flexible authentication layer. Further, our customers are reporting to be happy with <a href="https://www.emqx.io/">EMqX</a>, which is written in Erlang – itself a messaging-oriented programming language – and has been put through its paces in practice. If you’re dipping your toes into the unified namespace, either of those or another MQTT broker is currently recommended.</p>
<p>Note that it’s recommended to allow yourself flexibility in the broker, and treat it as a message-passing system, and your organization will be able to easily swap it out later if any other broker is a better fit later on.</p>
https://flowfuse.com/blog/2024/01/flowfuse-release-2-0/FlowFuse 2.0 ReleaseElevating Node-RED Device Management to new heights2024-01-18T00:00:00ZMarian Demme<p>Following the release of FlowFuse 1.0 end of 2022, we're excited to release FlowFuse 2.0, marking a significant step in managing Node-RED remote instances, which we call Devices. FlowFuse already was the best place to operate Node-RED at scale in the cloud or on-premise, now it's able to manage Node-RED where ever it's run.</p>
<!--more-->
<p>Many organizations position Node-RED instances on remote servers like edge or industrial devices. This way they can meet network requirement, interact with analog protocols, and overcome other infrastructure requirements. Management of remote instances is crucial for the overall success of closing the gap between IT and OT. A key enhancement was the introduction of Device Groups (from version 1.15) and the new feature to assign target snapshots. This allows for direct and streamlined management of Node-RED Device fleets, setting the stage for future advancements in device management capabilities.</p>
<p>For our FlowFuse users, this means it is no longer necessary or recommended to assign devices to an instance. Node-RED devices can be managed independently, and snapshots can be assigned via DevOps pipelines.</p>
<h2 id="enterprise-readiness" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/flowfuse-release-2-0/#enterprise-readiness"># </a> Enterprise-Readiness</h2>
<p>FlowFuse is committed to augmenting the enterprise-readiness of Node-RED with introductions like <a href="https://flowfuse.com/docs/admin/sso/">Single Sign-On (SSO)</a>, <a href="https://flowfuse.com/docs/user/user-settings/#two-factor-authentication">Multi-Factor Authentication (MFA)</a>, and <a href="https://flowfuse.com/docs/user/high-availability/">High Availability</a> since version 1.0. Furthermore, we recently achieved <a href="https://flowfuse.com/blog/2024/01/soc2/">SOC2 Type 1 compliance</a>. With these advancements, Node-RED, in combination with FlowFuse, is genuinely ready for enterprise and production use.</p>
<h2 id="enhanced-integration-capabilities" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/flowfuse-release-2-0/#enhanced-integration-capabilities"># </a> Enhanced Integration Capabilities</h2>
<p>The Node-RED Flow Library has always been a cornerstone, offering over 4800 connectors (nodes) for various OT and IT protocols. Thanks to the community and the Node-RED library. Building on this foundation, FlowFuse introduced "Certified Nodes" and "Blueprints". These <a href="https://flowfuse.com/blog/2023/10/blueprints/">Blueprints</a> are designed to provide an easier start with Node-RED, showcasing its full potential, while Certified Nodes ensure the security of the nodes used. Learn more about our new Certified Nodes <a href="https://flowfuse.com/blog/2023/10/certified-nodes/">here</a>.</p>
<h2 id="developer-velocity" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/flowfuse-release-2-0/#developer-velocity"># </a> Developer Velocity</h2>
<p>Node-RED team development is made possible with FlowFuse. Different development team members are able to share and collaborate on the same Node-RED instance. This makes for much easier collaboration between Node-RED developers. We've worked hard on maturing our <a href="https://flowfuse.com/docs/user/snapshots/">snapshot capabilties</a> and introduced <a href="https://flowfuse.com/docs/user/devops-pipelines/">DevOps Pipelines</a> that can be set up to stage Node-RED instances that have different development stages, e.g. test, development and production.</p>
<h2 id="looking-ahead" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/flowfuse-release-2-0/#looking-ahead"># </a> Looking Ahead</h2>
<p>At FlowFuse, our mission is to empower bottom-up innovation and enable organizations to transform their workflows into business-critical applications with unprecedented efficiency. As we move forward, we are excited to invite our users to actively engage with our future developments. Our <a href="https://flowfuse.com/product/roadmap/">Roadmap</a> lays out the advancements we're targeting, offering a glimpse into the features and enhancements that are on the horizon. We also encourage our users to stay informed and involved by checking out our latest updates in our detailed <a href="https://flowfuse.com/changelog/">changelog</a>. Your insights and feedback are crucial to us; they fuel our commitment to continuous improvement and innovation. We warmly invite you to <a href="https://flowfuse.com/contact-us/">share your thoughts and suggestions</a>, as your input is a vital part of our journey in shaping the next steps for FlowFuse.</p>
<h2 id="how-to-get-started" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/flowfuse-release-2-0/#how-to-get-started"># </a> How to get started</h2>
<p>You can install our <a href="https://flowfuse.com/docs/install/local/">local build</a>, use <a href="https://flowfuse.com/docs/install/docker/">Docker</a>, or <a href="https://flowfuse.com/docs/install/kubernetes/">Kubernetes</a>.</p>
<p>If you'd rather use our hosted offering: <a href="https://app.flowfuse.com/account/create">Get started for free</a> on FlowFuse Cloud.</p>
<h2 id="upgrading-flowfuse" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/flowfuse-release-2-0/#upgrading-flowfuse"># </a> Upgrading FlowFuse</h2>
<p><a href="https://app.flowfuse.com/">FlowFuse Cloud</a> is already running version 2.0.</p>
<p>If you installed a previous version of FlowFuse and want to upgrade, our documentation provides a
guide for <a href="https://flowfuse.com/docs/upgrade/">upgrading your FlowFuse instance</a>.</p>
<p>The version 2.0 release of the FlowFuse Helm Chart includes a breaking change for deployments making use of the <code>forge.localPostgresql</code> setting when upgrading. This is where the helm chart installs a dedicated PostgreSQL database instance.
With version 2.0 we have updated the version of the Bitnami PostgreSQL Helm sub-chart we bundle and the upgrade process will require some manual intervention to ensure things work correctly. A fresh install should not require any extra steps.</p>
<p>The steps are documented on the <a href="https://flowfuse.com/docs/install/kubernetes/#upgrade">Upgrade instructions</a> page, please read them carefully before upgrading</p>
<h2 id="getting-help" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/flowfuse-release-2-0/#getting-help"># </a> Getting help</h2>
<p>Please check FlowFuse's <a href="https://flowfuse.com/docs/">documentation</a> as the answers to many questions are covered there. Additionally you can go to the <a href="https://discourse.nodered.org/c/vendors/flowfuse/24">community forum</a> if you have
any feedback or feature requests.</p>
https://flowfuse.com/blog/2024/01/capture-data-edge-with-node-red-flowfuse/Capture Data from edge devices with Node-REDFlowFuse allows you to run Node-RED anywhere to capture all the data2024-01-17T00:00:00ZZJ van de Weg<p>While cloud computing has revolutionized data access and analysis, not all data can be accessed from the cloud. In many scenarios, data collection from the edge – the location where data is generated – is essential for real-time decision-making or process observability.</p>
<!--more-->
<p>FlowFuse enables data to be collected through Node-RED. Data can be processed locally on the edge or sent on to other services. FlowFuse doesn’t rely on continuous connections to the cloud, making it a good choice for locations with unreliable internet connectivity. Use cases like real-time monitoring of critical systems, proactive maintenance, and improved operational efficiency are now possible to implement.</p>
<h2 id="installing-the-flowfuse-agent" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/capture-data-edge-with-node-red-flowfuse/#installing-the-flowfuse-agent"># </a> Installing the FlowFuse agent</h2>
<p>To manage the capturing of data on the edge we’re going to first install the FlowFuse agent. It’s installed on your device to manage the communication between the edge device and the FlowFuse server, manage the installation of Node-RED, its execution environment, and facilitate communication between devices and the cloud.</p>
<p>The device agent can run anywhere you can run a Docker container or Node.JS runtime (version 16.0+) can be installed.</p>
<h3 id="registering-a-device-on-flowfuse" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/capture-data-edge-with-node-red-flowfuse/#registering-a-device-on-flowfuse"># </a> Registering a device on FlowFuse</h3>
<p>For the edge device to know what it’s supposed to do, it needs to listen to the FlowFuse commands. The agent's configuration is provided by a <code>device.yml</code> file from FlowFuse. Go to the team you’d like to add an edge device to, and select “Devices” on the left-hand menu, followed by the “Add Device” button.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/flowfuse-agent-setup-cwqx7_w6a8-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/flowfuse-agent-setup-cwqx7_w6a8-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Setting up a FlowFuse agent" alt="Setting up a FlowFuse agent" loading="lazy" decoding="async" src="https://flowfuse.com/img/flowfuse-agent-setup-cwqx7_w6a8-650.jpeg" width="650" height="505" /></picture></p>
<p>FlowFuse will prompt you to add a name (required), and a type (not required). When you’ve clicked <code>Add</code> you’ll get a new dialog to download the required file.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/device-yml-flowfuse-tJYk8TEO24-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/device-yml-flowfuse-tJYk8TEO24-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="The contents of a device.yml file" alt="Configuration file for the FlowFuse agent" loading="lazy" decoding="async" src="https://flowfuse.com/img/device-yml-flowfuse-tJYk8TEO24-650.jpeg" width="650" height="457" /></picture></p>
<h3 id="install-the-flowfuse-agent-through-docker" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/capture-data-edge-with-node-red-flowfuse/#install-the-flowfuse-agent-through-docker"># </a> Install the FlowFuse agent through Docker</h3>
<p>If your device supports it, the fastest way to run the FlowFuse agent is with containers. Assuming you’ve already got Docker installed, there are two steps to follow: first, move the device YAML file downloaded from FlowFuse to the edge device and save it in <code>/opt/flowfuse/device.yml</code>. Start the agent by running:</p>
<pre><code>docker run --mount type=bind,src=/path/to/device.yml,target=/opt/flowfuse-device/device.yml -p 1880:1880 flowfuse/device-agent:latest
</code></pre>
<p>Note that for production cases, ensure the container is restarted on reboot. Docker can do this for you, <a href="https://docs.docker.com/config/containers/start-containers-automatically/">please follow their guide</a>.</p>
<h3 id="install-the-flowfuse-agent-with-npm" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/capture-data-edge-with-node-red-flowfuse/#install-the-flowfuse-agent-with-npm"># </a> Install the FlowFuse agent with npm</h3>
<p>To install the agent through NPM, you’ll need a Node.JS version of 18.0 or later. Open a command prompt and run: <code>npm install -g @flowfuse/device-agent</code>.</p>
<p>This will install the FlowFuse Device Agent as a global npm module, making the flowfuse-device-agent command available in any directory on your system.</p>
<p>Once the installation is complete, you must configure the Device Agent to connect to your FlowFuse instance. In this guide, you’ve previously downloaded the <code>device.yml</code> file that’s needed now. On Linux or Mac, move the file to <code>/opt/flowfuse-device/device.yml</code>, and for Windows-based systems, move the file to <code>c:\opt\flowfuse-device\device.yml</code>.</p>
<p>Afterward, start the agent with: <code>flowfuse-device-agent</code>.</p>
<p>This will launch the Device Agent and connect it to your FlowFuse instance. The Device Agent will wait for instructions on which flows to run.</p>
<h3 id="programming-flows-for-the-edge" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/capture-data-edge-with-node-red-flowfuse/#programming-flows-for-the-edge"># </a> Programming flows for the edge</h3>
<p>Now the agent is running, the FlowFuse platform will show it has contacted back to the platform and is ready to do some work. First, add it to the application and start the developer mode. That enables the device editor and provides you secure access to the editor anywhere in the world for everyone in the FlowFuse team with the right access role.</p>
<p>When the development is done, be sure to create a snapshot of the developed flows to create a point-in-time backup, or to roll the snapshot out to many other devices later.</p>
https://flowfuse.com/blog/2024/01/soc2/FlowFuse is now SOC 2 Type 1 CompliantFlowFuse's Path to SOC 2 Type 1 Compliance - A Testament to Our Commitment to Securing Customer and User Data.2024-01-15T00:00:00ZGrey Dziuba<p>FlowFuse achieved SOC 2 type 1 compliance! SOC 2, governed by the American Institute of Certified Public Accountants (AICPA), is a crucial framework for organizations handling customer data.
An independent audit assessed that FlowFuse's controls are effectively designed and operationally applied. Achieving SOC 2 Type 1 compliance validates our practises as an business and provides our customers assurances we apply the highest standards to ensure their data is protected.</p>
<!--more-->
<h1 id="improving-our-security-posture" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/soc2/#improving-our-security-posture"># </a> Improving Our Security Posture</h1>
<p>At FlowFuse, we understand that professionalizing Node-RED deployments for our clients means adhering to the highest standards, including SOC 2 requirements. This commitment is at the core of our security philosophy. In a world rife with cybersecurity threats and data breaches, taking information security seriously isn't just an option—it's a critical necessity. Our SOC 2 audit was far more than just a procedural step. It represented a comprehensive, independent third-party validation of our robust controls and processes. We believe in transparency and accountability, which is why we document our policies in our open handbook, inviting scrutiny from vendors and reinforcing trust with our customers. Providing this level of independent audit not only serves our customers better and more efficiently but also offers FlowFuse valuable insights into enhancing our security measures and identifying any gaps in our policies. This proactive approach ensures we continue keeping your data safe and secure at all times.
As we continue to grow and evolve, ensuring the security of our systems and data becomes ever more critical. The next step on FlowFuse's journey to provide independant proof we're on the right track: We're currently in the observation phase of the SOC2 type 2.</p>
<p>SOC 2 Type 1 assesses the design of an organization's security controls at a specific point in time, while SOC 2 Type 2 evaluates the effectiveness of those controls over a period of time, typically three to twelve months.</p>
<h1 id="flowfuse's-journey-to-soc-2-compliance" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/soc2/#flowfuse's-journey-to-soc-2-compliance"># </a> FlowFuse's Journey to SOC 2 Compliance</h1>
<h2 id="compliance-partners" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/soc2/#compliance-partners"># </a> Compliance Partners</h2>
<p>The independent audit was performed by Advantage Partners. Their expertise played a large role in our successful attainment of this certification. Before the audit was performed the company went through an extensive process to uncover what policies were missing, required updating, or were already in place. Further, lots of tribal knowledge has been written down and is now enforced by internal policies. For example</p>
<ol>
<li><a href="https://flowfuse.com/handbook/company/security/data-management/#data-management-policy">Data Management Policy</a></li>
<li><a href="https://flowfuse.com/handbook/company/security/access-control/#access-control-policy">Access Control Policy</a></li>
<li><a href="https://flowfuse.com/handbook/company/security/incident-response/#incident-response-plan">Incident Response Policy</a></li>
<li><a href="https://flowfuse.com/handbook/company/security/human-resources/#human-resources-security-policy">Human Resources Security Policy</a></li>
</ol>
<p>It's been a team effort from engineering to updated HR polices!</p>
https://flowfuse.com/blog/2024/01/send-a-file/Send a File to Node-REDA guide to sending a CSV file to Node-RED and start interacting with it.2024-01-05T00:00:00ZGrey Dziuba<p>Have you ever needed to send a CSV file to your Node-RED instance? This file can go on to populate a shift schedule, product specifications, or some other configuration file that is used. In this guide, we provide a couple of options to upload the data to your Node-RED for further processing and to organize the data to be sent on or used.</p>
<!--more-->
<h1 id="why-would-you-need-to-send-a-file-to-node-red%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/send-a-file/#why-would-you-need-to-send-a-file-to-node-red%3F"># </a> Why would you need to send a file to Node-RED?</h1>
<p>Often times it is necessary to update lookup tables in a SQL database, but you don't necessarily want to give access to everyone to edit the database, nor do you want to have to do it all yourself. This can often be seen when new products are introduced into a manufacturing facility. It may not be often, but enough that it warrants its own application. This process will guide you in a way that will enable your teammates to upload the files to the system themselves.</p>
<p>Furthermore, on the management layer of most companies, Excel and Google Sheets are the go-to tools to perform data collection tasks. Getting management involved in processes might require you to build an import feature for them. Asking your manager to "Save as" CSV is much easier than teaching them SQL!</p>
<h1 id="2-ways-to-send-a-file-to-node-red" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/send-a-file/#2-ways-to-send-a-file-to-node-red"># </a> 2 Ways to send a file to node-RED</h1>
<p>There are many approaches that can be taken when solving this. We are going to go over 2 here.</p>
<ol>
<li><a href="https://flowfuse.com/blog/2024/01/send-a-file/#simple-python-script">Simple Python Script</a> - Simple script that will be shared below. It is a simple Python application that allows the user to send a file with a simple command, but this might require a little more technical skills that the end user may not feel comfortable with.</li>
<li><a href="https://flowfuse.com/blog/2024/01/send-a-file/#stand-alone-web-application">Stand Alone Web Application</a> - A web-based application that allows the user to upload files to a browser with a selectable endpoint.</li>
</ol>
<h2 id="simple-python-script" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/send-a-file/#simple-python-script"># </a> Simple Python Script</h2>
<p>This simple Python script sends a file to a Node-RED flow. The flow that will work with this script can be seen <a href="https://flowfuse.com/blog/2024/01/send-a-file/#node-red-ingress">here</a>.</p>
<p>The script requires <strong>requests</strong> and <strong>Python 3.x</strong>.</p>
<p>Install requests:</p>
<div style="position: relative">
<pre class="language-bash"><code id="code-43" class="language-bash">pip <span class="token function">install</span> requests</code></pre>
<button class="code-copy " data-clipboard-target="#code-43" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>Create a file called run.py and paste the contents into the file.</p>
<div style="position: relative">
<pre class="language-python"><code id="code-47" class="language-python"><span class="token keyword">import</span> requests<br /><br /><span class="token keyword">def</span> <span class="token function">send_file</span><span class="token punctuation">(</span>nodered_url<span class="token punctuation">,</span> file_path<span class="token punctuation">)</span><span class="token punctuation">:</span><br /> <span class="token comment"># Open the file in binary mode</span><br /> <span class="token keyword">with</span> <span class="token builtin">open</span><span class="token punctuation">(</span>file_path<span class="token punctuation">,</span> <span class="token string">'rb'</span><span class="token punctuation">)</span> <span class="token keyword">as</span> <span class="token builtin">file</span><span class="token punctuation">:</span><br /> files <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token string">'file'</span><span class="token punctuation">:</span> <span class="token punctuation">(</span><span class="token builtin">file</span><span class="token punctuation">.</span>name<span class="token punctuation">,</span> <span class="token builtin">file</span><span class="token punctuation">,</span> <span class="token string">'multipart/form-data'</span><span class="token punctuation">)</span><span class="token punctuation">}</span><br /> response <span class="token operator">=</span> requests<span class="token punctuation">.</span>post<span class="token punctuation">(</span>nodered_url<span class="token punctuation">,</span> files<span class="token operator">=</span>files<span class="token punctuation">)</span><br /><br /> <span class="token keyword">return</span> response<br /><br /><span class="token comment"># Update the ip address and port of your Node-RED instance</span><br />nodered_url <span class="token operator">=</span> <span class="token string">'http://localhost:1880/fileupload'</span><br /><br /><span class="token comment"># Update the location of your file</span><br />file_path <span class="token operator">=</span> <span class="token string">'C:/Users/myUser/Downloads/shiftSchedule.csv'</span><br /><br />response <span class="token operator">=</span> send_file<span class="token punctuation">(</span>nodered_url<span class="token punctuation">,</span> file_path<span class="token punctuation">)</span><br /><span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string-interpolation"><span class="token string">f"Response Status Code: </span><span class="token interpolation"><span class="token punctuation">{</span>response<span class="token punctuation">.</span>status_code<span class="token punctuation">}</span></span><span class="token string">"</span></span><span class="token punctuation">)</span><br /><span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string-interpolation"><span class="token string">f"Response Body: </span><span class="token interpolation"><span class="token punctuation">{</span>response<span class="token punctuation">.</span>text<span class="token punctuation">}</span></span><span class="token string">"</span></span><span class="token punctuation">)</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-47" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>Update the <strong>nodered_url</strong> to the location of the NodeRED instance. Be sure to adjust the port if the default port of 1880 isn't being used.</p>
<p>Update the <strong>file_path</strong> with the path to where the file to be uploaded will be located.</p>
<p><strong>Save</strong></p>
<p>To run:</p>
<div style="position: relative">
<pre class="language-python"><code id="code-60" class="language-python">python run<span class="token punctuation">.</span>py</code></pre>
<button class="code-copy " data-clipboard-target="#code-60" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<h2 id="stand-alone-web-application" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/send-a-file/#stand-alone-web-application"># </a> Stand Alone Web Application</h2>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/csv_upload_app-WEYnBQL1ty-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/csv_upload_app-WEYnBQL1ty-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="csv upload application" loading="lazy" decoding="async" src="https://flowfuse.com/img/csv_upload_app-WEYnBQL1ty-650.jpeg" width="650" height="319" /></picture></p>
<p>This stand-alone web application can be run on either Windows or Linux, .bat for Windows, and .sh for Linux.</p>
<h3 id="installation" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/send-a-file/#installation"># </a> Installation</h3>
<p>Clone the repository and navigate to the directory:</p>
<div style="position: relative">
<pre class="language-bash"><code id="code-76" class="language-bash"><span class="token function">git</span> clone https://github.com/gdziuba/FF_Send-File-to-NR.git <span class="token operator">&&</span> <span class="token builtin class-name">cd</span> FF_Send-File-to-NR</code></pre>
<button class="code-copy " data-clipboard-target="#code-76" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<h3 id="configuration" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/send-a-file/#configuration"># </a> Configuration</h3>
<p>Edit the lines in the body of <a href="https://github.com/gdziuba/FF_Send-File-to-NR/blob/21214f88c6c4536f49efb88cf5f84bf52071a88b/templates/index.html#L69">index.html</a> to include the endpoints to which you would like to send the files.</p>
<pre><code><option value="http://localhost:1880/fileupload">CSV File Upload</option>
</code></pre>
<h3 id="operating-systems" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/send-a-file/#operating-systems"># </a> Operating Systems</h3>
<h3 id="windows" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/send-a-file/#windows"># </a> Windows</h3>
<p>Run the script:</p>
<div style="position: relative">
<pre class="language-bash"><code id="code-93" class="language-bash">.<span class="token punctuation">\</span>start_app.bat</code></pre>
<button class="code-copy " data-clipboard-target="#code-93" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>This will install if necessary, start the Flask Application, and take you to localhost:5000 on the browser.</p>
<h3 id="linux" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/send-a-file/#linux"># </a> Linux</h3>
<p>Make the script executable by running running:</p>
<div style="position: relative">
<pre class="language-bash"><code id="code-103" class="language-bash"><span class="token function">chmod</span> +x setup_and_run.sh</code></pre>
<button class="code-copy " data-clipboard-target="#code-103" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>Then run the application with:</p>
<div style="position: relative">
<pre class="language-bash"><code id="code-107" class="language-bash">./setup_and_run.sh</code></pre>
<button class="code-copy " data-clipboard-target="#code-107" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>To access the application, open a browser to the <strong><node-red-host-ip>:5000</strong> of the running application.</p>
<h3 id="node-red-ingress" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/send-a-file/#node-red-ingress"># </a> Node-RED Ingress</h3>
<iframe width="100%" height="225px" src="https://flows.nodered.org/flow/effb53752e5d6f767b3c7e5d41a4a6e8/share?height=100" allow="clipboard-read; clipboard-write" style="border: none;"></iframe>
<p>Once we have a file ready to be sent, we now need to configure the receiving side in Node-RED. In this example, we are leveraging a CSV formatted file and then converting it to be used at a later time.</p>
<p>A link to the flow can be found <a href="https://flows.nodered.org/flow/effb53752e5d6f767b3c7e5d41a4a6e8">here</a>.</p>
<p>To import the flow, follow these <a href="https://flowfuse.com/blog/2023/03/3-quick-node-red-tips-5/#1.-copy-and-share-your-flows-using-export-and-import">instructions</a>.</p>
<p>A Simple HTTP In node can be used in the form of a Post, ensuring the configuration allows for a file.</p>
<h1 id="wanna-import-it-directly-into-your-node-red-instance-via-a-dashboard%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/send-a-file/#wanna-import-it-directly-into-your-node-red-instance-via-a-dashboard%3F"># </a> Wanna import it directly into your Node-RED instance via a Dashboard?</h1>
<p>Check out this <a href="https://flowfuse.com/blog/2024/01/import-a-file">blog</a> on how to directly import a file into a Node-RED instance via Dashboard 2.0.</p>
https://flowfuse.com/blog/2024/01/import-a-file/Import a File into Node-RED with Dashboard 2.0Use Dashboard 2.0 to import a CSV file into Node-RED.2024-01-05T00:00:00ZGrey Dziuba<p>Need to get a file into Node-RED, but don't want to over complicate things. This article outlines how you can leverage Dashboard 2.0 to import a file directly into Node-RED via a Dashboard.</p>
<!--more-->
<h1 id="why-would-you-need-to-import-a-file-to-node-red%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/import-a-file/#why-would-you-need-to-import-a-file-to-node-red%3F"># </a> Why would you need to import a file to Node-RED?</h1>
<p>Often times it is necessary to update lookup tables in a SQL database, but you don't necessarily want to give access to everyone to edit the database, nor do you want to have to do it all yourself. This can often be seen when new products are introduced into a manufacturing facility. It may not be often, but enough that it warrants its own application. This process will guide you in a way that will enable your teammates to upload the files to the system themselves.</p>
<p>Furthermore, on the management layer of most companies, Excel and Google Sheets are the go-to tools to perform data collection tasks. Getting management involved in processes might require you to build an import feature for them. Asking your manager to "Save as" CSV is much easier than teaching them SQL!</p>
<h2 id="node-red-dashboard-(flowfuse)" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/import-a-file/#node-red-dashboard-(flowfuse)"># </a> Node-RED Dashboard (FlowFuse)</h2>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/csv-dashboard-2SGfaHECgf-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/csv-dashboard-2SGfaHECgf-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="csv dashboard" loading="lazy" decoding="async" src="https://flowfuse.com/img/csv-dashboard-2SGfaHECgf-650.jpeg" width="650" height="421" /></picture></p>
<p>This simple flow allows the user to visualize data from a CSV in the Node-RED Dashboard. The button then allows the user to initiate a request to send the data to the next step. This next step could be anything from loading into a SQL database to saving it.</p>
<h3 id="instructions" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/import-a-file/#instructions"># </a> Instructions</h3>
<ol>
<li>Install Node-RED Dashboard 2.0. Follow these <a href="https://dashboard.flowfuse.com/getting-started.html">instructions</a> to install.</li>
<li>Import Flow - to import the flow into your Node-RED instance follow these <a href="https://flowfuse.com/blog/2023/03/3-quick-node-red-tips-5/#1.-copy-and-share-your-flows-using-export-and-import">instructions</a>.</li>
<li>Access Dashboard - To access the dashboard, navigate to the <code>https://<flowfuse-instance-name>.flowfuse.cloud/dashboard</code>.</li>
</ol>
<p>This dashboard is currently configured to take in CSV files and transform them into a single message that is sent to the table for visualization. Simultaneously the data from the import is stored locally in the flow context. From there, the button can be used to trigger the sending of the data from the flow context to the next destination. In this case, it is a simple debug node.</p>
<iframe width="100%" height="225px" src="https://flows.nodered.org/flow/8c505039ac1b8dbed2bee1e22ee2975a/share?height=100" allow="clipboard-read; clipboard-write" style="border: none;"></iframe>
<h1 id="need-to-send-a-file-to-node-red-from-another-application-or-source%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2024/01/import-a-file/#need-to-send-a-file-to-node-red-from-another-application-or-source%3F"># </a> Need to Send a File to Node-Red from another application or source?</h1>
<p>Chech out this <a href="https://flowfuse.com/blog/2024/01/send-a-file">blog</a> on how to send a file from either a stand alone web application or use the sample python script to imbed it into your current application.</p>
https://flowfuse.com/blog/2023/12/unified-namespace-data-modelling/Data Modeling for your Unified NamespaceHow to use FlowFuse as your Schema Registry?2023-12-27T00:00:00ZMarian Demme<p>In the realm of industrial manufacturing, the concept of a Unified Namespace (UNS) emerges as a pivotal instrument for enhanced communication within a manufacturing network framework. Predicated on an event-driven architectural model, this approach advocates for the universal accessibility of data, irrespective of the immediate presence of a data consumer.</p>
<!--more-->
<p>This paradigm allows for a flexible role allocation within the network, where nodes can dynamically switch between being data producers and consumers, contingent upon the fluctuating requirements of the system at any specific juncture. For those unfamiliar with UNS, I recommend revisiting my <a href="https://flowfuse.com/blog/2023/08/isa-95-automation-pyramid-to-unified-namespace/">previous article</a> on the subject.</p>
<p>This article aims to explain the process of data modeling for your UNS, highlighting the role of tools like the FlowFuse Team Library in schema management.</p>
<p><strong>Overview of Steps:</strong></p>
<ol>
<li><a href="https://flowfuse.com/blog/2023/12/unified-namespace-data-modelling/#step-1---connection-to-your-operational-technology-(ot)-equipment">Connection to your Operational Technology (OT) equipment</a></li>
<li><a href="https://flowfuse.com/blog/2023/12/unified-namespace-data-modelling/#step-2---structuring-your-payload">Structuring your payload</a></li>
<li><a href="https://flowfuse.com/blog/2023/12/unified-namespace-data-modelling/#step-3---building-your-topic-hierarchy">Building your Topic Hierarchy</a></li>
<li><a href="https://flowfuse.com/blog/2023/12/unified-namespace-data-modelling/#step-4---connection-to-your-unified-namespace">Connection to your Unified Namespace</a></li>
</ol>
<h2 id="step-1---connection-to-your-operational-technology-(ot)-equipment" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/unified-namespace-data-modelling/#step-1---connection-to-your-operational-technology-(ot)-equipment"># </a> Step 1 - Connection to your Operational Technology (OT) equipment</h2>
<p>The journey begins with establishing connections to OT equipment, which may include Programmable Logic Controllers (PLCs), Historian databases, and sensors. It is essential to facilitate compatibility with a diverse array of protocols. In this context, Node-RED emerges as a pivotal tool, bolstered by its expansive community-generated catalog featuring over 4500 nodes.</p>
<p>In my example, the focus is on integration with a RevolutionPi. To achieve this, the FlowFuse Device Agent was deployed on a RevolutionPi (see our <a href="https://flowfuse.com/docs/hardware/raspbian/">documentation</a>), and specific RevolutionPi nodes were installed. These nodes enable direct interaction with all interfaces of the PLC and are available through the <a href="https://flows.nodered.org/node/node-red-contrib-revpi-nodes">Node-RED library</a>. Subsequent steps involved acquiring temperature data directly from the PLC.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/revpi_nodes--rhb7iF9dw-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/revpi_nodes--rhb7iF9dw-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="" loading="lazy" decoding="async" src="https://flowfuse.com/img/revpi_nodes--rhb7iF9dw-650.jpeg" width="650" height="277" /></picture></p>
<p>For optimal data accuracy and integrity, it is recommended to timestamp data at the point of origin. In our scenario, the PLC outputs lack inherent timestamping. Consequently, I integrated a timestamp at the data acquisition stage within Node-RED, which runs on the same hardware.</p>
<p>A general recommendation is the imperative of maintaining data integrity during transmission from OT systems to the message broker. This is particularly salient in regulated sectors such as pharmaceuticals, where standards like GxP mandate the preservation of unaltered data during transfer to the UNS.</p>
<h2 id="step-2---structuring-your-payload" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/unified-namespace-data-modelling/#step-2---structuring-your-payload"># </a> Step 2 - Structuring your payload</h2>
<p>The payload is the core of transmitted data. Transforming the payload for mutual intelligibility between sender and receiver, even within the same protocol, is sometimes necessary. Standardizing payload formats ensures consistent data storage and transmission. I recommend including schema type information with the data to cater to diverse use cases.</p>
<p>Utilizing FlowFuse and Node-RED can enforce schema consistency. Node-RED's template node lets you define JSON schemas for your flows, while the FlowFuse Team Library facilitates schema sharing and consistency across your organization.</p>
<p>In my example, I use a very simple JSON schema as a structure for measurements for <code>StationA</code>:</p>
<div style="position: relative">
<pre class="language-json"><code id="code-65" class="language-json"><span class="token punctuation">{</span><br /> <span class="token property">"$schema"</span><span class="token operator">:</span> <span class="token string">"Enterprise/Site/Line1/StationA/measurements/_schema"</span><span class="token punctuation">,</span><br /> <span class="token property">"title"</span><span class="token operator">:</span> <span class="token string">"Measurement Schema for StationA"</span><span class="token punctuation">,</span><br /> <span class="token property">"type"</span><span class="token operator">:</span> <span class="token string">"object"</span><span class="token punctuation">,</span><br /> <span class="token property">"properties"</span><span class="token operator">:</span> <span class="token punctuation">{</span><br /> <span class="token property">"value"</span><span class="token operator">:</span> <span class="token punctuation">{</span><br /> <span class="token property">"description"</span><span class="token operator">:</span> <span class="token string">"The actual value being measured"</span><span class="token punctuation">,</span><br /> <span class="token property">"type"</span><span class="token operator">:</span> <span class="token string">"number"</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token property">"unit"</span><span class="token operator">:</span> <span class="token punctuation">{</span><br /> <span class="token property">"description"</span><span class="token operator">:</span> <span class="token string">"The unit of the measurement value"</span><span class="token punctuation">,</span><br /> <span class="token property">"type"</span><span class="token operator">:</span> <span class="token string">"string"</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token property">"timestamp"</span><span class="token operator">:</span> <span class="token punctuation">{</span><br /> <span class="token property">"description"</span><span class="token operator">:</span> <span class="token string">"The timestamp of the measurement in ISO 8601 format"</span><span class="token punctuation">,</span><br /> <span class="token property">"type"</span><span class="token operator">:</span> <span class="token string">"string"</span><br /> <span class="token punctuation">}</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token property">"required"</span><span class="token operator">:</span> <span class="token punctuation">[</span><br /> <span class="token string">"value"</span><span class="token punctuation">,</span><br /> <span class="token string">"unit"</span><span class="token punctuation">,</span><br /> <span class="token string">"timestamp"</span><br /> <span class="token punctuation">]</span><br /><span class="token punctuation">}</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-65" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>Example Data:</p>
<div style="position: relative">
<pre class="language-json"><code id="code-69" class="language-json"><span class="token punctuation">{</span><br /> <span class="token property">"value"</span><span class="token operator">:</span> msg.payload<span class="token punctuation">,</span><br /> <span class="token property">"unit"</span><span class="token operator">:</span> <span class="token string">"Celsius"</span><span class="token punctuation">,</span><br /> <span class="token property">"timestamp"</span><span class="token operator">:</span> msg.timestamp<br /><span class="token punctuation">}</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-69" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/template_node-LJCACM0E8d-377.avif 377w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/template_node-LJCACM0E8d-377.webp 377w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Node-RED template node" loading="lazy" decoding="async" src="https://flowfuse.com/img/template_node-LJCACM0E8d-377.jpeg" width="377" height="188" /></picture></p>
<p>The FlowFuse Team Library acts as my schema registry within my organization, allowing me to reuse my schemas and ensure consistency.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/team_library-HAn0-JG1C7-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/team_library-HAn0-JG1C7-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="FlowFuse Team Library" loading="lazy" decoding="async" src="https://flowfuse.com/img/team_library-HAn0-JG1C7-650.jpeg" width="650" height="294" /></picture></p>
<h2 id="step-3---building-your-topic-hierarchy" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/unified-namespace-data-modelling/#step-3---building-your-topic-hierarchy"># </a> Step 3 - Building your Topic Hierarchy</h2>
<p>Your topic hierarchy should reflect your physical plant structure or align with existing asset naming systems. This approach improves data visibility and eases navigation for OT engineers. Many enterprises opt for the <a href="https://www.isa.org/products/ansi-isa-95-00-02-2018-enterprise-control-system-i">ISA-95 part 2</a> model to structure their topics.</p>
<p>In our example, we follow the structure of: Enterprise/Site/Line1/StationA</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/mqtt_topic_tree-PvfzIAhzzE-650.avif 650w, https://flowfuse.com/img/mqtt_topic_tree-PvfzIAhzzE-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/mqtt_topic_tree-PvfzIAhzzE-650.webp 650w, https://flowfuse.com/img/mqtt_topic_tree-PvfzIAhzzE-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/mqtt_topic_tree-PvfzIAhzzE-650.jpeg 650w, https://flowfuse.com/img/mqtt_topic_tree-PvfzIAhzzE-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="MQTT Topic Tree" loading="lazy" decoding="async" src="https://flowfuse.com/img/mqtt_topic_tree-PvfzIAhzzE-650.jpeg" width="1300" height="213" /></picture></p>
<h2 id="step-4---connection-to-your-unified-namespace" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/unified-namespace-data-modelling/#step-4---connection-to-your-unified-namespace"># </a> Step 4 - Connection to your Unified Namespace</h2>
<p>Finally, transfer your data to the UNS, using protocols like MQTT or Kafka, depending on your UNS setup. While MQTT can handle up to 256 MB per payload, Kafka's default is 1MB, expandable to 10MB. These capacities suffice for most data types. In our example, we'll employ MQTT.</p>
<h2 id="conclusion" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/unified-namespace-data-modelling/#conclusion"># </a> Conclusion</h2>
<p>In conclusion, implementing a Unified Namespace (UNS) with efficient data modeling is a transformative step for any industrial manufacturing setup. By leveraging tools like FlowFuse Team Library, Node-RED, and protocols such as MQTT or Kafka, organizations can achieve a harmonious data ecosystem where information flows seamlessly across various nodes. As illustrated through practical examples, including the integration with a RevolutionPi, the importance of standardizing data schemas, maintaining data integrity, and structuring topic hierarchies cannot be overstated. Embracing these practices not only enhances operational efficiency but also paves the way for more advanced analytics and machine learning applications.</p>
<h3 id="the-complete-node-red-flow" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/unified-namespace-data-modelling/#the-complete-node-red-flow"># </a> The complete Node-RED flow</h3>
<iframe width="100%" height="225px" src="https://flows.nodered.org/flow/f6c783c6e9c1863145e0c63418eb5fe5/share?height=100" allow="clipboard-read; clipboard-write" style="border: none;"></iframe>
https://flowfuse.com/blog/2023/12/flowfuse-year-review-2023/Thank you for an incredible 2023!Reviewing an amazing 2023 for FlowFuse2023-12-22T00:00:00ZZJ van de Weg<p>At the end of the year there’s always an opportunity to review how the year went, and I'm gonna take this opportunity to share the review of 2023 for FlowFuse. It's been an incredible year for FlowFuse and we've achieved a lot with our team.</p>
<!--more-->
<h3 id="flowfuse-branding" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/flowfuse-year-review-2023/#flowfuse-branding"># </a> FlowFuse branding</h3>
<p>First off; in 2023 we were known as FlowForge. But, due to some trademark challenges, we went through a <a href="https://flowfuse.com/blog/2023/08/flowforge-is-now-flowfuse/">rebranding phase</a> over the summer. It's been a bit of an adjustment, and you might still catch us – and even some of our customers – occasionally slipping up with the old name. But overall, we're really pleased with how smoothly everything's transitioned.</p>
<h3 id="product-adoption" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/flowfuse-year-review-2023/#product-adoption"># </a> Product adoption</h3>
<p>On the product side: Growth in adoption of the FlowFuse platform has been tremendous, in many dimensions; revenue generated, customers onboarded, and how many users are now professionalizing their usage of Node-RED. Our development platform has been used by thousands of developers to acquire data from various sources and visualize it to build rich applications for their use cases. And at every step of the way we’ve been able to improve their experience.</p>
<p>Data acquisition was always possible without FlowFuse, however we’ve improved on the status quo through the <a href="https://flowfuse.com/certified-nodes/">Certified Nodes</a> program. A nascent program that vets often used custom nodes from the community to ensure business readiness and validate nodes to ensure there’s no malicious code installed.</p>
<p>Further, this year we’ve started <a href="https://dashboard.flowfuse.com/">Dashboard 2.0</a>. The development of the successor of <a href="https://flows.nodered.org/node/node-red-dashboard">node-red-dashboard</a>, which is built on deprecated technology and effectively on life-support. The development of the new Dashboard technology has taken massive steps and it’s very stable. Feature parity is not yet achieved, though we’re happy with the adoption of Dashboard 2.0 and the community <a href="https://github.com/FlowFuse/node-red-dashboard/issues">reporting issues and improvements</a>.</p>
<p>With the product improvements to FlowFuse, we’ve empowered large audiences to try and adopt the product. We’ve seen adoption in many areas:</p>
<ol>
<li>Process manufacturing – Mining, oil & gas, beverages.</li>
<li>Discrete manufacturing – Ranging from automotive to logistics use-cases.</li>
<li>Digital transformation – Digital only integration, from website back-ends to workflow engines for up-skilled employees.</li>
<li>Agriculture – From environment monitoring to controlling sprinklers, water-pumps, and more.</li>
<li>Education & Research – Hundreds of students have registered for FlowFuse to learn how IIoT works, start building solutions, and prepare themselves for employing these skills in their first jobs.</li>
</ol>
<p>We’re always happy to <a href="https://flowfuse.com/contact-us/">support you</a> in any of these or other industries where you may find value in how we streamline operations, manage your data acquisition logic and roll out, and remain compliant during your journey.</p>
<h3 id="pricing-changes" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/flowfuse-year-review-2023/#pricing-changes"># </a> Pricing changes</h3>
<p>A driving force behind the horizontal nature of adoption of the FlowFuse development platform has been the introduction of the 3 product tiers earlier this year. We’ve introduced a Starter package, Team and Enterprise tiers.</p>
<p>The <a href="https://flowfuse.com/blog/2023/08/new-starter-tier">starter package</a> allows everyone to adopt the core features of FlowFuse and Node-RED. It provides hosting of 2 Node-RED instances in the Cloud and management of 2 Node-REDs on the edge.</p>
<p>A user can be promoted to the <a href="https://flowfuse.com/changelog/2023/09/introduction-enterprise-tier/">Team or Enterprise tier</a> when they’re ready to further professionalize their adoption and have access to enhanced compliance, faster time to value for their developers, among other features.</p>
<h3 id="what-2024-will-bring" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/flowfuse-year-review-2023/#what-2024-will-bring"># </a> What 2024 will bring</h3>
<p>FlowFuse will continue to support the Node-RED community at large. In 2024 we’re looking to further grow into the main development platform for low-code developers. While our main focus will remain around Node-RED, there’s more to be done to become the defacto low-code development platform. Core of which are a few pillars:</p>
<ol>
<li>Time to value for developers</li>
<li>Empowering more employees to automate the software layer of the solution</li>
<li>Enhanced compliance and enforcement</li>
</ol>
<p>We’re hoping to continue to serve our customers and grow the customer base in 2024!</p>
<h3 id="holiday-season-support" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/flowfuse-year-review-2023/#holiday-season-support"># </a> Holiday Season Support</h3>
<p>Over the next couple of weeks (22nd December - 2nd January), most of our team will be taking some well deserved time off. Don't worry, we will still be available if you need emergency support. The best way to contact us is via our website's <a href="https://flowfuse.com/support/">support page</a>.</p>
https://flowfuse.com/blog/2023/12/introduction-to-unified-namespace/Introduction to the Unified NamespaceMaking data available for Industry 4.0 use-cases2023-12-20T00:00:00ZZJ van de Weg<p>As your organization is generating more data there’s key architectural
decisions to be made to ensure the full value can be unlocked and you’re
leveraging not just the tip of the iceberg. The Unified Namespace (UNS)
provides a blueprint to allow data to be consumed by many data-consumers.
FlowFuse helps you manage this migration and the operationalization of your
data.</p>
<!--more-->
<p>To facilitate a many to many connection between data producers and data consumers, there are two changes to be made to your architecture:</p>
<ol>
<li>Data transport through a hub-and-spokes model</li>
<li>Set structure of the Data</li>
</ol>
<h2 id="hub-and-spokes-model-replaces-point-to-point" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/introduction-to-unified-namespace/#hub-and-spokes-model-replaces-point-to-point"># </a> Hub and spokes model replaces Point to Point</h2>
<p>Traditionally, for example web servers serving web pages, the client requests a
page from a server. This is a point to point connection between those two parties.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/uns-point-to-point-teL84klihq-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/uns-point-to-point-teL84klihq-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Point to Point connection" alt="Point to point graphic" loading="lazy" decoding="async" src="https://flowfuse.com/img/uns-point-to-point-teL84klihq-650.jpeg" width="650" height="250" /></picture></p>
<p>For the same data to be transmitted to a new data consumer, the consumer needs
to make another request to obtain the data. This works great when you know what
data you need for building your solution, and if you know where to get it.</p>
<p>However, in manufacturing it’s not always possible to know up front who will
need your data. Some machines are built and placed years before another machine
would like to interact with the generated data. There might be many consumers
for the same data set. Lastly; consumers might not know when to fetch new data
points, and thus will try on a cycle or need another mechanism to understand if
new data is available.</p>
<p>This is why a hub and spoke model should be employed. For each data source or
data producer, a connection is made to a central hub; generally called a broker.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/uns-hub-fKoqSVxbXY-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/uns-hub-fKoqSVxbXY-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Unified Namespace Hub and Spokes communication" alt="Hub and spoke graphic" loading="lazy" decoding="async" src="https://flowfuse.com/img/uns-hub-fKoqSVxbXY-650.jpeg" width="650" height="325" /></picture></p>
<h2 id="structured-data" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/introduction-to-unified-namespace/#structured-data"># </a> Structured data</h2>
<p>When many producers are connected to many data consumers, but not directly,
the data producer needs to provide insight into what the events can be and will
contain. It cannot, nor should even if it could, tailor the event’s data structure
for a consumer so there’s decoupling on an architecture level. Structured data
makes information, without structure the consumer receives mere bytes.</p>
<p>This means that a schema for each event should be created and maintained. A
schema which both the producer and consumer can read and validate each event
against. As such a common Schema Definition Language (SDL) is chosen to provide
clarity of how the data is structured, how it can be parsed, and in some cases
also what it means for the developer.</p>
https://flowfuse.com/blog/2023/12/device-agent-as-a-windows-service/Run Node-RED as a service on WindowsStep by step guide to run FlowFuse device agent as a Windows service2023-12-18T00:00:00ZSteve McLaughlinRob MarcerGrey Dziuba<p>FlowFuse's device agent allows you to manage and run your Node-RED instances on
your own hardware such as a Raspberry Pi or Windows computer. This can be very useful where an
application you've written needs to run flows with direct access to hardware sensors.</p>
<p>In this article, we're going to explain the steps to configure our device agent to run as a service in Windows
using the <a href="https://nssm.cc/">nssm</a> utility.</p>
<!--more-->
<h2 id="why-run-the-device-agent-as-a-service%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/device-agent-as-a-windows-service/#why-run-the-device-agent-as-a-service%3F"># </a> Why run the device agent as a service?</h2>
<p>The standard process for running FlowFuse's device agent is to start it on the
command line using the command <code>flowfuse-device-agent</code>. This works fine for testing
but for long-term installations it's useful to run the device agent as a service.
Once running as a service, the device agent will continue to run even if you
log off or the computer is restarted and no user is logged in.</p>
<h2 id="summary" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/device-agent-as-a-windows-service/#summary"># </a> Summary</h2>
<p>The aim of this how-to is to install the FlowFuse device-agent as a service on a Windows computer.</p>
<p>There will be two main parts to this:</p>
<ol>
<li>Install the device-agent</li>
<li>Setup the device-agent to run as a Windows service</li>
</ol>
<p>Additionally, two user accounts will be needed for this configuration:</p>
<ol>
<li>A <strong>user</strong> account that will be used to run the device-agent (typically, non-admin account)</li>
<li>An <strong>admin</strong> account that can run elevated commands and will be used to setup the service</li>
</ol>
<p>We will create a directory for the device-agent files and set the permissions on that directory so that the <strong>user</strong> account can read and write files in that directory.
<em>This will be <code>c:\opt\flowfuse-device</code></em></p>
<p>To make the device-agent run as a service, we will (in this example), use <a href="https://nssm.cc/">nssm</a> but you are free to choose an alternative tool to run the device agent as a service.</p>
<p>Finally, we set the service to run under the <strong>service</strong> account.</p>
<p><em>NOTE: The instructions in this how to were written on <strong>Windows 11 Pro 22H2</strong></em></p>
<h3 id="tip%3A-using-domain-accounts" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/device-agent-as-a-windows-service/#tip%3A-using-domain-accounts"># </a> TIP: Using domain accounts</h3>
<p>If the account is a domain account, append the domain name to the <strong>user</strong> e.g. <code>user@domain</code> whenever the <strong>user</strong> name is used in the instructions below.</p>
<h3 id="tip%3A-launching-an-elevated-command-prompt-window-(e.g.-as-the-admin-user)" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/device-agent-as-a-windows-service/#tip%3A-launching-an-elevated-command-prompt-window-(e.g.-as-the-admin-user)"># </a> TIP: Launching an elevated command prompt window (e.g. as the admin user)</h3>
<div style="position: relative">
<pre class="language-bash"><code id="code-70" class="language-bash">powershell <span class="token parameter variable">-Command</span> "Start-Process <span class="token string">'cmd'</span> <span class="token parameter variable">-Verb</span> runAs</code></pre>
<button class="code-copy " data-clipboard-target="#code-70" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<h3 id="tip%3A-launching-an-elevated-powershell-prompt-window-(e.g.-as-the-admin-user)" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/device-agent-as-a-windows-service/#tip%3A-launching-an-elevated-powershell-prompt-window-(e.g.-as-the-admin-user)"># </a> TIP: Launching an elevated powershell prompt window (e.g. as the admin user)</h3>
<div style="position: relative">
<pre class="language-bash"><code id="code-74" class="language-bash">powershell <span class="token parameter variable">-Command</span> "Start-Process <span class="token string">'powershell'</span> <span class="token parameter variable">-Verb</span> runAs</code></pre>
<button class="code-copy " data-clipboard-target="#code-74" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<h2 id="pre-requisites" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/device-agent-as-a-windows-service/#pre-requisites"># </a> Pre-requisites</h2>
<h3 id="install-node.js" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/device-agent-as-a-windows-service/#install-node.js"># </a> Install Node.js</h3>
<p>The device-agent requires Node.js to be installed. You can download the latest version from https://nodejs.org/en/download/.</p>
<p>It is recommended to install the LTS version and to check the "Automatically install the necessary tools" option. This is especially important if you intend on using any nodes that require native modules (like serialport).</p>
<h3 id="create-a-new-windows-user" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/device-agent-as-a-windows-service/#create-a-new-windows-user"># </a> Create a New Windows User</h3>
<p>If you need to create a new <strong>user</strong> account follow these <a href="https://support.microsoft.com/en-us/windows/create-a-local-user-or-administrator-account-in-windows-20de74e0-ac7f-3502-a866-32915af2a34d#:~:text=Select%20Start%20%3E%20Settings%20%3E%20Accounts%20and,other%20user%2C%20select%20Add%20account.">instructions</a>.</p>
<h2 id="prepare-the-device-agent-files-directory" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/device-agent-as-a-windows-service/#prepare-the-device-agent-files-directory"># </a> Prepare the device-agent files directory</h2>
<p>As the admin user, open an <a href="https://flowfuse.com/blog/2023/12/device-agent-as-a-windows-service/#tip%3A-launching-an-elevated-command-prompt-window-(e.g.-as-the-admin-user)">elevated</a> command prompt, create the files directory and setup access permissions.</p>
<div style="position: relative">
<pre class="language-bash"><code id="code-99" class="language-bash"><span class="token comment"># In an elevated command prompt</span><br /><span class="token function">mkdir</span> c:<span class="token punctuation">\</span>opt<br /><span class="token function">mkdir</span> c:<span class="token punctuation">\</span>opt<span class="token punctuation">\</span>flowfuse-device<br /><span class="token comment"># grant full access to the service account that will run the device-agent</span><br />icacls c:<span class="token punctuation">\</span>opt<span class="token punctuation">\</span>flowfuse-device /grant <span class="token string">"user"</span>:F /T</code></pre>
<button class="code-copy " data-clipboard-target="#code-99" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p><em>where <code>"user"</code> is the service account (not the admin account)</em></p>
<h2 id="install-nssm" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/device-agent-as-a-windows-service/#install-nssm"># </a> Install nssm</h2>
<p><code>nssm</code> can simply be downloaded and executed from any path.
We will download it to the <code>c:\opt</code> directory, extract the files and copy the 64 bit version to the current directory.</p>
<h3 id="cmd-version-elevated-command-prompt" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/device-agent-as-a-windows-service/#cmd-version-elevated-command-prompt"># </a> <code>cmd</code> version <a href="https://flowfuse.com/blog/2023/12/device-agent-as-a-windows-service/#tip%3A-launching-an-elevated-command-prompt-window-(e.g.-as-the-admin-user)">elevated</a> command prompt</h3>
<div style="position: relative">
<pre class="language-bash"><code id="code-112" class="language-bash"><span class="token comment"># starting in the device-agent files directory</span><br /><span class="token builtin class-name">cd</span> c:<span class="token punctuation">\</span>opt<br /><span class="token comment"># download the nssm zip file</span><br /><span class="token function">curl</span> <span class="token parameter variable">-LJO</span> https://nssm.cc/release/nssm-2.24.zip<br /><span class="token comment"># extract the files</span><br /><span class="token function">tar</span> <span class="token parameter variable">-xf</span> nssm-2.24.zip<br /><span class="token comment"># copy the 64 bit version to the current directory</span><br />copy nssm-2.24<span class="token punctuation">\</span>win64<span class="token punctuation">\</span>nssm.exe <span class="token builtin class-name">.</span><br /><span class="token comment"># clean up</span><br />del nssm-2.24.zip<br /><span class="token function">rmdir</span> /s /q nssm-2.24</code></pre>
<button class="code-copy " data-clipboard-target="#code-112" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<h3 id="powershell-version-elevated-powershell-prompt" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/device-agent-as-a-windows-service/#powershell-version-elevated-powershell-prompt"># </a> <code>powershell</code> version <a href="https://flowfuse.com/blog/2023/12/device-agent-as-a-windows-service/#tip%3A-launching-an-elevated-powershell-prompt-window-(e.g.-as-the-admin-user)">elevated</a> powershell prompt</h3>
<p>If you don't have <code>cURL</code> installed, then powershell can be used to download the file. Here is how to do it:</p>
<div style="position: relative">
<pre class="language-powershell"><code id="code-119" class="language-powershell"><span class="token comment"># starting in the device-agent files directory</span><br />cd c:\opt<br /><span class="token comment"># download the nssm zip file</span><br /><span class="token function">Invoke-WebRequest</span> <span class="token operator">-</span>Uri https:<span class="token operator">/</span><span class="token operator">/</span>nssm<span class="token punctuation">.</span>cc/release/nssm-2<span class="token punctuation">.</span>24<span class="token punctuation">.</span>zip <span class="token operator">-</span>OutFile nssm-2<span class="token punctuation">.</span>24<span class="token punctuation">.</span>zip<br /><span class="token comment"># extract the files</span><br /><span class="token function">Expand-Archive</span> <span class="token operator">-</span>Path nssm-2<span class="token punctuation">.</span>24<span class="token punctuation">.</span>zip <span class="token punctuation">.</span><br /><span class="token comment"># copy the 64 bit version to the current directory</span><br /><span class="token function">Copy-Item</span> <span class="token operator">-</span>Path <span class="token punctuation">.</span>\nssm-2<span class="token punctuation">.</span>24\win64\nssm<span class="token punctuation">.</span>exe <span class="token operator">-</span>Destination <span class="token punctuation">.</span><br /><span class="token comment"># clean up</span><br /><span class="token function">Remove-Item</span> <span class="token operator">-</span>Path nssm-2<span class="token punctuation">.</span>24<span class="token punctuation">.</span>zip<br /><span class="token function">Remove-Item</span> <span class="token operator">-</span>Path nssm-2<span class="token punctuation">.</span>24 <span class="token operator">-</span>Recurse</code></pre>
<button class="code-copy " data-clipboard-target="#code-119" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<h3 id="manual-download" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/device-agent-as-a-windows-service/#manual-download"># </a> Manual download</h3>
<p>If you prefer, you can download the nssm zip file manually from <a href="https://nssm.cc/release/nssm-2.24.zip">https://nssm.cc/release/nssm-2.24.zip</a> and extract the files to the <code>c:\opt</code> directory. Then copy the 64 bit version to the current directory.</p>
<p>Ultimately, you should end up with a file named <code>nssm.exe</code> in the <code>c:\opt\</code> directory.</p>
<h2 id="install-and-configure-the-device-agent" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/device-agent-as-a-windows-service/#install-and-configure-the-device-agent"># </a> Install and configure the device-agent</h2>
<p>As the <strong>service</strong> account, to do so open a command prompt window and run the following and authenticate:</p>
<div style="position: relative">
<pre class="language-bash"><code id="code-135" class="language-bash">runas /user:<span class="token punctuation">{</span>serviceuser<span class="token punctuation">}</span> cmd<br /><span class="token comment"># e.g. runas /user:winserv cmd</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-135" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p><em>where <code>{serviceuser}</code> is the service account (not the admin account)</em></p>
<h3 id="check-the-users-npm-global-path-is-set-in-the-users-environment-variables" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/device-agent-as-a-windows-service/#check-the-users-npm-global-path-is-set-in-the-users-environment-variables"># </a> Check the users npm global path is set in the Users Environment Variables</h3>
<p>NOTE: The recommended flowfuse-device-agent instructions will result in the flowfuse-device-agent being installed in the NPM global directory. And the instructions to launch the device-agent expect the NPM global directory to be in your user path. This section will instruct you to a) find the NPM global path, then b) check the user’s path setting and, if necessary c) add the NPM global path to your user path.</p>
<p>First, make a note of the path currently set for npm global. You can do this by running the following command:</p>
<div style="position: relative">
<pre class="language-bash"><code id="code-148" class="language-bash"><span class="token function">npm</span> config get prefix</code></pre>
<button class="code-copy " data-clipboard-target="#code-148" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>Next, ensure the <code>Path</code> Variable under the "User variables for <em>user</em>" contains the npm global path that we obtained in the previous step.
Use the below command, to check the user’s <code>Path</code> setting. If it is not present, edit the path to include it.</p>
<div style="position: relative">
<pre class="language-bash"><code id="code-152" class="language-bash"><span class="token comment"># This commands opens the environment variables editor, </span><br /><span class="token comment"># look for the "Path" variable under "User variables for user",</span><br /><span class="token comment"># and ensure it contains the npm global path</span><br />rundll32 sysdm.cpl,EditEnvironmentVariables</code></pre>
<button class="code-copy " data-clipboard-target="#code-152" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>If you did have to add the npm path to the users <code>Path</code> variable, you will need to <strong>restart</strong> the command prompt for the change to take effect and relogin as <strong>user</strong>.</p>
<h3 id="install-the-device-agent" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/device-agent-as-a-windows-service/#install-the-device-agent"># </a> Install the device agent</h3>
<p>Note: you may have already installed the device-agent, however, <strong>we strongly recommend</strong> you do this step again as the service account and ensure that account has the latest version.</p>
<div style="position: relative">
<pre class="language-bash"><code id="code-162" class="language-bash"><span class="token function">npm</span> i <span class="token parameter variable">-g</span> @flowfuse/device-agent</code></pre>
<button class="code-copy " data-clipboard-target="#code-162" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<h3 id="link-the-device-agent-to-your-flowfuse-team" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/device-agent-as-a-windows-service/#link-the-device-agent-to-your-flowfuse-team"># </a> Link the device-agent to your flowfuse team</h3>
<p>First, we must run the device-agent and link it to our FlowFuse team. This will generate a "device configuration" details that we will use to configure the device-agent.
Below is how to run the device-agent with the UI enabled. This will allow you to configure the device-agent via its web UI.</p>
<div style="position: relative">
<pre class="language-bash"><code id="code-169" class="language-bash">flowfuse-device-agent <span class="token parameter variable">--ui</span> --ui-port <span class="token number">8080</span> --ui-user admin --ui-pass admin <span class="token parameter variable">-d</span> c:<span class="token punctuation">\</span>opt<span class="token punctuation">\</span>flowfuse-device <span class="token parameter variable">-p</span> <span class="token number">1880</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-169" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>The device-agent will now be running and you can access the UI at <a href="http://127.0.0.1:8080/">http://127.0.0.1:8080</a> with the user and password both "admin" (you can change these in the command line if required).
<em>NOTE: These credentials are temporary and only valid during the device setup</em></p>
<p>Proceed to configure the device-agent and link it to your flowfuse team. Full instructions can be found <a href="https://flowfuse.com/docs/device-agent/register/#generating-%22device-configuration%22">here</a>.
Once you have linked the device-agent to your team, you can stop it by pressing <code>ctrl+c</code> in the command prompt window.</p>
<h2 id="create-the-device-agent-service" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/device-agent-as-a-windows-service/#create-the-device-agent-service"># </a> Create the device-agent service</h2>
<p>As the admin user, open an elevated command prompt see <a href="https://flowfuse.com/blog/2023/12/device-agent-as-a-windows-service/#tip%3A-launching-an-elevated-command-prompt-window-(e.g.-as-the-admin-user)">TIP</a> above</p>
<h3 id="install-device-agent-as-a-service" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/device-agent-as-a-windows-service/#install-device-agent-as-a-service"># </a> Install device-agent as a service</h3>
<div style="position: relative">
<pre class="language-bash"><code id="code-185" class="language-bash"><span class="token builtin class-name">cd</span> c:<span class="token punctuation">\</span>opt<br />.<span class="token punctuation">\</span>nssm.exe <span class="token function">install</span> flowfuse-device-agent <span class="token string">"flowfuse-device-agent.cmd"</span><br />.<span class="token punctuation">\</span>nssm.exe <span class="token builtin class-name">set</span> flowfuse-device-agent AppDirectory <span class="token string">"c:\opt<span class="token entity" title="\f">\f</span>lowfuse-device"</span><br />.<span class="token punctuation">\</span>nssm.exe <span class="token builtin class-name">set</span> flowfuse-device-agent Description <span class="token string">"FlowFuse Device Agent"</span><br /><span class="token comment"># set the AppParameters (cli options) to tell the agent where its home directory is</span><br /><span class="token comment"># in our case, this is c:\opt\flowfuse-device and is set with the -d option</span><br />.<span class="token punctuation">\</span>nssm.exe <span class="token builtin class-name">set</span> flowfuse-device-agent AppParameters <span class="token string">"-d c:\opt<span class="token entity" title="\f">\f</span>lowfuse-device -p 1880"</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-185" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<h3 id="check-the-service-is-installed" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/device-agent-as-a-windows-service/#check-the-service-is-installed"># </a> Check the service is installed</h3>
<p>Run the following command to check the service is installed:</p>
<div style="position: relative">
<pre class="language-bash"><code id="code-192" class="language-bash">services.msc</code></pre>
<button class="code-copy " data-clipboard-target="#code-192" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>(look for a service named `flowfuse-device-agent').</p>
<p>Alternatively, you can use the <code>sc</code> command:</p>
<div style="position: relative">
<pre class="language-bash"><code id="code-199" class="language-bash">sc query flowfuse-device-agent</code></pre>
<button class="code-copy " data-clipboard-target="#code-199" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<h3 id="set-the-user-account-that-will-run-the-service" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/device-agent-as-a-windows-service/#set-the-user-account-that-will-run-the-service"># </a> Set the user account that will run the service</h3>
<p>Some things are easier to edit in the UI, so we will edit the service via the NSSM UI.</p>
<div style="position: relative">
<pre class="language-bash"><code id="code-206" class="language-bash">nssm edit flowfuse-device-agent</code></pre>
<button class="code-copy " data-clipboard-target="#code-206" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/nssm_service_editor-e6Wml3xiQM-431.avif 431w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/nssm_service_editor-e6Wml3xiQM-431.webp 431w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="nssm editor" loading="lazy" decoding="async" src="https://flowfuse.com/img/nssm_service_editor-e6Wml3xiQM-431.jpeg" width="431" height="232" /></picture></p>
<p>In the UI, you can edit the service name, description, startup type, etc.
The most important thing to check is the <code>Application</code> tab. This includes the path to the flowfuse-device-agent.cmd and its arguments.
Select the "Log on" tab, select "This account" and enter the service account name and password that will run the device-agent.
Click the "Edit Service" button to save the changes.</p>
<p>Now you have a service that will run the device-agent as the <strong>service</strong> account 🎉</p>
<h3 id="controlling-the-service" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/device-agent-as-a-windows-service/#controlling-the-service"># </a> Controlling the service</h3>
<p>You can start the service with the command:</p>
<div style="position: relative">
<pre class="language-bash"><code id="code-222" class="language-bash">sc start flowfuse-device-agent</code></pre>
<button class="code-copy " data-clipboard-target="#code-222" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>You can check the current status with the command:</p>
<div style="position: relative">
<pre class="language-bash"><code id="code-226" class="language-bash">sc query flowfuse-device-agent</code></pre>
<button class="code-copy " data-clipboard-target="#code-226" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>You can stop the service with the command:</p>
<div style="position: relative">
<pre class="language-bash"><code id="code-230" class="language-bash">sc stop flowfuse-device-agent</code></pre>
<button class="code-copy " data-clipboard-target="#code-230" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<h3 id="further-reading" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/device-agent-as-a-windows-service/#further-reading"># </a> Further reading</h3>
<p>If you'd like to learn about windows services via the <code>sc</code> command you can access
the help text by running <code>sc</code> from a command prompt.</p>
https://flowfuse.com/blog/2023/12/dashboard-0-10-0/Building a Custom Video Player in Dashboard 2.0We've just released the latest version of Dashboard 2.0, with a fully featured UI Templates node which now allows for full definition of a Vue component, external JS dependencies and CSS.2023-12-07T00:00:00ZJoe Pavitt<p>Dashboard 2.0 just got <em>a lot</em> more powerful with our new updates to the <code>ui-template</code> node. New features added to the node include:</p>
<ul>
<li>Support for a full Vue component to be defined using the VueJS Options API.</li>
<li>Running of raw JavaScript within <code><script /></code> tags</li>
<li>Loading of external dependencies through <code><script /></code> tags</li>
</ul>
<!--more-->
<p>In this article we're going to deepdive into an example of how you can use this new functionality to build a custom video player.</p>
<p>We're going to aim for 3 key features:</p>
<ol>
<li>Emit events into Node-RED when a user plays/pauses the video</li>
<li>Allow for the video to be played/paused from within Node-RED</li>
<li>Allow the user to seek to a specific point in the video from within Node-RED</li>
</ol>
<div style="background-color: #fff4b9; border:1px solid #ffc400; color: #a27110; padding: 12px; border-radius: 6px; font-style: italic;">Reminder: all new releases of Dashboard are now under the <code style="background-color: transparent;">@flowfuse</code> namespace, so you'll need to update to use <code style="background-color: transparent;">@flowfuse/node-red-dashboard</code>, and not <code style="background-color: transparent;">@flowforge</code>.</div>
<h2 id="building-a-vue-component" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/dashboard-0-10-0/#building-a-vue-component"># </a> Building a Vue Component</h2>
<p>With Dashboard 2.0, we switched over our underlying front-end framework to VueJS. We're aware that not everyone coming into Dashboard 2.0 will be familiar with VueJS.</p>
<p>We have a more detailed guide <a href="https://dashboard.flowfuse.com/nodes/widgets/ui-template.html#building-full-vue-components">here</a>, but we'll also give a quick overview of the elements from Vue "component" that we'll use here:</p>
<div style="position: relative">
<pre class="language-html"><code id="code-54" class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>template</span><span class="token punctuation">></span></span><br /> <span class="token comment"><!-- Our HTML content will go here --></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>template</span><span class="token punctuation">></span></span><br /><br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>script</span><span class="token punctuation">></span></span><span class="token script"><span class="token language-javascript"><br /><span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token punctuation">{</span><br /> <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'MyComponent'</span><span class="token punctuation">,</span><br /> <span class="token literal-property property">methods</span><span class="token operator">:</span> <span class="token punctuation">{</span><br /> <span class="token comment">// JS methods we want to use across our component will go here</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token function">mounted</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token comment">// Code we want to run when our component is loaded will go here</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token function">unmounted</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token comment">// Code we want to run when our component is unloaded will go here</span><br /> <span class="token punctuation">}</span><br /><span class="token punctuation">}</span><br /></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>script</span><span class="token punctuation">></span></span><br /><br /><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>style</span><span class="token punctuation">></span></span><span class="token style"><span class="token language-css"><br /> <span class="token comment">/* We can define custom CSS here too */</span><br /></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>style</span><span class="token punctuation">></span></span></code></pre>
<button class="code-copy " data-clipboard-target="#code-54" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>Some quick gotchas to note:</p>
<ul>
<li><code><div>{{ msg }}</div></code> - is an example of how you render variables into the HTML.</li>
<li><code><div v-if="myVar"></div></code> - lets you conditionally show/hide content based on a variable.</li>
<li><code><div v-for="item in items"></div></code> - lets you loop over an array of items and render them into the HTML.</li>
<li><code><div @click="myMethod"></div></code> - lets you bind a method to an event, in this case, when the user clicks on the div.</li>
<li><code><div :class="{ 'my-class': isActive }"></div></code> - <code>:</code> is a way to define a "bound" property. In this case, the class <code>my-class</code> will be applied when <code>isActive</code> is true.</li>
<li><code>console.log(this.myVar)</code> - when you're writing code inside the <code><script /></code> tags, you can access Component variables and methods using <code>this</code>.</li>
</ul>
<h3 id="built-in-extras" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/dashboard-0-10-0/#built-in-extras"># </a> Built-in Extras</h3>
<p>In addition to building a component from scratch, we'll also utilize some built-in features of <code>ui-template</code> too. These will be:</p>
<ul>
<li><strong>Variables:</strong>
<ul>
<li><code>id</code> - The unique ID for this node in Node-RED</li>
<li><code>msg</code> - The message that was most recently received into the node</li>
<li><code>$socket</code> - The underlying SocketIO connection to Node-RED. Use this to listen to any incoming events, and send new ones back.</li>
</ul>
</li>
<li><strong>Functions:</strong>
<ul>
<li><code>send(payload)</code> - Send a message back to Node-RED</li>
</ul>
</li>
</ul>
<p>As above, we have more detailed documentation on these features <a href="https://dashboard.flowfuse.com/nodes/widgets/ui-template.html#built-in-functionality">here</a>.</p>
<h2 id="building-the-video-player" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/dashboard-0-10-0/#building-the-video-player"># </a> Building the Video Player</h2>
<h3 id="defining-the-content-(html)" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/dashboard-0-10-0/#defining-the-content-(html)"># </a> Defining the Content (HTML)</h3>
<p>We're going to start by adding a basic HTML video player:</p>
<div style="position: relative">
<pre class="language-html"><code id="code-144" class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>template</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>video</span> <span class="token attr-name">ref</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>my-video<span class="token punctuation">"</span></span> <span class="token special-attr"><span class="token attr-name">style</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token value css language-css"><span class="token property">width</span><span class="token punctuation">:</span> 100%</span><span class="token punctuation">"</span></span></span> <span class="token attr-name">controls</span> <span class="token attr-name">@play</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>onPlay<span class="token punctuation">"</span></span> <span class="token attr-name">@pause</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>onPause<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>source</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>video/mp4<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> Your browser does not support the video tag.<br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>video</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>template</span><span class="token punctuation">></span></span></code></pre>
<button class="code-copy " data-clipboard-target="#code-144" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>A few things of importance to note here:</p>
<ul>
<li><code>ref</code> is Vue's replacement for <code>document.getElementById()</code>. This is copied to each instance of the component, meaning we can call <code>this.$refs['my-video']</code> to access the video element, and this doesn't break when duplicating the widget multiple times in Dashboard.</li>
<li><code>style=""</code> is required here to ensure the video fills the group/wrapper that it is contained within.</li>
<li><code>@play=</code> is Vue's way of binding onto the standard <code>onplay</code> event listener available on HTML video players. We'll define the <code>onPlay</code> method in the next section.</li>
<li><code>@pause=</code> is our event listener for when the video is paused by the user. As with <code>onPlay</code>, we'll define this shortly.</li>
</ul>
<p>With <em>just</em> the above defined, we end up with a standard video player rendered:</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/dashboard-video-1-OaL6U2jVtK-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/dashboard-video-1-OaL6U2jVtK-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="HTML5 Video Player rendered in Dashboard" loading="lazy" decoding="async" src="https://flowfuse.com/img/dashboard-video-1-OaL6U2jVtK-650.jpeg" width="650" height="386" /></picture></p>
<h3 id="defining-the-behaviors-(vuejs)" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/dashboard-0-10-0/#defining-the-behaviors-(vuejs)"># </a> Defining the Behaviors (VueJS)</h3>
<p>Now we begin to build our Vue component. Referring back to our earlier set of features, we'll tackle these one at a time.</p>
<h4 id="1.-emitting-events-to-node-red-on-play%2Fpause" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/dashboard-0-10-0/#1.-emitting-events-to-node-red-on-play%2Fpause"># </a> 1. Emitting Events to Node-RED on Play/Pause</h4>
<p>We can use <code>methods</code> to define our <code>onPlay</code> and <code>onPause</code> functions that are called <code>@play</code>/<code>@pause</code> respectively.</p>
<div style="position: relative">
<pre class="language-html"><code id="code-188" class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>script</span><span class="token punctuation">></span></span><span class="token script"><span class="token language-javascript"><br /><span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token punctuation">{</span><br /> <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'MyVideoPlayer'</span><span class="token punctuation">,</span><br /> <span class="token literal-property property">methods</span><span class="token operator">:</span> <span class="token punctuation">{</span><br /> <span class="token function">capture</span> <span class="token punctuation">(</span><span class="token parameter">eventType</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token comment">// let's define our own function that can be called onPlay/onPause</span><br /> <span class="token comment">// this prevents duplicated code across the two methods</span><br /><br /> <span class="token comment">// get the Video's DOM element</span><br /> <span class="token keyword">const</span> video <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>$refs<span class="token punctuation">[</span><span class="token string">'my-video'</span><span class="token punctuation">]</span><br /><br /> <span class="token comment">// send a msg to Node-RED using built-in "send" fcn</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span><br /> <span class="token comment">// specify which action is taking place</span><br /> <span class="token literal-property property">event</span><span class="token operator">:</span> eventType<span class="token punctuation">,</span><br /> <span class="token comment">// use Vue's $refs to get the video's currentTime</span><br /> <span class="token literal-property property">time</span><span class="token operator">:</span> video<span class="token punctuation">.</span>currentTime<br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token function">onPlay</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">capture</span><span class="token punctuation">(</span><span class="token string">'play'</span><span class="token punctuation">)</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token function">onPause</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">capture</span><span class="token punctuation">(</span><span class="token string">'pause'</span><span class="token punctuation">)</span><br /> <span class="token punctuation">}</span><br /> <span class="token punctuation">}</span><br /><span class="token punctuation">}</span><br /></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>script</span><span class="token punctuation">></span></span></code></pre>
<button class="code-copy " data-clipboard-target="#code-188" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>With this functionality in place, we can wire the <code>ui-template</code> node to a <code>debug</code> node, and see the following when we play/pause the video:</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/dashboard-video-2-o3x7uYRRNS-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/dashboard-video-2-o3x7uYRRNS-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Example debug output when our custom build video player is played/paused" loading="lazy" decoding="async" src="https://flowfuse.com/img/dashboard-video-2-o3x7uYRRNS-650.jpeg" width="650" height="290" /></picture></p>
<h4 id="2.-remote-control-of-play%2Fpause-from-node-red" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/dashboard-0-10-0/#2.-remote-control-of-play%2Fpause-from-node-red"># </a> 2. Remote control of play/pause from Node-RED</h4>
<p>We can use the built-in <code>$socket</code> variable to listen for incoming events from Node-RED. When Dashboard 2.0's nodes receive a <code>msg</code> inside Node-RED, they send a <code>msg-input:<node-id></code> event to the Dashboard client. We can listen for this event and then call the <code>play()</code> and <code>pause()</code> methods on the video element, depending on any properties of that message, in this case, the <code>msg.payload.event</code> value.</p>
<div style="position: relative">
<pre class="language-html"><code id="code-201" class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>script</span><span class="token punctuation">></span></span><span class="token script"><span class="token language-javascript"><br /><span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token punctuation">{</span><br /> <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'MyVideoPlayer'</span><span class="token punctuation">,</span><br /> <span class="token literal-property property">methods</span><span class="token operator">:</span> <span class="token punctuation">{</span><br /> <span class="token comment">// ...</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token function">mounted</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token comment">// listen for incoming msg's from Node-RED</span><br /> <span class="token comment">// note our topic is "msg-input" + the node's unique ID</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span>$socket<span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">'msg-input:'</span> <span class="token operator">+</span> <span class="token keyword">this</span><span class="token punctuation">.</span>id<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">msg</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token comment">// get the Video's DOM element</span><br /> <span class="token keyword">const</span> video <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>$refs<span class="token punctuation">[</span><span class="token string">'my-video'</span><span class="token punctuation">]</span><br /><br /> <span class="token comment">// if the event is "play", call the video's play() method</span><br /> <span class="token keyword">if</span> <span class="token punctuation">(</span>msg<span class="token punctuation">.</span>payload<span class="token operator">?.</span>event <span class="token operator">===</span> <span class="token string">'play'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> video<span class="token punctuation">.</span><span class="token function">play</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br /> <span class="token punctuation">}</span><br /><br /> <span class="token comment">// if the event is "pause", call the video's pause() method</span><br /> <span class="token keyword">if</span> <span class="token punctuation">(</span>msg<span class="token punctuation">.</span>payload<span class="token operator">?.</span>event <span class="token operator">===</span> <span class="token string">'pause'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> video<span class="token punctuation">.</span><span class="token function">pause</span><span class="token punctuation">(</span><span class="token punctuation">)</span><br /> <span class="token punctuation">}</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token function">unmounted</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token comment">// make sure we remove our listeners when the widget is destroyed</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span>$socket<span class="token punctuation">.</span><span class="token function">off</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">msg-input:</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token keyword">this</span><span class="token punctuation">.</span>id<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><br /> <span class="token punctuation">}</span><br /><span class="token punctuation">}</span><br /></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>script</span><span class="token punctuation">></span></span></code></pre>
<button class="code-copy " data-clipboard-target="#code-201" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<h4 id="3.-seeking-to-a-specific-point-in-the-video-from-within-node-red" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/dashboard-0-10-0/#3.-seeking-to-a-specific-point-in-the-video-from-within-node-red"># </a> 3. Seeking to a specific point in the video from within Node-RED</h4>
<p>With the <code>on('msg-input')</code> listener in place, we can now extend our handler to handle seeking to a specific point in the video.</p>
<div style="position: relative">
<pre class="language-html"><code id="code-208" class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>script</span><span class="token punctuation">></span></span><span class="token script"><span class="token language-javascript"><br /><span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token punctuation">{</span><br /> <span class="token literal-property property">name</span><span class="token operator">:</span> <span class="token string">'MyVideoPlayer'</span><span class="token punctuation">,</span><br /> <span class="token literal-property property">methods</span><span class="token operator">:</span> <span class="token punctuation">{</span><br /> <span class="token comment">// ...</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token function">mounted</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token comment">// ...</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span>$socket<span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">'msg-input:'</span> <span class="token operator">+</span> <span class="token keyword">this</span><span class="token punctuation">.</span>id<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">msg</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token comment">// ... other handlers</span><br /><br /> <span class="token comment">// if the event is "seek", call the video's currentTime() method</span><br /> <span class="token keyword">if</span> <span class="token punctuation">(</span>msg<span class="token punctuation">.</span>payload<span class="token operator">?.</span>event <span class="token operator">===</span> <span class="token string">'seek'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> video<span class="token punctuation">.</span>currentTime <span class="token operator">=</span> msg<span class="token punctuation">.</span>payload<span class="token punctuation">.</span>currentTime<br /> <span class="token punctuation">}</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token function">unmounted</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token comment">// ...</span><br /> <span class="token punctuation">}</span><br /><span class="token punctuation">}</span><br /></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>script</span><span class="token punctuation">></span></span></code></pre>
<button class="code-copy " data-clipboard-target="#code-208" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>and with that, we now have a Dashboard 2.0 widget to display a video, that can be controlled from Node-RED, and logs details of user activity back into Node-RED.</p>
<p>Other features available with the UI Template are detailed in the online documentation, and include:</p>
<ul>
<li><a href="https://dashboard.flowfuse.com/nodes/widgets/ui-template.html#loading-external-dependencies">Loading External Dependencies</a></li>
<li><a href="https://dashboard.flowfuse.com/nodes/widgets/ui-template.html#writing-raw-javascript">Running raw JavaScript</a></li>
</ul>
<h2 id="follow-our-progress" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/dashboard-0-10-0/#follow-our-progress"># </a> Follow our Progress</h2>
<p>You can also read the more comprehensive release notes for <code>v0.10.0</code> release here:</p>
<ul>
<li><a href="https://github.com/FlowFuse/node-red-dashboard/releases/tag/v0.10.0">0.10.0 Release Notes</a></li>
</ul>
<p>As always, thanks for reading and your interest in Dashboard 2.0. If you have any feature requests, bugs/complaints or general feedback, please do reach out, and raise issues on our relevant <a href="https://github.com/FlowFuse/node-red-dashboard">GitHub repository</a>.</p>
<ul>
<li><a href="https://github.com/orgs/FlowFuse/projects/15/views/1">Dashboard 2.0 Activity Tracker</a></li>
<li><a href="https://github.com/orgs/FlowFuse/projects/15/views/4">Dashboard 2.0 Planning Board</a></li>
</ul>
https://flowfuse.com/blog/2023/12/ai-use-cases/Beyond Automation - AI Use Cases that are shaping the next manufacturing frontierIn which AI-powered capabilities should one invest to bring about transformative changes in the manufacturing environment?2023-12-04T00:00:00ZMarian Demme<p>Are we standing on the brink of a Fifth Industrial Revolution? The manufacturing industry has been in a state of flux for some time, with the rise of automation and digitization transforming the way factories operate. But today, we are witnessing something even more profound: AI is pushing manufacturing to a whole new level. Some have even referred to it as “the fifth industrial revolution” due to its potential for disruption.</p>
<!--more-->
<p>But the question lingers for many plant managers and decision makers: in which AI-powered capabilities should one invest to bring about transformative changes in the manufacturing environment?</p>
<p>As we navigate this question, I want to focus on three AI uses that are not only ripe for investment but also pivotal in driving manufacturing success in today's competitive market.</p>
<h2 id="empowering-citizen-developer-strategy-with-ai" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/ai-use-cases/#empowering-citizen-developer-strategy-with-ai"># </a> Empowering Citizen Developer Strategy with AI</h2>
<p>The concept of citizen development stands as one of the most significant fields in my opinion, a sentiment I've detailed in my <a href="https://flowfuse.com/blog/2023/10/citizen-development/">previous article</a> about Citizen Developers. This approach is revolutionizing the manner in which applications are crafted and deployed across various industries. By empowering individuals—irrespective of their coding knowledge—to create applications, AI is dramatically hastening this process.</p>
<p>Investing in AI capabilities that bolster your citizen developer strategy can fast-track application development, offering intuitive, template-driven platforms that employ AI to navigate users through the creation process. As we've seen over recent months and years, AI can significantly assist in code generation, thereby granting your citizen developers an even smoother initiation into application development.</p>
<p>An excellent instance of this is the <a href="https://flowfuse.com/blog/2023/09/chatgpt-for-node-red-developers/">article and Node-RED Node</a> describing the potential for integrating Node-RED with ChatGPT to assist you in building applications. This integration highlights the practical, user-friendly solutions made possible through AI, making the realm of app development accessible to a broader range of innovators.</p>
<h2 id="refining-warehouse-management-through-ai-driven-demand-forecasting" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/ai-use-cases/#refining-warehouse-management-through-ai-driven-demand-forecasting"># </a> Refining Warehouse Management through AI-Driven Demand Forecasting</h2>
<p>In an era marked by complexities in supply chains and customer demand, AI's role in warehouse management becomes a game-changer. AI algorithms analyze historical data and market trends to predict future demand with astonishing accuracy, a step beyond traditional forecasting methods.</p>
<p>For decision makers, investing in AI for demand forecasting means significantly minimizing overproduction or stock outs, optimizing inventory levels, and improving customer satisfaction. The advanced analytics offered by AI not only predict what products are in demand but also when and where they are needed, thereby facilitating strategic planning and resource allocation.</p>
<h2 id="elevating-predictive-maintenance-and-quality-control" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/ai-use-cases/#elevating-predictive-maintenance-and-quality-control"># </a> Elevating Predictive Maintenance and Quality Control</h2>
<p>Unplanned downtime and quality inconsistencies are two of the biggest profit drains in manufacturing. AI's predictive capabilities are setting new standards in both maintenance and quality control protocols. By continuously monitoring equipment performance and production processes, AI can predict and identify machinery failures before they occur and detect quality deviations in real-time—allowing for immediate correction. Investing here means less downtime, reduced maintenance costs, improved product quality, and ultimately, an enhanced bottom line.</p>
<h2 id="your-digital-infrastructure-%26-architecture-is-key" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/12/ai-use-cases/#your-digital-infrastructure-%26-architecture-is-key"># </a> Your Digital Infrastructure & Architecture is key</h2>
<p>While understanding where concrete Use Caes are is crucial, it’s equally important to ensure that your digital strategy and architecture can support and quickly adapt to these advanced AI implementations. See also <a href="https://flowfuse.com/blog/2023/08/uns-article/">my article</a> about the Unified Namespace. A flexible system that integrates a unified namespace is critical for seamless data exchange across various systems and applications. Moreover, fostering a citizen developer environment is fundamental in ensuring that these AI investments are maximally utilized, empowering your workforce to contribute actively to the company's innovation cycle.</p>
https://flowfuse.com/blog/2023/11/device-agent-balena/Deploying the FlowFuse Device Agent via BalenaUsing Balena.io to Deploy fleets of devices2023-11-24T00:00:00ZBen Hardill<p>As part of the FlowFuse Staff Summit this year in Barcelona we met up with Marc Pous from <a href="https://www.balena.io/">Balena Io</a>. Balena is a platform for managing fleets of Edge Devices and it felt like the perfect fit for deploying the FlowFuse Device Agent.</p>
<!--more-->
<p>To do this you install the Balena OS on the devices, this is a stripped down Linux distribution that includes a client that connects back to Balena's platform and creates a VPN tunnel. As well as the Balena client it includes Docker and users can select containers to push to the devices.</p>
<p>These Docker container are hosted on Balena's own container registry and are built by doing a git push to Balena's git server.</p>
<p>A GitHub repository with all the required files <a href="https://github.com/FlowFuse/balena-device-agent">has been published</a>, a one click deploy button to allow you to quickly try this out.</p>
<h2 id="building-flowfuse-device-agent-for-balena" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/11/device-agent-balena/#building-flowfuse-device-agent-for-balena"># </a> Building FlowFuse Device Agent for Balena</h2>
<p>We already build a FlowFuse Device Agent Docker container so it was pretty simple to modify the existing <code>Dockerfile</code> for Balena.</p>
<div style="position: relative">
<pre class="language-docker"><code id="code-19" class="language-docker"><span class="token instruction"><span class="token keyword">FROM</span> balenalib/%%BALENA_MACHINE_NAME%%-alpine-node</span><br /><br /><span class="token instruction"><span class="token keyword">RUN</span> mkdir /opt/flowfuse-device</span><br /><span class="token instruction"><span class="token keyword">RUN</span> npm install -g @flowfuse/device-agent</span><br /><br /><span class="token instruction"><span class="token keyword">COPY</span> entrypoint.sh /usr/src/entrypoint.sh</span><br /><br /><span class="token instruction"><span class="token keyword">ENTRYPOINT</span> [<span class="token string">"/usr/src/entrypoint.sh"</span>]</span><br /><br /><span class="token instruction"><span class="token keyword">CMD</span> [<span class="token string">"flowfuse-device-agent"</span>]</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-19" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>There were 2 main changes from the default Device Agent <a href="https://github.com/FlowFuse/device-agent/blob/main/docker/Dockerfile"><code>Dockerfile</code></a></p>
<ol>
<li>
<p>Change the base image to Balena's image, this is because the <code>Dockerfile</code> is actually a template that can be used to build images optimized for all Balena's supported hardware platforms (We currently build the FlowFuse Device Agent containers for AMD64, ARMv7 and ARM64)</p>
</li>
<li>
<p>Adding a custom <code>entrypoint.sh</code>. This is to ensure that the hostname seen in the container matches the Balena device name, making it easier to match it up with what is seen in the FlowFuse application. It also generates the configuration file from the passed in environment variable (see <a href="https://flowfuse.com/blog/2023/11/device-agent-balena/#configuring-devices">below</a>)</p>
</li>
</ol>
<p>As well as the <code>Dockerfile</code> there is also a <code>docker-compose.yml</code> because Balena applications can be made up of multiple services packaged as container. In this case we just need a single container but the compose file contains all the information about what ports to expose and what volumes need creating to persist state.</p>
<h2 id="configuring-devices" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/11/device-agent-balena/#configuring-devices"># </a> Configuring Devices</h2>
<p>The FlowFuse Device agent can be configured in 2 ways.</p>
<ol>
<li>
<p>You can provide a configuration file that is provided by the FlowFuse application when you create a new Device. This file contains the unique identifiers for the Device and details of where to find the FlowFuse Application. This file can be provided to a Balena device by adding a device specific environment variable as described <a href="https://flowfuse.com/blog/2023/11/device-agent-balena/#environment-variable">below</a>.</p>
</li>
<li>
<p>You can provide a fleet of devices with a configuration file that contains details of where to find the FlowFuse application and a Provisioning token. Multiple Devices can all have the same Provisioning token and this will cause them to connect to the FlowFuse application on first start up and create a new Device bound to an existing team (and optionally an Application or Instance). This file can be passed to Balena devices by way of a Fleet wide environment variable as described <a href="https://flowfuse.com/blog/2023/11/device-agent-balena/#environment-variable">below</a>.
You can create a Provisioning Token file under the Team -> Settings page on the Devices tab.</p>
</li>
</ol>
<h3 id="environment-variable" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/11/device-agent-balena/#environment-variable"># </a> Environment Variable</h3>
<p>Because the <code>device.yml</code> file is multi line it needs to be base64 encoded, you can do this with the following</p>
<div style="position: relative">
<pre class="language-bash"><code id="code-62" class="language-bash">$ base64 <span class="token parameter variable">-w</span> <span class="token number">0</span> device.yml</code></pre>
<button class="code-copy " data-clipboard-target="#code-62" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>You can then use the Balena console to create either a device specific or a fleet wide environment variable called <code>FF_DEVICE_YML</code>.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/balena-env-var-RjtVPQn-so-650.avif 650w, https://flowfuse.com/img/balena-env-var-RjtVPQn-so-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/balena-env-var-RjtVPQn-so-650.webp 650w, https://flowfuse.com/img/balena-env-var-RjtVPQn-so-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/balena-env-var-RjtVPQn-so-650.jpeg 650w, https://flowfuse.com/img/balena-env-var-RjtVPQn-so-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="balena-env-var" loading="lazy" decoding="async" src="https://flowfuse.com/img/balena-env-var-RjtVPQn-so-650.jpeg" width="1300" height="206" /></picture></p>
https://flowfuse.com/blog/2023/11/dashboard-0-8-0/Overhauling the Dashboard 2.0 Build PipelineA month or so ago, we released the Third-Party widget support for Dashboard 2.0, but having seen the feedback, we missed the beat, so we've built it again!2023-11-23T00:00:00ZJoe Pavitt<p>As a developer, sometimes you have to hold up your hands and realise something you've spent two weeks building needs to be thrown away and restarted.</p>
<!--more-->
<p>Having shipped the <a href="https://flowfuse.com/blog/2023/10/dashboard-integrations/">third-party widget support for Dashboard 2.0</a> in line with Dashboard 1.0's approach, we then had the <a href="https://github.com/FlowFuse/node-red-dashboard/issues/307">feedback</a> that the way Dashboard 1.0 did things really wasn't good, and asking us to consider re-building the process to make the developer experience of working with Dashboard 2.0 far more seamless.</p>
<p>So, that's exactly what we've done with the <code>0.8.0</code> release, amongst a few other things.</p>
<div style="background-color: #fff4b9; border:1px solid #ffc400; color: #a27110; padding: 12px; border-radius: 6px; font-style: italic;">Reminder: all new releases of Dashboard are now under the <code style="background-color: transparent;">@flowfuse</code> namespace, so you'll need to update to use <code style="background-color: transparent;">@flowfuse/node-red-dashboard</code>, and not <code style="background-color: transparent;">@flowforge</code>.</div>
<h2 id="migrating-our-build-pipeline" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/11/dashboard-0-8-0/#migrating-our-build-pipeline"># </a> Migrating our Build Pipeline</h2>
<p>Without getting <em>too</em> technical, as part of this work in supporting third-party widgets, we overhauled our build pipeline for Dashboard 2.0. This pipeline is responsible for taking our source code, and compiling it into a format that then gets deployed by Node-RED when running Dashboard.</p>
<p>Previously, we used <em><strong>Webpack</strong></em>, but now, we've switched over to <em><strong>Vite</strong></em>. This is a newer build tool, and is much faster than Webpack. It's also what we've now updated out <a href="https://github.com/FlowFuse/node-red-dashboard-2-ui-example">Example Node</a> to use too.</p>
<p>So now, when working with a third-party widget, Vite builds up all of your code, wraps it into a single <code>umd.js</code> file, and Node-RED then serves that file up for Dashboard 2.0 to load in.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/dashboard-build-FyNBuCjiDS-650.avif 650w, https://flowfuse.com/img/dashboard-build-FyNBuCjiDS-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/dashboard-build-FyNBuCjiDS-650.webp 650w, https://flowfuse.com/img/dashboard-build-FyNBuCjiDS-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/dashboard-build-FyNBuCjiDS-650.jpeg 650w, https://flowfuse.com/img/dashboard-build-FyNBuCjiDS-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Vite Build Process" loading="lazy" decoding="async" src="https://flowfuse.com/img/dashboard-build-FyNBuCjiDS-650.jpeg" width="1300" height="758" /></picture></p>
<p>We've also re-written our <a href="https://dashboard.flowfuse.com/contributing/widgets/third-party.html">"Building Third Party Widgets"</a> guide to reflect this change.</p>
<h2 id="debugging-dashboard" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/11/dashboard-0-8-0/#debugging-dashboard"># </a> Debugging Dashboard</h2>
<p>A new feature we've added in <code>0.8.0</code> is also for those developing Dashboard's core and third-party widgets. You can now navigate to <code>/dashboard/_debug</code> to explore the full configuration that Dashboard receives from Node-RED.</p>
<p>This is particularly useful when you're trying to debug why a widget isn't loading, showing the correct data, or generally isn't behaving as you expect.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/debug-view-HIAUMnVQB_-650.avif 650w, https://flowfuse.com/img/debug-view-HIAUMnVQB_-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/debug-view-HIAUMnVQB_-650.webp 650w, https://flowfuse.com/img/debug-view-HIAUMnVQB_-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/debug-view-HIAUMnVQB_-650.jpeg 650w, https://flowfuse.com/img/debug-view-HIAUMnVQB_-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Dashboard's Debug View" loading="lazy" decoding="async" src="https://flowfuse.com/img/debug-view-HIAUMnVQB_-650.jpeg" width="1300" height="1086" /></picture></p>
<p>Note in the above example, where we can see that the <code>ui-dropdown</code> has had it's options overriden by <code>msg.options</code> on injection.</p>
<p>You can read more about the debugging view <a href="https://dashboard.flowfuse.com/contributing/widgets/debugging.html">here</a></p>
<h2 id="what-else-is-new-in-0.8.0%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/11/dashboard-0-8-0/#what-else-is-new-in-0.8.0%3F"># </a> What else is new in 0.8.0?</h2>
<p>Whilst we focussed this article on the build pipeline overhaul, changes to third-party wdgets and debugging Dashboard, we did also squeeze quite a lot more into the 0.8.0 releases too with plenty other fixes and improvements:</p>
<ul>
<li><a href="https://github.com/FlowFuse/node-red-dashboard/pull/345">Dynamic setting of msg.options for UI Dropdown</a></li>
<li><a href="https://github.com/FlowFuse/node-red-dashboard/pull/346">"Date" type for UI Text Input</a></li>
<li><a href="https://github.com/FlowFuse/node-red-dashboard/pull/365">Finer grain controls of Text Input event emissions</a></li>
<li><a href="https://github.com/FlowFuse/node-red-dashboard/pull/367">Control over when UI Slider emits events</a></li>
<li><a href="https://github.com/FlowFuse/node-red-dashboard/pull/364">Improved documentation for Bar Charts</a></li>
</ul>
<p>You can also read the more comprehensive release notes for the release here:</p>
<ul>
<li><a href="https://github.com/FlowFuse/node-red-dashboard/releases/tag/v0.8.0">0.8.0 Release Notes</a></li>
</ul>
<h2 id="follow-our-progress" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/11/dashboard-0-8-0/#follow-our-progress"># </a> Follow our Progress</h2>
<p>As always, thanks for reading and your interested in Dashboard 2.0. If you have any feature requests, bugs/complaints or general feedback, please do reach out, and raise issues on our relevant <a href="https://github.com/FlowFuse/node-red-dashboard">GitHub repository</a>.</p>
<ul>
<li><a href="https://github.com/orgs/FlowFuse/projects/15/views/1">Dashboard 2.0 Activity Tracker</a></li>
<li><a href="https://github.com/orgs/FlowFuse/projects/15/views/4">Dashboard 2.0 Planning Board</a></li>
</ul>
https://flowfuse.com/blog/2023/11/ai-assistant/Integrate with ChatGPT Assistants with Node-REDGet start quickly leveraging Flows utilizing ChatGPT Assistant2023-11-21T00:00:00ZGrey Dziuba<h2 id="introduction-to-the-world-of-gpts-and-ai-assistants" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/11/ai-assistant/#introduction-to-the-world-of-gpts-and-ai-assistants"># </a> Introduction to the World of GPTs and AI Assistants</h2>
<p>In the ever-evolving landscape of artificial intelligence, Generative Pre-trained Transformers (GPTs) have emerged as groundbreaking tools. These advanced AI models, developed by OpenAI, are capable of understanding and generating human-like text, offering vast possibilities across numerous applications. GPTs learn from various internet texts, enabling them to respond to queries with human-like understanding.</p>
<p>Among the most intriguing developments in this field are AI Assistants. These are specialized applications of GPTs, accessible through an API, designed to enhance and streamline various tasks. Tasks that include code interpreter, functions, retrieval, and leveraging uploading files to interact with. Unlike traditional GPTs, which primarily focus on generating text, AI Assistants can interact, comprehend, and assist in real-time, making them invaluable in industries ranging from manufacturing to finance to healthcare.</p>
<!--more-->
<p><a href="https://flows.nodered.org/flow/073548c276832e804f037f3212014e60">TLDR: Give me the Flows</a></p>
<h2 id="node-red-and-ai-assistants" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/11/ai-assistant/#node-red-and-ai-assistants"># </a> Node-RED and AI Assistants</h2>
<p>The integration of Node-RED with AI Assistants brings a unique set of advantages. By leveraging Node-RED's user-friendly platform, developers and citizen developers can easily harness the power of AI Assistants. This integration allows for creation of bespoke solutions tailored to specific industry needs, ranging from automated customer service to advanced data analytics. The real-world impact is substantial – imagine a manufacturing line where real-time data is seamlessly integrated with a prescriptive AI-driven decision-making prompt, enhancing efficiency and reducing downtime. In healthcare, it provides patients with real-time updates to their personal data and provides contextual information, while in retail, it could enhance customer engagement through personalized interactions. The future shaped by these technologies is one where automation and intelligence converge, leading to unprecedented levels of efficiency and innovation in various sectors.</p>
<h2 id="experience-the-integration-firsthand" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/11/ai-assistant/#experience-the-integration-firsthand"># </a> Experience the Integration Firsthand</h2>
<p>We invite you to explore the possibilities firsthand. Try out the flows we've created and share your feedback. This is your getting started package. In the provided flows, you can do the following:</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/ai-flows-gR89-H3X4R-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/ai-flows-gR89-H3X4R-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="OpenAI Assistant integration on Node-RED" loading="lazy" decoding="async" src="https://flowfuse.com/img/ai-flows-gR89-H3X4R-650.jpeg" width="650" height="319" /></picture></p>
<ol>
<li>
<p><strong>Create Assistant</strong>: This flow creates a new assistant. It starts with an inject node that sets the assistant's name, instructions, tools, and model. The HTTP request node then sends a POST request to the OpenAI API to create the assistant. The assistant's ID is stored in the flow context for later use.</p>
</li>
<li>
<p><strong>List Assistants</strong>: This flow lists all the assistants that have been created. It starts with an inject node that triggers the flow. The HTTP request node sends a GET request to the OpenAI API to retrieve the list of assistants. The results are then displayed in the debug node.</p>
</li>
<li>
<p><strong>Delete Assistant</strong>: This flow deletes an assistant. It starts with an inject node that sets the assistant's ID. The template node constructs the URL for the HTTP request node, which sends a DELETE request to the OpenAI API to delete the assistant. The results are then displayed in the debug node.</p>
</li>
<li>
<p><strong>Adjust Assistant Instructions and Models</strong>: This flow adjusts the instructions and model of an assistant. It starts with an inject node that sets the assistant's ID, new instructions, and new model. The change node prepares the payload for the HTTP request node, which sends a POST request to the OpenAI API to update the assistant. The results are then displayed in the debug node.</p>
</li>
<li>
<p><strong>Create Thread and Run</strong>: This flow creates a new thread and runs it. It starts with an inject node that sets the assistant's ID and the message to be sent. The subflow node then handles the creation of the thread, sending of the message, and retrieval of the response. The results are then displayed in the debug node.</p>
</li>
</ol>
<p>How do you envision leveraging this integration in your day-to-day operations or within your industry? Your insights are valuable in shaping the future of our industry. Begin your journey <a href="https://flows.nodered.org/flow/073548c276832e804f037f3212014e60">here.</a></p>
<h2 id="embracing-the-future-of-ai-and-automation" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/11/ai-assistant/#embracing-the-future-of-ai-and-automation"># </a> Embracing the Future of AI and Automation</h2>
<p>Integrating Node-RED with OpenAI's Assistants is a testament to the ever-evolving landscape of technology. It represents a step towards a future where powerful AI tools are within reach of a wider audience, enabling the creation of bespoke, flexible, and resilient applications across industries. By embracing this integration, we open doors to innovation and efficiency previously unimagined.</p>
<p><em>Always consult with management before uploading company data to public services like ChatGPT.</em></p>
https://flowfuse.com/blog/2023/11/chatgpt-gpt/Node-Red Builder a GPT (Alpha) by FlowFuseSpeed Up Flow Creation with Your Personal Assistant2023-11-15T00:00:00ZGrey Dziuba<p>When ChatGPT was first released, my expectations were quite low. I had grown accustomed to the usual industry buzz for AI and ML that often led to underwhelming solutions. Naturally, I approached ChatGPT with similar reservations. It wasn't until a few months after its announcement that I decided to give it a try. To my surprise, within just 10 minutes, I found myself so captivated that I decided to purchase the pro version.</p>
<!--more-->
<p>On November 6th, OpenAI unveiled a new offering: GPTs. These function as custom ChatGPT environments, allowing the author to provide additional context, giving it a specific and focused purpose. With new content emerging daily for both Node-RED and FlowFuse, the ability to update and provide essential documentation became increasingly valuable.</p>
<p>ChatGPT is already a fantastic tool for building Node-RED flows, and if you haven't tried it yet, I highly recommend giving it a go. Now, let me introduce you to Node-Red Builder, a preconfigured environment where all the necessary prompts are already set up to ensure your success. Furthermore, the latest knowledge on Node-RED and FlowFuse is readily available within the GPT, allowing you to tap into the most up-to-date documentation for your prompts.</p>
<p>Node-Red Builder streamlines the development of Node-RED flows, making it more accessible, especially for those new to this environment. We've even provided context to emphasize the use of default nodes over function nodes. Imagine being able to simply drag and drop elements, connect nodes, and create functional flows without delving deep into complex coding. This is precisely what Node-Red Builder makes easier, effectively opening the doors of Node-RED to a wider audience.</p>
<p><a href="https://chat.openai.com/g/g-V5Kyn4omE-node-red-builder-by-flowfuse-v1-0-2">Access to the GPT - Node-RED builder by FlowFuse</a></p>
https://flowfuse.com/blog/2023/11/dashboard-2.0-user-tracking/Tracking Who Has Opened a DashboardUsing FlowFuse Authentication Audit Dashboard v2 Access2023-11-13T00:00:00ZBen Hardill<p>As we continue to add features to the Node-RED Dashboard v2 one feature request that came in was to track which users had visited a Dashboard. Multi user support for the Dashboard is on the backlog but this could be solved with the parts that are currently available.</p>
<!--more-->
<h2 id="flowfuse-authentication" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/11/dashboard-2.0-user-tracking/#flowfuse-authentication"># </a> FlowFuse Authentication</h2>
<p>One of the features we offer on FlowFuse is the ability to protect HTTP endpoints and Dashboards using the same FlowFuse user authentication that protects access to the FlowFuse Application and the Node-RED instances.</p>
<p>We even offer a specific RBAC 'viewer' role that just allows access to these endpoints but not the FlowFuse application.</p>
<p>FlowFuse authentication can be enabled from the Instance Settings page on the Security tab</p>
<p>This can be used to secure access to a Dashboard hosted in a Node-RED Instance. At the moment the Dashboard while protected by this authentication, it is not aware of which user is accessing it.</p>
<p>But if we include an element in the Dashboard loaded via a HTTP-in/HTTP-response node we gain access to details of the authenticated user.</p>
<h2 id="implementation" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/11/dashboard-2.0-user-tracking/#implementation"># </a> Implementation</h2>
<p>First we will create a HTTP-in/HTTP-response pair to serve up a single pixel SVG image. I chose SVG as it doesn't require creating a binary image file to load.</p>
<p>The following flow snippet includes both the HTTP-in/HTTP-response nodes and a change node to set the <code>msg.payload</code> to the SVG content and to set the HTTP headers to include the correct mime type.</p>
<p>There is also a second change node which extracts the user information.</p>
<div style="position: relative">
<pre class="language-json"><code id="code-34" class="language-json"><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"7f22dc81d8192d4d"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"http in"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"98c8d7ea66149291"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"url"</span><span class="token operator">:</span><span class="token string">"/tracker"</span><span class="token punctuation">,</span><span class="token property">"method"</span><span class="token operator">:</span><span class="token string">"get"</span><span class="token punctuation">,</span><span class="token property">"upload"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"swaggerDoc"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">210</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">460</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"7d36739c02cd04ec"</span><span class="token punctuation">,</span><span class="token string">"5f4647c97917cce1"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"58fd30516a077e29"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"http response"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"98c8d7ea66149291"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"statusCode"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"headers"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">630</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">460</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"7d36739c02cd04ec"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"98c8d7ea66149291"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">"<svg width=\"1\" height=\"1\"> <rect width=\"1\" height=\"1\" style=\"fill:rgb(255,255,255);stroke-width:3;stroke:rgb(0,0,0)\" /> Sorry, your browser does not support inline SVG.</svg>"</span><span class="token punctuation">,</span><span class="token property">"tot"</span><span class="token operator">:</span><span class="token string">"str"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"headers"</span><span class="token punctuation">,</span><span class="token property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">"{\"Content-Type\":\"image/svg+xml\"}"</span><span class="token punctuation">,</span><span class="token property">"tot"</span><span class="token operator">:</span><span class="token string">"json"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">420</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">460</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"58fd30516a077e29"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"5f4647c97917cce1"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"98c8d7ea66149291"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">"req.session.user"</span><span class="token punctuation">,</span><span class="token property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">420</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">520</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"ddc02b4e9c30c807"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"ddc02b4e9c30c807"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"debug"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"98c8d7ea66149291"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"debug 2"</span><span class="token punctuation">,</span><span class="token property">"active"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"tosidebar"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"console"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"tostatus"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"complete"</span><span class="token operator">:</span><span class="token string">"false"</span><span class="token punctuation">,</span><span class="token property">"statusVal"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"statusType"</span><span class="token operator">:</span><span class="token string">"auto"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">600</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">520</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">]</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-34" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>Next we need to add the SVG to the Dashboard, this can be done by adding a Template node with the following HTML content.</p>
<div style="position: relative">
<pre class="language-html"><code id="code-38" class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>object</span> <span class="token attr-name">data</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/tracker<span class="token punctuation">"</span></span> <span class="token attr-name">height</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>1<span class="token punctuation">"</span></span> <span class="token attr-name">width</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>1<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>object</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span></code></pre>
<button class="code-copy " data-clipboard-target="#code-38" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>This will load the image every time the Dashboard page loads and hence trigger the earlier flow allowing the user to be logged.</p>
<h2 id="linking-to-sso-users" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/11/dashboard-2.0-user-tracking/#linking-to-sso-users"># </a> Linking to SSO Users</h2>
<p>With the release of FlowFuse v1.14.0 the session object will also include the users email address which is the shared identifier between FlowFuse and the SSO system. This will allow the logging to use a single unified identifier.</p>
https://flowfuse.com/blog/2023/11/dashboard-0-7/Chart Improvements & Migrating to Dashboard 2.0With the 0.7.x Releases of Dashboard 2.0, we've made big improvements to Charts, generated a migration guide, and much more...2023-11-09T00:00:00ZJoe Pavitt<p>It's been a little while since we've done an update, since we last posted we've moved into the 0.7.x releases for Dashboard 2.0. With these we're making big strides in improving the UX for charting your data, as well as starting to focus on migration paths from Dashboard 1.0 to 2.0.</p>
<!--more-->
<h2 id="package-name-changes" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/11/dashboard-0-7/#package-name-changes"># </a> Package Name Changes</h2>
<p>Firstly a bit of news regarding the <code>npm</code> package we publish. Inline with our own <a href="https://flowfuse.com/blog/2023/08/flowforge-is-now-flowfuse">company name change</a>, we've had to update Dashboard 2.0's npm package, and so, we've changed from <code>@flowforge/node-red-dashboard</code> to <code>@flowfuse/node-red-dashboard</code>.</p>
<p>In the short term, we'll be keeping @flowforge available on the Node-RED Palette Manager, but it will be removed soon, and the associated NPM Package will be put into a "deprecated" mode.</p>
<h3 id="npm-package-migration" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/11/dashboard-0-7/#npm-package-migration"># </a> NPM Package Migration</h3>
<p>Unfortunately, this migration from <code>@flowforge/</code> to <code>@flowfuse/</code> requires a little bit of manual work, and isn't as easy as just clicking "update" in the Node-RED Editor.</p>
<p>In any case, there is no need to update your flow in this migration, you'll just need to uninstall <code>@flowforge/node-red-dashboard</code> and install <code>@flowfuse/node-red-dashboard</code> instead.</p>
<h4 id="running-locally" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/11/dashboard-0-7/#running-locally"># </a> Running Locally</h4>
<p>If you're running Node-RED locally, or in your own infrastructure, you'll need to manually uninstall the old package:</p>
<div style="position: relative">
<pre class="language-bash"><code id="code-28" class="language-bash"><span class="token function">npm</span> uninstall @flowforge/node-red-dashboard</code></pre>
<button class="code-copy " data-clipboard-target="#code-28" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>and re-install the new one:</p>
<div style="position: relative">
<pre class="language-bash"><code id="code-32" class="language-bash"><span class="token function">npm</span> <span class="token function">install</span> @flowfuse/node-red-dashboard</code></pre>
<button class="code-copy " data-clipboard-target="#code-32" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<h4 id="running-in-flowfuse" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/11/dashboard-0-7/#running-in-flowfuse"># </a> Running in FlowFuse</h4>
<p>Navigate to your Instance > Settings > Palette, and then change the <code>@flowforge/node-red-dashboard</code> entry to <code>@flowfuse/node-red-dashboard</code> (the latest version as of this post is <code>0.7.2</code>).</p>
<p>Restart your instance, and the new package will automatically install.</p>
<h2 id="dashboard-1.0-to-2.0-migration-guide" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/11/dashboard-0-7/#dashboard-1.0-to-2.0-migration-guide"># </a> Dashboard 1.0 to 2.0 Migration Guide</h2>
<p>As part of our mission to ensure a smooth transition from Dashboard 1.0 to Dashboard 2.0, we have published a first draft of a <a href="https://dashboard.flowfuse.com/user/migration.html">Migration Guide</a>.</p>
<p>As a starting point, we have comprehesively covered the Dashboard 1.0 widgets and their associated properties. We've then detailed which properties are already supported, which have partial support, and where appropriate, we do not support and <em>why</em> (most of the time, it's just because we haven't got round to it yet!)</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/migration-guide-snippet-MZJIpyqjWq-650.avif 650w, https://flowfuse.com/img/migration-guide-snippet-MZJIpyqjWq-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/migration-guide-snippet-MZJIpyqjWq-650.webp 650w, https://flowfuse.com/img/migration-guide-snippet-MZJIpyqjWq-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/migration-guide-snippet-MZJIpyqjWq-650.jpeg 650w, https://flowfuse.com/img/migration-guide-snippet-MZJIpyqjWq-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Migration Guide Snippet" loading="lazy" decoding="async" src="https://flowfuse.com/img/migration-guide-snippet-MZJIpyqjWq-650.jpeg" width="1300" height="1128" /></picture></p>
<p>We fully appreciate that the migration path is not yet complete, and we that we are missing some features and properties, but please know that we are working hard to ensure that as many of the features from Dashboard 1.0 are available in Dashboard 2.0. We will be updating this guide as we progress.</p>
<p>We will also be adding "event" and "dynamic properties" sections to the guide, to detail how you can update and control elements via runtime messages (e.g. dynamically change the label of a button), and how this differs (if at all) from Dashboard 1.0.</p>
<p>Whilst we aren't quite there yet, this guide offers a comprehensive breakdown on our progress in backporting all of the properties from Dashboard 1.0</p>
<h3 id="automated-script" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/11/dashboard-0-7/#automated-script"># </a> Automated Script</h3>
<p>An ambitious plan that we have is to also provide a <a href="https://github.com/FlowFuse/node-red-dashboard/issues/261">Migration Script</a>. Any feedback, ideas or concerns are most welcome as comments on the issue.</p>
<p>Whilst this will never provide 100% perfect migration, we hope to be able to provide a script that can be run against your flows to automatically convert as much as possible from Dashboard 1.0 to 2.0. In most cases, as you can see in the Migration guide, we match most properties 1:1, so this should do a lot of the heavy lifting for you.</p>
<h2 id="updates-to-ui-chart" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/11/dashboard-0-7/#updates-to-ui-chart"># </a> Updates to UI Chart</h2>
<h3 id="key-mapping" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/11/dashboard-0-7/#key-mapping"># </a> Key Mapping</h3>
<p>One of the core purposes of Node-RED Dashboard has always been to provide low-code access to charting your data. With the 0.7.x releases we've made some big improvements to the UI Chart node to make it easier to use and more powerful.</p>
<p>In Dashboard 1.0, it was common place to have to regularly re-format your own data into <code>{x, y}</code> structure to be chart-friendly. In <code>0.7.0</code> we've introduced the concept of <strong>key mapping</strong>, where you can specify which keys in your data object should be used for the x and y axes. This means you can now pass in data in the format you want to use, and the chart will do the rest.</p>
<p>For example, when rendering a chart of our weekly npm downloads, we have a data structure:</p>
<div style="position: relative">
<pre class="language-json"><code id="code-87" class="language-json"><span class="token punctuation">[</span><span class="token punctuation">{</span><br /> <span class="token property">"day"</span><span class="token operator">:</span> <span class="token string">"YYYY-MM-DD"</span><span class="token punctuation">,</span><br /> <span class="token property">"downloads"</span><span class="token operator">:</span> <span class="token number">128</span><br /><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span><br /> <span class="token property">"day"</span><span class="token operator">:</span> <span class="token string">"YYYY-MM-DD"</span><span class="token punctuation">,</span><br /> <span class="token property">"downloads"</span><span class="token operator">:</span> <span class="token number">256</span><br /><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span><br /> <span class="token property">"day"</span><span class="token operator">:</span> <span class="token string">"YYYY-MM-DD"</span><span class="token punctuation">,</span><br /> <span class="token property">"downloads"</span><span class="token operator">:</span> <span class="token number">512</span><br /><span class="token punctuation">}</span><span class="token punctuation">]</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-87" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>Rather than having to pipe this into a <code>function</code> node and re-map the properties to <code>{ x, y }</code>, we can now use the <code>ui-chart</code>'s key mapping properties:</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/ui-chart-keymap-properties--ZCq9BowE9-650.avif 650w, https://flowfuse.com/img/ui-chart-keymap-properties--ZCq9BowE9-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/ui-chart-keymap-properties--ZCq9BowE9-650.webp 650w, https://flowfuse.com/img/ui-chart-keymap-properties--ZCq9BowE9-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/ui-chart-keymap-properties--ZCq9BowE9-650.jpeg 650w, https://flowfuse.com/img/ui-chart-keymap-properties--ZCq9BowE9-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="ui-chart-key-mapping" loading="lazy" decoding="async" src="https://flowfuse.com/img/ui-chart-keymap-properties--ZCq9BowE9-650.jpeg" width="1300" height="184" /></picture></p>
<p>Resulting in the following chart:</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/ui-chart-mapping-j8hAXD6G6Q-650.avif 650w, https://flowfuse.com/img/ui-chart-mapping-j8hAXD6G6Q-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/ui-chart-mapping-j8hAXD6G6Q-650.webp 650w, https://flowfuse.com/img/ui-chart-mapping-j8hAXD6G6Q-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/ui-chart-mapping-j8hAXD6G6Q-650.jpeg 650w, https://flowfuse.com/img/ui-chart-mapping-j8hAXD6G6Q-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="ui-chart-key-mapping" loading="lazy" decoding="async" src="https://flowfuse.com/img/ui-chart-mapping-j8hAXD6G6Q-650.jpeg" width="1300" height="470" /></picture></p>
<h3 id="multiple-lines" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/11/dashboard-0-7/#multiple-lines"># </a> Multiple Lines</h3>
<p>Note above, another new option has been added to define <em>"Series"</em>. In Dashboard 1.0 this was fixed as <code>msg.topic</code> at all times, and defined which line/series data points rendered too. Now, this is configurable, and can even be set as a <code>key:</code> type too, whereby each data point being treated individually, and grouped based on a given key/property.</p>
<p>Another great new feature here is the type <code>JSON</code> for this property. We can provide a <em>list</em> of series labels, and the chart will render each value from a single data point as separate lines.</p>
<p>For example, if we consider the data:</p>
<div style="position: relative">
<pre class="language-json"><code id="code-112" class="language-json"><span class="token punctuation">[</span><span class="token punctuation">{</span><br /> <span class="token property">"day"</span><span class="token operator">:</span> <span class="token string">"2023-10-23"</span><span class="token punctuation">,</span><br /> <span class="token property">"temperature"</span><span class="token operator">:</span> <span class="token number">28</span><span class="token punctuation">,</span><br /> <span class="token property">"humidity"</span><span class="token operator">:</span> <span class="token number">16</span><br /><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span><br /> <span class="token property">"day"</span><span class="token operator">:</span> <span class="token string">"2023-10-24"</span><span class="token punctuation">,</span><br /> <span class="token property">"temperature"</span><span class="token operator">:</span> <span class="token number">26</span><span class="token punctuation">,</span><br /> <span class="token property">"humidity"</span><span class="token operator">:</span> <span class="token number">19</span><br /><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span><br /> <span class="token property">"day"</span><span class="token operator">:</span> <span class="token string">"2023-10-25"</span><span class="token punctuation">,</span><br /> <span class="token property">"temperature"</span><span class="token operator">:</span> <span class="token number">27</span><span class="token punctuation">,</span><br /> <span class="token property">"humidity"</span><span class="token operator">:</span> <span class="token number">24</span><br /><span class="token punctuation">}</span><span class="token punctuation">]</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-112" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>We can provide a series: <code>["temperature", "humidity"]</code> like so:</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/ui-chart-series-property--BVAofVJL9-650.avif 650w, https://flowfuse.com/img/ui-chart-series-property--BVAofVJL9-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/ui-chart-series-property--BVAofVJL9-650.webp 650w, https://flowfuse.com/img/ui-chart-series-property--BVAofVJL9-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/ui-chart-series-property--BVAofVJL9-650.jpeg 650w, https://flowfuse.com/img/ui-chart-series-property--BVAofVJL9-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="ui-chart-key-mapping" loading="lazy" decoding="async" src="https://flowfuse.com/img/ui-chart-series-property--BVAofVJL9-650.jpeg" width="1300" height="169" /></picture></p>
<p>Which would result in the following plot:</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/ui-chart-multipoint-FipKs1UdB_-650.avif 650w, https://flowfuse.com/img/ui-chart-multipoint-FipKs1UdB_-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/ui-chart-multipoint-FipKs1UdB_-650.webp 650w, https://flowfuse.com/img/ui-chart-multipoint-FipKs1UdB_-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/ui-chart-multipoint-FipKs1UdB_-650.jpeg 650w, https://flowfuse.com/img/ui-chart-multipoint-FipKs1UdB_-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="ui-chart-key-mapping" loading="lazy" decoding="async" src="https://flowfuse.com/img/ui-chart-multipoint-FipKs1UdB_-650.jpeg" width="1300" height="461" /></picture></p>
<p>We appreciate this offers a new way of working with data in Dashboard, but hopefully, once you've tried it, you'll find it much easier to work with, and see the value it brings when working with your own data sets.</p>
<h2 id="what-else-is-new-in-0.7.x%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/11/dashboard-0-7/#what-else-is-new-in-0.7.x%3F"># </a> What else is new in 0.7.x?</h2>
<p>Whilst we focussed this article on the migration paths and new UI Chart features, we did also squeeze quite a lot more into the 0.7.x releases too with plenty other fixes and improvements:</p>
<ul>
<li><a href="https://github.com/FlowFuse/node-red-dashboard/pull/279">Re-architecture of Server-side State Management</a></li>
<li><a href="https://github.com/FlowFuse/node-red-dashboard/pull/327">Y Axis Min/Max Options</a></li>
<li><a href="https://github.com/FlowFuse/node-red-dashboard/pull/320">"Focus" button for widgets added to Sidebar</a></li>
<li><a href="https://github.com/FlowFuse/node-red-dashboard/pull/310">No more "blue screen" and improved error reporting</a></li>
<li><a href="https://github.com/FlowFuse/node-red-dashboard/pull/301">Better route handling</a></li>
</ul>
<p>You can also read the more comprehensive release notes for each release here:</p>
<ul>
<li><a href="https://github.com/FlowFuse/node-red-dashboard/releases/tag/v0.7.0">0.7.0 Release Notes</a></li>
<li><a href="https://github.com/FlowFuse/node-red-dashboard/releases/tag/v0.7.1">0.7.1 Release Notes</a></li>
<li><a href="https://github.com/FlowFuse/node-red-dashboard/releases/tag/v0.7.2">0.7.2 Release Notes</a></li>
</ul>
<h2 id="follow-our-progress" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/11/dashboard-0-7/#follow-our-progress"># </a> Follow our Progress</h2>
<p>As always, thanks for reading and your interested in Dashboard 2.0. If you have any feature requests, bugs/complaints or general feedback, please do reach out, and raise issues on our relevant <a href="https://github.com/FlowFuse/node-red-dashboard">GitHub repository</a>.</p>
<ul>
<li><a href="https://github.com/orgs/FlowFuse/projects/15/views/1">Dashboard 2.0 Activity Tracker</a></li>
<li><a href="https://github.com/orgs/FlowFuse/projects/15/views/4">Dashboard 2.0 Planning Board</a></li>
</ul>
https://flowfuse.com/blog/2023/11/community-news-11/Community News November 2023Your monthly update for the FlowFuse and Node-RED communities2023-11-09T00:00:00ZGrey Dziuba<p>Welcome to the FlowFuse newsletter for November 2023, a monthly roundup of what’s been happening with FlowFuse and the wider Node-RED community.</p>
<!--more-->
<h2 id="flowfuse-team-summit---barcelona-by-grey" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/11/community-news-11/#flowfuse-team-summit---barcelona-by-grey"># </a> FlowFuse Team Summit - Barcelona by Grey</h2>
<p>The first week of November in Barcelona, the FlowFuse team embraced a blend of culture, collaboration, and creativity at our biannual summit. As a global remote-first company, these gatherings are key to nurturing the camaraderie and clear communication that fuels our work.</p>
<p>My first summit was a vibrant tableau of wit and good-natured sarcasm, a perfect fit for my sense of humor. But it wasn't just about the fun; we delved deep into aligning our strategies to streamline communication with the vast community that recognizes the value of Node-RED.</p>
<p>From segway tours through historic streets to culinary competitions, we bonded and built memories. During the day, we crafted go-to-market strategies, fortified our team dynamics through board games, and honed our sales approaches. The latest dashboard visualizations and product roadmaps were discussed, with our shared vision to simplify the complex for companies worldwide.</p>
<p><strong>“The easy things should be easy, and the hard things should be possible.”</strong></p>
<p>Our goal remains steadfast: to enhance bidirectional communication with you, our valued community, and make Node-RED's power more accessible than ever.</p>
<img src="https://flowfuse.com/blog/2023/11/images/IMG_6334.jpg" width="500" />
<h2 id="announcements-tldr" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/11/community-news-11/#announcements-tldr"># </a> Announcements TLDR</h2>
<p>We're excited to share some significant enhancements that will elevate your experience with FlowFuse and Node-RED. We've announced that Dashboards 2.0 are in Beta version. Recent additions to Dashboards 2.0 include integrating Vuetify and Mermaid into Dashboard 2.0 unlocking a suite of custom UI components to enrich your dashboards. Our step-by-step guide will walk you through creating dynamic elements like countdown timers, leveraging the power of VueJS for seamless updates.</p>
<p>We're also thrilled to introduce FlowFuse Blueprints - a game-changer in building bespoke, flexible, and resilient manufacturing applications. Our initial set of Blueprints, including ANDON Operator Terminal, Performance Overview Dashboard, and OEE Calculator, provide preconfigured Node-RED applications that streamline your development process. Dive into the world of Blueprints and discover how they can accelerate your project's journey from concept to operational reality. Join the <a href="https://flowfuse.com/webinars/2023/blueprints/">webinar</a> to find out more.</p>
<h2 id="recent-changelog-updates" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/11/community-news-11/#recent-changelog-updates"># </a> Recent Changelog Updates</h2>
<ul>
<li><a href="https://flowfuse.com/blog/2023/10/dashboard-integrations/">Integrate your own widgets with Dashboard 2.0</a></li>
<li><a href="https://flowfuse.com/changelog/2023/10/blueprints/">Blueprints</a></li>
<li><a href="https://flowfuse.com/changelog/2023/10/device-snapshot-selection/">Enhanced Snapshot Selection</a></li>
<li><a href="https://flowfuse.com/changelog/2023/10/path-bug-fix/">Device Agent path bug fix</a></li>
<li><a href="https://flowfuse.com/changelog/2023/10/resource-alerts/">Resource Monitoring in Audit Log</a></li>
<li><a href="https://flowfuse.com/changelog/2023/10/certified-nodes/">Certified Nodes</a></li>
</ul>
<h2 id="upcoming-events" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/11/community-news-11/#upcoming-events"># </a> Upcoming events</h2>
<h3 id="flowfuse-blueprints%3A-your-pathway-to-enhanced-manufacturing" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/11/community-news-11/#flowfuse-blueprints%3A-your-pathway-to-enhanced-manufacturing"># </a> FlowFuse Blueprints: Your Pathway to Enhanced Manufacturing</h3>
<p>Explore building manufacturing applications with FlowFuse Blueprints in our upcoming webinar. Blueprints make it easy to get started building applications with Node-RED.</p>
<p><a href="https://flowfuse.com/webinars/2023/blueprints/">Sign-up today</a> to join us on November 30th.</p>
<h2 id="from-our-blog" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/11/community-news-11/#from-our-blog"># </a> From our Blog</h2>
<ul>
<li>
<p><a href="https://flowfuse.com/blog/2023/11/meet-us-at-sps-nuremberg/">Meet FlowFuse at SPS Nuremberg</a> - Talk about Node-RED and how FlowFuse can help you operationalize your flows!</p>
</li>
<li>
<p><a href="https://flowfuse.com/blog/2023/11/raspberry-pi-5-flowfuse-edge-agent/">Install the FlowFuse Edge Agent on the Raspberry Pi 5</a> - Managing your Raspberry Pi 5 with Node-RED through FlowFuse is easy to set up</p>
</li>
<li>
<p><a href="https://flowfuse.com/blog/2023/10/citizen-development/">Innovate from within - Why manufacturing must embrace Citizen Developers</a> - Empower your Operational Technology teams as Citizen Developers</p>
</li>
<li>
<p><a href="https://flowfuse.com/blog/2023/10/mes-build-buy/">Embracing Innovation: Build vs Buy in MES</a> - Bridging the Gap: Uniting MES Development with Automation System Practices</p>
</li>
<li>
<p><a href="https://flowfuse.com/blog/2023/10/blueprints/">What are FlowFuse Blueprints?</a> - Preconfigured Node-RED Applications</p>
</li>
<li>
<p><a href="https://flowfuse.com/blog/2023/10/dashboard-integrations/">Integrate your own widgets with Dashboard 2.0</a> - With the 0.6.0 Release of Dashboard 2.0, we now support third-party widget integration. Read more in this deep dive.</p>
</li>
<li>
<p><a href="https://flowfuse.com/blog/2023/10/blueprints/">What are FlowFuse Blueprints?</a> - Preconfigured Node-RED Applications</p>
</li>
</ul>
<h2 id="join-our-team" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/11/community-news-11/#join-our-team"># </a> Join Our Team</h2>
<p>FlowFuse is expanding our team. Check out the current openings:</p>
<ul>
<li><a href="https://boards.greenhouse.io/flowfuse/jobs/4911532004">Contract Front-End Engineer – Node-RED Dashboard</a></li>
</ul>
https://flowfuse.com/blog/2023/11/meet-us-at-sps-nuremberg/Meet FlowFuse at SPS NurembergTalk about Node-RED and how FlowFuse can help you operationalize your flows!2023-11-08T00:00:00ZZJ van de Weg<p>FlowFuse is excited to be exhibiting at the SPS in Nuremberg next week. We will
be located in Hall 5 Booth 145.</p>
<p>At the SPS, we will be showcasing our latest FlowFuse platform, which is a
powerful and user-friendly tool for creating and managing Node-RED flows. There's
also an option to get a demonstration of how FlowFuse can be used to solve a
variety of industrial automation problems.</p>
<p>We are also keen to meet with Node-RED users and FlowFuse prospective customers
at the SPS. If you would like to book a meeting with us, please visit our
<a href="https://flowfuse.com/contact-us/">contact us</a> page.</p>
<p>We look forward to seeing you at the SPS!</p>
<!--more-->
<h3 id="about-flowfuse" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/11/meet-us-at-sps-nuremberg/#about-flowfuse"># </a> About FlowFuse</h3>
<p>FlowFuse is a software company that develops tools for creating and managing
Node-RED flows. Node-RED is a popular open-source platform for flow-based programming. FlowFuse makes it easy to create and manage complex Node-RED flows, even for users with no prior programming experience.</p>
<p>FlowFuse is used by a wide range of organizations, including manufacturers, utilities, and research institutions. FlowFuse is used to solve a variety of industrial automation problems, such as data acquisition, data enrichment,
and process monitoring.</p>
<h3 id="about-sps-nuremberg" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/11/meet-us-at-sps-nuremberg/#about-sps-nuremberg"># </a> About SPS Nuremberg</h3>
<p>SPS Nuremberg is the world's leading trade fair for electric automation. The fair takes place annually in Nuremberg, Germany. SPS Nuremberg is a showcase for the latest innovations in industrial automation.</p>
<p>We hope to see you at the SPS!</p>
https://flowfuse.com/blog/2023/11/raspberry-pi-5-flowfuse-edge-agent/Install the FlowFuse Edge Agent on the Raspberry Pi 5Managing your Raspberry Pi 5 with Node-RED through FlowFuse is easy to set up2023-11-07T00:00:00ZZJ van de Weg<p>Since the Raspberry Pi 5 was recently announced I pre-ordered it to use with
Node-RED and FlowFuse for a data collection job in my home. During this time I've had the pleasure of installing both the Raspberry Pi OS and the FlowFuse
Device Agent on this new hardware. It's a rather fast experience if and when you understand what steps to follow.</p>
<!--more-->
<p>In my case I was going to only ever use my Raspberry Pi 5 in headless mode, which
means it won't have an attached keyboard, mouse, or monitor. A few years ago this
was challenging as it needed a lot of fiddling either before starting the Pi, or
what I usually did; boot it with monitor and perifirals to set it up in a way it
would work without.</p>
<p>These days it's much easier to achieve a headless Pi right from the get go when
you use the <a href="https://www.raspberrypi.com/software/">official Raspberry Pi Imager</a>.
When you've installed the imager, select the correct version of the software
(64 bits) and the inserted SD-card.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/raspberry-pi-5-flash-os-Fw6ls_lMAa-650.avif 650w, https://flowfuse.com/img/raspberry-pi-5-flash-os-Fw6ls_lMAa-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/raspberry-pi-5-flash-os-Fw6ls_lMAa-650.webp 650w, https://flowfuse.com/img/raspberry-pi-5-flash-os-Fw6ls_lMAa-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/raspberry-pi-5-flash-os-Fw6ls_lMAa-650.jpeg 650w, https://flowfuse.com/img/raspberry-pi-5-flash-os-Fw6ls_lMAa-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Flash Raspberry Pi OS on an SD-card" loading="lazy" decoding="async" src="https://flowfuse.com/img/raspberry-pi-5-flash-os-Fw6ls_lMAa-650.jpeg" width="1300" height="892" /></picture></p>
<p><strong>Before</strong> you click Write, you'll need to update the settings if you're going
to be using the headless mode. Wifi needs to be configured, SSH enabled, and
authentication setup is required too.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/raspberry-pi-5-config-before-flash-KJGwXYodF7-650.avif 650w, https://flowfuse.com/img/raspberry-pi-5-config-before-flash-KJGwXYodF7-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/raspberry-pi-5-config-before-flash-KJGwXYodF7-650.webp 650w, https://flowfuse.com/img/raspberry-pi-5-config-before-flash-KJGwXYodF7-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/raspberry-pi-5-config-before-flash-KJGwXYodF7-650.jpeg 650w, https://flowfuse.com/img/raspberry-pi-5-config-before-flash-KJGwXYodF7-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Configure RPi OS before flashing" loading="lazy" decoding="async" src="https://flowfuse.com/img/raspberry-pi-5-config-before-flash-KJGwXYodF7-650.jpeg" width="1300" height="892" /></picture></p>
<p>When this is all done, the OS and the configuration will need to be written to
the SD-card. This will take about 10 minutes. When it's done, eject the SD-card
and put it in the Raspberry Pi. Afterwards you can boot the device.</p>
<p>When the device is powered, it can take a minute or so to show up in your
network. I was able to connect to it through ssh using a terminal:</p>
<div style="position: relative">
<pre class="language-sh"><code id="code-25" class="language-sh"><span class="token function">ssh</span> pi@raspberrypi.local</code></pre>
<button class="code-copy " data-clipboard-target="#code-25" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>As general hygene items I updated the repositories, and installed the updates now
available for the system:</p>
<div style="position: relative">
<pre class="language-sh"><code id="code-29" class="language-sh"><span class="token function">sudo</span> <span class="token function">apt-get</span> update<br /><span class="token function">sudo</span> <span class="token function">apt-get</span> upgrade <span class="token parameter variable">-y</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-29" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<h2 id="installing-the-agent" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/11/raspberry-pi-5-flowfuse-edge-agent/#installing-the-agent"># </a> Installing the Agent</h2>
<p>The FlowFuse Device Agent is a software agent that runs on a Raspberry Pi. It manages
all things about Node-RED that's going to run later on the same device. Think
about the Node-RED version and upgrades, setup and management of the process,
access controls, and much more.</p>
<p>You can read <a href="https://flowfuse.com/docs/hardware/raspbian/">the full documentation</a> on how to
install the agent, though it comes down to:</p>
<div style="position: relative">
<pre class="language-sh"><code id="code-39" class="language-sh"><span class="token function">bash</span> <span class="token operator"><</span><span class="token punctuation">(</span><span class="token function">curl</span> <span class="token parameter variable">-sL</span> https://raw.githubusercontent.com/FlowFuse/device-agent/main/service/raspbian-install-device-agent.sh<span class="token punctuation">)</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-39" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>This installs a Node.JS runtime, the agent, and sets up the Pi to run the FlowFuse
agent every time it boots up, and restart it if it ever crashes.</p>
<h3 id="configuration-of-the-agent" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/11/raspberry-pi-5-flowfuse-edge-agent/#configuration-of-the-agent"># </a> Configuration of the agent</h3>
<p>To have FlowFuse Cloud know what devices belong to me we need the device to
be configured with a token to identify itself. The token is obtained when you
register a new device to you team. The FlowFuse documentation explain
<a href="https://flowfuse.com/docs/user/introduction/#working-with-devices">how to setup a team</a>.</p>
<p>When registering a device you'll get an YAML file, which should be copied to
<code>/opt/flowforge/device.yml</code>. I've just copy-pasted this file, though SCP or the
web interface from the device is available.</p>
<p>When you reboot the raspberry pi it should now start the agent automatically fully configured. The device will then ping back to FlowFuse and is available
for work to be done!</p>
https://flowfuse.com/blog/2023/10/citizen-development/Innovate from within - Why manufacturing must embrace Citizen DevelopersEmpower your Operational Technology teams as Citizen Developers2023-10-30T00:00:00ZMarian Demme<p>In the early days when I was working as a solution architect, I found myself in a peculiar position, observing an intriguing relationship between Operational Technology (OT) and Information Technology (IT) departments. While OT departments struggled to develop digital solutions, the IT departments held an unspoken authority in this domain, leading to a paradoxical dynamic that often seemed to hinder rather than facilitate progress.</p>
<!--more-->
<p>As a solution architect working within this environment, I found myself uniquely positioned to bridge the gap between these two groups while also helping them find common ground on which they could build successful projects together. To do so effectively, I needed to understand each group's perspective and determine how best they could collaborate without compromising either side's autonomy or objectives. This task was not always easy but ultimately proved rewarding once achieved successfully.</p>
<h2 id="a-tale-of-shadow-it" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/citizen-development/#a-tale-of-shadow-it"># </a> A Tale of Shadow IT</h2>
<p>In the best-case scenarios, IT departments considered themselves as vendors, and OT, the customers. However, the IT-driven, off-the-shelf solutions seldom proved to be the right fit for the problems at hand. This mismatch often led to the birth of shadow IT systems—solutions that were not sanctioned by IT, yet were deemed necessary to maintain operational efficiency.
In this realm of shadow IT, I've observed countless solutions running on desktop PCs, hidden from the eyes of IT departments, solving problems in manufacturing quickly—a situation born of necessity, with which no one could be satisfied. I cannot deny that Node-RED, an open-source low-code programming tool, has very often been one of these shadow IT systems, enabling data modification, lightweight HMI creation, and empowering the OT workforce.</p>
<p>However, this under-the-radar approach is fraught with dangers. With unprotected systems and without official oversight, the potential for security breaches is a real and present danger. I would wager that even today, a simple scan on port 1880 would reveal a multitude of open Node-RED environments. This double-edged sword of innovation and insecurity highlights the urgent need for a paradigm shift.</p>
<h2 id="why-are-citizen-developers-important-in-manufacturing%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/citizen-development/#why-are-citizen-developers-important-in-manufacturing%3F"># </a> Why are Citizen Developers Important in Manufacturing?</h2>
<p>Citizen developers are individuals who create applications and software solutions for their organizations without any background in computer programming. These citizen developers leverage low-code platforms to build apps that automate tasks, streamline processes, and improve existing systems' user experiences. Citizen developers are a growing trend in the industry, serving as a key factor in harmonizing IT and OT interests. They bring an array of benefits that can make businesses more efficient and cost-effective. From reducing development costs to increasing productivity, citizen developers offer significant value to organizations seeking ways to stay competitive.</p>
<ol>
<li>
<p><strong>Acceleration of Software Development:</strong> Low-code platforms significantly expedite the software development process, enabling more efficient realization of business requirements. By quickening development, these platforms free up time and resources for design and innovation, leading to higher-quality software that better serves the business's needs.</p>
</li>
<li>
<p><strong>Crafting Bespoke Applications:</strong> By empowering non-professional coders with the right tools and resources, organizations can democratize digital solutions. This not only facilitates the creation of custom systems that fit seamlessly into existing infrastructures but also enables rapid ideation and development, even for those without prior coding experience.</p>
</li>
<li>
<p><strong>Enhancement of Operational Processes and Customer Experiences:</strong> With the automation capabilities of low-code platforms and the innovative solutions generated by citizen developers, operational processes can be optimized, and customer experiences significantly improved. The synergy between these elements can lead to efficiency gains through automation and the delivery of more effective, customer-centric solutions.</p>
</li>
</ol>
<p>This shift toward embracing citizen development within manufacturing represents a unique opportunity where both sides benefit significantly; not only do OT departments gain access to custom applications tailored precisely for their needs, but IT teams can lead guidance for self-empowerment, resulting in greater efficiency through automation.</p>
<h2 id="democratize-application-development-with-node-red" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/citizen-development/#democratize-application-development-with-node-red"># </a> Democratize Application Development with Node-RED</h2>
<p>For the past decade, Node-RED has been a pioneer in low-code tools, democratizing application development in manufacturing. It provides powerful data collection, transformation, and visualization capabilities, simplifying the application-building process.
As an open-source tool with no associated costs or licensing fees, Node-RED is <a href="https://flowfuse.com/blog/2023/03/integration-platform-for-edge-computing/#the-standard-for-edge-computing-and-plcs">increasingly popular</a> among manufacturers seeking to quickly develop custom applications without extensive coding knowledge or experience.
FlowFuse takes things one step further, offering organizations a way to officially incorporate and scale Node-RED, making it compliant, governed, and secure within the existing solution landscape.</p>
<h2 id="the-strategic-imperative-of-citizen-development" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/citizen-development/#the-strategic-imperative-of-citizen-development"># </a> The Strategic Imperative of Citizen Development</h2>
<p>For industry decision-makers, this is a call to action. It is imperative to nurture this growing community within your workforce, providing them with the tools, platforms, and, importantly, the organizational support they require. The empowerment of citizen developers could very well be the deciding factor in your organization's ability to stay competitive, agile, and innovative in a rapidly evolving market.</p>
<p>Looking to the future, the success of modern manufacturing lies in its people and their ability to solve problems with the right tools at their fingertips. Citizen development has the potential to break down the barriers. Organizations that recognize and invest in this potential will undoubtedly lead the charge.</p>
https://flowfuse.com/blog/2023/10/certified-nodes/What are Certified Nodes?Enhanced Security, Quality, and Support2023-10-27T00:00:00ZMarian Demme<p>We are thrilled to introduce a new feature for our Teams and Enterprise Tier customers - <strong>Certified Nodes for Node-RED</strong>. This new offering is designed to reinforce your flows's robustness by granting you access to Node-RED nodes that stand up to our rigorous quality and security standards.</p>
<!--more-->
<h2 id="what-is-a-certified-node%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/certified-nodes/#what-is-a-certified-node%3F"># </a> What is a certified node?</h2>
<p>A certified node is a module from the Node-RED library that undergoes a certification process, ensuring it adheres to standards that address three core pillars:</p>
<p><strong>Quality</strong></p>
<ul>
<li>Testing phases for each node.</li>
<li>Operational reliability and compatibility.</li>
</ul>
<p><strong>Security</strong></p>
<ul>
<li>Proactive resolution of potential vulnerabilities.</li>
<li>Revocation of certification for nodes falling short on security, with prompt notifications to affected customers.</li>
</ul>
<p><strong>Support</strong></p>
<ul>
<li>Ambitious aim towards effective issue resolution.</li>
<li>Assistance for troubleshooting.</li>
</ul>
<h2 id="how-to-use-certfied-nodes%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/certified-nodes/#how-to-use-certfied-nodes%3F"># </a> How to use certfied nodes?</h2>
<p>Accessing certified nodes is straightforward—they're integrated directly within your Node-RED palette manager, simplifying selection and implementation. All new instances since October 26, 2023, have automatic access to the catalogue. If you want to add Certified Nodes to one of your existing instances, just <a href="https://flowfuse.com/support/">contact us</a>.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/certified-nodes-OjDKSFWsS4-568.avif 568w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/certified-nodes-OjDKSFWsS4-568.webp 568w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Node-RED palette manager" loading="lazy" decoding="async" src="https://flowfuse.com/img/certified-nodes-OjDKSFWsS4-568.jpeg" width="568" height="412" /></picture></p>
<h2 id="what-kind-of-nodes-are-included%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/certified-nodes/#what-kind-of-nodes-are-included%3F"># </a> What kind of Nodes are included?</h2>
<p>Our initial roll-out includes a curated assortment of certified nodes. We're continuously expanding our library, with upcoming weeks bringing a wider array of options. Should you find a gap in your desired functionalities, we encourage you to <a href="https://discourse.nodered.org/c/vendors/flowfuse/24/">reach out</a>. Your feedback drives our journey forward, influencing the nodes we introduce next.</p>
<ul>
<li>Linting for Node-RED</li>
<li>Enhanced debugging for Node-RED</li>
<li>FlowFuse Snapshot Plugin</li>
<li>Node-RED Dashboard 2.0</li>
<li>E-Mail Communication</li>
<li>Base64 converter</li>
<li>Buffer Parser</li>
<li>PostgreSQL</li>
<li>InfluxDB</li>
<li>Omron PLC</li>
<li>MC Protocol (Mitsubishi PLCs)</li>
</ul>
<h3 id="what-will-follow-in-the-coming-weeks%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/certified-nodes/#what-will-follow-in-the-coming-weeks%3F"># </a> What will follow in the coming weeks?</h3>
<ul>
<li>Siemens PLC</li>
<li>Modbus</li>
<li>Mssql</li>
<li>Rockwell and Allen Bradley</li>
<li>OPC-UA</li>
<li>MongoDB</li>
<li>MySQL</li>
<li>WhatsAPP, Telegram, Slack</li>
</ul>
https://flowfuse.com/blog/2023/10/mes-build-buy/Embracing Innovation: Build vs Buy in MESBridging the Gap: Uniting MES Development with Automation System Practices2023-10-20T00:00:00ZGrey Dziuba<p>In today's fast-paced manufacturing landscape, the question of whether to build or buy Manufacturing Execution System (MES) solutions is more pertinent than ever. Traditional practices often involve outsourcing MES development to system integration (SI) companies or purchasing a software MES package, leaving manufacturing engineers with limited control and flexibility. However, a shift toward a hybrid approach, combining the strengths of both building and buying, is revolutionizing the way we approach MES systems. This article explores the advantages of using Node-RED in combination with FlowFuse for MES deployment and how it can empower manufacturing companies to achieve new levels of efficiency and adaptability.</p>
<!--more-->
<h2 id="the-hybrid-approach%3A-a-best-of-both-worlds-strategy" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/mes-build-buy/#the-hybrid-approach%3A-a-best-of-both-worlds-strategy"># </a> The Hybrid Approach: A Best of Both Worlds Strategy</h2>
<p>Much like the practice of outsourcing machine installation while specifying detailed requirements, a hybrid approach to MES systems leverages the expertise of SI companies while retaining control over critical aspects of system design. This approach recognizes that automation engineers possess valuable insights into the unique needs of their manufacturing processes. They can specify crucial details such as wire coloring schemes, downtime conventions, Andon board standards, PLC types, and even the code used on PLCs.</p>
<h2 id="node-red%3A-the-mes-code's-best-friend" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/mes-build-buy/#node-red%3A-the-mes-code's-best-friend"># </a> Node-RED: The MES Code's Best Friend</h2>
<p>Node-RED emerges as a game-changer in this paradigm. It is an open-source, flow-based development tool renowned for its ability to connect everything, from PLCs to relational databases to firewalls, empowering engineers to create MES system logic visually. Node-RED simplifies the process by enabling engineers to drag and drop nodes and wires to define the logic flow. This visual approach not only streamlines development but also enhances the transparency of the codebase.</p>
<h2 id="the-power-of-standardization-and-code-clarity" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/mes-build-buy/#the-power-of-standardization-and-code-clarity"># </a> The Power of Standardization and Code Clarity</h2>
<p>One of the primary reasons behind Node-RED's appeal is its ability to standardize code. Just as Ladder Logic and Function Block Diagrams have long been favored for their clarity, Node-RED fosters a coding environment where engineers can easily understand and build upon each other's work. This standardization ensures that MES systems remain in sync with the rest of the plant, making troubleshooting and maintenance more efficient.</p>
<h2 id="flowfuse%3A-bridging-the-gap-to-deployment" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/mes-build-buy/#flowfuse%3A-bridging-the-gap-to-deployment"># </a> FlowFuse: Bridging the Gap to Deployment</h2>
<p>When it comes to deploying MES systems, FlowFuse enters the scene as a vital companion to Node-RED. FlowFuse is a deployment platform that seamlessly integrates with Node-RED, allowing for effortless deployment of applications to a customer's environment. Its user-friendly interface makes it easy for automation engineers to manage and scale their MES systems.</p>
<h2 id="pioneering-the-future%3A-the-strategic-adoption-of-node-red-and-flowfuse" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/mes-build-buy/#pioneering-the-future%3A-the-strategic-adoption-of-node-red-and-flowfuse"># </a> Pioneering the Future: The Strategic Adoption of Node-RED and FlowFuse</h2>
<p>Embracing Node-RED and FlowFuse in MES system development is not just a technical choice; it's a strategic one. By adopting this hybrid approach, manufacturing companies position themselves as thought leaders in the industry. They demonstrate a commitment to innovation, transparency, and adaptability.</p>
<h2 id="elevate-your-mes-strategy%3A-embrace-node-red-and-flowfuse-today" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/mes-build-buy/#elevate-your-mes-strategy%3A-embrace-node-red-and-flowfuse-today"># </a> Elevate Your MES Strategy: Embrace Node-RED and FlowFuse Today</h2>
<p>In conclusion, the answer to the build vs. buy dilemma for MES systems is not one or the other—it's both. Node-RED and FlowFuse offer a dynamic partnership that empowers manufacturing companies to craft MES solutions that are tailored to their needs while harnessing the expertise of System Integration companies. The call to action is clear: Embrace Node-RED and FlowFuse as the catalysts for your manufacturing innovation journey.</p>
<p>For more information about FlowFuse and how it can revolutionize your MES system deployment, visit FlowFuse.com Start building MES systems that are not just efficient but also future-ready, and become a trailblazer in the world of industrial manufacturing.</p>
https://flowfuse.com/blog/2023/10/service-disruption-report-2023-10-11/Service Disruption Report for October 11th, 20232023-10-18T00:00:00ZNick O'Leary<p>On October 11th, 2023, we had an issue where users were not able to access the
Node-RED editor, recieving a 'Access Denied' error message.
This post examines the issue that was hit, the timeline of events and
what we've done to resolve it.</p>
<!--more-->
<h2 id="summary" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/service-disruption-report-2023-10-11/#summary"># </a> Summary</h2>
<p>As part of our company rebranding, we planned a migration for our FlowFuse Cloud
platform from <code>app.flowforge.com</code> to <code>app.flowfuse.com</code>.</p>
<p>We applied this change in co-ordination with our customers using Single Sign On
as it required an update to their configuration to match.</p>
<p>This was done on Tuesday October 10th and all confirmed working with those customers.</p>
<p>On Wednesday October 11th we received two reports that separate users could not
access their Node-RED editors. We quickly identified the issue was related to
how the Node-RED editors authenticated users against the platform for non-SSO users.</p>
<p>A workaround was identified to ensure users were logged in via the new domain.</p>
<p>We then looked at options to mitigate this for other users. We could not roll
back the domain name migration as it would have required co-ordinated action with
multiple SSO customers - who were not otherwise impacted by this issue.</p>
<h2 id="resolution" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/service-disruption-report-2023-10-11/#resolution"># </a> Resolution</h2>
<p>We tested various approaches of adding automatic redirection from one domain to
the other. Due to the fact all existing Instances and Devices had the old domain
name hardcoded into their settings, we were limited in what we could do here.</p>
<p>We ultimately applied a single redirect for <code>https://app.flowforge.com</code> to
<code>https://app.flowfuse.com</code> - without any redirecting of paths beneath either domain.</p>
<p>This URL is only accessed by real users when coming to log into the platform. By
redirecting at that point in time, it ensures they are logged into the new domain
and everything works as expected.</p>
<p>For users with active sessions on the old domain, a simple log out and log back in
will get them on to the new domain.</p>
<h2 id="next-steps" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/service-disruption-report-2023-10-11/#next-steps"># </a> Next Steps</h2>
<p>Having resolved the immediate issue we looked at how this situation came to happen
and why it wasn't caught in our preparation for the migration.</p>
<p>We have a staging environment where we verify any changes before they get applied
to production. We all have SSO enabled in that environment and a small number of
test users without SSO enabled.</p>
<p>Our testing had focused on the SSO users which, by virtue of the SSO process, ensured
they ended up logged into the new domain.</p>
<p>The testing done with non-SSO users was more limited and didn't hit the right combination
of having existing log sessions on one or other of the domains to match the scenario
hit by our customers.</p>
<p>We also identified some items to follow up on around how the existing Instances
and Devices handle HTTP redirects. Currently, the Device Agent is not configured
to follow redirects. That is a change we have <a href="https://github.com/FlowFuse/device-agent/issues/182">added to the backlog</a>.</p>
<h2 id="timeline" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/service-disruption-report-2023-10-11/#timeline"># </a> Timeline</h2>
<p><em>All times are BST.</em></p>
<p><strong>Tuesday October 10th</strong></p>
<p>We updated the platform's primary domain name to <code>app.flowfuse.com</code> whilst keeping <code>app.flowforge.com</code> active. This was done in co-ordination with our SSO customers who needed to make an update to their SSO configuration at the same time. Both customers reported success following the change.</p>
<p>Our own validation demonstrated we could login via our own SSO, access editors, and devices continued to work as before (in particular, device editor and snapshot gathering).</p>
<p><strong>Wednesday October 11th</strong></p>
<ul>
<li><strong>11:50</strong> and <strong>11:57</strong> - we received two support request from a user getting an 'access denied' error when trying to access an editor.</li>
<li><strong>12:09</strong> - Workaround shared with both customers to login via the new domain first</li>
<li><strong>12:30</strong> - We applied a blanket redirect for <code>app.flowforge.com</code> to <code>app.flowfuse.com</code>.</li>
<li><strong>12:50</strong> - We then reduced the scope of the redirect so that devices would not be impacted</li>
<li><strong>13:14</strong> - A secondary issue with logging into the editor when logged in on the new domain was reported internally.</li>
<li><strong>13:44</strong> - Reverted all of the redirect handling whilst reviewing the problems with the previous redirects.</li>
<li><strong>14:20</strong> - We applied a redirect to just the root of the domain and documented for our support channel</li>
</ul>
<p>No further reports were received after this time.</p>
https://flowfuse.com/blog/2023/10/blueprints/What are FlowFuse Blueprints?Preconfigured Node-RED Applications2023-10-16T00:00:00ZMarian Demme<p>Starting today, FlowFuse Blueprints are available on FlowFuse Cloud. Additionally, upon request, all our Teams and Enterprise Self-Hosted customers gain access to this collection. But what exactly are FlowFuse Blueprints?</p>
<!--more-->
<h2 id="flowfuse-blueprints" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/blueprints/#flowfuse-blueprints"># </a> FlowFuse Blueprints</h2>
<p>FlowFuse Blueprints aim to make the Node-RED experience more accessible for newcomers, while also offering a treasure trove of fresh ideas for seasoned Node-RED users. When setting up a new Node-RED instance, you now have the option to choose a blueprint tailored for specific use cases. For example, our "ANDON Operator Terminal" blueprint can be selected, and it will automatically configure the Node-RED instance, sparing you the need to start from scratch. While these templates are powerful out-of-the-box, they're also fully customizable, allowing you to tweak them to suit your unique requirements. Ultimately, blueprints speed up the learning curve for new users and expedite the solution-building process for experienced ones.</p>
<h3 id="how-to-use-blueprints%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/blueprints/#how-to-use-blueprints%3F"># </a> How to use Blueprints?</h3>
<p>All our FlowFuse Cloud users can select a Blueprint directly while creating a new Node-RED instance. Self-hosted customers can request access to our blueprints via a <a href="https://flowfuse.com/support/">support ticket</a>.</p>
<h2 id="the-first-three-blueprints" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/blueprints/#the-first-three-blueprints"># </a> The first three Blueprints</h2>
<p>In the coming weeks, we'll be releasing a multitude of blueprints tailored for diverse use cases. However, we decided to start with with three foundational manufacturing applications designed with the <a href="https://dashboard.flowfuse.com/">Node-RED Dashboard 2.0</a>.</p>
<h3 id="andon-operator-terminal" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/blueprints/#andon-operator-terminal"># </a> ANDON Operator Terminal</h3>
<p>The Andon Operator Terminal is designed to be at the start of an Andon process, allowing end-users to report any issues with the cell to a supervisor.
<picture><source type="image/avif" srcset="https://flowfuse.com/img/ANDON1-mOan0CEMsR-650.avif 650w, https://flowfuse.com/img/ANDON1-mOan0CEMsR-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/ANDON1-mOan0CEMsR-650.webp 650w, https://flowfuse.com/img/ANDON1-mOan0CEMsR-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/ANDON1-mOan0CEMsR-650.jpeg 650w, https://flowfuse.com/img/ANDON1-mOan0CEMsR-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="ANDON Blueprint Screenshot" loading="lazy" decoding="async" src="https://flowfuse.com/img/ANDON1-mOan0CEMsR-650.jpeg" width="1300" height="741" /></picture></p>
<h3 id="performance-overview-dashboard" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/blueprints/#performance-overview-dashboard"># </a> Performance Overview Dashboard</h3>
<p>The Performance Overview Dashboard Blueprint provides a real-time snapshot of key performance metrics, delivering a comprehensive overview of manufacturing operations for a specific station or entire line.
<picture><source type="image/avif" srcset="https://flowfuse.com/img/performance-dashboard-5-FqFZ_6h_-650.avif 650w, https://flowfuse.com/img/performance-dashboard-5-FqFZ_6h_-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/performance-dashboard-5-FqFZ_6h_-650.webp 650w, https://flowfuse.com/img/performance-dashboard-5-FqFZ_6h_-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/performance-dashboard-5-FqFZ_6h_-650.jpeg 650w, https://flowfuse.com/img/performance-dashboard-5-FqFZ_6h_-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Performance Overview Screenshot" loading="lazy" decoding="async" src="https://flowfuse.com/img/performance-dashboard-5-FqFZ_6h_-650.jpeg" width="1300" height="585" /></picture></p>
<h3 id="oee-calculator" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/blueprints/#oee-calculator"># </a> OEE Calculator</h3>
<p>If automatic calculations are not feasible, the OEE Calculator Blueprint enables end-users to manually input production data to compute the Overall Equipment Effectiveness (OEE) for a given machine.
<picture><source type="image/avif" srcset="https://flowfuse.com/img/dashboard-data-YSqQcKPnn8-650.avif 650w, https://flowfuse.com/img/dashboard-data-YSqQcKPnn8-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/dashboard-data-YSqQcKPnn8-650.webp 650w, https://flowfuse.com/img/dashboard-data-YSqQcKPnn8-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/dashboard-data-YSqQcKPnn8-650.jpeg 650w, https://flowfuse.com/img/dashboard-data-YSqQcKPnn8-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="OEE Calculator Screenshot" loading="lazy" decoding="async" src="https://flowfuse.com/img/dashboard-data-YSqQcKPnn8-650.jpeg" width="1300" height="605" /></picture></p>
https://flowfuse.com/blog/2023/10/dashboard-integrations/Integrate your own widgets with Dashboard 2.0With the 0.6.0 Release of Dashboard 2.0, we now support third-party widget integration. Read more in this deep dive.2023-10-06T00:00:00ZJoe Pavitt<p>With a new release, comes new features for Dashboard 2.0, and the focus of this release has been on improving the developer experience for those building third-party widgets for Dashboard 2.0.</p>
<!--more-->
<p>Dashboard 1.0 had a hugely popular ecosystem of third party widgets (e.g. <code>ui-worldmap</code>, <code>ui-svg</code>) and something we've been keen to support is a platform where these widgets (and more) can be built and used within Dashboard 2.0 too.</p>
<p>Whilst we can't support the existing Dashboard 1.0 extensions directly (given that we're now VueJS-based, rather than AngularJS), we hope that the framework, documentation and this article, will help springboard the community to build new (and transfer over old) widgets for Dashboard 2.0.</p>
<h2 id="building-from-ui-template" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/dashboard-integrations/#building-from-ui-template"># </a> Building from <code>ui-template</code></h2>
<p>As with Dashboard 1.0, we've utilised the flexibility of our <code>ui-template</code> node here to enable third-party integrations.</p>
<p>If you're used the new <code>ui-template</code> in Dashboard 2.0 already, you'll know that you can provide raw Vue (HTML) content and it'll render that into your Dashboard. In 0.6.0, we've added <em>a lot</em> of new functionality to the guts of <code>ui-template</code>, which we can then extend with our third-party widgets.</p>
<p>This new functionality includes:</p>
<ul>
<li><strong>Custom Dependencies</strong> - Injection of external widget dependencies (e.g. other JavaScript libraries) via <code><head></code>.</li>
<li><strong>On Input</strong> - <code>onInput</code> defines behaviour of the widget in Dashboard when it receives a message in Node-RED.</li>
<li><strong>On Load</strong> - <code>onMounted</code> defines functionality when a widget first loads in Dashboard.</li>
<li><strong>Custom Functions</strong> - Define general functions that can be called from within your widget at any point of your choosing</li>
<li><strong>Extend Built-In Events</strong> - Our built in <code>send</code> function can be called within your widget's template, and will send a message back to Node-RED, with any content of your choosing.</li>
<li><strong>Custom SocketIO Event Handlers</strong> - If you want to extend the communication between Dashboard and Node-RED, you can emit your own SocketIO events from Dashboard, and have respective handlers for those events in Node-RED.</li>
</ul>
<p>We also have plans to expose more of this new functionality to the <code>ui-template</code> interface itself within Node-RED, but for now it's mostly available when developing third-party widgets.</p>
<h2 id="useful-resources" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/dashboard-integrations/#useful-resources"># </a> Useful Resources</h2>
<p>If you're interested in building integrations, then we've also built a couple of resources to help you get started:</p>
<ul>
<li><a href="https://dashboard.flowfuse.com/contributing/widgets/third-party.html">Widget Development Guide</a> - A guide for how to structure your own widgets, and</li>
<li><a href="https://github.com/FlowFuse/node-red-dashboard-example-node">Example Integration (Repo)</a> - We've open sourced a very simple <code>ui-example</code> node that demonstrates how you can build your own widget for Dashboard 2.0, that utilises all of the features highlighted above.</li>
</ul>
<h2 id="what-else-is-new-in-0.6.0%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/dashboard-integrations/#what-else-is-new-in-0.6.0%3F"># </a> What else is new in 0.6.0?</h2>
<p>Whilst we focussed this article on the third-party integrations, we did also squeeze quite a lot more into the 0.6.0 release too with plenty <a href="https://github.com/FlowFuse/node-red-dashboard/releases/tag/v0.6.0">other fixes and improvements</a>, including the separation of the Dash oard 2.0 nodes into a new "Dashboard 2" category in the Node-RED palette.</p>
<p>As always, thanks for reading and your interested in Dashboard 2.0. If you have any feature requests, bugs/complaints or general feedback, please do reach out, and raise issues on our relevant <a href="https://github.com/FlowFuse/node-red-dashboard">GitHub repository</a>.</p>
<ul>
<li><a href="https://github.com/orgs/FlowFuse/projects/15/views/1">Dashboard 2.0 Activity Tracker</a></li>
<li><a href="https://github.com/orgs/FlowFuse/projects/15/views/4">Dashboard 2.0 Planning Board</a></li>
</ul>
https://flowfuse.com/blog/2023/10/community-news-10/Community News October 2023Your monthly update for the FlowFuse and Node-RED communities2023-10-05T00:00:00Z<p>Welcome to the FlowFuse newsletter for October 2023, a monthly roundup of what’s been happening with FlowFuse and the wider Node-RED community.</p>
<!--more-->
<h2 id="quicker-releases-for-flowfuse-cloud-and-new-changelog" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/community-news-10/#quicker-releases-for-flowfuse-cloud-and-new-changelog"># </a> Quicker Releases for FlowFuse Cloud and New Changelog</h2>
<p>FlowFuse is committed to delivery new features to our customers and community as fast as possible. We are now rolling out new builds of FlowFuse to FlowFuse Cloud more regularly than the previous monthly release. This will allow FlowFuse Cloud users to benefit from the latest enhancements as they become available. The self-hosted version of FlowFuse will continue to have releases every 4 weeks.</p>
<p>To allow FlowFuse Cloud users to keep up to date on the new changes, we have started a <a href="https://flowfuse.com/changelog/">Changelog</a> to announce newly deployed features.</p>
<h2 id="recent-changelog-updates" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/community-news-10/#recent-changelog-updates"># </a> Recent Changelog Updates</h2>
<ul>
<li><a href="https://flowfuse.com/changelog/2023/09/devops-actions/">DevOps Pipeline with action selection</a></li>
<li><a href="https://flowfuse.com/changelog/2023/09/snapshots-devices/">Usability improvements to Device Management</a></li>
<li><a href="https://flowfuse.com/changelog/2023/09/introduction-enterprise-tier/">Introducing the Enterprise tier</a></li>
<li><a href="https://flowfuse.com/changelog/2023/09/pipeline-api/">API Endpoints for DevOps Pipeline</a></li>
<li><a href="https://flowfuse.com/blog/2023/10/use-private-custom-nodes-with-flowfuse/">Private Node Support</a></li>
</ul>
<h2 id="upcoming-events" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/community-news-10/#upcoming-events"># </a> Upcoming events</h2>
<h3 id="dashboard-2.0---where-we-are%2C-and-what%E2%80%99s-next%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/community-news-10/#dashboard-2.0---where-we-are%2C-and-what%E2%80%99s-next%3F"># </a> Dashboard 2.0 - Where we are, and what’s next?</h3>
<p>The next generation of the Node-RED dashboard is starting to mature. Development work on Dashboard 2.0 started earlier this year and amazing progress has been made already. Join Joe Pavitt, leader of the Dashboard 2.0 project, who will demonstrate the new dashboard project and discuss future plans during our October webinar.</p>
<p><a href="https://flowfuse.com/webinars/2023/dashboard-20/">Sign-up today</a> to join us on October 26.</p>
<h2 id="from-our-blog" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/community-news-10/#from-our-blog"># </a> From our Blog</h2>
<ul>
<li>
<p><a href="https://flowfuse.com/blog/2023/10/custom-vuetify-components-dashboard/">Custom Vuetify components for Dashboard 2.0</a> - the new dashboard project allows for custom UI components</p>
</li>
<li>
<p><a href="https://flowfuse.com/blog/2023/09/rebranding-our-components/">Updating our branding across GitHub, npm and Dockerhub</a> - our GitHub, npm and DockerHub locations are now called FlowFuse, due to the rename from FlowForge.</p>
</li>
<li>
<p><a href="https://flowfuse.com/blog/2023/09/chatgpt-for-node-red-developers/">How ChatGPT improves Node-RED Developer Experience</a> - lots of interest in ChapGPT in the Node-RED community. A quick review of different integrations.</p>
</li>
<li>
<p><a href="https://flowfuse.com/blog/2023/09/flow-viewer/">Share & Preview Flows on flows.nodered.org</a> - A new way to visualize flows in web pages.</p>
</li>
<li>
<p><a href="https://flowfuse.com/blog/2023/09/dashboard-chart-for-rest-api-data/">Charting REST API Data in a Dashboard</a> - A short tutorial on how to gather data from a REST API for a dashboard.</p>
</li>
<li>
<p>Modernize your legacy industrial data - Two part series on making sense of your industrial data.</p>
<ul>
<li><a href="https://flowfuse.com/blog/2023/09/modernize-your-legacy-industrial-data/">Part 1</a></li>
<li><a href="https://flowfuse.com/blog/2023/09/modernize-your-legacy-industrial-data-part2/">Part 2</a></li>
</ul>
</li>
</ul>
<h2 id="join-our-team" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/community-news-10/#join-our-team"># </a> Join Our Team</h2>
<p>FlowFuse is expanding our team. Check out the current openings:</p>
<ul>
<li><a href="https://boards.greenhouse.io/flowfuse/jobs/4911532004">Contract Front-End Engineer – Node-RED Dashboard</a></li>
</ul>
https://flowfuse.com/blog/2023/10/use-private-custom-nodes-with-flowfuse/How to Use Private Custom Nodes in FlowFuse?Run your own private Node-RED catalogue and npm repository for custom nodes2023-10-02T00:00:00ZMarian DemmeBen Hardill<p>With version 1.12 of FlowFuse, it is now possible to use your custom nodes. In this article, we'll explain how to do that.</p>
<!--more-->
<p>What do we mean by custom nodes? Typically, Node-RED nodes are hosted publicly on the npmjs registry, making them accessible to everyone for download and contribution. However, there are use cases where you may not want to share your developed nodes publicly. In such scenarios, it becomes necessary to run your own private Node-RED catalog and npm repository. This approach allows you to manage your custom nodes securely and efficiently.</p>
<h2 id="step-1---setting-up-a-private-npm-repository" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/use-private-custom-nodes-with-flowfuse/#step-1---setting-up-a-private-npm-repository"># </a> Step 1 - Setting Up a Private npm Repository</h2>
<p>Before you can use custom nodes, you'll need a place to store them.</p>
<h3 id="option-1---service-provider" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/use-private-custom-nodes-with-flowfuse/#option-1---service-provider"># </a> Option 1 - Service Provider</h3>
<p>Choose a public service provider, like <a href="https://www.npmjs.com/">npmjs</a>, that allows you to host private packages and upload your node module.</p>
<h3 id="option-2---verdaccio" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/use-private-custom-nodes-with-flowfuse/#option-2---verdaccio"># </a> Option 2 - Verdaccio</h3>
<p>Another option is to use Verdaccio, a lightweight private npm proxy registry that allows you to run your own registry.</p>
<h4 id="installing-verdaccio" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/use-private-custom-nodes-with-flowfuse/#installing-verdaccio"># </a> Installing Verdaccio</h4>
<ol>
<li>Install Verdaccio using npm:</li>
</ol>
<div style="position: relative">
<pre class="language-sh"><code id="code-35" class="language-sh"><span class="token function">npm</span> <span class="token function">install</span> <span class="token parameter variable">-g</span> verdaccio</code></pre>
<button class="code-copy " data-clipboard-target="#code-35" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<ol start="2">
<li>Run Verdaccio:</li>
</ol>
<div style="position: relative">
<pre class="language-sh"><code id="code-43" class="language-sh">verdaccio</code></pre>
<button class="code-copy " data-clipboard-target="#code-43" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>This will start Verdaccio on <code>http://localhost:4873</code></p>
<h4 id="configuring-verdaccio" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/use-private-custom-nodes-with-flowfuse/#configuring-verdaccio"># </a> Configuring Verdaccio</h4>
<p>The default configuration supports scoped packages and allows any user to access all packages, although only authenticated users can publish.</p>
<p>If necesarry you can edit the Verdaccio configuration file, usually found at <strong>~/.config/verdaccio/config.yaml</strong>.</p>
<p>Refer to the <a href="https://verdaccio.org/docs/configuration/">documentation</a> for all configuration options.</p>
<p>It is important that if you intend to use a private NPM registry with FlowForge Cloud, the registry will need to be publicly exposed to the internet. Please make sure you understand how to secure it appropriately.</p>
<h4 id="publish-your-package" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/use-private-custom-nodes-with-flowfuse/#publish-your-package"># </a> Publish your package</h4>
<ol>
<li>Create a user</li>
</ol>
<div style="position: relative">
<pre class="language-sh"><code id="code-72" class="language-sh"><span class="token function">npm</span> adduser <span class="token parameter variable">--registry</span> http://localhost:4873/</code></pre>
<button class="code-copy " data-clipboard-target="#code-72" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<ol start="2">
<li>Publish you package</li>
</ol>
<div style="position: relative">
<pre class="language-sh"><code id="code-80" class="language-sh"><span class="token function">npm</span> publish <span class="token parameter variable">--registry</span> http://localhost:4873/</code></pre>
<button class="code-copy " data-clipboard-target="#code-80" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<h2 id="step-2---creating-your-private-node-red-catalog" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/use-private-custom-nodes-with-flowfuse/#step-2---creating-your-private-node-red-catalog"># </a> Step 2 - Creating Your Private Node-RED Catalog</h2>
<p>There are several ways to generate your own <code>catalogue.json</code>, which is necessary for Node-RED to understand which packages are available where. Below, we'll show you two of the many options to create and host a <code>catalogue.json</code>.</p>
<h3 id="option-1---web-app" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/use-private-custom-nodes-with-flowfuse/#option-1---web-app"># </a> Option 1 - Web App</h3>
<p>To create and host a Node-RED catalog, we recommend the package <a href="https://github.com/hardillb/node-red-private-catalogue-builder"><code>node-red-private-catalogue-builder</code></a>.</p>
<p>The container accepts the following environment variables:</p>
<ul>
<li>PORT - Which port to listen on (defaults to 3000)</li>
<li>HOST - Which local IP Address to bind to (defaults to 0.0.0.0)</li>
<li>REGISTRY - A host and optional port number to connect to the NPM registry (defaults to http:/ registry:4873)</li>
<li>KEYWORD - The npm keyword to filter on (defaults to node-red)</li>
</ul>
<p><strong>It presents 2 HTTP endpoints</strong></p>
<ul>
<li>/update - a POST to this endpoint will trigger a rebuild of the catalogue</li>
<li>/catalogue.json - a GET request returns the current catalogue</li>
</ul>
<p>The <code>/update</code> endpoint can be used with the Verdaccio <a href="https://verdaccio.org/docs/notifications">notification</a> events to trigger the catalogue to automatically when nodes are added or updated.</p>
<div style="position: relative">
<pre class="language-yaml"><code id="code-136" class="language-yaml"><span class="token key atrule">notify</span><span class="token punctuation">:</span><br /> <span class="token key atrule">method</span><span class="token punctuation">:</span> POST<br /> <span class="token key atrule">headers</span><span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token key atrule">'Content-Type'</span><span class="token punctuation">:</span> <span class="token string">'application/json'</span><span class="token punctuation">}</span><span class="token punctuation">]</span><br /> <span class="token key atrule">endpoint</span><span class="token punctuation">:</span> http<span class="token punctuation">:</span>//localhost<span class="token punctuation">:</span>3000/update<br /> <span class="token key atrule">content</span><span class="token punctuation">:</span> <span class="token string">'{"name": "", "versions": "", "dist-tags": ""}'</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-136" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<h3 id="option-2---node-red" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/use-private-custom-nodes-with-flowfuse/#option-2---node-red"># </a> Option 2 - Node-RED</h3>
<p>You can also use a FlowFuse Node-RED instance and the <a href="https://flows.nodered.org/node/node-red-contrib-catalogue"><code>node-red-contrib-catalogue</code></a> package to generate and host your <code>catalogue.json</code> file.</p>
<iframe width="100%" height="100%" src="https://flows.nodered.org/flow/1f01a92fdbd4172c75fcb88b44e64954/share" allow="clipboard-read; clipboard-write" style="border: none;"></iframe>
<h2 id="step-3---flowfuse-configuration" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/use-private-custom-nodes-with-flowfuse/#step-3---flowfuse-configuration"># </a> Step 3 - FlowFuse configuration</h2>
<p>Next, you'll need to add all the details to your FlowFuse instance configuration.</p>
<ol>
<li>Add the Catalog: Go to your <strong>Instance</strong> -> <strong>Settings</strong> -> <strong>Palette</strong>. Here, you'll have the option to add a catalogue.json. You'll need to provide the URL from which the catalogue.json can be accessed.</li>
</ol>
<p>For example: <strong>https://catalogue.nodered.org/catalogue.json</strong></p>
<p>It is import to remember that this URL must be accessible from the browser running the Node-RED editor and when used with FlowFuse (or any other Node-RED editor accessed via HTTPS) it must be served with HTTPS.</p>
<ol start="2">
<li>Modify the npmrc File: You'll need to configure where to find the packages from the catalog, possibly specifying a scope.</li>
</ol>
<pre><code># Set a new registry for a scoped package
@myscope:registry=https://mycustomregistry.example.org
</code></pre>
<p>If necessary, set authentication-related configurations. See the <a href="https://docs.npmjs.com/cli/v9/configuring-npm/npmrc#auth-related-configuration">documentaion</a> for details.</p>
<ol start="3">
<li>Save and Restart Your Node-RED Instance: The new npm modules should now be visible in the Node-RED Palette Manager.</li>
</ol>
https://flowfuse.com/blog/2023/10/custom-vuetify-components-dashboard/Custom Vuetify components for Dashboard 2.0Expand your dashboard with the full collection of Vuetify components2023-10-02T00:00:00ZZJ van de Weg<p>Vuetify is a library of UI components using Vue. This saves the developers of
Dashboard 2.0 a lot of time, but it can also help you, the end-user. As Vuetify
is now included, it can be used to include <em>any</em> of their components. So in this
post we're going to use a few of these to teach you how to use any of them.</p>
<!--more-->
<p>Let's install the <a href="https://dashboard.flowfuse.com/getting-started.html">Dashboard 2.0 package</a> if you want to follow along. When that's done, let's figure
out how to build custom components on dashboards.</p>
<h2 id="custom-components" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/custom-vuetify-components-dashboard/#custom-components"># </a> Custom components</h2>
<p>While going through the list of components on <a href="https://vuetifyjs.com/en/components/">Vuetify</a>
there's several examples that aren't natively implemented in Dashboard 2.0.
One example we'll use in a dashboard in this post is the
<a href="https://vuetifyjs.com/en/components/progress-circular/">Progress circular</a> to
build a count down timer.</p>
<p>The documentation explains which elements one can change, in this case the size and
width. Having set those to the values you'd want in your dashboard, the HTML is
generated for you, in my case it's:</p>
<div style="position: relative">
<pre class="language-html"><code id="code-16" class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>v-progress-circular</span> <span class="token attr-name">model-value</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>20<span class="token punctuation">"</span></span> <span class="token attr-name">:size</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>128<span class="token punctuation">"</span></span> <span class="token attr-name">:width</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>12<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>v-progress-circular</span><span class="token punctuation">></span></span></code></pre>
<button class="code-copy " data-clipboard-target="#code-16" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<h3 id="using-the-template-node" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/custom-vuetify-components-dashboard/#using-the-template-node"># </a> Using the template node</h3>
<p>Like the <a href="https://flowfuse.com/node-red/core-nodes/template">template core node</a>, the dashboard package
comes with <a href="https://dashboard.flowfuse.com/nodes/widgets/ui-template.html">a template node of its own</a>.
If we take the HTML from the Vuetify docs pages and copy it in a template node
the spinner will show up on the dashboard.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/custom-element-dashboard-UyxiK6jozz-378.avif 378w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/custom-element-dashboard-UyxiK6jozz-378.webp 378w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Custom widget on Dashboard 2.0" alt=""Custom widget on Dashboard 2.0"" loading="lazy" decoding="async" src="https://flowfuse.com/img/custom-element-dashboard-UyxiK6jozz-378.jpeg" width="378" height="464" /></picture></p>
<h2 id="dynamic-templates" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/custom-vuetify-components-dashboard/#dynamic-templates"># </a> Dynamic templates</h2>
<p>While a custom element on a page is cool, and shows you can inject arbitrary HTML
on a Dashboard, it's even better if we could make the element dynamic. So let's
start with a first dynamic element. The quickest way to get that done is have
an <a href="https://flowfuse.com/node-red/core-nodes/inject"><code>Inject</code></a> node output a random number every second.</p>
<p>So let's hook up an Inject, with <code>msg.payload</code>'s output being a JSONata expression
<code>$round($random() * 100)</code> to generate a random number. And let's make sure it
sends a message every second.</p>
<p>Then we need to update the template node to the following snippet:</p>
<div style="position: relative">
<pre class="language-html"><code id="code-38" class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>v-progress-circular</span> <span class="token attr-name">v-model</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>msg.payload<span class="token punctuation">"</span></span> <span class="token attr-name">:size</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>128<span class="token punctuation">"</span></span> <span class="token attr-name">:width</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>12<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>v-progress-circular</span><span class="token punctuation">></span></span></code></pre>
<button class="code-copy " data-clipboard-target="#code-38" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>The difference is subtle, but important. Instead of hard-coding the <code>model-value</code>
to 20, the tag has changed name and it's set to <code>msg.payload</code>. The latter makes
the value dynamic.</p>
<p>Changing <code>model-value</code> to <code>v-model</code> is due to leaking implementation details of
Dashboard 2.0. It uses VueJS to provide, among other features, easy updating of
components. If components are dynamic, <em>always use <code>v-model</code></em>. This allows VueJS
to pick up changes made dynamically.</p>
<p><picture><source type="image/gif" srcset="https://flowfuse.com/img/random-progress-element-71UFWKWzzV-462.gif 462w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Progress spinner, random values" alt=""Progress spinner, random values"" loading="lazy" decoding="async" src="https://flowfuse.com/img/random-progress-element-71UFWKWzzV-462.webp" width="462" height="664" /></picture></p>
<h3 id="finishing-the-count-down-timer" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/10/custom-vuetify-components-dashboard/#finishing-the-count-down-timer"># </a> Finishing the count down timer</h3>
<p>This is mostly a programmers job, but it's not hard, so let's get to it. A button
would be great to reset the timer, and for the sake of this post we can hardcode
the deadline to 1m from the button press.</p>
<p>When dragging in a button node, connect it to a <a href="https://flowfuse.com/node-red/core-nodes/change">change</a>
node. In the change node set the flow variable <code>flow.deadline</code> to the timestamp. The
Inject node from earlier needs updating to inject the <code>flow.deadline</code>. All that's
left is calculating how many seconds passed, and normalizing 60 seconds to the
range between 0-100.</p>
<p>The complete flow is:</p>
<div style="position: relative">
<pre class="language-json"><code id="code-60" class="language-json"><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"ce9bb8f74e3fc934"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui-template"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"24065a0aadb305e3"</span><span class="token punctuation">,</span><span class="token property">"group"</span><span class="token operator">:</span><span class="token string">"8fa772a709ae3316"</span><span class="token punctuation">,</span><span class="token property">"dashboard"</span><span class="token operator">:</span><span class="token string">"e5a3f4cdb11e5e3b"</span><span class="token punctuation">,</span><span class="token property">"page"</span><span class="token operator">:</span><span class="token string">"5bedf7f49d5a6037"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Progress spinner"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"format"</span><span class="token operator">:</span><span class="token string">"<v-progress-circular v-model=\"msg.payload\" :size=\"128\" :width=\"12\"></v-progress-circular>\n"</span><span class="token punctuation">,</span><span class="token property">"storeOutMessages"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"fwdInMessages"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"resendOnRefresh"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"templateScope"</span><span class="token operator">:</span><span class="token string">"local"</span><span class="token punctuation">,</span><span class="token property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">810</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">80</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"8f3e6631414aa096"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"24065a0aadb305e3"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Inject deadline"</span><span class="token punctuation">,</span><span class="token property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"repeat"</span><span class="token operator">:</span><span class="token string">"1"</span><span class="token punctuation">,</span><span class="token property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"once"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"onceDelay"</span><span class="token operator">:</span><span class="token number">0.1</span><span class="token punctuation">,</span><span class="token property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"payload"</span><span class="token operator">:</span><span class="token string">"deadline"</span><span class="token punctuation">,</span><span class="token property">"payloadType"</span><span class="token operator">:</span><span class="token string">"flow"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">140</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">80</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"293cd6f9d727fa02"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"bd9032719d24a53d"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui-button"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"24065a0aadb305e3"</span><span class="token punctuation">,</span><span class="token property">"group"</span><span class="token operator">:</span><span class="token string">"8fa772a709ae3316"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"label"</span><span class="token operator">:</span><span class="token string">"Reset"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"passthru"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"tooltip"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"color"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"bgcolor"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"icon"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"payload"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"payloadType"</span><span class="token operator">:</span><span class="token string">"date"</span><span class="token punctuation">,</span><span class="token property">"topic"</span><span class="token operator">:</span><span class="token string">"deadline"</span><span class="token punctuation">,</span><span class="token property">"topicType"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">170</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">140</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"61ef83d8b06ff626"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"61ef83d8b06ff626"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"24065a0aadb305e3"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"deadline"</span><span class="token punctuation">,</span><span class="token property">"pt"</span><span class="token operator">:</span><span class="token string">"flow"</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"tot"</span><span class="token operator">:</span><span class="token string">"date"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">350</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">140</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"293cd6f9d727fa02"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"24065a0aadb305e3"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Secs since reset"</span><span class="token punctuation">,</span><span class="token property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">"($millis() - msg.payload)/1000"</span><span class="token punctuation">,</span><span class="token property">"tot"</span><span class="token operator">:</span><span class="token string">"jsonata"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">340</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">80</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"9742da7e74fd3cd2"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"9742da7e74fd3cd2"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"range"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"24065a0aadb305e3"</span><span class="token punctuation">,</span><span class="token property">"minin"</span><span class="token operator">:</span><span class="token string">"0"</span><span class="token punctuation">,</span><span class="token property">"maxin"</span><span class="token operator">:</span><span class="token string">"60"</span><span class="token punctuation">,</span><span class="token property">"minout"</span><span class="token operator">:</span><span class="token string">"0"</span><span class="token punctuation">,</span><span class="token property">"maxout"</span><span class="token operator">:</span><span class="token string">"100"</span><span class="token punctuation">,</span><span class="token property">"action"</span><span class="token operator">:</span><span class="token string">"clamp"</span><span class="token punctuation">,</span><span class="token property">"round"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"property"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Seconds to percentages"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">570</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">80</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"ce9bb8f74e3fc934"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"8fa772a709ae3316"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui-group"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Group Name"</span><span class="token punctuation">,</span><span class="token property">"page"</span><span class="token operator">:</span><span class="token string">"5bedf7f49d5a6037"</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token string">"6"</span><span class="token punctuation">,</span><span class="token property">"height"</span><span class="token operator">:</span><span class="token string">"1"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"disp"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"e5a3f4cdb11e5e3b"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui-base"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"UI Name"</span><span class="token punctuation">,</span><span class="token property">"path"</span><span class="token operator">:</span><span class="token string">"/dashboard"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"5bedf7f49d5a6037"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui-page"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Page Name"</span><span class="token punctuation">,</span><span class="token property">"ui"</span><span class="token operator">:</span><span class="token string">"e5a3f4cdb11e5e3b"</span><span class="token punctuation">,</span><span class="token property">"path"</span><span class="token operator">:</span><span class="token string">"/"</span><span class="token punctuation">,</span><span class="token property">"layout"</span><span class="token operator">:</span><span class="token string">"grid"</span><span class="token punctuation">,</span><span class="token property">"theme"</span><span class="token operator">:</span><span class="token string">"8240fbe7c09bc81c"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"8240fbe7c09bc81c"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui-theme"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Theme Name"</span><span class="token punctuation">,</span><span class="token property">"colors"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token property">"surface"</span><span class="token operator">:</span><span class="token string">"#ffffff"</span><span class="token punctuation">,</span><span class="token property">"primary"</span><span class="token operator">:</span><span class="token string">"#0094ce"</span><span class="token punctuation">,</span><span class="token property">"bgPage"</span><span class="token operator">:</span><span class="token string">"#eeeeee"</span><span class="token punctuation">,</span><span class="token property">"groupBg"</span><span class="token operator">:</span><span class="token string">"#ffffff"</span><span class="token punctuation">,</span><span class="token property">"groupOutline"</span><span class="token operator">:</span><span class="token string">"#cccccc"</span><span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token punctuation">]</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-60" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
https://flowfuse.com/blog/2023/09/rebranding-our-components/Updating our branding across GitHub, npm and DockerhubRenaming our packages and containers and what it means for our users2023-09-27T00:00:00ZNick O'Leary<p>Following our rename to FlowFuse last month, we are about to take the next
set of steps to complete the rebrand. This time, focussed on the technical
assets we produce.</p>
<!--more-->
<p>Rebranding a company isn't a small undertaking, especially when your company
name is also your product name. When we announced our <a href="https://flowfuse.com/blog/2023/08/flowforge-is-now-flowfuse/">new name last month</a> we
prioritised updating the website, our documentation and social media presences.
All of the most visible things relating to the company name.</p>
<p>But we knew that wasn't the whole job done. The name <code>flowforge</code> still appears
in the technical resources we use and the artefacts we publish. Changing them
is not as simple a task as changing some words on a website, so it has taken a bit
more time to get our plans in place for this next step.</p>
<p>I wanted to highlight the set of changes we'll be making in the coming days to
complete this migration. For the vast majority of users, expecially those using
FlowFuse Cloud, these changes will be completely transparent.</p>
<p>However, if you are contributing to any of our open source components, or consuming
our npm or Docker packages directly, then please read on.</p>
<p>There are four areas we need to migrate.</p>
<h3 id="github-organization" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/rebranding-our-components/#github-organization"># </a> GitHub Organization</h3>
<p>As a company everything we do revolves around our GitHub Organization. Our
source code, release planning, this website, and far more all live there.</p>
<p>Step one of our migration will be renaming the organization to <code>FlowFuse</code>, so instead
of <code>https://github.com/flowforge</code> we will now live at <code>https://github.com/FlowFuse</code>.</p>
<p>Renaming organizations on GitHub, whilst not something done lightly, is well catered
for. Many existing urls should get automatically redirected - so any existing
links will still work. We will, of course, do the work to update any urls in our docs.</p>
<h3 id="npm-package-names" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/rebranding-our-components/#npm-package-names"># </a> NPM package names</h3>
<p>We publish a number of packages to the public Node.js Package Manager (npm) repository
under the <code>@flowforge</code> name.</p>
<p>After this week's release is done, we'll be updating all of our packages to publish
under the <code>@flowfuse</code> name and no longer updating the packages under the old name.</p>
<p>This will impact anyone who has installed any of our components directly from <code>npm</code>. For
example, the Device Agent or Node-RED Dashboard 2.0.</p>
<p>We will provide specific upgrade instructions for each of the affected components once
the move is done.</p>
<h3 id="docker-images" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/rebranding-our-components/#docker-images"># </a> Docker Images</h3>
<p>We publish container images to Dockerhub under the <code>flowforge</code> name. Once
we've updated our npm package names, we'll also be updating our container tags
to use the new name.</p>
<p>If you are using our helm or Docker Compose projects, we'll have a new release that
will help get you moved over to the new image names. Likewise our Digital Ocean
and AWS Marketplace offerings will be updated - and instructions provided for existing
users to migrate over.</p>
<h3 id="flowfuse-cloud" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/rebranding-our-components/#flowfuse-cloud"># </a> FlowFuse Cloud</h3>
<p>The final step we have to make is to move FlowFuse Cloud over to its new home
at <code>app.flowfuse.com</code>. We have to co-ordinate the update with all of our customers
who use SSO to login to ensure they can continue to access the platform.</p>
<p>Once that is done, it will be a seamless transition for everyone. Existing Node-RED
instances will continue to use the <code>*.flowforge.cloud</code> domain, but then all new
instances will use the <code>*.flowfuse.cloud</code> domain.</p>
https://flowfuse.com/blog/2023/09/chatgpt-for-node-red-developers/How ChatGPT improves Node-RED Developer ExperienceLanguage models have made an impact in the Node-RED community2023-09-23T00:00:00ZZJ van de Weg<p>ChatGPT has the potential to have a significant impact on the Node-RED community. It is a powerful language model that can be used to generate flows, interpret them, and provide documentation, maybe soon even write the flow! The combination of ChatGPT, or generative AI at large, with Node-RED can significantly improve the developer experience with Node-RED. In this post we’ll review what the community has already built.</p>
<!--more-->
<h2 id="how-generative-ai-like-chatgpt-is-used-for-node-red" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/chatgpt-for-node-red-developers/#how-generative-ai-like-chatgpt-is-used-for-node-red"># </a> How generative AI like ChatGPT is used for Node-RED</h2>
<h3 id="function-node-%3C3-chatgpt" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/chatgpt-for-node-red-developers/#function-node-%3C3-chatgpt"># </a> Function node <3 ChatGPT</h3>
<p>ChatGPT, and other models, can write code for you, much like <a href="https://github.com/features/copilot">GitHub CoPilot</a> or <a href="https://about.gitlab.com/gitlab-duo/">GitLab Duo</a>. As Node-RED is ‘low-code’ the ability for generative AI to write the required code for you creates a paradigm shift to ‘no-code’!</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/chatgpt-fcn-example-izByhNHfVO-650.avif 650w, https://flowfuse.com/img/chatgpt-fcn-example-izByhNHfVO-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/chatgpt-fcn-example-izByhNHfVO-650.webp 650w, https://flowfuse.com/img/chatgpt-fcn-example-izByhNHfVO-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/chatgpt-fcn-example-izByhNHfVO-650.jpeg 650w, https://flowfuse.com/img/chatgpt-fcn-example-izByhNHfVO-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Example of Chat GPT to generate contents of a function node" loading="lazy" decoding="async" src="https://flowfuse.com/img/chatgpt-fcn-example-izByhNHfVO-650.jpeg" width="1300" height="1159" /></picture></p>
<p>At FlowFuse we’ve written about this <a href="https://flowfuse.com/blog/2023/05/chatgpt-nodered-fcn-node/">before</a>, and published a <a href="https://github.com/FlowFuse/node-red-function-gpt">plugin</a>. This node allows flow developers to be more productive and efficient. While this works only for the function node, there’s countless other possibilities to describe a flow in text and import a ChatGPT generated flow that are on the horizon!</p>
<h3 id="flow-interpretation" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/chatgpt-for-node-red-developers/#flow-interpretation"># </a> Flow Interpretation</h3>
<p>When developing larger projects with multiple tabs, it’s important to understand what each tab contributes to the full project. This problem is compounded when the flows are developed by a team or the time between the flow was last updated is higher.</p>
<p><img alt="ChatGPT Flow Interpretation" loading="lazy" decoding="async" src="https://raw.githubusercontent.com/node-red-jp/node-red-contrib-plugin-chatgpt/main/infotab.png" width="undefined" height="undefined" /></p>
<p><a href="https://www.linkedin.com/in/kazuhitoyokoi/">Kazuhito-san</a> wrote a module for Node-RED to interpret the flow, nodes, and their order into a well structured documentation. Through a click of a button it's generated by the well-known OpenAI
model. This is especially interesting as it's thus able regenerate it when changes were made by the developers.</p>
<p>It’s a plugin that requires very little setup, and can be found in the <a href="https://www.npmjs.com/package/node-red-contrib-plugin-chatgpt">flow library</a>.</p>
<h3 id="lots-of-plugins" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/chatgpt-for-node-red-developers/#lots-of-plugins"># </a> Lots of plugins</h3>
<p>The ecosystem of Node-RED has always been a fast adopter of new technology. There's
nodes for <a href="https://flows.nodered.org/node/node-red-contrib-chatgpt">ChatGPT</a>,
<a href="https://flows.nodered.org/node/node-red-contrib-bard">Google's Bard</a>, and many
more. These plugins genernally let you build on top of these models, and don't
nessecairly improve the developer experience. It's however a great source of
inspiration!</p>
<h3 id="further-discussion" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/chatgpt-for-node-red-developers/#further-discussion"># </a> Further discussion</h3>
<p>These were three examples of how generative AI is used in the Node-RED community. Please let us know if you're using ChatGPT or other AI models with Node-RED? And what would be the killer feature for Node-RED and AI?</p>
https://flowfuse.com/blog/2023/09/flow-viewer/Share & Preview Flows on flows.nodered.orgFlowFuse has just contributed an interactive "Flow Viewer" to flows.nodered.org, allowing users to preview flows, and embed them in articles & forum posts.2023-09-20T00:00:00ZJoe Pavitt<p>For years, Node-RED's website has provided functionality to share flows through <a href="https://flows.nodered.org/">flows.nodered.org</a></p>
<p>This week, we at FlowFuse have contributed a new feature to the site that allows users to visually preview those flows, and embed/share those flows in articles and on forum posts.</p>
<!--more-->
<h2 id="visual-flow-previews" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/flow-viewer/#visual-flow-previews"># </a> Visual Flow Previews</h2>
<p>A huge thank you for this work needs to go Gerrit Riessen's work published on his <a href="https://blog.openmindmap.org/">Open Mind Map Blog</a>. He recently open-sourced some great work to GitHub (<a href="https://github.com/gorenje/node-red-flowviewer-js">repo</a>), and with some adaptation and collaboration, we've been able to utilise this as a foundation for the functionality we've added into the flows site.</p>
<p>Adding this to <a href="https://flows.nodered.org/">flows.nodered.org</a> will make it far easier to learn how others use Node-RED, and to share your own flows with others too. The embedding functionality should also make talking about Node-RED in your own articles & forums much easier.</p>
<h3 id="example%3A-simple-flow" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/flow-viewer/#example%3A-simple-flow"># </a> Example: Simple Flow</h3>
<p>Here's a demonstration of a simple <code>Inject</code> > <code>Debug</code> node:</p>
<iframe width="100%" height="200px" src="https://flows.nodered.org/flow/500ee13719e54e42493c8ec96fa733b6/share?height=100" allow="clipboard-read; clipboard-write" style="border: none;"></iframe>
<h3 id="example%3A-subflows%2C-groups%2C-links-%26-switches" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/flow-viewer/#example%3A-subflows%2C-groups%2C-links-%26-switches"># </a> Example: Subflows, Groups, Links & Switches</h3>
<p>Here's a non-functional flow that just demonstrates how FlowViewer renders the range of node types available in Node-RED:</p>
<iframe width="100%" height="500px" src="https://flows.nodered.org/flow/82a8602b615740491d30c083e5292e5f/share" allow="clipboard-read; clipboard-write" style="border: none;"></iframe>
<h2 id="sharing-%26-embedding-flows" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/flow-viewer/#sharing-%26-embedding-flows"># </a> Sharing & Embedding Flows</h2>
<p>Any flow on <a href="https://flows.nodered.org/">flows.nodered.org</a> now has a <code>Share Flow</code> option in the <code>Actions</code> section on the right side of the flows page. Clicking this will provide you with an iframe like:</p>
<div style="position: relative">
<pre class="language-html"><code id="code-36" class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>iframe</span> <span class="token attr-name">width</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>100%<span class="token punctuation">"</span></span> <span class="token attr-name">height</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>100%<span class="token punctuation">"</span></span><br /> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>https://flows.nodered.org/flow/7c2dd3ccde70746a40ef8f5aa58c591c/share<span class="token punctuation">"</span></span><br /> <span class="token attr-name">allow</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>clipboard-read; clipboard-write<span class="token punctuation">"</span></span> <span class="token special-attr"><span class="token attr-name">style</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token value css language-css"><span class="token property">border</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span></span><span class="token punctuation">"</span></span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>iframe</span><span class="token punctuation">></span></span></code></pre>
<button class="code-copy " data-clipboard-target="#code-36" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>Which you can paste/embed into any website or blog post. Nick has also <a href="https://discourse.nodered.org/t/previewing-flows-on-the-flow-library/">enabled the Node-RED forums to support these embeds too</a>, and is also how we've embeded the above flows too.</p>
<p>If you want more control over the sizing of the viewer, you can also include a <code>?height=</code> query parameter on the <code>src</code> value of the <code>iframe</code>. You may also need to hardcode the <code>height</code> property of the <code>iframe</code> itself to account for this change, depending on where you're embedding it to. For example:</p>
<div style="position: relative">
<pre class="language-html"><code id="code-43" class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>iframe</span> <span class="token attr-name">width</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>100%<span class="token punctuation">"</span></span> <span class="token attr-name">height</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>250px<span class="token punctuation">"</span></span><br /> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>https://flows.nodered.org/flow/7c2dd3ccde70746a40ef8f5aa58c591c/share?height=100<span class="token punctuation">"</span></span><br /> <span class="token attr-name">allow</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>clipboard-read; clipboard-write<span class="token punctuation">"</span></span> <span class="token special-attr"><span class="token attr-name">style</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token value css language-css"><span class="token property">border</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span></span><span class="token punctuation">"</span></span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>iframe</span><span class="token punctuation">></span></span></code></pre>
<button class="code-copy " data-clipboard-target="#code-43" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>We know it's still not perfect, and there's plenty more we can do with it, but hopefully this is a welcome contribution to the Node-RED community.</p>
https://flowfuse.com/blog/2023/09/dashboard-chart-for-rest-api-data/Charting REST API Data in a DashboardWithin a couple of minutes you'll learn how to request data from a REST endpoint and build a chart to display data points2023-09-20T00:00:00ZZJ van de Weg<p>There are many different ways to get data for a Node-RED dashboard. One common
way is to use a REST API.</p>
<p>A REST API is a set of web services that allow developers to interact with a
server and its resources. To get data from a REST API, you can use the HTTP
nodes in Node-RED to send HTTP requests to the API and receive the data in
the response. In this post we'll guide you through the process.</p>
<!--more-->
<p>First, let's consider what data we want to get. For a dashboard chart it's nice
if there were at least two dimensions to it. For this guide we'll create a chart
of the number of downloads for a certain NPM package.</p>
<h3 id="getting-some-data" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/dashboard-chart-for-rest-api-data/#getting-some-data"># </a> Getting some data</h3>
<p>Reading the data for a package is done through a <code>HTTP GET</code> request, for example:
<code>https://api.npmjs.org/downloads/range/last-month/@flowforge/node-red-dashboard</code>.</p>
<p>A simple flow to achieve this would be:</p>
<iframe width="100%" height="225px" src="https://flows.nodered.org/flow/7c2dd3ccde70746a40ef8f5aa58c591c/share?height=100" allow="clipboard-read; clipboard-write" style="border: none;"></iframe>
<p>Where we paste the URL from above into the settings panel:</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/http-get-npmapi-xML0pMxSWj-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/http-get-npmapi-xML0pMxSWj-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="HTTP GET URL setting" alt=""HTTP GET URL setting"" loading="lazy" decoding="async" src="https://flowfuse.com/img/http-get-npmapi-xML0pMxSWj-650.jpeg" width="650" height="338" /></picture></p>
<p>When running this flow you'll see a blob of text in the <code>Debug</code> pane. This is a
great first start, but a blob isn't useful for the rest of the flow.</p>
<p>We need to parse the data as JSON. While the <a href="https://flowfuse.com/node-red/core-nodes/json">JSON node</a>
would work, the HTTP request node can do this natively. Let <code>a parsed JSON object</code>
the <code>Return</code> settings of the HTTP request node.</p>
<p>So now we got the data, and a little more than we need, so let's change the
message output to keep only what we're interested in; <code>payload.downloads</code>. To
do this, we'll use the <a href="https://flowfuse.com/node-red/core-nodes/change">change node</a>.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/change-node-set-downloads-payload-sUf36H7eVp-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/change-node-set-downloads-payload-sUf36H7eVp-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Change node to set the payload" alt="Change node to set the payload with downloads" loading="lazy" decoding="async" src="https://flowfuse.com/img/change-node-set-downloads-payload-sUf36H7eVp-650.jpeg" width="650" height="223" /></picture></p>
<h2 id="building-the-dashboard" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/dashboard-chart-for-rest-api-data/#building-the-dashboard"># </a> Building the Dashboard</h2>
<p>For this article we're going to be using the new dashboard and we'll install
<code>@flowforge/node-red-dashboard</code>. Please follow the instruction <a href="https://dashboard.flowfuse.com/getting-started.html#installation">on the Dashboard website</a>.</p>
<p>Now we drag in the <code>chart</code> node that's available after installing the dashboard
package and make sure it' input comes from the configured <code>change</code> node. Before
hitting the deploy button the dashboard itself needs configuring:</p>
<p>First add configuration for the <code>ui-group</code>: <picture><source type="image/avif" srcset="https://flowfuse.com/img/dashboard-config-chart-Y5wwXHOtvY-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/dashboard-config-chart-Y5wwXHOtvY-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Configure the chart" alt="Configure the UI Group" loading="lazy" decoding="async" src="https://flowfuse.com/img/dashboard-config-chart-Y5wwXHOtvY-650.jpeg" width="650" height="238" /></picture></p>
<p>To setup the <code>ui-group</code> correctly you'll need to add configuration for the <code>ui-page</code>: <picture><source type="image/avif" srcset="https://flowfuse.com/img/dashboard-config-ui-group-_xNp_iwFyS-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/dashboard-config-ui-group-_xNp_iwFyS-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Configure the UI group" alt=""Configure the ui-group"" loading="lazy" decoding="async" src="https://flowfuse.com/img/dashboard-config-ui-group-_xNp_iwFyS-650.jpeg" width="650" height="298" /></picture>.</p>
<p>To create the UI page it requires another 2 config settings, <code>ui-base</code>, and the theming through <code>ui-theme</code>.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/dashboard-config-ui-base-zVe22FXGw7-650.avif 650w, https://flowfuse.com/img/dashboard-config-ui-base-zVe22FXGw7-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/dashboard-config-ui-base-zVe22FXGw7-650.webp 650w, https://flowfuse.com/img/dashboard-config-ui-base-zVe22FXGw7-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/dashboard-config-ui-base-zVe22FXGw7-650.jpeg 650w, https://flowfuse.com/img/dashboard-config-ui-base-zVe22FXGw7-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Configure the UI Base" loading="lazy" decoding="async" src="https://flowfuse.com/img/dashboard-config-ui-base-zVe22FXGw7-650.jpeg" width="1300" height="478" /></picture></p>
<p>The default theme is great, so just accept that, and save all dialogs to continue the chart creation.</p>
<h3 id="normalizing-the-data" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/dashboard-chart-for-rest-api-data/#normalizing-the-data"># </a> Normalizing the data</h3>
<p>The data for the chart needs to be changed before we can show it. The messages should have a <code>x</code> and <code>y</code> key. So let's prepare the data with
a combination of the <a href="https://flowfuse.com/node-red/core-nodes/split">Split</a> and change node.</p>
<p>The Split node with the default configuration allows to 30 elements of the array
to be mapped individually. The change node will set the <code>payload.x</code> and <code>payload.y</code>
on the message:</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/change-node-prepare-data-chart-qc3FhGaSuH-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/change-node-prepare-data-chart-qc3FhGaSuH-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Prepare data for the chart" alt="Change node to prepare the data for a chart" loading="lazy" decoding="async" src="https://flowfuse.com/img/change-node-prepare-data-chart-qc3FhGaSuH-650.jpeg" width="650" height="482" /></picture></p>
<p>Connect the change node output to a new chart node, and voila:</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/chart-with-data-wH-KL0dR61-650.avif 650w, https://flowfuse.com/img/chart-with-data-wH-KL0dR61-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/chart-with-data-wH-KL0dR61-650.webp 650w, https://flowfuse.com/img/chart-with-data-wH-KL0dR61-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/chart-with-data-wH-KL0dR61-650.jpeg 650w, https://flowfuse.com/img/chart-with-data-wH-KL0dR61-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Data in the chart node" loading="lazy" decoding="async" src="https://flowfuse.com/img/chart-with-data-wH-KL0dR61-650.jpeg" width="1300" height="463" /></picture></p>
<h2 id="keeping-the-data-up-to-date" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/dashboard-chart-for-rest-api-data/#keeping-the-data-up-to-date"># </a> Keeping the data up-to-date</h2>
<p>While we created a chart and it has some data, there's one more thing to explain.
How can the data be kept up-to-date? It's straight forward to have the <code>Inject</code>
node <a href="https://flowfuse.com/node-red/core-nodes/inject/#run-a-flow-daily-at-midnight">run every night</a>,
but the chart would now have multiple data points
for the same day. This paints multiple lines on top of each other. While that works,
the hover of the chart will display the duplication and it's wastefull.</p>
<p>So before we update the chart we need to send a message to the chart where the
<a href="https://dashboard.flowfuse.com/nodes/widgets/ui-chart.html#removing-data">payload is <code>[]</code></a>.
That way the chart is emptied first, and right afterwards it will
receive the new data to write.</p>
<iframe width="100%" height="500px" src="https://flows.nodered.org/flow/47f4cda247f2f2e0172ab61c795308bb/share" allow="clipboard-read; clipboard-write" style="border: none;"></iframe>https://flowfuse.com/blog/2023/09/modernize-your-legacy-industrial-data-part2/Modernize your legacy industrial data. Part 2.A deeper dive with into making the most of legacy industrial data from the likes of Modbus and older, non IIoT protocols and putting it to work in an IIoT world.2023-09-17T00:00:00ZSteve McLaughlin<p>In <a href="https://flowfuse.com/blog/2023/09/modernize-your-legacy-industrial-data/">part 1 of this series</a>, I introduced the topic of working with legacy industrial data from the likes of Modbus and older, non IIoT protocols and putting it to work in an IIoT world. We looked at some of the challenges and how Node-RED with <code>node-red-contrib-buffer-parser</code> node can help.</p>
<p>In this article, I will dive a little deeper into the topic and discuss some of the finer details. I hope to demonstrate a smarter approach that can make a huge difference to data accuracy, performance and maintainability while significantly reducing developer time. Not only that, ending with a no-code solution.</p>
<!--more-->
<h3 id="obtaining-industrial-data" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/modernize-your-legacy-industrial-data-part2/#obtaining-industrial-data"># </a> Obtaining Industrial Data</h3>
<p>In order to convert the legacy data to a format more suited to IIoT we first need to <em>grab</em> that data.</p>
<p>Node-RED has core nodes that can help you and many more contribution nodes exist that provide access to a wide range of industrial devices. To give you an idea, <code>node-red-contrib-modbus</code>, <code>node-red-contrib-s7comm</code>, <code>node-red-contrib-omron-fins</code>, <code>node-red-contrib-mcprotocol</code>, <code>node-red-contrib-df1</code> and <code>node-red-contrib-cip-st-ethernet-ip</code> are just some of the PLC data access nodes available.</p>
<p>But getting the data is just the beginning, it's the methods and considerations you need to make that can make the difference between success and failure. Read on...</p>
<h3 id="data-consistency" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/modernize-your-legacy-industrial-data-part2/#data-consistency"># </a> Data consistency</h3>
<p>An often overlooked aspect of working with legacy industrial data is the consistency of the data being read. In the context of this article, consistency means that the multiple values that make up a related data set are read in a way that they are all valid to one another at the point in time it was read.</p>
<p>Let's take a look at a simple example. We have a process PLC recording production metrics and wish to get this data from its Modbus interface for reporting and decision making. The PLC has 5 values that we need to read:</p>
<table>
<thead>
<tr>
<th>Register</th>
<th>Value</th>
<th>Description</th>
<th>Data Type</th>
</tr>
</thead>
<tbody>
<tr>
<td>1, 2</td>
<td>10</td>
<td>Part Count</td>
<td>UINT32</td>
</tr>
<tr>
<td>3, 4</td>
<td>2.5</td>
<td>Cycle Time (sec)</td>
<td>UINT32/100</td>
</tr>
<tr>
<td>5, 6</td>
<td>30</td>
<td>Production Time (sec)</td>
<td>UINT32/100</td>
</tr>
<tr>
<td>7, 8</td>
<td>20</td>
<td>Run Time (sec)</td>
<td>UINT32/100</td>
</tr>
<tr>
<td>9, 10</td>
<td>11</td>
<td>Stoppage Time (sec)</td>
<td>UINT32/100</td>
</tr>
</tbody>
</table>
<p>In the above data sample, we can see the total production time is 30 seconds and the run time is 20 seconds. The expectation is that the Stoppage Time should be 10 seconds. However, as we can see, Stoppage Time in this sample is 11 seconds. That is because this data is not consistent.</p>
<h4 id="why-is-the-data-inconsistent%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/modernize-your-legacy-industrial-data-part2/#why-is-the-data-inconsistent%3F"># </a> Why is the data inconsistent?</h4>
<p>The most common reason for the data inconsistency is that the data is being read from the PLC while the PLC is running. The data is changing as it is being read.</p>
<p>Typically this happens when a developer, unfamiliar with the protocol or end device, begins by reading the data individually. Here is how this journey might look:</p>
<p><em>Image 1: individual reads</em>
<picture><source type="image/avif" srcset="https://flowfuse.com/img/industrial-legacy-data-pt2-demo1-Rg1l2Ra-Yu-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/industrial-legacy-data-pt2-demo1-Rg1l2Ra-Yu-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="image showing 10 individual reads" loading="lazy" decoding="async" src="https://flowfuse.com/img/industrial-legacy-data-pt2-demo1-Rg1l2Ra-Yu-650.jpeg" width="650" height="466" /></picture></p>
<p>That is a lot of nodes and a lot of duplication!</p>
<p>What is worse, is that the developer continues down this path and begins converting the data ready for publishing to MQTT. Here is how this might evolve:</p>
<p><em>Image 2: individual reads with data processing</em>
<picture><source type="image/gif" srcset="https://flowfuse.com/img/industrial-legacy-data-pt2-10polls-6_DbG3YIuA-650.gif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Image showing 10 individual reads with data processing" loading="lazy" decoding="async" src="https://flowfuse.com/img/industrial-legacy-data-pt2-10polls-6_DbG3YIuA-650.webp" width="650" height="431" /></picture></p>
<p>Yippie! We have the data, it works, we publish it to MQTT, job done. Right?</p>
<p>Unfortunately, no. The data is inconsistent.</p>
<h4 id="so-whats-the-big-deal%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/modernize-your-legacy-industrial-data-part2/#so-whats-the-big-deal%3F"># </a> So whats the big deal?</h4>
<p>Inconsistent data is not useful data and errors can get compounded over time. This leads to bad decisions being made and a loss of confidence in the data. Ultimately, this leads to the data being ignored and the opportunities to make improvements are lost. Loss of improvements means loss of money!</p>
<p>Not only that, from a developer or maintainers perspective, it has many problems:</p>
<ol>
<li>Lots of error prone manual configuration (yes, I made several mistakes while creating the example)</li>
<li>Hard coded register addresses</li>
<li>Duplication</li>
<li>Inextensible - what if we need to read more registers?</li>
<li>Inconsistent data - as discussed above</li>
<li>Slow - each read takes time</li>
<li>Inefficient use of network bandwidth - each read requires a request and response packet</li>
</ol>
<h4 id="how-can-we-make-the-data-consistent%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/modernize-your-legacy-industrial-data-part2/#how-can-we-make-the-data-consistent%3F"># </a> How can we make the data consistent?</h4>
<p>The most obvious solution is to stop the PLC before reading the data.
However, I am faily certain your boss will not be super pleased with stopping the manufacturing process.
The next best thing is for the PLC to sample and store the data in an internal memory buffer, waiting, unchanging, to be collected. Unfortunately, this too is not always possible either due to limited in-house skills, locked down PLCs or simply because the PLC does not have the memory to store the data.</p>
<p>The next best thing to do is to read relative data as quickly as possible and in one block.</p>
<h4 id="a-quick-side-bar-(timing-is-...-everything)" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/modernize-your-legacy-industrial-data-part2/#a-quick-side-bar-(timing-is-...-everything)"># </a> A quick side-bar (timing is ... everything)</h4>
<p>In many protocols, including Modbus, data must be polled. Each poll, depending on many factors, can take a number of milliseconds.</p>
<p>Lets say, on a relatively quiet serial network, a single register poll takes 25 milliseconds (assume 9600 baud, 1 byte/ms, request packet size 8 bytes, response packet size 7 bytes, 10ms latency for the PLC to receive, process and respond to the request)</p>
<ul>
<li>If we read 10 registers individually, then the time taken to read the 10 registers is 250 milliseconds.</li>
<li>If we actually needed a more realistic number of registers, say 32, then the time taken to read them individually is a whopping 800 milliseconds. In the world of PLCs, that is an eternity.</li>
</ul>
<p>Now, lets look at that from a different approach. If we were to read the 32 registers in one go, the time taken based on the above constants would be 87 milliseconds. That is over 9 times faster than reading the registers individually. The improvements don't stop there either, the number of total bytes transferred on your network is reduced by 84% and, more importantly, the data is consistent since it was read from the same scan of the PLC scan.</p>
<p><em>Image 3: A comparison of individual reads vs block reads</em>
<picture><source type="image/avif" srcset="https://flowfuse.com/img/industrial-legacy-data-pt2-table-1ZaRnlRt2W-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/industrial-legacy-data-pt2-table-1ZaRnlRt2W-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="A data table comparing polls vs block read" loading="lazy" decoding="async" src="https://flowfuse.com/img/industrial-legacy-data-pt2-table-1ZaRnlRt2W-650.jpeg" width="650" height="118" /></picture></p>
<p>OK, back to the topic at hand.</p>
<h3 id="getting-the-data-in-a-more-consistent-way" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/modernize-your-legacy-industrial-data-part2/#getting-the-data-in-a-more-consistent-way"># </a> Getting the data in a more consistent way</h3>
<p>Here is the same example as above but this time we are reading the data in one go:</p>
<p><em>Image 4: Getting data in one block</em>
<picture><source type="image/avif" srcset="https://flowfuse.com/img/industrial-legacy-data-pt2-demo1b-YS5YTJEG-Y-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/industrial-legacy-data-pt2-demo1b-YS5YTJEG-Y-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="image showing 1 read for 10 registers" loading="lazy" decoding="async" src="https://flowfuse.com/img/industrial-legacy-data-pt2-demo1b-YS5YTJEG-Y-650.jpeg" width="650" height="348" /></picture></p>
<p>Note how much simpler this is? Not only that, it is easier to maintain, faster, more extensible and most importantly, the data is consistent.</p>
<p>Great, lets move on.</p>
<h3 id="processing-the-data-in-readiness-for-iiot%3A-mqtt" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/modernize-your-legacy-industrial-data-part2/#processing-the-data-in-readiness-for-iiot%3A-mqtt"># </a> Processing the data in readiness for IIoT: MQTT</h3>
<p>Now that we have good data, we need to process it in readiness for IIoT. In this example, we are going to publish the data to an MQTT broker as individual topics. This is a common approach as it allows the data to be easily consumed by other systems and applications. Using <code>node-red-contrib-buffer-parser</code> we can easily convert the data into more meaningful formats.</p>
<p>The first, instinctive approach is to fan out the data and process it individually:</p>
<p><em>Image 5: block reads, individual processing</em>
<picture><source type="image/gif" srcset="https://flowfuse.com/img/industrial-legacy-data-pt2-1poll-fixed-8MQZ8FpStS-650.gif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="image showing 1 modbus poll with individual processing" loading="lazy" decoding="async" src="https://flowfuse.com/img/industrial-legacy-data-pt2-1poll-fixed-8MQZ8FpStS-650.webp" width="650" height="446" /></picture></p>
<p>This may be fine for a handful of registers but it soon becomes unwieldy and unmaintainable.</p>
<p>But lets be smarter about this. We know that the data is consistent and we know that we can read it in one go. So, lets process it in one go too:</p>
<p><em>Image 6: block reads, smart processing, no-code solution</em>
<picture><source type="image/gif" srcset="https://flowfuse.com/img/industrial-legacy-data-pt2-1poll-extensible-wws3PDBqV--650.gif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="image showing 1 modbus poll with smart processing" loading="lazy" decoding="async" src="https://flowfuse.com/img/industrial-legacy-data-pt2-1poll-extensible-wws3PDBqV--650.webp" width="650" height="455" /></picture></p>
<h4 id="wrap-up" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/modernize-your-legacy-industrial-data-part2/#wrap-up"># </a> Wrap up</h4>
<p>I hope this article has given you some food for thought and some ideas on not only simplifying your journey to IIoT but also the pitfalls to avoid along the way.</p>
<p>A parting thought, there are times when the data is not contiguous. There are ways to deal with this too but that is for another day.</p>
<p>P.S. I will post the flows used for the examples above in the comments below. If you have any questions or comments, please reach out there too.</p>
https://flowfuse.com/blog/2023/09/tulip-event-report/Tulip Operation Calling Event ReportThoughts and insighs from Tulip's recent customer event2023-09-14T00:00:00Z<p>This week I attended the Tulip event called <a href="https://www.operationscalling.com/">Operations Calling</a> in Boston. Here are some quick observations from the event.</p>
<!--more-->
<p>For those that might not know <a href="https://tulip.co/">Tulip</a>, they are a Boston based company focused on frontline operations in the manufacturing and industrial automation industry. They provide the software to help factory workers be more efficient at their job. Some people refer to this category as MES but Tulip avoids this term since MES can carry a lot of negative baggage from legacy MES vendors.</p>
<p>Some quick thoughts on the event:</p>
<ul>
<li>I would estimate about 300 people attended the event. It was held at Tulip’s office, which is actually in an old Ford factory. The offices and environment were very cool.</li>
<li>There was a large emphasis on Tulip partners and the ecosystem. Tulip knows it needs to be open and play well with others. There were 27 different vendors showing in their partner pavillion. Pretty impressive given the size of Tulip.</li>
<li>Tulip has a no-code environment for setting up their software. However, they realize you also need low-code, like Node-RED, for integrating hardware and software into Tulip. I attended two sessions that discussed how Node-RED is an important part of the Tulip integration and customization strategy. Node-RED was also being used in some of their demos stations.</li>
<li>Tulip talks about ‘citizen developers’ and ‘composable apps’. This is the future of manufacturing. Organizations need to start thinking in terms of smaller applications that do a specific task that can also be rolled up into something bigger at a later time. These small applications need to be developed by the people closest to the problem, not the IT team or a system integrator.</li>
<li>During the closing panel, it was stated that ‘Today, Excel is the most popular digital automation platform used in industry.’ There are a lot of spreadsheets being used to collect and visualize data. However, the industry needs to find a better way. Node-RED is an important part of the solution. The people who can run Excel spreadsheets can easily use Node-RED. However, using Node-RED will let them do even more than what Excel allows them to do.</li>
</ul>
<p>Operation Calling was definitely an event worth attending and I hope to return next year.</p>
https://flowfuse.com/blog/2023/09/modernize-your-legacy-industrial-data/Modernize your legacy industrial dataWorking with legacy industrial protocol data from the likes of Modbus and older, non IIoT protocols and putting it to work in an IIoT world.2023-09-14T00:00:00ZSteve McLaughlin<p>In today's rapidly evolving industrial landscape, the ability to collect, analyse, and act upon data is more critical than ever.
The Industrial Internet of Things (IIoT) has ushered in a new era of connectivity and automation, but what about the wealth of data locked away in legacy industrial protocols like Modbus?
How can we unlock and make sense of this valuable information in <em>any</em> data, e.g. serial comms with no protocol, Siemens S7, Omron Fins, Mitsubishi MC-Protocol, or Allen Bradley DF1, etc.
in the IIoT era? That's where tools like Node-RED and <code>node-red-contrib-buffer-parser</code> come into play.</p>
<!--more-->
<h3 id="legacy-industrial-data%3A-modbus" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/modernize-your-legacy-industrial-data/#legacy-industrial-data%3A-modbus"># </a> Legacy Industrial Data: Modbus</h3>
<p>Modbus is one of the most widely used industrial protocols. Originally developed in the late 1970s, it has been a popular choice for industrial communication ever since. However, its data format can be challenging to work with in the context of modern IIoT applications. Modbus typically represents data in 16-bit unsigned registers, making it necessary to convert this data into more usable formats like Signed integer, Float, Signed and Unsigned Long, String, or even individual bits.</p>
<h3 id="a-short-primer-on-data-types" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/modernize-your-legacy-industrial-data/#a-short-primer-on-data-types"># </a> A short primer on data types</h3>
<p>Before we dive into how to make sense of Modbus data, let's take a quick look at some of the common data types we have to deal with.</p>
<h4 id="16-bit-unsigned" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/modernize-your-legacy-industrial-data/#16-bit-unsigned"># </a> 16-bit unsigned</h4>
<p>16-bit unsigned data is an integer that can only be positive. It can represent values from 0 to 65535. For example, the number 12345 is represented as <code>0x3039</code> in hexadecimal or <code>0011000000111001</code> in binary.</p>
<h4 id="16-bit-signed" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/modernize-your-legacy-industrial-data/#16-bit-signed"># </a> 16-bit signed</h4>
<p>16-bit signed data is an integer that can be positive or negative. It can represent values from -32768 to 32767. For example, the number -12345 is represented as <code>0xCFC7</code> in hexadecimal or <code>1100111111000111</code> in binary.</p>
<h4 id="32-bit-data" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/modernize-your-legacy-industrial-data/#32-bit-data"># </a> 32-bit data</h4>
<p>32-bit data, like 16-bit data can mean many things. It could be signed or unsigned, or even a floating point number. For example, the number 12345 is represented as <code>0x00003039</code> in hexadecimal or <code>00000000000000000011000000111001</code> in binary. Typically, 32-bit data is represented as two 16-bit registers. Therefore, when dealing with 32-bit data, you need to combine two 16-bit registers to get the full value.</p>
<h4 id="endianness" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/modernize-your-legacy-industrial-data/#endianness"># </a> Endianness</h4>
<p>Endianness, particularly in the context of data communications, refers to the order of bytes and how they are stored or transmitted. There are two types of endianness: big-endian (BE) and little-endian (LE). In big-endian, the most significant byte is first, while in little-endian, the least significant byte is first. For example, the number 12345 is represented as <code>0x3039</code> in a big-endian word and <code>0x3930</code> in little-endian word. This can often cause confusion and complicate the process of converting Modbus data into more usable formats.</p>
<h3 id="node-red-and-node-red-contrib-buffer-parser-to-the-rescue" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/modernize-your-legacy-industrial-data/#node-red-and-node-red-contrib-buffer-parser-to-the-rescue"># </a> Node-RED and node-red-contrib-buffer-parser to the rescue</h3>
<p>Node-RED is an open-source flow-based development tool for visual programming. It's particularly well-suited for IIoT applications because of its versatility and extensive library of nodes. One such node, <code>node-red-contrib-buffer-parser</code>, provides a solution to the legacy data conversion challenge.</p>
<p>This powerful Node-RED module allows you to parse a Buffer of bytes or an Array of integer data (which, by no coincidence, the popular module <code>node-red-contrib-modbus</code> outputs), and convert it into various data types. It can output pretty much any data type, including byte-swapped data, WORD swapped data, masked/shifted/scaled data, and even individual bits.</p>
<p>Here's a quick overview of how it works:</p>
<ol>
<li>
<p><strong>Data Parsing</strong>: Start by setting up a Modbus READ node in Node-RED to retrieve data from your industrial device. Then, use the buffer parser node to parse the Modbus data.</p>
</li>
<li>
<p><strong>Data Conversion</strong>: With the buffer parser, you can easily convert the 16-bit unsigned data into more meaningful formats. Whether you need to translate it into Float, Long, String, or even extract specific bits, this tool makes the process straightforward.</p>
</li>
<li>
<p><strong>Publishing to MQTT, influxDB, a dashboard, an IIoT system</strong>: Once your data is in a usable format, Node-RED enables you to publish it to many places. MQTT (Message Queuing Telemetry Transport), a popular protocol for IIoT communication is a perfect example. This makes your data accessible to other IIoT systems and applications for further analysis and action.</p>
</li>
</ol>
<h3 id="unlocking-the-potential-of-legacy-data" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/modernize-your-legacy-industrial-data/#unlocking-the-potential-of-legacy-data"># </a> Unlocking the Potential of Legacy Data</h3>
<p>By leveraging Node-RED and buffer parser, you can bridge the gap between legacy industrial protocols and the IIoT world. This means you can extract valuable insights from your existing infrastructure without the need for costly hardware upgrades or replacements.</p>
<p>In the era of the Industrial Internet of Things, making sense of your industrial data is no longer a daunting challenge. With the right tools approach, you can unlock the full potential of your legacy data and drive efficiency, productivity, and innovation in your industrial processes. Yey!</p>
<h3 id="3-quick-demos-of-node-red-and-the-buffer-parser-node-in-action" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/modernize-your-legacy-industrial-data/#3-quick-demos-of-node-red-and-the-buffer-parser-node-in-action"># </a> 3 quick demos of Node-RED and the buffer parser node in action</h3>
<p>Here are 3 quick demonstrations that barely scratch the surface of possibilities:</p>
<h4 id="example-1%3A-modbus-to-mqtt" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/modernize-your-legacy-industrial-data/#example-1%3A-modbus-to-mqtt"># </a> Example 1: Modbus to MQTT</h4>
<p>Converting an array of 16-bit unsigned integers to String, Float and a scaled integer and passing them to an MQTT broker in 4 nodes!
<picture><source type="image/webp" srcset="https://flowfuse.com/img/industrial-legacy-data-to-mqtt-JkpUlp_dyS-650.webp 650w, https://flowfuse.com/img/industrial-legacy-data-to-mqtt-JkpUlp_dyS-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/gif" srcset="https://flowfuse.com/img/industrial-legacy-data-to-mqtt-JkpUlp_dyS-650.gif 650w, https://flowfuse.com/img/industrial-legacy-data-to-mqtt-JkpUlp_dyS-1300.gif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Legacy data to MQTT" loading="lazy" decoding="async" src="https://flowfuse.com/img/industrial-legacy-data-to-mqtt-JkpUlp_dyS-650.webp" width="1300" height="310" /></picture></p>
<h4 id="example-2%3A-modbus-to-influxdb" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/modernize-your-legacy-industrial-data/#example-2%3A-modbus-to-influxdb"># </a> Example 2: Modbus to InfluxDB</h4>
<p>Converting an array of 16-bit unsigned integers to String, Float and a scaled integer for publishing to influxDB!
<picture><source type="image/avif" srcset="https://flowfuse.com/img/industrial-legacy-data-to-influx-4f0_LkwORM-650.avif 650w, https://flowfuse.com/img/industrial-legacy-data-to-influx-4f0_LkwORM-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/industrial-legacy-data-to-influx-4f0_LkwORM-650.webp 650w, https://flowfuse.com/img/industrial-legacy-data-to-influx-4f0_LkwORM-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/industrial-legacy-data-to-influx-4f0_LkwORM-650.jpeg 650w, https://flowfuse.com/img/industrial-legacy-data-to-influx-4f0_LkwORM-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Legacy data to influxDB" loading="lazy" decoding="async" src="https://flowfuse.com/img/industrial-legacy-data-to-influx-4f0_LkwORM-650.jpeg" width="1300" height="268" /></picture>
<picture><source type="image/avif" srcset="https://flowfuse.com/img/industrial-legacy-data-to-influx2-MUgdhB-Lfz-650.avif 650w, https://flowfuse.com/img/industrial-legacy-data-to-influx2-MUgdhB-Lfz-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/industrial-legacy-data-to-influx2-MUgdhB-Lfz-650.webp 650w, https://flowfuse.com/img/industrial-legacy-data-to-influx2-MUgdhB-Lfz-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/industrial-legacy-data-to-influx2-MUgdhB-Lfz-650.jpeg 650w, https://flowfuse.com/img/industrial-legacy-data-to-influx2-MUgdhB-Lfz-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Legacy data to influxDB2" loading="lazy" decoding="async" src="https://flowfuse.com/img/industrial-legacy-data-to-influx2-MUgdhB-Lfz-650.jpeg" width="1300" height="692" /></picture></p>
<h4 id="example-3%3A-modbus-data-on-a-dashboard" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/modernize-your-legacy-industrial-data/#example-3%3A-modbus-data-on-a-dashboard"># </a> Example 3: Modbus data on a dashboard</h4>
<p>Converting an array of 16-bit unsigned integers to String, Float and a scaled integer for publishing to a dashboard!
<picture><source type="image/avif" srcset="https://flowfuse.com/img/industrial-legacy-data-to-dashboard-85RdTa3-n6-650.avif 650w, https://flowfuse.com/img/industrial-legacy-data-to-dashboard-85RdTa3-n6-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/industrial-legacy-data-to-dashboard-85RdTa3-n6-650.webp 650w, https://flowfuse.com/img/industrial-legacy-data-to-dashboard-85RdTa3-n6-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/industrial-legacy-data-to-dashboard-85RdTa3-n6-650.jpeg 650w, https://flowfuse.com/img/industrial-legacy-data-to-dashboard-85RdTa3-n6-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Legacy data to dashboard" loading="lazy" decoding="async" src="https://flowfuse.com/img/industrial-legacy-data-to-dashboard-85RdTa3-n6-650.jpeg" width="1300" height="687" /></picture></p>
<h3 id="learn-more" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/modernize-your-legacy-industrial-data/#learn-more"># </a> Learn More</h3>
<p>We will be publishing follow-up blog posts with more details, best practices and examples on how to use Node-RED to make sense of your industrial data. In the meantime, you can learn more about these tools by visiting the following links:</p>
<ul>
<li><a href="https://flowfuse.com/blog/node-red/">Node-RED blog posts</a></li>
<li><a href="https://www.youtube.com/playlist?list=PLpcyqc7kNgp09XeRx_cae1fEIOloPqM1C">Node-RED videos</a></li>
<li><a href="https://flows.nodered.org/node/node-red-contrib-buffer-parser">Buffer Parser Node</a></li>
</ul>
https://flowfuse.com/blog/2023/09/community-news-09/Community News September 2023Your monthly update for the FlowFuse and Node-RED communities2023-09-09T00:00:00Z<p>Welcome to the FlowFuse newsletter for September 2023, a monthly roundup of what’s been happening with FlowFuse and the wider Node-RED community.</p>
<h2 id="new-name" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/community-news-09/#new-name"># </a> New Name</h2>
<p>The big news this month is that <a href="https://flowfuse.com/blog/2023/08/flowforge-is-now-flowfuse/">FlowForge is now FlowFuse</a>. Yes, we have changed our name but we are still focus on delivering great products for the Node-RED community.</p>
<!--more-->
<h2 id="new-releases" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/community-news-09/#new-releases"># </a> New Releases</h2>
<ul>
<li>Node-RED 3.1 has been <a href="https://nodered.org/blog/2023/09/06/version-3-1-released">released</a>. Among the changes are Mermaid chart support, locking flows, and much more.</li>
<li>Last week, FlowFuse 1.11 was released. This release included personal access tokens for FlowFuse API and new tiers for FlowFuse Cloud, including a new starter tier. Check out the details in our <a href="https://flowfuse.com/blog/2023/08/flowfuse-1-11-release/">announcement</a>.</li>
</ul>
<h2 id="upcoming-events" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/community-news-09/#upcoming-events"># </a> Upcoming events</h2>
<h3 id="celebrate-10-years-of-node-red-and-what%E2%80%99s-new-in-3.1-and-beyond" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/community-news-09/#celebrate-10-years-of-node-red-and-what%E2%80%99s-new-in-3.1-and-beyond"># </a> Celebrate 10 Years of Node-RED and What’s New in 3.1 and Beyond</h3>
<p>Hard to believe that Node-RED was launched 10 years ago. We want to celebrate this great accomplishment and also show off the new Node-RED 3.1 release. Join Nick O'Leary for the 10 year celebration and here what is coming next.</p>
<p><a href="https://flowfuse.com/webinars/2023/node-red-10-years/">Sign-up today</a> to join us on September 21.</p>
<h2 id="from-our-blog" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/community-news-09/#from-our-blog"># </a> From our Blog</h2>
<ul>
<li>
<p>The Node-RED Dashboard 2.0 project is making excellent progress. Two updates were published in the last month. Make sure you check out the latest release and provide feedback.</p>
<ul>
<li><a href="https://flowfuse.com/blog/2023/09/dashboard-notebook-layout/">Dynamic Markdown, Tables & Notebooks with Dashboard 2.0</a></li>
<li><a href="https://flowfuse.com/blog/2023/08/dashboard-community-update/">Dashboard 2.0 - Community Update</a></li>
</ul>
</li>
<li>
<p><a href="https://flowfuse.com/blog/2023/09/bosch-rexroth-announce/">FlowFuse announces a Node-RED stack for Industry 4.0 applications on Bosch Rexroth ctrlX Automation</a> - a fully supported Node-RED stack for Bosch customers.</p>
</li>
<li>
<p><a href="https://flowfuse.com/blog/2023/08/aws-marketplace-announce/">FlowFuse is now available on the AWS Marketplace</a> - making it easier to run FlowFuse on the AWS cloud.</p>
</li>
<li>
<p><a href="https://flowfuse.com/blog/2023/08/open-source-is-a-tier-not-competition/">Our Open Source offering is a tier, not our competition</a> - some insight from our CEO into our open source strategy.</p>
</li>
<li>
<p><a href="https://flowfuse.com/blog/2023/08/isa-95-automation-pyramid-to-unified-namespace/">Why the Automation Pyramid blocks digital transformation - The Role of Unified Namespace</a> - some insight from the FlowFuse product manager into the role of a Unified Namespace.</p>
</li>
</ul>
<h2 id="from-the-community" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/community-news-09/#from-the-community"># </a> From the Community</h2>
<ul>
<li>A new plugin for the generation of <a href="https://flows.nodered.org/node/@node-red-matter/node-red-matter">Matter devices witin Node-RED</a> has been published.</li>
</ul>
<h2 id="join-our-team" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/community-news-09/#join-our-team"># </a> Join Our Team</h2>
<p>FlowFuse is expanding our team. Check out the current openings:</p>
<ul>
<li><a href="https://boards.greenhouse.io/flowfuse/jobs/4911532004">Contract Front-End Engineer – Node-RED Dashboard</a></li>
<li><a href="https://boards.greenhouse.io/flowfuse/jobs/4958271004">Developer Relations Engineer - Manufacturing & Industrial Automation</a></li>
</ul>
https://flowfuse.com/blog/2023/09/bosch-rexroth-announce/FlowFuse announces a Node-RED stack for Industry 4.0 applications on ctrlX AUTOMATIONRexroth ctrlX now have fully supported Node-RED stack available for production use2023-09-07T00:00:00Z<p>FlowFuse is pleased to announce they are now offering Node-RED plus select third party nodes from the Bosch Rexroth ctrlX World marketplace.</p>
<!--more-->
<p>FlowFuse is pleased to announce they are now offering Node-RED plus select third party nodes from the <a href="https://developer.community.boschrexroth.com/t5/Store-and-How-to/FlowFuse-Node-RED/ba-p/82135">Bosch Rexroth ctrlX Store</a> marketplace. Rexroth customers building Industry 4.0 applications will now have a trusted vendor, in FlowFuse, to provide support and updates for using open source Node-RED in production. By partnering with FlowFuse, customers can reduce their risk of using Node-RED in production by relying upon FlowFuse Node-RED experts to assist with any development or production issues.</p>
<p><a href="https://nodered.org/">Node-RED</a> is a popular open source low-code development environment widely used in industries for collecting and processing industrial data to deliver Industry 4.0 applications. FlowFuse is uniquely positioned to partner with ctrlX customers looking to use Node-RED in production. FlowFuse CTO Nick O’Leary is the co-creator and project leader of Node-RED. FlowFuse employs many Node-RED experts who have years of experience helping customers with successful deployment of Node-RED applications.</p>
<p>The FlowFuse package offered in the ctrlX World marketplace will provide ctrlX customers the following benefits:</p>
<ul>
<li>Support for Node-RED development and production deployments</li>
<li>Support for third party nodes of popular industrial protocols including: Modbus, OMRON, S7 and MC Protocol.</li>
</ul>
<p>FlowFuse is the only vendor providing professional technical support for Node-RED on the ctrlX platform.</p>
<p>The package is available today at ctrlX World. Interested customers should contact their Rexroth sales representative for purchasing details. Interested customers can also contact FlowFuse directly at <a href="mailto:sales@flowfuse.com">sales@flowfuse.com</a> for additional information about the offering.</p>
https://flowfuse.com/blog/2023/09/dashboard-notebook-layout/Dynamic Markdown, Tables & Notebooks with Dashboard 2.0A dive into the new features available in 0.4.0 - The "Notebook" Layout and new dynamic Markdown & Table widgets.2023-09-06T00:00:00ZJoe Pavitt<p>Whilst we're still busy backporting through the existing Dashboard 1.0 features, we did want to highlight some new features we've built in Dashboard 2.0 released this week.</p>
<!--more-->
<p>In our v0.4.0 release, we've introduced a new "Notebook" layout, alongside a new Table widget.</p>
<p>The Notebook layout is designed to allow users to create Dashboards structured like a Notebook (most often seen with the likes of <a href="https://jupyter.org/">Jupyter Notebooks</a> or <a href="https://observablehq.com/">ObservableHQ</a>).</p>
<p>Here we will deepdive into the Notebook layout, and show how, alongside our new <strong>Markdown Node</strong> (<a href="https://dashboard.flowfuse.com/nodes/widgets/ui-markdown.html">docs</a>), <strong>Table Node</strong> (<a href="https://dashboard.flowfuse.com/nodes/widgets/ui-table.html">docs</a>) and others, it's becoming easier to create dynamic and interactive Dashboards.</p>
<p><em>Note: If you're not familiar with Markdown, it's a simple markup language that allows you to format text. You can learn more about it <a href="https://www.markdownguide.org/cheat-sheet/">here</a>.</em></p>
<h2 id="dashboard-hierarchy" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/dashboard-notebook-layout/#dashboard-hierarchy"># </a> Dashboard Hierarchy</h2>
<p>As a quick introductory note ahead of our below guide, each Dashboard is structured accordingly:</p>
<ul>
<li><strong>Widget</strong>: An individual functional block, e.g. button, chart, slider</li>
<li><strong>Group</strong>: A collection of widgets that render together</li>
<li><strong>Page</strong>: A single page/tab in your Dashboard. Each page can have it's own Layout, in this case we'll use "Notebook"</li>
<li><strong>UI</strong>: Contains a collection of pages, deployed from Node-RED, provides the basic side navigation to switch between Pages.</li>
</ul>
<h2 id="building-a-notebook" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/dashboard-notebook-layout/#building-a-notebook"># </a> Building a Notebook</h2>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/db-notebook-example-owO0_T3fAc-650.avif 650w, https://flowfuse.com/img/db-notebook-example-owO0_T3fAc-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/db-notebook-example-owO0_T3fAc-650.webp 650w, https://flowfuse.com/img/db-notebook-example-owO0_T3fAc-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/db-notebook-example-owO0_T3fAc-650.jpeg 650w, https://flowfuse.com/img/db-notebook-example-owO0_T3fAc-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Example Notebook created in Dashboard" loading="lazy" decoding="async" src="https://flowfuse.com/img/db-notebook-example-owO0_T3fAc-650.jpeg" width="1300" height="748" /></picture></p>
<p>To get started, drop your first widget (in this case, we'll add a <code>ui-markdown</code>) onto the Node-RED canvas. This in turn will prompt us to create our first Group/Page/Dashboard which we can name and configure accordingly.</p>
<p>Let's add the following Markdown to our first widget:</p>
<div style="position: relative">
<pre class="language-md"><code id="code-56" class="language-md"><span class="token title important"><span class="token punctuation">#</span> Markdown Content</span><br /><br />Here we can render dynamic Markdown content that is<br />easily <span class="token italic"><span class="token punctuation">_</span><span class="token content">styled</span><span class="token punctuation">_</span></span>.<br /><br /><br />We can inject <span class="token code-snippet code keyword">`msg.payload`</span>. For example, here is a<br />timestamp updating every second: {{ msg.payload }}<br /></code></pre>
<button class="code-copy " data-clipboard-target="#code-56" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>The joy of <code>ui-markdown</code> in Dashboard 2.0 is <em>dynamic</em> content, i.e. content that can be updated by passing messages to the <code>ui-markdown</code> node. We can wire an <code>inject</code> node, set it up to repeat every second, and connect it to <code>ui-markdown</code>. Now, our Markdown content will automatically update show this value.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/db-notebook-inject-II6FdXD8Rs-650.avif 650w, https://flowfuse.com/img/db-notebook-inject-II6FdXD8Rs-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/db-notebook-inject-II6FdXD8Rs-650.webp 650w, https://flowfuse.com/img/db-notebook-inject-II6FdXD8Rs-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/db-notebook-inject-II6FdXD8Rs-650.jpeg 650w, https://flowfuse.com/img/db-notebook-inject-II6FdXD8Rs-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Screenshot to show how an inject node can drive content of a ui-markdown node" loading="lazy" decoding="async" src="https://flowfuse.com/img/db-notebook-inject-II6FdXD8Rs-650.jpeg" width="1300" height="919" /></picture></p>
<p>Resulting in:</p>
<p><picture><source type="image/webp" srcset="https://flowfuse.com/img/md-timestamp-xxFVIvAA41-650.webp 650w, https://flowfuse.com/img/md-timestamp-xxFVIvAA41-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/gif" srcset="https://flowfuse.com/img/md-timestamp-xxFVIvAA41-650.gif 650w, https://flowfuse.com/img/md-timestamp-xxFVIvAA41-1300.gif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Dynamic markdown with an updating timestamp every 1 second" loading="lazy" decoding="async" src="https://flowfuse.com/img/md-timestamp-xxFVIvAA41-650.webp" width="1300" height="314" /></picture></p>
<h2 id="adding-more-widgets" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/dashboard-notebook-layout/#adding-more-widgets"># </a> Adding More Widgets</h2>
<p>Because the Notebook is <em>just</em> a layout, we can still wire together any of the available widgets and existing nodes and display them accordingly.</p>
<p>Let's wire a <code>ui-button</code>, HTTP Request, and <code>ui-table</code> node. When we click the button, it will perform the HTTP request, and then render the response in the table.</p>
<p>For this, we're going to use the Random Jokes API, and in particular, a call to <code>https://official-joke-api.appspot.com/jokes/ten</code> which will return 10 random jokes.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/generate-jokes-flow-p2CormG-_Z-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/generate-jokes-flow-p2CormG-_Z-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Screenshot showing a simple Button > HTTP Request > Table flow" loading="lazy" decoding="async" src="https://flowfuse.com/img/generate-jokes-flow-p2CormG-_Z-650.jpeg" width="650" height="157" /></picture></p>
<p>We can also re-order the widgets on the page using the Dashboard 2.0 sidebar (as you could in Dashboard 1.0).</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/db-notebook-order-IlMATyXnac-650.avif 650w, https://flowfuse.com/img/db-notebook-order-IlMATyXnac-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/db-notebook-order-IlMATyXnac-650.webp 650w, https://flowfuse.com/img/db-notebook-order-IlMATyXnac-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/db-notebook-order-IlMATyXnac-650.jpeg 650w, https://flowfuse.com/img/db-notebook-order-IlMATyXnac-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Screenshot to show how an inject node can drive content of a ui-markdown node" loading="lazy" decoding="async" src="https://flowfuse.com/img/db-notebook-order-IlMATyXnac-650.jpeg" width="1300" height="1210" /></picture></p>
<p>The above effort results in the following output in our Notebook:</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/db-notebook-jokes-table-TTd0Taui34-650.avif 650w, https://flowfuse.com/img/db-notebook-jokes-table-TTd0Taui34-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/db-notebook-jokes-table-TTd0Taui34-650.webp 650w, https://flowfuse.com/img/db-notebook-jokes-table-TTd0Taui34-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/db-notebook-jokes-table-TTd0Taui34-650.jpeg 650w, https://flowfuse.com/img/db-notebook-jokes-table-TTd0Taui34-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Screenshot to show how an inject node can drive content of a ui-markdown node" loading="lazy" decoding="async" src="https://flowfuse.com/img/db-notebook-jokes-table-TTd0Taui34-650.jpeg" width="1300" height="1150" /></picture></p>
<h2 id="what-else-is-new-in-0.4.0%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/09/dashboard-notebook-layout/#what-else-is-new-in-0.4.0%3F"># </a> What else is new in 0.4.0?</h2>
<p>The above demonstrates just a few of the new features in the 0.4.0 Release, but we've also added <a href="https://github.com/FlowFuse/node-red-dashboard/releases/tag/v0.4.0">other fixes and improvements</a>. In particular, I want to call out Steve's great work on implementing custom class injection, the first of our new <a href="https://dashboard.flowfuse.com/user/dynamic-properties.html">"Dynamic Properties"</a>, of which there will be more (e.g. visibility, disabled, etc.) to come.</p>
<p>As always, thanks for reading and your interested in Dashboard 2.0. If you have any feature requests, bugs/complaints or general feedback, please do reach out, and raise issues on our relevant <a href="https://github.com/FlowFuse/node-red-dashboard">GitHub repository</a>.</p>
<ul>
<li><a href="https://github.com/orgs/FlowFuse/projects/15/views/1">Dashboard 2.0 Activity Tracker</a></li>
<li><a href="https://github.com/orgs/FlowFuse/projects/15/views/4">Dashboard 2.0 Planning Board</a></li>
</ul>
https://flowfuse.com/blog/2023/08/new-starter-tier/FlowFuse Cloud Starter package - The easiest way to get started with Node-REDIntroducing tiers and pricing changes for FlowFuse Cloud2023-08-31T00:00:00ZNick O'Leary<p>FlowFuse is used by businesses and hobbyists alike. We aim to provide a platform that meets the needs of both, recognizing the importance of hobbyists in the Node-RED community and the long term success of FlowFuse as a company. We want to make it as easy as possible for people to get started on FlowFuse Cloud and help them understand the full value the platform offers. One of the barriers we've seen has been the current pricing structure of FlowFuse Cloud.</p>
<!--more-->
<p>Since FlowFuse Cloud was introduced there’s been essentially one tier for everyone to adopt. Customers were charged $15 per month for each Node-RED instance managed by the FlowFuse platform, whether running in the cloud or on their own hardware using our Device Agent.</p>
<p>Today we’re introducing different tiers: Starter and Team. The Starter tier gives you access to 2 FlowFuse managed Node-RED instances, 2 Node-RED devices, with up to 2 team members - all for a flat rate of $15 per month.</p>
<p>The new Team tier unlocks more value to adopt FlowFuse in a professional environment and grow beyond the Starter tier. It’s well suited for teams up to 20 members, and includes increased limits for file storage and persistent context. It also unlocks some key features such as the shared Team Library and Project Nodes, used to seamlessly transport data between instances. Pricing starts at $25 per managed Node-RED instance and $15 per device.</p>
<p>We will soon be launching our third tier, more targeted at Enterprise users. This tier enhances the compliance capabilities through Single-Sign on (SSO), and provides higher SLA’s for both support and high availability for running Node-RED at scale.</p>
<p>We expect these layers to fit the customers as they grow in their FlowFuse and Node-RED adoption journey.</p>
<h2 id="faq" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/new-starter-tier/#faq"># </a> FAQ</h2>
<h3 id="do-you-have-an-overview-of-the-different-tiers%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/new-starter-tier/#do-you-have-an-overview-of-the-different-tiers%3F"># </a> Do you have an overview of the different tiers?</h3>
<p>Certainly, an overview of the tiers and prices are available at our <a href="https://flowfuse.com/pricing">pricing page</a>.</p>
<h3 id="how-do-i-upgrade-from-starter-to-team-tier%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/new-starter-tier/#how-do-i-upgrade-from-starter-to-team-tier%3F"># </a> How do I upgrade from Starter to Team tier?</h3>
<p>You can update your existing team to either tier via the ‘Change Team Type’ option under Team Settings.</p>
<h3 id="how-do-i-migrate-my-existing-team-to-the-newly-introduced-starter-package-or-team-tier%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/new-starter-tier/#how-do-i-migrate-my-existing-team-to-the-newly-introduced-starter-package-or-team-tier%3F"># </a> How do I migrate my existing team to the newly introduced Starter package or Team tier?</h3>
<p>You can update your existing team to either tier via the ‘Change Team Type’ option under Team Settings on the "Danger" tab.</p>
<h3 id="how-do-i-cancel-the-starter-package%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/new-starter-tier/#how-do-i-cancel-the-starter-package%3F"># </a> How do I cancel the Starter Package?</h3>
<p>Once you have deleted any instances, applications or devices in the team, you can delete the Team itself under the Team Settings section.</p>
<h3 id="i%E2%80%99m-self-hosting-flowfuse---do-these-changes-affect-me%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/new-starter-tier/#i%E2%80%99m-self-hosting-flowfuse---do-these-changes-affect-me%3F"># </a> I’m self-hosting FlowFuse - do these changes affect me?</h3>
<p>No, the new team tiers and pricing are on FlowFuse Cloud only.</p>
<h3 id="i%E2%80%99m-using-the-digitalocean%2Faws-marketplace-version---do-these-changes-affect-me%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/new-starter-tier/#i%E2%80%99m-using-the-digitalocean%2Faws-marketplace-version---do-these-changes-affect-me%3F"># </a> I’m using the DigitalOcean/AWS Marketplace version - do these changes affect me?</h3>
<p>No, the new team tiers and pricing are on FlowFuse Cloud only.</p>
<h3 id="anything-else%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/new-starter-tier/#anything-else%3F"># </a> Anything else?</h3>
<p>If you have any further questions, please <a href="https://flowfuse.com/contact-us/">contact us</a> and we’ll be happy to discuss.</p>
https://flowfuse.com/blog/2023/08/flowfuse-1-11-release/FlowFuse 1.11 makes it easier to get started with FlowFuse and Node-REDOur latest release includes a new starter tier for FlowFuse Cloud, Personal Access Tokens for API access and improvements to device management.2023-08-31T00:00:00Z<p>FlowFuse 1.11 introduces a new starter tier for FlowFuse Cloud that makes it easier to get started with FlowFuse and Node-RED.</p>
<!--more-->
<h2 id="new-flowfuse-cloud-starter-tier-%232328" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/flowfuse-1-11-release/#new-flowfuse-cloud-starter-tier-%232328"># </a> New FlowFuse Cloud Starter Tier <a href="https://github.com/FlowFuse/flowfuse/issues/2328">#2328</a></h2>
<p>It is now easier for Node-RED developers to get started with FlowFuse and Node-RED. The new starter tier allows developers to use two Node-RED instances and two remote device deployments. Ideal for creating proof of concepts or running a home automation system with Node-RED.</p>
<p>FlowFuse provides a cloud hosted version of Node-RED so developers don't need to worry about Node-RED installation or operation. This makes it a lot easier to get started with Node-RED and easier to maintain a running instance.</p>
<h2 id="flowfuse-api-access-now-possible-via-personal-access-tokens-%2314" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/flowfuse-1-11-release/#flowfuse-api-access-now-possible-via-personal-access-tokens-%2314"># </a> FlowFuse API access now possible via personal access tokens <a href="https://github.com/FlowFuse/flowfuse/issues/14">#14</a></h2>
<p>FlowFuse APIs are now accessible via personal access tokens (PAT). This makes it possible to create automation scripts that interact with the FlowFuse platform using the API and authenticate the scripts with the PAT.</p>
<h2 id="usability-improvements-to-device-management-%232294" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/flowfuse-1-11-release/#usability-improvements-to-device-management-%232294"># </a> Usability Improvements to Device Management <a href="https://github.com/FlowFuse/flowfuse/issues/2334">#2294</a></h2>
<p>A number of usability improvements have been added to the FlowFuse device management solution to make it more flexible and intuitive to use. These improvements include being able to associate devices at the application level allowing for easier editing of Node-RED instances on edge devices.</p>
<h2 id="flowfuse-rebranding-%23119" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/flowfuse-1-11-release/#flowfuse-rebranding-%23119"># </a> FlowFuse Rebranding <a href="https://github.com/orgs/FlowFuse/projects/1?pane=issue&itemId=34719640">#119</a></h2>
<p>Earlier in August, <a href="https://flowfuse.com/blog/2023/08/flowforge-is-now-flowfuse/">FlowForge announced</a> a change to our company and product name to FlowFuse. Work has begun to change the product branding to FlowFuse. The UI has been rebranded and the remaining points will be changed in the next release.</p>
<h2 id="other-new-features" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/flowfuse-1-11-release/#other-new-features"># </a> Other New Features</h2>
<ul>
<li>Add ability to add a description to an application and display it in the portal <a href="https://github.com/FlowFuse/flowfuse/issues/2279">#2279</a></li>
<li>UI Improvements to device management <a href="https://github.com/FlowFuse/flowfuse/issues/2427">#2427</a></li>
<li>Improve landing page for documentation <a href="https://github.com/FlowFuse/website/issues/842">#842</a></li>
<li>Restructure of user interface navigation <a href="https://github.com/FlowFuse/flowfuse/issues/2474">#2474</a></li>
</ul>
<h2 id="bug-fixes" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/flowfuse-1-11-release/#bug-fixes"># </a> Bug Fixes</h2>
<ul>
<li>Device running old snapshot <a href="https://github.com/FlowFuse/device-agent/issues/132">#132</a></li>
</ul>
<h2 id="what's-next%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/flowfuse-1-11-release/#what's-next%3F"># </a> What's next?</h2>
<p>We're always working to enhance your experience with FlowFuse. Here's how you can stay informed and contribute:</p>
<ul>
<li><strong>Roadmap Overview</strong>: Check out our <a href="https://flowfuse.com/product/roadmap/">Product Roadmap Page</a> to see what we're planning for future updates.</li>
<li><strong>Entire Roadmap</strong>: Visit our <a href="https://github.com/orgs/FlowFuse/projects/5">Roadmap on GitHub</a> to follow our progress and contribute your ideas.</li>
<li><strong>Feedback</strong>: We're interested in your thoughts about FlowFuse. Your feedback is crucial to us, and we'd love to hear about your experiences with the new features and improvements. Please share your thoughts, suggestions, or report any <a href="https://github.com/FlowFuse/flowfuse/issues/new/choose">issues on GitHub</a>.</li>
</ul>
<p>Together, we can make FlowFuse better with each release!</p>
<h2 id="try-it-out" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/flowfuse-1-11-release/#try-it-out"># </a> Try it out</h2>
<p>We're confident you can have self managed FlowFuse running locally in under 30 minutes.
You can install our <a href="https://flowfuse.com/docs/install/local/">local build</a>, use <a href="https://flowfuse.com/docs/install/docker/">Docker</a>, or <a href="https://flowfuse.com/docs/install/kubernetes/">Kubernetes</a>.</p>
<p>If you'd rather use our hosted offering: <a href="https://app.flowfuse.com/account/create">Get started for free</a> on FlowFuse Cloud.</p>
<h2 id="upgrading-flowfuse" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/flowfuse-1-11-release/#upgrading-flowfuse"># </a> Upgrading FlowFuse</h2>
<p><a href="https://app.flowfuse.com/">FlowFuse Cloud</a> is already running 1.11.</p>
<p>If you installed a previous version of FlowFuse and want to upgrade, our documentation provides a
guide for <a href="https://flowfuse.com/docs/upgrade/">upgrading your FlowFuse instance</a>.</p>
<h2 id="getting-help" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/flowfuse-1-11-release/#getting-help"># </a> Getting help</h2>
<p>Please check FlowFuse's <a href="https://flowfuse.com/docs/">documentation</a> as the answers to many questions are covered there. Additionally you can go to the <a href="https://discourse.nodered.org/c/vendors/flowfuse/24">community forum</a> if you have
any feedback or feature requests.</p>
https://flowfuse.com/blog/2023/08/aws-marketplace-announce/FlowFuse is now available on AWS MarketplaceMaking is easier to run Node-RED and FlowFuse on AWS Cloud2023-08-21T00:00:00Z<p>Many customers want to run FlowFuse in their own cloud environment, AWS being a great example. Today we're excited to announce that FlowFuse is now available from the <a href="https://aws.amazon.com/marketplace/pp/prodview-3ycrknfg67rug?sr=0-1&ref_=beagle&applicationId=AWSMPContessa">AWS Marketplace</a>. This makes it very easy for customers to install and run Node-RED and FlowFuse within minutes.</p>
<!--more-->
<p>FlowFuse allows organizations to reliably deliver Node-RED applications in a continuous, collaborative and secure manner. Customers running FlowFuse on AWS Cloud will benefit from FlowFuse's features, including:</p>
<ul>
<li>Team collaboration for Node-RED developers, allowing multiple developers to work together on a single Node-RED instance, including the ability to have an audit log of changes.</li>
<li>DevOps deliver pipelines that support a software development lifecycle for Node-RED development. Pipelines can be setup to establish development, test and production environments for Node-RED instances.</li>
<li>Snapshot of Node-RED instances to create a version history of changes to Node-RED applications. This also includes the ability to rollback to a previous version of a Node-RED instance.</li>
</ul>
<p>FlowFuse on the AWS Marketplace is available under the Apache License c2.0 open source license. Customers can use FlowFuse free of charge but will need to pay AWS EC2 usage for hosting FlowFuse. FlowFuse offers commercially licensed Premimum and Enterprise tiers that includes enterprise oriented features, including:</p>
<ul>
<li>24/7 technical support</li>
<li>Single Sign-on</li>
<li>High Availability for Node-RED applications</li>
<li>Remote device management</li>
</ul>
<p>Customers can easily upgrade to the premium or enterprise tier by obtaining a commercial license from FlowFuse. To understand what FlowFuse can do for your use-case, please <a href="https://flowfuse.com/book-demo">book a demo</a>.</p>
<p>FlowFuse on AWS Marketplace is available <a href="https://aws.amazon.com/marketplace/pp/prodview-3ycrknfg67rug?sr=0-1&ref_=beagle&applicationId=AWSMPContessa">immediately</a>. Please refer to our <a href="https://flowfuse.com/docs/install/docker/aws-marketplace/#installing-flowfuse-from-aws-market-place">documentation</a> and give it a try and let us know what you think.</p>
https://flowfuse.com/blog/2023/08/open-source-is-a-tier-not-competition/Our Open Source offering is a tier, not our competition2023-08-18T00:00:00ZZJ van de Weg<p>More than once we’ve been in discussion with prospective customers on what tier
is the right tier for their current Node-RED adoption. The question is likely to
come up "Why wouldn't we just use the open source version of FlowFuse?". The
implicit discussion created is one that is alike the question:
“Why wouldn’t we go with your competition?”. For FlowFuse, and most other open-core
companies like us, the open licensed and free to use core is tier, not competition.</p>
<!--more-->
<p>In the traditional sense, the prospective customer is right. By the definition,
a customer <strong>buys</strong> goods or services by exchanging it for <strong>money</strong>. For
FlowFuse’s open-source edition, which is free as in beer and free as in speech,
no money changes hands. It can be installed and run by anyone. Once the software
is being installed and used, we consider we've gained a new customer.
There’s an agreement in place, the Apache 2.0 license, and value is obtained by
the customer. The only missing component compared to an ‘ordinary’ sale is the lack
of money from the customer to FlowFuse. The fact that no monetary value is exchanged,
like the situation where a customer picks the competitor, doesn’t make the open
source tier competition. It is just a free tier.</p>
<p>Another reason it's really a tier is that the core of the product is the same. In
many open-core products, the path to upgrade from the open source license product to
the paid tier is much alike customers are used to on SaaS models. In the reals of
self-managed software that's mostly uploading a license and at times a few configuration
steps.</p>
<p>Furthermore, the open tier is a tier as the customer choses to not adopt all
capabilities. They're leaving value on the table. Either this is because it's not
quite clear what the value is or if the higher tiers provides
enough business value to warrant the expense. Or the adoption journey for the
customer doesn't yet require the full featured tiers.</p>
<p>What’s unique about open source software, is that customers can exchange value
towards the company and community building the software in other forms: by
opening issues, updating documentation, advocating for the OSS variant, among
other ways. While this is not <strong>money</strong>, it is significant for a young company
like FlowFuse.</p>
<h2 id="challenges-with-a-open-core-free-tier" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/open-source-is-a-tier-not-competition/#challenges-with-a-open-core-free-tier"># </a> Challenges with a open core free tier</h2>
<p>That's not to say that an open source tier is a silver bullet for a company. For
one, it's hard to track how many users a software package has, and who these users
are. For example; FlowFuse has <a href="https://flowfuse.com/docs/admin/telemetry/#usage-telemetry">Telemetry</a>,
though it can be turned off. Nor do we know who hosts this software.</p>
<p>Another challenge is around product and feature packaging. At FlowFuse and other open core companies it's
uncommon to move features from the open tier to paid tier only. If this choice has
been made it's a done deal, even when the product team got it wrong. Usually the
initial thoughts are therefor to move all features into the paid tiers. However,
this hampers long term growth as adoption of paid features are adopted later or
not at all. We follow the
<a href="https://opencoreventures.com/blog/2023-01-open-core-standard-pricing-model">Open-Core buyer based model</a>
to segregate the value, about which I'll write a post next time.</p>
<p>Photo by <a href="https://unsplash.com/@matthardy">Matt Hardy</a>.</p>
https://flowfuse.com/blog/2023/08/flowforge-is-now-flowfuse/FlowForge is now FlowFuseNew identity but same vision for industrial data integration2023-08-17T00:00:00ZZJ van de Weg<p>We are happy to announce that FlowForge is changing its name to FlowFuse. Changing our corporate identity wasn’t our top priority but a recent trademark challenge has promoted us to create a new brand for our company.</p>
<!--more-->
<p>We believe that this new name better reflects our core mission and aspirations. Just as electricity fuses elements to create energy, the FlowFuse platform fuses together data, ideas, processes, and technologies to generate a powerful force of innovation and transformation.</p>
<p>Selecting a new name for a company or product is never easy. Some of the requirements we set for a new name were: 1) it should be reasonably close to FlowForge so it will be easier to transition the brand identity, 2) it should even better reflect our mission, and 3) keeping the FF acronym will help with environment variable prefixes :-). I think we have accomplished all the above and am delighted to move forward as FlowFuse.</p>
<p><strong>What to Expect Next</strong></p>
<p>Our team is heads down building a platform to allow organizations to reliably deliver Node-RED applications in a continuous, collaborative, and secure manner. We'll continue to release regular updates packed with new features and enhancements that keeps moving us towards this goal.</p>
<p>A complete rebranding is a big piece of work - today marks the start of a process as we introduce the new FlowFuse name and updated <a href="https://flowfuse.com/">website</a>. Over the next number of days and weeks we'll continue to roll this change out, including our social media accounts and other accounts. The product branding will be changed over the next couple of releases, including FlowForge Cloud and FlowForge open source edition. The underlying software will be the as-if you’re running the next FlowForge release, though now called FlowFuse. We'll share more technical details of this when any changes are made.</p>
<p>We are excited by the future FlowFuse presents to our customers and the industry. Node-RED and FlowFuse is a powerful combination that gives access to industrial data to transform organizations and drive forward innovation across industries. Join us as we continue our journey.</p>
https://flowfuse.com/blog/2023/08/dashboard-community-update/Dashboard 2.0 - Community UpdateOur latest Community Update for Dashboard 2.0, including the latest new widgets, fixes and updates on what's next.2023-08-10T00:00:00ZJoe Pavitt<p>Welcome to the latest Node-RED Dashboard 2.0 update. We've added lots of new widgets, cleaned up compatibility issues alongside Dashboard 1.0 and made strides to improve the events system linking the Node-RED editor with the Dashboard.</p>
<!--more-->
<p>I firstly need to begin with a <em>"Thank You"</em> to the dozens of pre-alpha users we've had so far. Thanks for being patient whilst we're shipping fast and breaking things. We've had some great feedback, and we're working hard to implement is as best as possible.</p>
<p>With all of the changes we've been making, we've also made the decision to jump to minor version numbers, and so, <strong>0.1.0 is available now</strong>.</p>
<p>Below you'll find a summary of the changes we've made since our <a href="https://flowfuse.com/blog/2023/07/dashboard-0-1-release">last community update</a>.</p>
<h2 id="new-widgets" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/dashboard-community-update/#new-widgets"># </a> New Widgets</h2>
<h3 id="template-(docs)" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/dashboard-community-update/#template-(docs)"># </a> Template (<a href="https://dashboard.flowfuse.com/nodes/widgets/ui-template.html" target="_blank">docs</a>)</h3>
<p>Steve has been doing some incredible work on the new <code>ui-template</code> widget. This widget allows you to create your own custom components using raw HTML, but also works with any of the components in the <a href="https://vuetifyjs.com/en/components/all/">Vuetify</a> component library. It's a powerful tool that will enable users to be creative with their own widgets that are not currently available with the standard set of widgets.</p>
<p><img alt="Examples of ui-template" loading="lazy" decoding="async" src="https://dashboard.flowfuse.com/images/node-examples/ui-template.png" width="undefined" height="undefined" /></p>
<p>The Template node also provides access to two built-in functions that can be used to send data back to Node-RED:</p>
<ul>
<li><strong>send(msg)</strong>: Outputs a message (defined by the input to this function call) from this node in the Node-RED flow.</li>
<li><strong>submit()</strong>: Send a <code>FormData</code> object when attached to a <code><form></code> element. The created object will consist of the <code>name</code> attributes for each form element, corresponding to their respective <code>value</code> attributes.</li>
</ul>
<h3 id="toggle-switch-(docs)" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/dashboard-community-update/#toggle-switch-(docs)"># </a> Toggle Switch (<a href="https://dashboard.flowfuse.com/nodes/widgets/ui-switch.html" target="_blank">docs</a>)</h3>
<p><img alt="Examples of ui-switch" loading="lazy" decoding="async" src="https://dashboard.flowfuse.com/images/node-examples/ui-switch.png" width="undefined" height="undefined" /></p>
<p>Adds a toggle switch to the user interface that can be rendered with a label, and traditional toggle switch, or, as in Dashboard 1.0, can be a square element with an icon & colour provided.</p>
<h2 id="fixes-%26-other-changes" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/dashboard-community-update/#fixes-%26-other-changes"># </a> Fixes & Other Changes</h2>
<h3 id="sidebar" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/dashboard-community-update/#sidebar"># </a> Sidebar</h3>
<p>As requested on multiple occasions by the community when we released v0.0.4 of Dashboard 2.0, we've now added a side menu, as per Dashboard 1.0. Currently, this <em>just</em> provides a link to the Dashboard UI, but gives us a canvas on which to expand functionality in the future.</p>
<h3 id="improved-events-system" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/dashboard-community-update/#improved-events-system"># </a> Improved Events System</h3>
<p>We've re-structured the hierarchy of the events system to make it more streamlined. Now, the <code>ui-base</code> manages comms via single channels dedicated to each event type, and the widget's ID is then used as a topic. Previously, we had a separate channel for each <code>action:id</code>.</p>
<p>If you're interested in learning more about our events architecture, you can read about it <a href="https://dashboard.flowfuse.com/contributing/guides/events.html">here</a> in the docs.</p>
<h3 id="documentation-updates" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/dashboard-community-update/#documentation-updates"># </a> Documentation Updates</h3>
<p>It's not glamorous, but it's important. We've made sure that all documentation and help text inside Node-RED is fully up to date for the Dashboard 2.0 nodes. We've also include rendered examples for all widgets in our <a href="https://dashboard.flowfuse.com/">online documentation</a> too.</p>
<p>We've also made sure that any legacy options that had been transferred over from Dashboard 1.0 that haven't been fully implemented yet are temporarily hidden. This means, any options you're seeing, <em>should</em> be working. If they're not - it's a bug.</p>
<h2 id="what's-next%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/dashboard-community-update/#what's-next%3F"># </a> What's Next?</h2>
<p>We have a lot of things to keep us busy, we are documenting them all in GitHub, and have made public our <a href="https://github.com/orgs/FlowFuse/projects/15/views/1">planning board</a>. You can see what we're working on, what's coming up next, and what we've got planned for the future.</p>
<p>As always, we're open to ideas, feedback & contributions. If you'd like to get involved, please check out our GitHub Repository <a href="https://github.com/FlowFuse/node-red-dashboard">here</a>.</p>
<h2 id="join-our-team" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/dashboard-community-update/#join-our-team"># </a> Join Our Team</h2>
<p>If you'd like to be paid to directly contribute to Dashboard 2.0, we are hiring for a 2-3 month position to do just that:</p>
<ul>
<li><a href="https://boards.greenhouse.io/flowfuse/jobs/4911532004">Contract Front-End Engineer – Node-RED Dashboard</a></li>
</ul>
https://flowfuse.com/blog/2023/08/isa-95-automation-pyramid-to-unified-namespace/Why the Automation Pyramid blocks digital transformation - The Role of Unified NamespaceA Critical Examination of the Automation Pyramid's Obstruction to Digital Transformation2023-08-09T00:00:00ZMarian Demme<p>A few years ago, I wrote an <a href="https://www.linkedin.com/pulse/iiot-circle-marian-raphael-demme/">article</a>, in German, detailing my understanding of how the Automation Pyramid, a widely adopted reference model for the IT landscape of manufacturing firms, is essentially hindering digital transformation. Now, as conversations around the Unified Namespace (UNS) and particular frameworks continue to evolve, I revisit my earlier notions, review the latest updates to reference frameworks, and update my article.</p>
<!--more-->
<h2 id="the-pyramid%E2%80%99s-dilemma" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/isa-95-automation-pyramid-to-unified-namespace/#the-pyramid%E2%80%99s-dilemma"># </a> The Pyramid’s Dilemma</h2>
<p>The Automation Pyramid is grounded in the standard <a href="https://www.isa.org/products/ansi-isa-95-00-01-2010-iec-62264-1-mod-enterprise">ISA-95</a>, which aligns with <a href="https://www.iso.org/standard/57308.html">IEC 62264</a> and <a href="https://www.beuth.de/en/standard/din-en-62264-1/207270059">DIN EN 62264</a>. It delineates the functional hierarchy within a manufacturing enterprise. Over 25 variations of the Automation Pyramid exist in academic literature, all of them fundamentally mapping to the same core concept, tracing back to the <a href="https://en.wikipedia.org/wiki/Computer-integrated_manufacturing">Computer-integrated manufacturing</a> (CIM)-Pyramid of the 1970s. Although ISA-95 does not explicitly refer to a pyramid, it introduces five functional hierarchical levels often visualized as a pyramid.</p>
<h4 id="isa-95---visualization" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/isa-95-automation-pyramid-to-unified-namespace/#isa-95---visualization"># </a> ISA-95 - Visualization</h4>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/ISA95-sAb2sw61Qu-650.avif 650w, https://flowfuse.com/img/ISA95-sAb2sw61Qu-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/ISA95-sAb2sw61Qu-650.webp 650w, https://flowfuse.com/img/ISA95-sAb2sw61Qu-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/ISA95-sAb2sw61Qu-650.jpeg 650w, https://flowfuse.com/img/ISA95-sAb2sw61Qu-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="ISA95" loading="lazy" decoding="async" src="https://flowfuse.com/img/ISA95-sAb2sw61Qu-650.jpeg" width="1300" height="731" /></picture></p>
<h4 id="automation-pyramid---visualization" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/isa-95-automation-pyramid-to-unified-namespace/#automation-pyramid---visualization"># </a> Automation Pyramid - Visualization</h4>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/Automation-Pyramid-752K9D7VCA-650.avif 650w, https://flowfuse.com/img/Automation-Pyramid-752K9D7VCA-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/Automation-Pyramid-752K9D7VCA-650.webp 650w, https://flowfuse.com/img/Automation-Pyramid-752K9D7VCA-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/Automation-Pyramid-752K9D7VCA-650.jpeg 650w, https://flowfuse.com/img/Automation-Pyramid-752K9D7VCA-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Automation Pyramid" loading="lazy" decoding="async" src="https://flowfuse.com/img/Automation-Pyramid-752K9D7VCA-650.jpeg" width="1300" height="891" /></picture>
Source: Katti, Badarinath. (2020). Ontology-Based Approach to Decentralized Production Control in the Context of Cloud Manufacturing Execution Systems. 10.13140/RG.2.2.11486.46402.</p>
<p>A notable critique of ISA-95 is the absence of some operational functions and hierarchical levels commonly seen in manufacturing, leading to a rigidity that limits its applicability. This inflexibility has been acknowledged in a more recent framework, called the <a href="https://www.isa.org/intech-home/2019/march-april/features/rami-4-0-reference-architectural-model-for-industr">"Reference Architectural Model Industry 4.0"</a> RAMI 4.0 (<a href="https://www.beuth.de/en/norm/pd-iec-pas-63088/272832590">IEC PAS 63088</a>). As a result, the authors' introduced a <a href="https://syc-se.iec.ch/wp-content/uploads/2019/10/Reference_Architecture_final.pdf">"Smart Grid Architecture Model"</a> (SGAM) with three primary dimensions: Life Cycle & Value Stream (<a href="https://www.vde-verlag.de/iec-standards/248992/iec-62890-2020.html">IEC 62890</a>), Hierarchy Levels (<a href="https://www.iso.org/standard/57308.html">IEC 62264</a> and <a href="https://www.vde-verlag.de/iec-standards/216764/iec-61512-4-2009.html">IEC 61512</a>), and six main layers displaying the functional architecture of the asset and the separation into physical and digital world.</p>
<p><picture><source type="image/gif" srcset="https://flowfuse.com/img/RAMI40-pGTuEcO-TN-520.gif 520w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="RAMI4.0" loading="lazy" decoding="async" src="https://flowfuse.com/img/RAMI40-pGTuEcO-TN-520.webp" width="520" height="292" /></picture></p>
<p>However, my primary critique revolves around another issue – the structure and proposed communication methodology. Models based on layers, where each tier represents a functional area and could be covered by one or more applications, almost always lead to three fundamental problems:</p>
<h3 id="problem-1%3A-information-loss-and-transaction-costs" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/isa-95-automation-pyramid-to-unified-namespace/#problem-1%3A-information-loss-and-transaction-costs"># </a> Problem 1: Information Loss and Transaction Costs</h3>
<p>In the traditional model, data collection flows upward from Levels 0 to 4, while planning goes downward from Level 4 to 0. Information traversing from Level 0 to Level 4 has to pass through at least four stages. Despite the theoretical lossless transmission of information, the practical scenario inevitably results in some degree of information loss between levels. The result is that the original information from Level 0 arrives at Level 4 late, altered, or not at all.</p>
<p><strong>Example:</strong> In a manufacturing plant, multiple sensors at Level 1 detect a sudden event. By the time this information passes through intermediary layers (e.g. PLC, SCADA, MES) to reach Level 4 where a planning decision can be made, it is delayed and distorted due to the multiple transitions. The factory might suffer damage before proper actions are taken because the original data didn't arrive on time or at all.</p>
<h3 id="problem-2%3A-the-expense-of-one-to-one-connections" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/isa-95-automation-pyramid-to-unified-namespace/#problem-2%3A-the-expense-of-one-to-one-connections"># </a> Problem 2: The Expense of One-to-One Connections</h3>
<p>The Automation Pyramid is based on different layers. Consequently, one-to-one connections between IT systems become a necessity for data transfer between levels. For example, Level 3 IT systems need at least two connections to the adjacent levels. This can lead to thousands of one-to-one interfaces between IT systems, incurring exorbitant costs for projects and maintenance.</p>
<p><strong>Example:</strong> In a semiconductor company, the Manufacturing Execution System (MES) serves as a critical intermediary in the Automation Pyramid. It must be integrated both with PLCs at the lower level for real-time control and with the ERP system at the higher level for business planning. This complex integration leads to the creation of numerous one-to-one connections. Furthermore, in implementing Industry 4.0 use cases like analytical applications, MES data is often required, creating even more connections. The multitude of connections complicates the system, making changes extremely difficult and maintenance intensive. This inflexibility becomes a barrier to adaptability and growth, hindering the efficient digital transformation of the manufacturing process.</p>
<h3 id="problem-3%3A-ai's-dependence-on-data" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/isa-95-automation-pyramid-to-unified-namespace/#problem-3%3A-ai's-dependence-on-data"># </a> Problem 3: AI's Dependence on Data</h3>
<p>Artificial intelligence (AI) requires extensive, well-organized data. Given the current architecture, data would have to be collected and prepared from case to case for each individual system and level. This would invariably lead to numerous new one-to-one connections, offering no flexibility. Hence, AI and the Automation Pyramid can only collaborate in a significantly restricted manner.</p>
<p><strong>Example:</strong> A car manufacturing firm aims to leverage a neural network for predictive maintenance. Within the constraints of the existing Automation Pyramid's architecture, the positioning for such an application is nonexistent. To train the neural network and subsequently analyse the data, a consolidation of varying hierarchical data is essential, such as sensory input, maintenance records, production scheduling plans, etc. Under the current architecture, the introduction of this application precipitates the creation of a multitude of new one-to-one connections. Consequently, it underscores the pressing need to rethink the structural paradigms.</p>
<h2 id="iiot-circle-and-unified-namespace" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/isa-95-automation-pyramid-to-unified-namespace/#iiot-circle-and-unified-namespace"># </a> IIoT Circle and Unified Namespace</h2>
<p>To overcome the limitations of traditional industrial data architecture, a paradigm shift towards a modern distributed architecture is necessary. Rather than allowing data to exist in silos within and across layers of the technology stack, data should be made accessible in a unified manner, creating a single, centralized repository. This approach facilitates a single centralized source for all enterprise systems to access the required data for their operations. This framework, which I have been calling the IIoT Circle, modernizes the original idea of the Automation Pyramid. A "Unified Namespace" operates as the core element that processes, and permits data streams to be loaded and exported from other systems. All other applications communicate exclusively through the Unified Namespace, requiring only a single interface to be maintained per application.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/IIoT-Circle-DlMPBfxJt0-650.avif 650w, https://flowfuse.com/img/IIoT-Circle-DlMPBfxJt0-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/IIoT-Circle-DlMPBfxJt0-650.webp 650w, https://flowfuse.com/img/IIoT-Circle-DlMPBfxJt0-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/IIoT-Circle-DlMPBfxJt0-650.jpeg 650w, https://flowfuse.com/img/IIoT-Circle-DlMPBfxJt0-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="IToT Circle Image" loading="lazy" decoding="async" src="https://flowfuse.com/img/IIoT-Circle-DlMPBfxJt0-650.jpeg" width="1300" height="731" /></picture></p>
<p>In essence, Unified Namespace serves as the main data exchange hub within an organization. It structures, organizes, and maintains a real-time flow of data from a variety of sources, becoming the indisputable source of truth across the business. It simplifies data integration, eliminating the frequently convoluted, layered approach of traditional data systems.</p>
<h3 id="single-source-of-truth" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/isa-95-automation-pyramid-to-unified-namespace/#single-source-of-truth"># </a> Single Source of Truth</h3>
<p>The Unified Namespace breaks down the linear and deterministic data structure, which create data silos restricted to their specific systems. Instead, Unified Namespace centralizes data from across the entire organization. This results in a 'single source of truth' - a consolidated, current, and comprehensive overview of the organization's data.</p>
<h3 id="the-organizational-structure" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/isa-95-automation-pyramid-to-unified-namespace/#the-organizational-structure"># </a> The Organizational Structure</h3>
<p>Unified Namespace organizes data using a semantic hierarchy, similar to a meticulously arranged file share system. It can use the <a href="https://www.isa.org/products/ansi-isa-95-00-02-2018-enterprise-control-system-i">ISA-95 part 2</a> or the RAMI 4.0 Hierarchy Level standards to structure the hierarchy. This data organization facilitates navigation, management, and decision-making.</p>
<h3 id="the-pub-sub-approach" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/isa-95-automation-pyramid-to-unified-namespace/#the-pub-sub-approach"># </a> The Pub-Sub Approach</h3>
<p>The Publish-Subscribe (Pub-Sub) model facilitates communication that decouples the sender (publisher) from the receiver (subscriber), providing an efficient communication protocol to avoid one-to-one connections. It offers flexibility and scalability as it allows for one-to-many and many-to-one communications, enabling data to flow freely between systems.</p>
<h2 id="a-necessity-for-open-source" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/isa-95-automation-pyramid-to-unified-namespace/#a-necessity-for-open-source"># </a> A Necessity for Open Source</h2>
<p>Moreover, in this discourse on the Unified Namespace, we cannot overlook the role of open-source. Owning foundational digital services, such as the Unified Namespace, is a necessity for any corporation embarking on its digital transformation journey. This ownership provides a solid foundation, allowing companies to chart their destinies. To avoid the constraining bounds of vendor lock-in, which can significantly limit a company's digital capabilities; open-source or self-developed software offers the best recourse. By its nature, open-source promotes transparency, collaboration, and freedom of use. These aspects are fundamental to fostering innovation and continuous improvement. As exemplified by the <a href="https://flowfuse.com/blog/2023/02/ming-blog/">MING Stack</a>, open source software can and should be incorporated into every level of the hierarchy.</p>
<h2 id="summary-%E2%80%93-advancing-current-standards" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/isa-95-automation-pyramid-to-unified-namespace/#summary-%E2%80%93-advancing-current-standards"># </a> Summary – Advancing Current Standards</h2>
<p>The lag of standards behind the latest innovation is an open secret, a problem rooted in the nature and development of these standards. However, maintaining and updating these standards remains crucial as many people adhere to them.</p>
<p>ISA-95 Part 6 mentions a Messaging Service Model (MSM) and proposes a "publish-subscribe" model as an option for transactions. This is a great step in the right direction. My recommendation for ISA-95 is to further develop Part 6 to clearly delineate the implementation pattern of the Unified Namespace. Additionally, ISA-95 Part 1 should make explicit references to the communication pattern detailed in Part 6 and transition from a layer model to a cycle, with the Unified Namespace as an integral part of the framework.</p>
<p>RAMI 4.0's Communication Layer is rather abstract. It suggests the use of OPC-UA for everything in manufacturing, from "Product" to "Work Center". For "Enterprise" and "Connected World", it states "still undecided". My improvement suggestion is to define the "Communication Layer" new and to be more technology-agnostic. Be more explicit about what needs to be done and more flexible about how to do it.</p>
https://flowfuse.com/blog/2023/08/community-news-08/Community News August 2023Your monthly update for the FlowFuse and Node-RED communities2023-08-08T00:00:00Z<p>Welcome to the FlowFuse newsletter for August 2023, a monthly roundup of what’s been happening with FlowFuse and the wider Node-RED community.</p>
<!--more-->
<h2 id="new-release" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/community-news-08/#new-release"># </a> New Release</h2>
<p>Last week we released FlowFuse 1.10, featuring improvements to our device management solutions and the new ability to import environment variable templates. Read about the details of FlowFuse 1.10 in our <a href="https://flowfuse.com/blog/2023/08/flowforge-1-10-release/">release announcement</a>.</p>
<h2 id="upcoming-events" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/community-news-08/#upcoming-events"># </a> Upcoming events</h2>
<h3 id="getting-started-with-opc-ua-and-node-red" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/community-news-08/#getting-started-with-opc-ua-and-node-red"># </a> Getting Started with OPC-UA and Node-RED</h3>
<p>OPC-UA is a popular communication protocol used to communicate industrial data between different types of hardware and software. Our next webinar show how to use Node-RED to create an OPC-UA client that can read OPC data and visualize the data in Node-RED. We are glad to welcome Mika Karaila, Research Director @ Valmet Automation and creator of the OPC-UA nodes, as our webinar speaker.</p>
<p><a href="https://flowfuse.com/webinars/2023/getting-started-opcua-node-red/">Sign-up today</a> to join us on July 27.</p>
<h2 id="from-our-blog" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/community-news-08/#from-our-blog"># </a> From our Blog</h2>
<ul>
<li>
<p>Our developer advocate, Richard Meyer, published a series of articles on OPC-UA:</p>
<ul>
<li>Part 1: <a href="https://flowfuse.com/blog/2023/07/how-to-deploy-a-basic-opc-ua-server-in-node-red/">How to Deploy a Basic OPC-UA Server in Node-RED</a></li>
<li>Part 2: <a href="https://flowfuse.com/blog/2023/07/how-to-build-a-secure-opc-ua-server-for-plcs-in-node-red/">How to Build a Secure OPC-UA Server for PLCs in Node-RED</a></li>
<li>Part 3: <a href="https://flowfuse.com/blog/2023/07/how-to-build-a-opc-client-dashboard-in-node-red/">How to Build an OPC UA Client Dashboard in Node-RED</a></li>
</ul>
</li>
<li>
<p><a href="https://flowfuse.com/blog/2023/07/dashboard-0-1-release/">First Pre-Alpha Release of the new Node-RED Dashboard</a> - update on FlowFuse's work to develop the next generation of Node-RED dashboard.</p>
</li>
<li>
<p><a href="https://flowfuse.com/blog/2023/07/images-in-node-red-dashboards/">How to add images to Node-RED dashboards when using FlowFuse</a> - some tips on how to add images to a dashboard when running Node-RED instances in a docker environment, like FlowFuse.</p>
</li>
<li>
<p><a href="https://flowfuse.com/blog/2023/07/influxdb-historical-data/">Creating a Historical Data Dashboard with InfluxDB and Node-RED</a> - an in-depth article on how to store historical data in InfluxDB that can be visualize with Node-RED dashboard.</p>
</li>
</ul>
<h2 id="from-the-community" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/community-news-08/#from-the-community"># </a> From the Community</h2>
<ul>
<li><strong>Featured Node</strong>: <a href="https://flows.nodered.org/node/node-red-contrib-buffer-parser">Buffer Parser</a> - a really useful node for parsing buffers/arrays that are common in industrial data.</li>
</ul>
<h2 id="join-our-team" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/community-news-08/#join-our-team"># </a> Join Our Team</h2>
<p>FlowFuse is expanding our team. Check out the current openings:</p>
<ul>
<li><a href="https://boards.greenhouse.io/flowfuse/jobs/4911532004">Contract Front-End Engineer – Node-RED Dashboard</a></li>
</ul>
https://flowfuse.com/blog/2023/08/flowforge-1-10-release/FlowFuse 1.10 Release Now AvailableNew FlowFuse 1.10 also includes improvements to device management and importing environment variable templates.2023-08-03T00:00:00Z<p>FlowFuse 1.10 release includes improvements to device management and importing environment variable templates.</p>
<!--more-->
<h2 id="import-environment-variable-templates-%232372" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/flowforge-1-10-release/#import-environment-variable-templates-%232372"># </a> Import Environment Variable Templates <a href="https://github.com/FlowFuse/flowfuse/issues/2372">#2372</a></h2>
<p>FlowFuse 1.10 now allows users to import environment variable templates. This makes it much easier and less error prone to maintain and add new environment variables to Node-RED instances running on FlowFuse.</p>
<h2 id="devops-pipelines-now-can-include-devices-%232243" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/flowforge-1-10-release/#devops-pipelines-now-can-include-devices-%232243"># </a> DevOps Pipelines now can include devices <a href="https://github.com/FlowFuse/flowfuse/issues/2243">#2243</a></h2>
<p>DevOps pipelines have proven very popular for creating dev/test/production environments for Node-Red flow development. Now, devices can be associated with a pipeline so when a snapshot is created it can be pushed to all the devices associated with the pipeline. This will improve the overall quality and reliability of Node-RED development for remote devices.</p>
<h2 id="devices-can-now-access-the-team-library-%232294" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/flowforge-1-10-release/#devices-can-now-access-the-team-library-%232294"># </a> Devices can now access the team library <a href="https://github.com/FlowFuse/flowfuse/issues/2294">#2294</a></h2>
<p>Team libraries allow Node-RED development team to share common flows and nodes through a shared library. Until the 1.10 release, Node-RED running remotely on a device did not have access to the team library. This limitation is now removed so device development can benefit from reusing standard flows.</p>
<h2 id="other-new-features" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/flowforge-1-10-release/#other-new-features"># </a> Other New Features</h2>
<ul>
<li>Add description of device type field <a href="https://github.com/FlowFuse/flowfuse/issues/2428">#2428</a></li>
<li>Improve reliability of device editor <a href="https://github.com/FlowFuse/flowfuse/issues/2483">#2483</a></li>
<li>Improve error feedback from device editor tunnel <a href="https://github.com/FlowFuse/flowfuse/issues/2473">#2473</a></li>
</ul>
<h2 id="bug-fixes" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/flowforge-1-10-release/#bug-fixes"># </a> Bug Fixes</h2>
<ul>
<li>Improve visualization of Last Seen & Last Known with large amounts of devices. <a href="https://github.com/FlowFuse/flowfuse/issues/2380">#2380</a></li>
<li>Fix billing information error in FlowFuse Cloud <a href="https://github.com/FlowFuse/flowfuse/issues/2416">#2416</a></li>
<li>Fix T&C checkbox on sign-up page <a href="https://github.com/FlowFuse/flowfuse/issues/2419">#2419</a></li>
</ul>
<h2 id="community-contributions" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/flowforge-1-10-release/#community-contributions"># </a> Community Contributions</h2>
<p>Thanks to our community members for their contributions to this release.</p>
<ul>
<li><a href="https://github.com/dfulgham">dfulgham</a> - Added support for annotation substitutions <a href="https://github.com/FlowFuse/flowforge-driver-k8s/pull/95">#95</a></li>
<li><a href="https://github.com/elenaviter">elanaviter</a> - Editors: allow optional service account linkage <a href="https://github.com/FlowFuse/flowforge-driver-k8s/pull/92">#92</a></li>
</ul>
<h2 id="what's-next%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/flowforge-1-10-release/#what's-next%3F"># </a> What's next?</h2>
<p>We're always working to enhance your experience with FlowFuse. Here's how you can stay informed and contribute:</p>
<ul>
<li><strong>Roadmap Overview</strong>: Check out our <a href="https://flowfuse.com/product/roadmap/">Product Roadmap Page</a> to see what we're planning for future updates.</li>
<li><strong>Entire Roadmap</strong>: Visit our <a href="https://github.com/orgs/FlowFuse/projects/5">Roadmap on GitHub</a> to follow our progress and contribute your ideas.</li>
<li><strong>Feedback</strong>: We're interested in your thoughts about FlowFuse. Your feedback is crucial to us, and we'd love to hear about your experiences with the new features and improvements. Please share your thoughts, suggestions, or report any <a href="https://github.com/FlowFuse/flowfuse/issues/new/choose">issues on GitHub</a>.</li>
</ul>
<p>Together, we can make FlowFuse better with each release!</p>
<h2 id="try-it-out" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/flowforge-1-10-release/#try-it-out"># </a> Try it out</h2>
<p>We're confident you can have self managed FlowFuse running locally in under 30 minutes.
You can install our <a href="https://flowfuse.com/docs/install/local/">local build</a>, use <a href="https://flowfuse.com/docs/install/docker/">Docker</a>, or <a href="https://flowfuse.com/docs/install/kubernetes/">Kubernetes</a>.</p>
<p>If you'd rather use our hosted offering: <a href="https://app.flowfuse.com/account/create">Get started for free</a> on FlowFuse Cloud.</p>
<h2 id="upgrading-flowfuse" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/flowforge-1-10-release/#upgrading-flowfuse"># </a> Upgrading FlowFuse</h2>
<p><a href="https://app.flowfuse.com/">FlowFuse Cloud</a> is already running 1.10.</p>
<p>If you installed a previous version of FlowFuse and want to upgrade, our documentation provides a
guide for <a href="https://flowfuse.com/docs/upgrade/">upgrading your FlowFuse instance</a>.</p>
<h2 id="getting-help" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/08/flowforge-1-10-release/#getting-help"># </a> Getting help</h2>
<p>Please check FlowFuse's <a href="https://flowfuse.com/docs/">documentation</a> as the answers to many questions are covered there. Additionally you can go the the <a href="https://discourse.nodered.org/c/vendors/flowfuse/24">community forum</a> if you have
any feedback or feature requests.</p>
https://flowfuse.com/blog/2023/07/how-to-build-a-opc-client-dashboard-in-node-red/How to Build an OPC UA Client Dashboard in Node-RED - Part 3Interactive OPC UA Client dashboard that communicates with a 3rd party OPC UA Server2023-07-27T00:00:00Z<p>This article is the third and final part of our OPC UA content series. In the <a href="https://flowfuse.com/blog/2023/07/how-to-deploy-a-basic-opc-ua-server-in-node-red/">first article</a>, we cover some OPC UA fundamentals and walk through an example OPC UA Server flow. In the <a href="https://flowfuse.com/blog/2023/07/how-to-build-a-secure-opc-ua-server-for-plcs-in-node-red/">second article</a>, we built a SSL-secured OPC UA server using data from an Allen Bradley PLC as a source.
In this article, we show how to build an OPC Client in Node-RED that communicates with a 3rd party OPC UA Server and utilizes an interactive dashboard.</p>
<!--more-->
<p>This article will requires the <a href="https://prosysopc.com/products/opc-ua-simulation-server/">Prosys OPC UA Simulation Server</a>, an application designed for testing OPC UA client applications and learning the technology. It’s a free cross-platform application that supports Windows, Linux, and MacOS. This article will use the Windows version.</p>
<p>Note: full source code for the OPC Client Dashboard is included at the end of the article.</p>
<h2 id="custom-nodes-used-%26-assumptions" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/how-to-build-a-opc-client-dashboard-in-node-red/#custom-nodes-used-%26-assumptions"># </a> Custom Nodes Used & Assumptions</h2>
<p>Several custom nodes are required in order to properly deploy this flow. For more detailed information on how to install a custom node, follow the instructions from an <a href="https://flowfuse.com/blog/2023/06/node-red-as-a-no-code-ethernet_ip-to-s7-protocol-converter/">earlier article</a> where the process on installing custom nodes is explained in detail.</p>
<ul>
<li><a href="https://flows.nodered.org/node/node-red-dashboard">node-red-dashboard</a></li>
<li><a href="https://flows.nodered.org/node/node-red-contrib-opcua">node-red-contrib-opcua</a></li>
<li><a href="https://flows.nodered.org/node/node-red-contrib-ui-led/">node-red-contrib-ui-led</a></li>
</ul>
<p>As this is not a production application, no security will be utilized, and it is assumed that the OPC UA Server is running on the same network as the Node-RED OPC Client.</p>
<p>Is it also assumed that the end user of this article has familiarization with dashboards. There are many dashboard basic guides available online, including a <a href="https://flowfuse.com/blog/2023/06/3-quick-node-red-tips-7/">node red quick tips - dashboard edition</a> here on FlowFuse. You can still deploy the flow and access the dashboard UI at the url <a href="http://localhost:1880/ui">http://localhost:1880/ui</a> (if the default settings are used), though this article does not delve into the details of dashboard building.</p>
<h2 id="install-and-deploy-the-prosys-opc-ua-simulation-server" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/how-to-build-a-opc-client-dashboard-in-node-red/#install-and-deploy-the-prosys-opc-ua-simulation-server"># </a> Install and Deploy the Prosys OPC UA Simulation Server</h2>
<p>The Prosys OPC UA Simulation Server is <a href="https://prosysopc.com/products/opc-ua-simulation-server/evaluate/">free to download</a>, but requires a sign-up process. Download and install the server, then run the application. Once the application is started, the first thing you should do is go to <code>options -> switch to expert mode</code>.</p>
<p>This will give us access to the address space tab, which we will need to develop our client application in Node-RED.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/expert-mode-XONwVsGs5B-553.avif 553w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/expert-mode-XONwVsGs5B-553.webp 553w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="expert-mode.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/expert-mode-XONwVsGs5B-553.jpeg" width="553" height="292" /></picture></p>
<p>When the application is run, an endpoint url will be displayed on the <code>status</code> tab, along with an indication that the server is currently running.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/opc-endpoint-url-1dSkqDR2vN-650.avif 650w, https://flowfuse.com/img/opc-endpoint-url-1dSkqDR2vN-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/opc-endpoint-url-1dSkqDR2vN-650.webp 650w, https://flowfuse.com/img/opc-endpoint-url-1dSkqDR2vN-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/opc-endpoint-url-1dSkqDR2vN-650.jpeg 650w, https://flowfuse.com/img/opc-endpoint-url-1dSkqDR2vN-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="opc-endpoint-url.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/opc-endpoint-url-1dSkqDR2vN-650.jpeg" width="1300" height="797" /></picture>
Copy the connection endpoint, but be warned that you will likely need to replace the computer name (in my case <code>DESKTOP-0K0483A</code>, with the actual IP address of the machine running the server. The IP address of the machine on my local network is <code>192.168.0.141</code>, which changes my UA TCP endpoint address to <code>opc.tcp://192.168.0.141:53530/OPCUA/SimulationServer</code>.</p>
<p>Now the simulation server is set up and we are ready to start developing the OPC Client application.</p>
<h2 id="objectives-of-the-node-red-opc-client-dashboard-application" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/how-to-build-a-opc-client-dashboard-in-node-red/#objectives-of-the-node-red-opc-client-dashboard-application"># </a> Objectives of the Node-RED OPC Client Dashboard Application</h2>
<p>The goal is not to develop a production-level application, rather, it’s to show a variety of features that one can utilize to demonstrate common OPC UA Client application capabilities in Node-RED, while also demonstrating a variety of methods to visualize the results in a dashboard. There are 4 main objectives of the Node-RED OPC Client Dashboard application. They are:</p>
<ol>
<li>Browse hierarchical server address space structure & display on a dashboard</li>
<li>Read OPC UA values from various namespaces, showing a variety of datatypes and different ways they can be visualized</li>
<li>Write OPC UA values back to the OPC UA server directly from the OPC UA Client dashboard</li>
<li>Read alarms & events from the OPC UA Server and display them on the dashboard</li>
</ol>
<p>Rather than building the flow step-by-step, the flow source code will be presented for each objective, and a the flow will be explained so that it is understood what is happening in each section of code.</p>
<h2 id="browse-hierarchical-server-address-space-structure-with-opc-ua-browser-node" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/how-to-build-a-opc-client-dashboard-in-node-red/#browse-hierarchical-server-address-space-structure-with-opc-ua-browser-node"># </a> Browse Hierarchical Server Address Space Structure With OPC UA Browser Node</h2>
<p>The first flow will browse the hierarchical OPC UA Server address space structure and display it on the dashboard.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/image-20230727-085611-MV_odYooCa-650.avif 650w, https://flowfuse.com/img/image-20230727-085611-MV_odYooCa-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/image-20230727-085611-MV_odYooCa-650.webp 650w, https://flowfuse.com/img/image-20230727-085611-MV_odYooCa-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/image-20230727-085611-MV_odYooCa-650.jpeg 650w, https://flowfuse.com/img/image-20230727-085611-MV_odYooCa-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="image-20230727-085611.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/image-20230727-085611-MV_odYooCa-650.jpeg" width="1300" height="484" /></picture>
You can import this flow into Node-RED using the code below:</p>
<div style="position: relative">
<pre class="language-javascript"><code id="code-100" class="language-javascript"><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"3e09b7a420dd81d2"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"group"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Browse Hierarchical Address Space Structure & Display on Dashboard"</span><span class="token punctuation">,</span><span class="token string-property property">"style"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"stroke"</span><span class="token operator">:</span><span class="token string">"#a4a4a4"</span><span class="token punctuation">,</span><span class="token string-property property">"color"</span><span class="token operator">:</span><span class="token string">"#000000"</span><span class="token punctuation">,</span><span class="token string-property property">"fill"</span><span class="token operator">:</span><span class="token string">"#ffffff"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token string-property property">"nodes"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"6b17b2da2b942bb4"</span><span class="token punctuation">,</span><span class="token string">"61797eccf2785257"</span><span class="token punctuation">,</span><span class="token string">"4d92d940177b6ee3"</span><span class="token punctuation">,</span><span class="token string">"68a113d5893b7c01"</span><span class="token punctuation">,</span><span class="token string">"98560994a7884f15"</span><span class="token punctuation">,</span><span class="token string">"4dd13685c3c2879e"</span><span class="token punctuation">,</span><span class="token string">"a29358cca5c1c12a"</span><span class="token punctuation">,</span><span class="token string">"d0c969b6a59fac3a"</span><span class="token punctuation">,</span><span class="token string">"639da01fc957e547"</span><span class="token punctuation">,</span><span class="token string">"29437ca7222d9a64"</span><span class="token punctuation">,</span><span class="token string">"49983d5da0958bf2"</span><span class="token punctuation">,</span><span class="token string">"49040d0cf1144f0a"</span><span class="token punctuation">,</span><span class="token string">"e7c55f412ef86543"</span><span class="token punctuation">,</span><span class="token string">"7b53b798a025f1d8"</span><span class="token punctuation">,</span><span class="token string">"71512a0d602095a0"</span><span class="token punctuation">,</span><span class="token string">"9c3b0c36d69c05cf"</span><span class="token punctuation">,</span><span class="token string">"de21b7ad98a05833"</span><span class="token punctuation">,</span><span class="token string">"2d56e9a431c21a3b"</span><span class="token punctuation">,</span><span class="token string">"ac95bd0e2b304eec"</span><span class="token punctuation">,</span><span class="token string">"6fdabcc2950ccf4e"</span><span class="token punctuation">,</span><span class="token string">"1c49fa5142d2cf17"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">54</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">19</span><span class="token punctuation">,</span><span class="token string-property property">"w"</span><span class="token operator">:</span><span class="token number">1172</span><span class="token punctuation">,</span><span class="token string-property property">"h"</span><span class="token operator">:</span><span class="token number">422</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"6b17b2da2b942bb4"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"OpcUa-Browser"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3e09b7a420dd81d2"</span><span class="token punctuation">,</span><span class="token string-property property">"endpoint"</span><span class="token operator">:</span><span class="token string">"53f4394dbf12c6b7"</span><span class="token punctuation">,</span><span class="token string-property property">"item"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"datatype"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"items"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"OPC Client Namespace Browse"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">510</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">160</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"4d92d940177b6ee3"</span><span class="token punctuation">,</span><span class="token string">"d0c969b6a59fac3a"</span><span class="token punctuation">,</span><span class="token string">"639da01fc957e547"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"61797eccf2785257"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3e09b7a420dd81d2"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Get Base Folder Structure"</span><span class="token punctuation">,</span><span class="token string-property property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"topic"</span><span class="token punctuation">,</span><span class="token string-property property">"vt"</span><span class="token operator">:</span><span class="token string">"str"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"repeat"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"once"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"onceDelay"</span><span class="token operator">:</span><span class="token string">"0.3"</span><span class="token punctuation">,</span><span class="token string-property property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"payload"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"payloadType"</span><span class="token operator">:</span><span class="token string">"date"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">240</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">160</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"6b17b2da2b942bb4"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"4d92d940177b6ee3"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3e09b7a420dd81d2"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Simulation Folder"</span><span class="token punctuation">,</span><span class="token string-property property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"Objects.Simulation.nodeId"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"flow"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload[2].item.nodeId"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload[2].item.browseName.name"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">790</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">100</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"98560994a7884f15"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"68a113d5893b7c01"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3e09b7a420dd81d2"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Display on Dashboard"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1100</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">60</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"98560994a7884f15"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_text"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3e09b7a420dd81d2"</span><span class="token punctuation">,</span><span class="token string-property property">"group"</span><span class="token operator">:</span><span class="token string">"4340b56a2335c304"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token string-property property">"height"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Simulation"</span><span class="token punctuation">,</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token string">"Namespace 3"</span><span class="token punctuation">,</span><span class="token string-property property">"format"</span><span class="token operator">:</span><span class="token string">" <i class=\"fa fa-folder\" aria-hidden=\"true\"></i>"</span><span class="token punctuation">,</span><span class="token string-property property">"layout"</span><span class="token operator">:</span><span class="token string">"col-center"</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"style"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"font"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"fontSize"</span><span class="token operator">:</span><span class="token number">16</span><span class="token punctuation">,</span><span class="token string-property property">"color"</span><span class="token operator">:</span><span class="token string">"#000000"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1070</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">100</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"4dd13685c3c2879e"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_text"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3e09b7a420dd81d2"</span><span class="token punctuation">,</span><span class="token string-property property">"group"</span><span class="token operator">:</span><span class="token string">"4340b56a2335c304"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token string-property property">"height"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"StaticData"</span><span class="token punctuation">,</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token string">"Namespace 5"</span><span class="token punctuation">,</span><span class="token string-property property">"format"</span><span class="token operator">:</span><span class="token string">" <i class=\"fa fa-folder\" aria-hidden=\"true\"></i> <i class=\"fa fa-sort-desc\" aria-hidden=\"true\"></i>"</span><span class="token punctuation">,</span><span class="token string-property property">"layout"</span><span class="token operator">:</span><span class="token string">"col-center"</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"style"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"font"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"fontSize"</span><span class="token operator">:</span><span class="token number">16</span><span class="token punctuation">,</span><span class="token string-property property">"color"</span><span class="token operator">:</span><span class="token string">"#000000"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1070</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">160</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"a29358cca5c1c12a"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_text"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3e09b7a420dd81d2"</span><span class="token punctuation">,</span><span class="token string-property property">"group"</span><span class="token operator">:</span><span class="token string">"4340b56a2335c304"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">9</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token string-property property">"height"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"MyObjects"</span><span class="token punctuation">,</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token string">"Namespace 6"</span><span class="token punctuation">,</span><span class="token string-property property">"format"</span><span class="token operator">:</span><span class="token string">" <i class=\"fa fa-folder\" aria-hidden=\"true\"></i> <i class=\"fa fa-sort-desc\" aria-hidden=\"true\"></i>"</span><span class="token punctuation">,</span><span class="token string-property property">"layout"</span><span class="token operator">:</span><span class="token string">"col-center"</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"style"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"font"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"fontSize"</span><span class="token operator">:</span><span class="token number">16</span><span class="token punctuation">,</span><span class="token string-property property">"color"</span><span class="token operator">:</span><span class="token string">"#000000"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1070</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">220</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"d0c969b6a59fac3a"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3e09b7a420dd81d2"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"MyObjects Folder"</span><span class="token punctuation">,</span><span class="token string-property property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"Objects.MyObjects.nodeId"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"flow"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload[4].item.nodeId"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload[4].item.browseName.name"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">790</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">220</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"a29358cca5c1c12a"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"639da01fc957e547"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3e09b7a420dd81d2"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"StaticData Folder"</span><span class="token punctuation">,</span><span class="token string-property property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"Objects.StaticData.nodeId"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"flow"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload[3].item.nodeId"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload[3].item.browseName.name"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">790</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">160</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"4dd13685c3c2879e"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"29437ca7222d9a64"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"OpcUa-Browser"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3e09b7a420dd81d2"</span><span class="token punctuation">,</span><span class="token string-property property">"endpoint"</span><span class="token operator">:</span><span class="token string">"53f4394dbf12c6b7"</span><span class="token punctuation">,</span><span class="token string-property property">"item"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"datatype"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"items"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"OPC Client Namespace Browse"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">510</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">320</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"49040d0cf1144f0a"</span><span class="token punctuation">,</span><span class="token string">"e7c55f412ef86543"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"49983d5da0958bf2"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3e09b7a420dd81d2"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Get StaticData Folder Structure"</span><span class="token punctuation">,</span><span class="token string-property property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"topic"</span><span class="token punctuation">,</span><span class="token string-property property">"v"</span><span class="token operator">:</span><span class="token string">"Objects.StaticData.nodeId"</span><span class="token punctuation">,</span><span class="token string-property property">"vt"</span><span class="token operator">:</span><span class="token string">"flow"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"repeat"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"once"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"onceDelay"</span><span class="token operator">:</span><span class="token string">"0.3"</span><span class="token punctuation">,</span><span class="token string-property property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"payload"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"payloadType"</span><span class="token operator">:</span><span class="token string">"date"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">230</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">320</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"29437ca7222d9a64"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"49040d0cf1144f0a"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3e09b7a420dd81d2"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"AnalogItemArrays Folder"</span><span class="token punctuation">,</span><span class="token string-property property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"Objects.StaticData.AnalogItemArrays.nodeId"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"flow"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload[1].item.nodeId"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload[1].item.browseName.name"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">810</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">340</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"7b53b798a025f1d8"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"e7c55f412ef86543"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3e09b7a420dd81d2"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"StaticArrayVariables Folder"</span><span class="token punctuation">,</span><span class="token string-property property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"Objects.StaticData.StaticArrayVariables.nodeId"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"flow"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload[6].item.nodeId"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload[6].item.browseName.name"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">820</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">280</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"71512a0d602095a0"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"7b53b798a025f1d8"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_text"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3e09b7a420dd81d2"</span><span class="token punctuation">,</span><span class="token string-property property">"group"</span><span class="token operator">:</span><span class="token string">"4340b56a2335c304"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">8</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token number">4</span><span class="token punctuation">,</span><span class="token string-property property">"height"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"AnalogItemArrays"</span><span class="token punctuation">,</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"format"</span><span class="token operator">:</span><span class="token string">"<i class=\"fa fa-folder\" aria-hidden=\"true\"></i> "</span><span class="token punctuation">,</span><span class="token string-property property">"layout"</span><span class="token operator">:</span><span class="token string">"col-center"</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"style"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"font"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"fontSize"</span><span class="token operator">:</span><span class="token number">16</span><span class="token punctuation">,</span><span class="token string-property property">"color"</span><span class="token operator">:</span><span class="token string">"#000000"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1090</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">340</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"71512a0d602095a0"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_text"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3e09b7a420dd81d2"</span><span class="token punctuation">,</span><span class="token string-property property">"group"</span><span class="token operator">:</span><span class="token string">"4340b56a2335c304"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">6</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token number">4</span><span class="token punctuation">,</span><span class="token string-property property">"height"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"StaticArrayVariables"</span><span class="token punctuation">,</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"format"</span><span class="token operator">:</span><span class="token string">" <i class=\"fa fa-folder\" aria-hidden=\"true\"></i> "</span><span class="token punctuation">,</span><span class="token string-property property">"layout"</span><span class="token operator">:</span><span class="token string">"col-center"</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"style"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"font"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"fontSize"</span><span class="token operator">:</span><span class="token number">16</span><span class="token punctuation">,</span><span class="token string-property property">"color"</span><span class="token operator">:</span><span class="token string">"#000000"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1100</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">280</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"9c3b0c36d69c05cf"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_text"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3e09b7a420dd81d2"</span><span class="token punctuation">,</span><span class="token string-property property">"group"</span><span class="token operator">:</span><span class="token string">"4340b56a2335c304"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">12</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token number">4</span><span class="token punctuation">,</span><span class="token string-property property">"height"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"MyDevice"</span><span class="token punctuation">,</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"format"</span><span class="token operator">:</span><span class="token string">"<i class=\"fa fa-cube\" aria-hidden=\"true\"></i> "</span><span class="token punctuation">,</span><span class="token string-property property">"layout"</span><span class="token operator">:</span><span class="token string">"col-center"</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"style"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"font"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"fontSize"</span><span class="token operator">:</span><span class="token number">16</span><span class="token punctuation">,</span><span class="token string-property property">"color"</span><span class="token operator">:</span><span class="token string">"#000000"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1060</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">400</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"de21b7ad98a05833"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3e09b7a420dd81d2"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"MyDevice Object"</span><span class="token punctuation">,</span><span class="token string-property property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"Objects.MyObjects.MyDevice.nodeId"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"flow"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload[0].item.nodeId"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload[0].item.browseName.name"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">790</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">400</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"9c3b0c36d69c05cf"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"2d56e9a431c21a3b"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3e09b7a420dd81d2"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Get MyObjects Object Structure"</span><span class="token punctuation">,</span><span class="token string-property property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"topic"</span><span class="token punctuation">,</span><span class="token string-property property">"v"</span><span class="token operator">:</span><span class="token string">"Objects.MyObjects.nodeId"</span><span class="token punctuation">,</span><span class="token string-property property">"vt"</span><span class="token operator">:</span><span class="token string">"flow"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"repeat"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"once"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"onceDelay"</span><span class="token operator">:</span><span class="token string">"0.5"</span><span class="token punctuation">,</span><span class="token string-property property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"payload"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"payloadType"</span><span class="token operator">:</span><span class="token string">"date"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">230</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">400</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"ac95bd0e2b304eec"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"ac95bd0e2b304eec"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"OpcUa-Browser"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3e09b7a420dd81d2"</span><span class="token punctuation">,</span><span class="token string-property property">"endpoint"</span><span class="token operator">:</span><span class="token string">"53f4394dbf12c6b7"</span><span class="token punctuation">,</span><span class="token string-property property">"item"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"datatype"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"items"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"OPC Client Namespace Browse"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">510</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">400</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"de21b7ad98a05833"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"6fdabcc2950ccf4e"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3e09b7a420dd81d2"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Store & Parse nodeId & browseName"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">810</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">60</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"1c49fa5142d2cf17"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3e09b7a420dd81d2"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Global Address Space Folder Browse"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">390</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">120</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"53f4394dbf12c6b7"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"OpcUa-Endpoint"</span><span class="token punctuation">,</span><span class="token string-property property">"endpoint"</span><span class="token operator">:</span><span class="token string">"opc.tcp://192.168.0.141:53530/OPCUA/SimulationServer"</span><span class="token punctuation">,</span><span class="token string-property property">"secpol"</span><span class="token operator">:</span><span class="token string">"None"</span><span class="token punctuation">,</span><span class="token string-property property">"secmode"</span><span class="token operator">:</span><span class="token string">"None"</span><span class="token punctuation">,</span><span class="token string-property property">"none"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"login"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"usercert"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"usercertificate"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"userprivatekey"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"4340b56a2335c304"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_group"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Address Space Structure"</span><span class="token punctuation">,</span><span class="token string-property property">"tab"</span><span class="token operator">:</span><span class="token string">"0113eb87060106be"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"disp"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token string">"7"</span><span class="token punctuation">,</span><span class="token string-property property">"collapse"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"0113eb87060106be"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_tab"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"OPC UA"</span><span class="token punctuation">,</span><span class="token string-property property">"icon"</span><span class="token operator">:</span><span class="token string">"dashboard"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">7</span><span class="token punctuation">,</span><span class="token string-property property">"disabled"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"hidden"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">}</span><span class="token punctuation">]</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-100" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>To understand what is going on in this flow, we must refer back to the OPC UA Simulation Server <code>Address Space</code> tab.</p>
<p>When we browse the OPC Server base folder structure in Node-RED, we will be browsing everything included under the <code>Objects</code> tree.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/address-space-GTnyuyqBAk-617.avif 617w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/address-space-GTnyuyqBAk-617.webp 617w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="address-space.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/address-space-GTnyuyqBAk-617.jpeg" width="617" height="574" /></picture>
In our flow, we get the base folder structure by using an OPC-UA Browser node, as shown, with an endpoint that points to our OPC UA Server endpoint url we grabbed earlier in this article. It is also worth noting we leave the <code>Topic</code> blank. By doing this, we will browse the entire folder structure by default.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/image-20230727-090252-Mo57laBVp4-650.avif 650w, https://flowfuse.com/img/image-20230727-090252-Mo57laBVp4-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/image-20230727-090252-Mo57laBVp4-650.webp 650w, https://flowfuse.com/img/image-20230727-090252-Mo57laBVp4-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/image-20230727-090252-Mo57laBVp4-650.jpeg 650w, https://flowfuse.com/img/image-20230727-090252-Mo57laBVp4-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="image-20230727-090252.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/image-20230727-090252-Mo57laBVp4-650.jpeg" width="1300" height="335" /></picture>
The configuration of the endpoint properties includes no security credentials, as shown below.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/endpoint-configure-ahbCzBrGLI-461.avif 461w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/endpoint-configure-ahbCzBrGLI-461.webp 461w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="endpoint-configure.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/endpoint-configure-ahbCzBrGLI-461.jpeg" width="461" height="369" /></picture></p>
<p>Using the output of a debug node, we get from the OPC UA Browser yield a payload with an array of 5 objects.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/address-debug-5FhYgmtk6--650.avif 650w, https://flowfuse.com/img/address-debug-5FhYgmtk6--1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/address-debug-5FhYgmtk6--650.webp 650w, https://flowfuse.com/img/address-debug-5FhYgmtk6--1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/address-debug-5FhYgmtk6--650.jpeg 650w, https://flowfuse.com/img/address-debug-5FhYgmtk6--1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="address-debug.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/address-debug-5FhYgmtk6--650.jpeg" width="1300" height="202" /></picture></p>
<p>Each object returned represents the 5 objects that are in our OPC UA Server Objects tree.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/browse-payload-1-SF32TKjJ39-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/browse-payload-1-SF32TKjJ39-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="browse-payload-1.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/browse-payload-1-SF32TKjJ39-650.jpeg" width="650" height="226" /></picture></p>
<p>However, of those 5 objects, only 3 of them are folders that contain actual OPC values. <code>MyObjects</code>, <code>Simulation</code>, and <code>StaticData</code>. We can ignore <code>Aliases</code> and <code>Server</code>.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/address-space-folders-only-wHXmvFf8t5-389.avif 389w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/address-space-folders-only-wHXmvFf8t5-389.webp 389w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="address-space-folders-only.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/address-space-folders-only-wHXmvFf8t5-389.jpeg" width="389" height="441" /></picture>
So looking deeper into the payload of our global browse from the <code>OPC UA Browser node</code>, we can drill down into the details and see how they correlate with the folders in the server.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/browse-node-if_5jPubJi-650.avif 650w, https://flowfuse.com/img/browse-node-if_5jPubJi-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/browse-node-if_5jPubJi-650.webp 650w, https://flowfuse.com/img/browse-node-if_5jPubJi-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/browse-node-if_5jPubJi-650.jpeg 650w, https://flowfuse.com/img/browse-node-if_5jPubJi-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="browse-node.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/browse-node-if_5jPubJi-650.jpeg" width="1300" height="1194" /></picture></p>
<p>As shown above, element 2 in the array returned from the global browse corresponds to the <code>Simulation</code> folder. And we are interested in two important values in this data-structure - the <code>NodeId</code>, which is topic an OPC Client uses to point specific OPC values, and the <code>browseName</code>, which is the name we see visually when we try to identify an OPC topic. We can now use this logic to parse out this useful information using a change node.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/simulation-folder-K6kzOji5J5-650.avif 650w, https://flowfuse.com/img/simulation-folder-K6kzOji5J5-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/simulation-folder-K6kzOji5J5-650.webp 650w, https://flowfuse.com/img/simulation-folder-K6kzOji5J5-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/simulation-folder-K6kzOji5J5-650.jpeg 650w, https://flowfuse.com/img/simulation-folder-K6kzOji5J5-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="simulation-folder.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/simulation-folder-K6kzOji5J5-650.jpeg" width="1300" height="548" /></picture>
This change node is grabbing the <code>nodeId</code> and <code>browseName</code> . The <code>nodeId</code> is stored in a context variable for later use, while the <code>browseName</code> is used as the payload to be displayed on our dashboard.</p>
<p>The rest of the flow follows this same pattern, to end up with a folder structure that we can display on our dashboard that matches the structure on our OPC Server</p>
<ul>
<li>note - to make the flow more manageable, not all browsable folders were included in the dashboard, as this flow is just meant to serve as an example, rather than be a 1:1 copy of everything in the server.</li>
</ul>
<p>If you deploy the flow and pull up the dashboard, it results in the following output -</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/address-space-dashboard-9gPXGaFC3L-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/address-space-dashboard-9gPXGaFC3L-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="address-space-dashboard.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/address-space-dashboard-9gPXGaFC3L-650.jpeg" width="650" height="435" /></picture>
Showing side-by-side with the server, you can see that we successfully browsed a portion of the address space and displayed the values on the dashboard. Admittedly, a lot of work for not much pay-off, but it’s a worthwhile exercise in understanding how to browse topics using the <code>OPC UA Browser</code> node. The browser node is best used for reading OPC UA values, which will be covered next.</p>
<h2 id="read-opc-ua-values-using-opc-ua-browser-node" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/how-to-build-a-opc-client-dashboard-in-node-red/#read-opc-ua-values-using-opc-ua-browser-node"># </a> Read OPC UA Values Using OPC UA Browser Node</h2>
<p>The next set of flows read OPC UA values from the server and displays them on the dashboard.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/read-opc-values-gfktuq8Poq-650.avif 650w, https://flowfuse.com/img/read-opc-values-gfktuq8Poq-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/read-opc-values-gfktuq8Poq-650.webp 650w, https://flowfuse.com/img/read-opc-values-gfktuq8Poq-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/read-opc-values-gfktuq8Poq-650.jpeg 650w, https://flowfuse.com/img/read-opc-values-gfktuq8Poq-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="read-opc-values.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/read-opc-values-gfktuq8Poq-650.jpeg" width="1300" height="723" /></picture>
You can import these flows into Node-RED using the code below:</p>
<div style="position: relative">
<pre class="language-javascript"><code id="code-168" class="language-javascript"><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"ab8e5ebe8c14819d"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"group"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Read Simulation Values & Display on Dashboard"</span><span class="token punctuation">,</span><span class="token string-property property">"style"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token string-property property">"stroke"</span><span class="token operator">:</span><span class="token string">"#a4a4a4"</span><span class="token punctuation">,</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"color"</span><span class="token operator">:</span><span class="token string">"#001f60"</span><span class="token punctuation">,</span><span class="token string-property property">"fill"</span><span class="token operator">:</span><span class="token string">"#ffffff"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token string-property property">"nodes"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"482da272d75f9fc9"</span><span class="token punctuation">,</span><span class="token string">"36b93ad2d6b4b695"</span><span class="token punctuation">,</span><span class="token string">"1819591e5ebae68d"</span><span class="token punctuation">,</span><span class="token string">"740c976dd5aca65a"</span><span class="token punctuation">,</span><span class="token string">"8d671460beac82d8"</span><span class="token punctuation">,</span><span class="token string">"80e5270d14633586"</span><span class="token punctuation">,</span><span class="token string">"de478581d1839a70"</span><span class="token punctuation">,</span><span class="token string">"0128582021fb3fbc"</span><span class="token punctuation">,</span><span class="token string">"454fe6a32820dbc9"</span><span class="token punctuation">,</span><span class="token string">"5e955dbca478356f"</span><span class="token punctuation">,</span><span class="token string">"57da7c9808e5fa56"</span><span class="token punctuation">,</span><span class="token string">"5658b05beada4467"</span><span class="token punctuation">,</span><span class="token string">"8f866373ed32349c"</span><span class="token punctuation">,</span><span class="token string">"35f53fe496f4f68a"</span><span class="token punctuation">,</span><span class="token string">"c9e043783aeaf0fa"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">34</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">519</span><span class="token punctuation">,</span><span class="token string-property property">"w"</span><span class="token operator">:</span><span class="token number">1372</span><span class="token punctuation">,</span><span class="token string-property property">"h"</span><span class="token operator">:</span><span class="token number">302</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"482da272d75f9fc9"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"OpcUa-Browser"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"ab8e5ebe8c14819d"</span><span class="token punctuation">,</span><span class="token string-property property">"endpoint"</span><span class="token operator">:</span><span class="token string">"53f4394dbf12c6b7"</span><span class="token punctuation">,</span><span class="token string-property property">"item"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"datatype"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"items"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"OPC Client Namespace Browse"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">510</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">680</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"80e5270d14633586"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"36b93ad2d6b4b695"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"ab8e5ebe8c14819d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Update Simulation Values @ 1 second"</span><span class="token punctuation">,</span><span class="token string-property property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"topic"</span><span class="token punctuation">,</span><span class="token string-property property">"v"</span><span class="token operator">:</span><span class="token string">"Objects.Simulation.nodeId"</span><span class="token punctuation">,</span><span class="token string-property property">"vt"</span><span class="token operator">:</span><span class="token string">"flow"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"repeat"</span><span class="token operator">:</span><span class="token string">"1"</span><span class="token punctuation">,</span><span class="token string-property property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"once"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"onceDelay"</span><span class="token operator">:</span><span class="token number">0.1</span><span class="token punctuation">,</span><span class="token string-property property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"payload"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"payloadType"</span><span class="token operator">:</span><span class="token string">"date"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">240</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">680</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"482da272d75f9fc9"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"1819591e5ebae68d"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"ab8e5ebe8c14819d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Read Simulation Values"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">400</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">640</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"740c976dd5aca65a"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"ab8e5ebe8c14819d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Get Counter Value"</span><span class="token punctuation">,</span><span class="token string-property property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload[1].item.value"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1010</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">600</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"8d671460beac82d8"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"8d671460beac82d8"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_gauge"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"ab8e5ebe8c14819d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"group"</span><span class="token operator">:</span><span class="token string">"825fe3323bd36ae6"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token string">"0"</span><span class="token punctuation">,</span><span class="token string-property property">"height"</span><span class="token operator">:</span><span class="token string">"0"</span><span class="token punctuation">,</span><span class="token string-property property">"gtype"</span><span class="token operator">:</span><span class="token string">"gage"</span><span class="token punctuation">,</span><span class="token string-property property">"title"</span><span class="token operator">:</span><span class="token string">"Counter"</span><span class="token punctuation">,</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token string">"units"</span><span class="token punctuation">,</span><span class="token string-property property">"format"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"min"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"max"</span><span class="token operator">:</span><span class="token string">"30"</span><span class="token punctuation">,</span><span class="token string-property property">"colors"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"#00b500"</span><span class="token punctuation">,</span><span class="token string">"#e6e600"</span><span class="token punctuation">,</span><span class="token string">"#ca3838"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"seg1"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"seg2"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"diff"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1260</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">600</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"80e5270d14633586"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"switch"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"ab8e5ebe8c14819d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"empty check"</span><span class="token punctuation">,</span><span class="token string-property property">"property"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token string-property property">"propertyType"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"nempty"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"checkall"</span><span class="token operator">:</span><span class="token string">"true"</span><span class="token punctuation">,</span><span class="token string-property property">"repair"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"outputs"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">730</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">680</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"740c976dd5aca65a"</span><span class="token punctuation">,</span><span class="token string">"de478581d1839a70"</span><span class="token punctuation">,</span><span class="token string">"454fe6a32820dbc9"</span><span class="token punctuation">,</span><span class="token string">"57da7c9808e5fa56"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"de478581d1839a70"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"ab8e5ebe8c14819d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Get Random Number Value"</span><span class="token punctuation">,</span><span class="token string-property property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload[2].item.value"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1040</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">660</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"0128582021fb3fbc"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"0128582021fb3fbc"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_text"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"ab8e5ebe8c14819d"</span><span class="token punctuation">,</span><span class="token string-property property">"group"</span><span class="token operator">:</span><span class="token string">"825fe3323bd36ae6"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">7</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token string">"Random Number"</span><span class="token punctuation">,</span><span class="token string-property property">"format"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"layout"</span><span class="token operator">:</span><span class="token string">"col-center"</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"style"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"font"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"fontSize"</span><span class="token operator">:</span><span class="token number">16</span><span class="token punctuation">,</span><span class="token string-property property">"color"</span><span class="token operator">:</span><span class="token string">"#000000"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1290</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">660</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"454fe6a32820dbc9"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"ab8e5ebe8c14819d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Get Sawtooth Value"</span><span class="token punctuation">,</span><span class="token string-property property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload[3].item.value"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1020</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">720</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"5e955dbca478356f"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"5e955dbca478356f"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_chart"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"ab8e5ebe8c14819d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"group"</span><span class="token operator">:</span><span class="token string">"825fe3323bd36ae6"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">8</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token string">"Sawtooth"</span><span class="token punctuation">,</span><span class="token string-property property">"chartType"</span><span class="token operator">:</span><span class="token string">"line"</span><span class="token punctuation">,</span><span class="token string-property property">"legend"</span><span class="token operator">:</span><span class="token string">"false"</span><span class="token punctuation">,</span><span class="token string-property property">"xformat"</span><span class="token operator">:</span><span class="token string">"HH:mm:ss"</span><span class="token punctuation">,</span><span class="token string-property property">"interpolate"</span><span class="token operator">:</span><span class="token string">"linear"</span><span class="token punctuation">,</span><span class="token string-property property">"nodata"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"dot"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"ymin"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"ymax"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"removeOlder"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"removeOlderPoints"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"removeOlderUnit"</span><span class="token operator">:</span><span class="token string">"60"</span><span class="token punctuation">,</span><span class="token string-property property">"cutout"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"useOneColor"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"useUTC"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"colors"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"#1f77b4"</span><span class="token punctuation">,</span><span class="token string">"#aec7e8"</span><span class="token punctuation">,</span><span class="token string">"#ff7f0e"</span><span class="token punctuation">,</span><span class="token string">"#2ca02c"</span><span class="token punctuation">,</span><span class="token string">"#98df8a"</span><span class="token punctuation">,</span><span class="token string">"#d62728"</span><span class="token punctuation">,</span><span class="token string">"#ff9896"</span><span class="token punctuation">,</span><span class="token string">"#9467bd"</span><span class="token punctuation">,</span><span class="token string">"#c5b0d5"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"outputs"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"useDifferentColor"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1260</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">720</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"57da7c9808e5fa56"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"ab8e5ebe8c14819d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Get Sawtooth Value"</span><span class="token punctuation">,</span><span class="token string-property property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload[4].item.value"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1020</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">780</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"5658b05beada4467"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"5658b05beada4467"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_chart"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"ab8e5ebe8c14819d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"group"</span><span class="token operator">:</span><span class="token string">"825fe3323bd36ae6"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">9</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token string">"Sinusoid"</span><span class="token punctuation">,</span><span class="token string-property property">"chartType"</span><span class="token operator">:</span><span class="token string">"line"</span><span class="token punctuation">,</span><span class="token string-property property">"legend"</span><span class="token operator">:</span><span class="token string">"false"</span><span class="token punctuation">,</span><span class="token string-property property">"xformat"</span><span class="token operator">:</span><span class="token string">"HH:mm:ss"</span><span class="token punctuation">,</span><span class="token string-property property">"interpolate"</span><span class="token operator">:</span><span class="token string">"linear"</span><span class="token punctuation">,</span><span class="token string-property property">"nodata"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"dot"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"ymin"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"ymax"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"removeOlder"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"removeOlderPoints"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"removeOlderUnit"</span><span class="token operator">:</span><span class="token string">"60"</span><span class="token punctuation">,</span><span class="token string-property property">"cutout"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"useOneColor"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"useUTC"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"colors"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"#1f77b4"</span><span class="token punctuation">,</span><span class="token string">"#aec7e8"</span><span class="token punctuation">,</span><span class="token string">"#ff7f0e"</span><span class="token punctuation">,</span><span class="token string">"#2ca02c"</span><span class="token punctuation">,</span><span class="token string">"#98df8a"</span><span class="token punctuation">,</span><span class="token string">"#d62728"</span><span class="token punctuation">,</span><span class="token string">"#ff9896"</span><span class="token punctuation">,</span><span class="token string">"#9467bd"</span><span class="token punctuation">,</span><span class="token string">"#c5b0d5"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"outputs"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"useDifferentColor"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1260</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">780</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"8f866373ed32349c"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"ab8e5ebe8c14819d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Discard Empty Datasets"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">720</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">640</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"35f53fe496f4f68a"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"ab8e5ebe8c14819d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Parse Simulation Values"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1010</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">560</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"c9e043783aeaf0fa"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"ab8e5ebe8c14819d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Display on Dashboard"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1280</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">560</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"53f4394dbf12c6b7"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"OpcUa-Endpoint"</span><span class="token punctuation">,</span><span class="token string-property property">"endpoint"</span><span class="token operator">:</span><span class="token string">"opc.tcp://192.168.0.141:53530/OPCUA/SimulationServer"</span><span class="token punctuation">,</span><span class="token string-property property">"secpol"</span><span class="token operator">:</span><span class="token string">"None"</span><span class="token punctuation">,</span><span class="token string-property property">"secmode"</span><span class="token operator">:</span><span class="token string">"None"</span><span class="token punctuation">,</span><span class="token string-property property">"none"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"login"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"usercert"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"usercertificate"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"userprivatekey"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"825fe3323bd36ae6"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_group"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Simulation Values"</span><span class="token punctuation">,</span><span class="token string-property property">"tab"</span><span class="token operator">:</span><span class="token string">"0113eb87060106be"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token string-property property">"disp"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token string">"6"</span><span class="token punctuation">,</span><span class="token string-property property">"collapse"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"0113eb87060106be"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_tab"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"OPC UA"</span><span class="token punctuation">,</span><span class="token string-property property">"icon"</span><span class="token operator">:</span><span class="token string">"dashboard"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">7</span><span class="token punctuation">,</span><span class="token string-property property">"disabled"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"hidden"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"23696c742b062ee0"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"group"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Read StaticData Values & Display on Dashboard"</span><span class="token punctuation">,</span><span class="token string-property property">"style"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token string-property property">"stroke"</span><span class="token operator">:</span><span class="token string">"#a4a4a4"</span><span class="token punctuation">,</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"color"</span><span class="token operator">:</span><span class="token string">"#000000"</span><span class="token punctuation">,</span><span class="token string-property property">"fill"</span><span class="token operator">:</span><span class="token string">"#ffffff"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token string-property property">"nodes"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"e573ccc34fdcde6e"</span><span class="token punctuation">,</span><span class="token string">"cf673bdce7b5b77a"</span><span class="token punctuation">,</span><span class="token string">"eb9263b229ec4811"</span><span class="token punctuation">,</span><span class="token string">"551d276aed309e6e"</span><span class="token punctuation">,</span><span class="token string">"9c84f8d19ae7ea45"</span><span class="token punctuation">,</span><span class="token string">"bf9e5ad82b0f9a0e"</span><span class="token punctuation">,</span><span class="token string">"14eaeb56e3922c6a"</span><span class="token punctuation">,</span><span class="token string">"12be1bc3729ee611"</span><span class="token punctuation">,</span><span class="token string">"d9f2b147a2519719"</span><span class="token punctuation">,</span><span class="token string">"09882f19a74faff8"</span><span class="token punctuation">,</span><span class="token string">"d89e22654946066d"</span><span class="token punctuation">,</span><span class="token string">"9c5762fc7fdbae59"</span><span class="token punctuation">,</span><span class="token string">"a5981d515cfadb55"</span><span class="token punctuation">,</span><span class="token string">"a736c876b46c763f"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">34</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">859</span><span class="token punctuation">,</span><span class="token string-property property">"w"</span><span class="token operator">:</span><span class="token number">1372</span><span class="token punctuation">,</span><span class="token string-property property">"h"</span><span class="token operator">:</span><span class="token number">202</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"e573ccc34fdcde6e"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"OpcUa-Browser"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"23696c742b062ee0"</span><span class="token punctuation">,</span><span class="token string-property property">"endpoint"</span><span class="token operator">:</span><span class="token string">"53f4394dbf12c6b7"</span><span class="token punctuation">,</span><span class="token string-property property">"item"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"datatype"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"items"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"OPC Client Namespace Browse"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">570</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">940</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"9c84f8d19ae7ea45"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"cf673bdce7b5b77a"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"23696c742b062ee0"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Update AnalogItemArrays Values @ 1 second"</span><span class="token punctuation">,</span><span class="token string-property property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"topic"</span><span class="token punctuation">,</span><span class="token string-property property">"v"</span><span class="token operator">:</span><span class="token string">"Objects.StaticData.AnalogItemArrays.nodeId"</span><span class="token punctuation">,</span><span class="token string-property property">"vt"</span><span class="token operator">:</span><span class="token string">"flow"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"repeat"</span><span class="token operator">:</span><span class="token string">"1"</span><span class="token punctuation">,</span><span class="token string-property property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"once"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"onceDelay"</span><span class="token operator">:</span><span class="token number">0.1</span><span class="token punctuation">,</span><span class="token string-property property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"payload"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"payloadType"</span><span class="token operator">:</span><span class="token string">"date"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">260</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">940</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"e573ccc34fdcde6e"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"eb9263b229ec4811"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"23696c742b062ee0"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Read StaticData Values"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">460</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">900</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"551d276aed309e6e"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"23696c742b062ee0"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Get ByteAnalogItemArray Value"</span><span class="token punctuation">,</span><span class="token string-property property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload[0].item.value"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1010</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">940</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"bf9e5ad82b0f9a0e"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"9c84f8d19ae7ea45"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"switch"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"23696c742b062ee0"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"empty check"</span><span class="token punctuation">,</span><span class="token string-property property">"property"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token string-property property">"propertyType"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"nempty"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"checkall"</span><span class="token operator">:</span><span class="token string">"true"</span><span class="token punctuation">,</span><span class="token string-property property">"repair"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"outputs"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">770</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">940</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"551d276aed309e6e"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"bf9e5ad82b0f9a0e"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_text"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"23696c742b062ee0"</span><span class="token punctuation">,</span><span class="token string-property property">"group"</span><span class="token operator">:</span><span class="token string">"92444e82445bab62"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token string">"ByteAnalogItemArray"</span><span class="token punctuation">,</span><span class="token string-property property">"format"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"layout"</span><span class="token operator">:</span><span class="token string">"col-center"</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"style"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"font"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"fontSize"</span><span class="token operator">:</span><span class="token number">16</span><span class="token punctuation">,</span><span class="token string-property property">"color"</span><span class="token operator">:</span><span class="token string">"#000000"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1280</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">940</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"14eaeb56e3922c6a"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"OpcUa-Browser"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"23696c742b062ee0"</span><span class="token punctuation">,</span><span class="token string-property property">"endpoint"</span><span class="token operator">:</span><span class="token string">"53f4394dbf12c6b7"</span><span class="token punctuation">,</span><span class="token string-property property">"item"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"datatype"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"items"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"OPC Client Namespace Browse"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">570</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1020</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"09882f19a74faff8"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"12be1bc3729ee611"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"23696c742b062ee0"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Update StaticArrayVariables Values @1 second"</span><span class="token punctuation">,</span><span class="token string-property property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"topic"</span><span class="token punctuation">,</span><span class="token string-property property">"v"</span><span class="token operator">:</span><span class="token string">"Objects.StaticData.StaticArrayVariables.nodeId"</span><span class="token punctuation">,</span><span class="token string-property property">"vt"</span><span class="token operator">:</span><span class="token string">"flow"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"repeat"</span><span class="token operator">:</span><span class="token string">"1"</span><span class="token punctuation">,</span><span class="token string-property property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"once"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"onceDelay"</span><span class="token operator">:</span><span class="token number">0.1</span><span class="token punctuation">,</span><span class="token string-property property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"payload"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"payloadType"</span><span class="token operator">:</span><span class="token string">"date"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">260</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1020</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"14eaeb56e3922c6a"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"d9f2b147a2519719"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"23696c742b062ee0"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Get BooleanArray Value"</span><span class="token punctuation">,</span><span class="token string-property property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload[0].item.value"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">990</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1020</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"d89e22654946066d"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"09882f19a74faff8"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"switch"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"23696c742b062ee0"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"empty check"</span><span class="token punctuation">,</span><span class="token string-property property">"property"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token string-property property">"propertyType"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"nempty"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"checkall"</span><span class="token operator">:</span><span class="token string">"true"</span><span class="token punctuation">,</span><span class="token string-property property">"repair"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"outputs"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">770</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1020</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"d9f2b147a2519719"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"d89e22654946066d"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_text"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"23696c742b062ee0"</span><span class="token punctuation">,</span><span class="token string-property property">"group"</span><span class="token operator">:</span><span class="token string">"92444e82445bab62"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token string">"BooleanArray"</span><span class="token punctuation">,</span><span class="token string-property property">"format"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"layout"</span><span class="token operator">:</span><span class="token string">"col-center"</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"style"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"font"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"fontSize"</span><span class="token operator">:</span><span class="token number">16</span><span class="token punctuation">,</span><span class="token string-property property">"color"</span><span class="token operator">:</span><span class="token string">"#000000"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1260</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1020</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"9c5762fc7fdbae59"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"23696c742b062ee0"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Discard Empty Datasets"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">760</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">900</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"a5981d515cfadb55"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"23696c742b062ee0"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Parse StaticData Values"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1010</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">900</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"a736c876b46c763f"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"23696c742b062ee0"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Display on Dashboard"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1280</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">900</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"92444e82445bab62"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_group"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"StaticData Values"</span><span class="token punctuation">,</span><span class="token string-property property">"tab"</span><span class="token operator">:</span><span class="token string">"0113eb87060106be"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token string-property property">"disp"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token string">"6"</span><span class="token punctuation">,</span><span class="token string-property property">"collapse"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"38f43e1ab70fe0cf"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"group"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Read MyDevice Values & Display on Dashboard"</span><span class="token punctuation">,</span><span class="token string-property property">"style"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"color"</span><span class="token operator">:</span><span class="token string">"#000000"</span><span class="token punctuation">,</span><span class="token string-property property">"fill"</span><span class="token operator">:</span><span class="token string">"#ffffff"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token string-property property">"nodes"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"513d07a651243e9e"</span><span class="token punctuation">,</span><span class="token string">"96294bbf031d67e8"</span><span class="token punctuation">,</span><span class="token string">"3140b66e39039a37"</span><span class="token punctuation">,</span><span class="token string">"8eda44307f47c12f"</span><span class="token punctuation">,</span><span class="token string">"cb0a56243f0a6b5e"</span><span class="token punctuation">,</span><span class="token string">"d6d60ff6a933ad1d"</span><span class="token punctuation">,</span><span class="token string">"7de0892e28c6fea9"</span><span class="token punctuation">,</span><span class="token string">"13c6bf381ff0d8b2"</span><span class="token punctuation">,</span><span class="token string">"8b48799434be36cf"</span><span class="token punctuation">,</span><span class="token string">"e29a74ea9a1de0ef"</span><span class="token punctuation">,</span><span class="token string">"a27699b4e9697558"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">34</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1099</span><span class="token punctuation">,</span><span class="token string-property property">"w"</span><span class="token operator">:</span><span class="token number">1292</span><span class="token punctuation">,</span><span class="token string-property property">"h"</span><span class="token operator">:</span><span class="token number">182</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"513d07a651243e9e"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"OpcUa-Browser"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"38f43e1ab70fe0cf"</span><span class="token punctuation">,</span><span class="token string-property property">"endpoint"</span><span class="token operator">:</span><span class="token string">"53f4394dbf12c6b7"</span><span class="token punctuation">,</span><span class="token string-property property">"item"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"datatype"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"items"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"OPC Client Namespace Browse"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">530</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1200</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"cb0a56243f0a6b5e"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"96294bbf031d67e8"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"38f43e1ab70fe0cf"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Read MyDevice Values @ 1 second"</span><span class="token punctuation">,</span><span class="token string-property property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"topic"</span><span class="token punctuation">,</span><span class="token string-property property">"v"</span><span class="token operator">:</span><span class="token string">"Objects.MyObjects.MyDevice.nodeId"</span><span class="token punctuation">,</span><span class="token string-property property">"vt"</span><span class="token operator">:</span><span class="token string">"flow"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"repeat"</span><span class="token operator">:</span><span class="token string">"1"</span><span class="token punctuation">,</span><span class="token string-property property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"once"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"onceDelay"</span><span class="token operator">:</span><span class="token number">0.1</span><span class="token punctuation">,</span><span class="token string-property property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"payload"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"payloadType"</span><span class="token operator">:</span><span class="token string">"date"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">230</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1200</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"513d07a651243e9e"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"3140b66e39039a37"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"38f43e1ab70fe0cf"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Read MyDevice"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">420</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1160</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"8eda44307f47c12f"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"38f43e1ab70fe0cf"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Get MyLevel Value"</span><span class="token punctuation">,</span><span class="token string-property property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload[0].item.value"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">970</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1180</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"7de0892e28c6fea9"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"cb0a56243f0a6b5e"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"switch"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"38f43e1ab70fe0cf"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"empty check"</span><span class="token punctuation">,</span><span class="token string-property property">"property"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token string-property property">"propertyType"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"nempty"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"checkall"</span><span class="token operator">:</span><span class="token string">"true"</span><span class="token punctuation">,</span><span class="token string-property property">"repair"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"outputs"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">750</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1200</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"8eda44307f47c12f"</span><span class="token punctuation">,</span><span class="token string">"d6d60ff6a933ad1d"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"d6d60ff6a933ad1d"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"38f43e1ab70fe0cf"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Get MySwitch Value"</span><span class="token punctuation">,</span><span class="token string-property property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload[4].item.value"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">980</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1240</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"13c6bf381ff0d8b2"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"7de0892e28c6fea9"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_gauge"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"38f43e1ab70fe0cf"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"group"</span><span class="token operator">:</span><span class="token string">"b095aee62f84e514"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">4</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token string">"0"</span><span class="token punctuation">,</span><span class="token string-property property">"height"</span><span class="token operator">:</span><span class="token string">"0"</span><span class="token punctuation">,</span><span class="token string-property property">"gtype"</span><span class="token operator">:</span><span class="token string">"wave"</span><span class="token punctuation">,</span><span class="token string-property property">"title"</span><span class="token operator">:</span><span class="token string">"MyLevel"</span><span class="token punctuation">,</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token string">"%"</span><span class="token punctuation">,</span><span class="token string-property property">"format"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"min"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"max"</span><span class="token operator">:</span><span class="token string">"100"</span><span class="token punctuation">,</span><span class="token string-property property">"colors"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"#00b500"</span><span class="token punctuation">,</span><span class="token string">"#e6e600"</span><span class="token punctuation">,</span><span class="token string">"#ca3838"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"seg1"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"seg2"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"diff"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1200</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1180</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"13c6bf381ff0d8b2"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_led"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"38f43e1ab70fe0cf"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token string-property property">"group"</span><span class="token operator">:</span><span class="token string">"b095aee62f84e514"</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token string">"MySwitch"</span><span class="token punctuation">,</span><span class="token string-property property">"labelPlacement"</span><span class="token operator">:</span><span class="token string">"left"</span><span class="token punctuation">,</span><span class="token string-property property">"labelAlignment"</span><span class="token operator">:</span><span class="token string">"left"</span><span class="token punctuation">,</span><span class="token string-property property">"colorForValue"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"color"</span><span class="token operator">:</span><span class="token string">"#ff0000"</span><span class="token punctuation">,</span><span class="token string-property property">"value"</span><span class="token operator">:</span><span class="token string">"false"</span><span class="token punctuation">,</span><span class="token string-property property">"valueType"</span><span class="token operator">:</span><span class="token string">"bool"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"color"</span><span class="token operator">:</span><span class="token string">"#008000"</span><span class="token punctuation">,</span><span class="token string-property property">"value"</span><span class="token operator">:</span><span class="token string">"true"</span><span class="token punctuation">,</span><span class="token string-property property">"valueType"</span><span class="token operator">:</span><span class="token string">"bool"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"allowColorForValueInMessage"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"shape"</span><span class="token operator">:</span><span class="token string">"circle"</span><span class="token punctuation">,</span><span class="token string-property property">"showGlow"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1190</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1240</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"8b48799434be36cf"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"38f43e1ab70fe0cf"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Display on Dashboard"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1200</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1140</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"e29a74ea9a1de0ef"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"38f43e1ab70fe0cf"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Parse MyDevice Values"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">980</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1140</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"a27699b4e9697558"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"38f43e1ab70fe0cf"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Discard Empty Datasets"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">740</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1160</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"b095aee62f84e514"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_group"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"MyDevice Status & Control"</span><span class="token punctuation">,</span><span class="token string-property property">"tab"</span><span class="token operator">:</span><span class="token string">"0113eb87060106be"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">4</span><span class="token punctuation">,</span><span class="token string-property property">"disp"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token string">"6"</span><span class="token punctuation">,</span><span class="token string-property property">"collapse"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">}</span><span class="token punctuation">]</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-168" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>The values are derived from the <code>nodeId</code> values we stored in memory in our previous flow, via our <code>change</code> nodes in the previous flow.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/flow-context-nodeid-6rC5Y9yn2t-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/flow-context-nodeid-6rC5Y9yn2t-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="flow-context-nodeid.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/flow-context-nodeid-6rC5Y9yn2t-650.jpeg" width="650" height="923" /></picture>
As stated earlier, you reference a OPC UA topic by its <code>nodeId</code>. So we will use these node IDs to read actual values from our OPC nodes.</p>
<p>In our first flow, we want to read the values in the <code>Simulation</code> folder at a 1 second interval. So we use an <code>inject</code> node with a <code>msg.topic</code> that references the <code>nodeId</code> corresponding to the <code>Simulation</code> folder.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/simulation-injection-Q-sJSo3Ig8-650.avif 650w, https://flowfuse.com/img/simulation-injection-Q-sJSo3Ig8-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/simulation-injection-Q-sJSo3Ig8-650.webp 650w, https://flowfuse.com/img/simulation-injection-Q-sJSo3Ig8-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/simulation-injection-Q-sJSo3Ig8-650.jpeg 650w, https://flowfuse.com/img/simulation-injection-Q-sJSo3Ig8-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="simulation-injection.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/simulation-injection-Q-sJSo3Ig8-650.jpeg" width="1300" height="807" /></picture>
That <code>msg.topic</code> tells the <code>OPC UA Browser</code> node what <code>nodeId</code> to browse. If we look at the debug output of the browser <code>msg.payload</code>, we can see that it produces an array of 7 objects, and an empty set array.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/simulation-debug-jWOAJlLbRY-650.avif 650w, https://flowfuse.com/img/simulation-debug-jWOAJlLbRY-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/simulation-debug-jWOAJlLbRY-650.webp 650w, https://flowfuse.com/img/simulation-debug-jWOAJlLbRY-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/simulation-debug-jWOAJlLbRY-650.jpeg 650w, https://flowfuse.com/img/simulation-debug-jWOAJlLbRY-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="simulation-debug.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/simulation-debug-jWOAJlLbRY-650.jpeg" width="1300" height="313" /></picture>
If we allow that empty array to be passed, that means all values will be reset to 0 on each read. So to prevent that from happening, we use a <code>switch</code> node to filter out the empty set.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/empty-check-PxeQZ-0nXA-650.avif 650w, https://flowfuse.com/img/empty-check-PxeQZ-0nXA-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/empty-check-PxeQZ-0nXA-650.webp 650w, https://flowfuse.com/img/empty-check-PxeQZ-0nXA-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/empty-check-PxeQZ-0nXA-650.jpeg 650w, https://flowfuse.com/img/empty-check-PxeQZ-0nXA-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="empty-check.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/empty-check-PxeQZ-0nXA-650.jpeg" width="1300" height="1196" /></picture>
Now only non-empty payloads will be passed, preventing the values being reset to 0 on each read.</p>
<p>Now we can actually read the values. To do this, we use a <code>change</code> node again, referencing the non-empty payload and drilling down to the <code>value</code> that corresponds to the <code>name</code> of the node we want to read. In this case, we’re getting the value of the node <code>Counter</code> located in the <code>Simulation</code> folder.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/get-counter-value-_U-Vv5c-Bb-650.avif 650w, https://flowfuse.com/img/get-counter-value-_U-Vv5c-Bb-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/get-counter-value-_U-Vv5c-Bb-650.webp 650w, https://flowfuse.com/img/get-counter-value-_U-Vv5c-Bb-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/get-counter-value-_U-Vv5c-Bb-650.jpeg 650w, https://flowfuse.com/img/get-counter-value-_U-Vv5c-Bb-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="get-counter-value.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/get-counter-value-_U-Vv5c-Bb-650.jpeg" width="1300" height="587" /></picture>
Going back to our OPC Server, we can see that exactly where that value is derived below -</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/sim-counter-server-ibKYm0jerQ-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/sim-counter-server-ibKYm0jerQ-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="sim-counter-server.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/sim-counter-server-ibKYm0jerQ-650.jpeg" width="650" height="450" /></picture></p>
<p>Now we add a <code>gauge</code> dashboard node to visualize the counter on the dashboard. In the OPC Server, it is shown that the counter increments in a range of 0-30 in 1 count increments.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/counter-properties-50YBzS9T7x-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/counter-properties-50YBzS9T7x-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="counter-properties.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/counter-properties-50YBzS9T7x-650.jpeg" width="650" height="565" /></picture>
Now that we’ve gone through the full process of reading an OPC UA value and displaying it on the dashboard, we can apply the same logic other values published by the OPC UA Server, which are repeated in the remaining parts of the flow.</p>
<p>The end result on the dashboard now looks like this -</p>
<p><picture><source type="image/gif" srcset="https://flowfuse.com/img/opc-read-dashboard-BTdDag-r9a-650.gif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="opc-read-dashboard.gif" loading="lazy" decoding="async" src="https://flowfuse.com/img/opc-read-dashboard-BTdDag-r9a-650.webp" width="650" height="365" /></picture></p>
<h2 id="write-opc-ua-values-to-server-using-opcua-item-and-opc-ua-client-nodes" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/how-to-build-a-opc-client-dashboard-in-node-red/#write-opc-ua-values-to-server-using-opcua-item-and-opc-ua-client-nodes"># </a> Write OPC UA Values To Server Using OpcUa-Item and Opc-Ua-Client Nodes</h2>
<p>The next flow writes OPC UA values to the server using dashboard UI elements.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/write-mydevice-eIU3YiDe1z-650.avif 650w, https://flowfuse.com/img/write-mydevice-eIU3YiDe1z-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/write-mydevice-eIU3YiDe1z-650.webp 650w, https://flowfuse.com/img/write-mydevice-eIU3YiDe1z-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/write-mydevice-eIU3YiDe1z-650.jpeg 650w, https://flowfuse.com/img/write-mydevice-eIU3YiDe1z-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="write-mydevice.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/write-mydevice-eIU3YiDe1z-650.jpeg" width="1300" height="385" /></picture>
You can import this flow into Node-RED using the code below:</p>
<div style="position: relative">
<pre class="language-javascript"><code id="code-217" class="language-javascript"><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"b1eeba37b0d982ef"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"group"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Write MyDevice Values to OPC UA Server"</span><span class="token punctuation">,</span><span class="token string-property property">"style"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"color"</span><span class="token operator">:</span><span class="token string">"#000000"</span><span class="token punctuation">,</span><span class="token string-property property">"fill"</span><span class="token operator">:</span><span class="token string">"#ffffff"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token string-property property">"nodes"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"2cb01ef75f8b5f39"</span><span class="token punctuation">,</span><span class="token string">"36daedb0c2a5295d"</span><span class="token punctuation">,</span><span class="token string">"f6d73ab104914017"</span><span class="token punctuation">,</span><span class="token string">"16224a3eefb5184e"</span><span class="token punctuation">,</span><span class="token string">"711c6f36547b4efb"</span><span class="token punctuation">,</span><span class="token string">"cb0e16ceab421d58"</span><span class="token punctuation">,</span><span class="token string">"968a8b27d03f6372"</span><span class="token punctuation">,</span><span class="token string">"19c427f70d0ed845"</span><span class="token punctuation">,</span><span class="token string">"01153fddbbb2cd73"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">74</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1399</span><span class="token punctuation">,</span><span class="token string-property property">"w"</span><span class="token operator">:</span><span class="token number">792</span><span class="token punctuation">,</span><span class="token string-property property">"h"</span><span class="token operator">:</span><span class="token number">182</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"2cb01ef75f8b5f39"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_switch"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"b1eeba37b0d982ef"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token string">"Toggle MySwitch"</span><span class="token punctuation">,</span><span class="token string-property property">"tooltip"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"group"</span><span class="token operator">:</span><span class="token string">"d60c2dfabc359e22"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"passthru"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"decouple"</span><span class="token operator">:</span><span class="token string">"false"</span><span class="token punctuation">,</span><span class="token string-property property">"topic"</span><span class="token operator">:</span><span class="token string">"topic"</span><span class="token punctuation">,</span><span class="token string-property property">"topicType"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"style"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"onvalue"</span><span class="token operator">:</span><span class="token string">"true"</span><span class="token punctuation">,</span><span class="token string-property property">"onvalueType"</span><span class="token operator">:</span><span class="token string">"bool"</span><span class="token punctuation">,</span><span class="token string-property property">"onicon"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"oncolor"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"offvalue"</span><span class="token operator">:</span><span class="token string">"false"</span><span class="token punctuation">,</span><span class="token string-property property">"offvalueType"</span><span class="token operator">:</span><span class="token string">"bool"</span><span class="token punctuation">,</span><span class="token string-property property">"officon"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"offcolor"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"animate"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">190</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1480</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"36daedb0c2a5295d"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"36daedb0c2a5295d"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"OpcUa-Item"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"b1eeba37b0d982ef"</span><span class="token punctuation">,</span><span class="token string-property property">"item"</span><span class="token operator">:</span><span class="token string">"ns=6;s=MySwitch"</span><span class="token punctuation">,</span><span class="token string-property property">"datatype"</span><span class="token operator">:</span><span class="token string">"Boolean"</span><span class="token punctuation">,</span><span class="token string-property property">"value"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Toggle MySwitch"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">450</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1480</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"f6d73ab104914017"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"f6d73ab104914017"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"OpcUa-Client"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"b1eeba37b0d982ef"</span><span class="token punctuation">,</span><span class="token string-property property">"endpoint"</span><span class="token operator">:</span><span class="token string">"53f4394dbf12c6b7"</span><span class="token punctuation">,</span><span class="token string-property property">"action"</span><span class="token operator">:</span><span class="token string">"write"</span><span class="token punctuation">,</span><span class="token string-property property">"deadbandtype"</span><span class="token operator">:</span><span class="token string">"a"</span><span class="token punctuation">,</span><span class="token string-property property">"deadbandvalue"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"time"</span><span class="token operator">:</span><span class="token number">10</span><span class="token punctuation">,</span><span class="token string-property property">"timeUnit"</span><span class="token operator">:</span><span class="token string">"s"</span><span class="token punctuation">,</span><span class="token string-property property">"certificate"</span><span class="token operator">:</span><span class="token string">"n"</span><span class="token punctuation">,</span><span class="token string-property property">"localfile"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"localkeyfile"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"securitymode"</span><span class="token operator">:</span><span class="token string">"None"</span><span class="token punctuation">,</span><span class="token string-property property">"securitypolicy"</span><span class="token operator">:</span><span class="token string">"None"</span><span class="token punctuation">,</span><span class="token string-property property">"folderName4PKI"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"useTransport"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"maxChunkCount"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"maxMessageSize"</span><span class="token operator">:</span><span class="token number">8192</span><span class="token punctuation">,</span><span class="token string-property property">"receiveBufferSize"</span><span class="token operator">:</span><span class="token number">8192</span><span class="token punctuation">,</span><span class="token string-property property">"sendBufferSize"</span><span class="token operator">:</span><span class="token number">8192</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Write MySwitch"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">700</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1480</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"16224a3eefb5184e"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"b1eeba37b0d982ef"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Dashboard Input"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">180</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1440</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"711c6f36547b4efb"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_slider"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"b1eeba37b0d982ef"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token string">"Modify MyLevel"</span><span class="token punctuation">,</span><span class="token string-property property">"tooltip"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"group"</span><span class="token operator">:</span><span class="token string">"d60c2dfabc359e22"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"passthru"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"outs"</span><span class="token operator">:</span><span class="token string">"all"</span><span class="token punctuation">,</span><span class="token string-property property">"topic"</span><span class="token operator">:</span><span class="token string">"topic"</span><span class="token punctuation">,</span><span class="token string-property property">"topicType"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"min"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"max"</span><span class="token operator">:</span><span class="token string">"100"</span><span class="token punctuation">,</span><span class="token string-property property">"step"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">180</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1540</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"cb0e16ceab421d58"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"cb0e16ceab421d58"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"OpcUa-Item"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"b1eeba37b0d982ef"</span><span class="token punctuation">,</span><span class="token string-property property">"item"</span><span class="token operator">:</span><span class="token string">"ns=6;s=MyLevel"</span><span class="token punctuation">,</span><span class="token string-property property">"datatype"</span><span class="token operator">:</span><span class="token string">"Double"</span><span class="token punctuation">,</span><span class="token string-property property">"value"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Modify MyLevel"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">440</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1540</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"968a8b27d03f6372"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"968a8b27d03f6372"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"OpcUa-Client"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"b1eeba37b0d982ef"</span><span class="token punctuation">,</span><span class="token string-property property">"endpoint"</span><span class="token operator">:</span><span class="token string">"53f4394dbf12c6b7"</span><span class="token punctuation">,</span><span class="token string-property property">"action"</span><span class="token operator">:</span><span class="token string">"write"</span><span class="token punctuation">,</span><span class="token string-property property">"deadbandtype"</span><span class="token operator">:</span><span class="token string">"a"</span><span class="token punctuation">,</span><span class="token string-property property">"deadbandvalue"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"time"</span><span class="token operator">:</span><span class="token number">10</span><span class="token punctuation">,</span><span class="token string-property property">"timeUnit"</span><span class="token operator">:</span><span class="token string">"s"</span><span class="token punctuation">,</span><span class="token string-property property">"certificate"</span><span class="token operator">:</span><span class="token string">"n"</span><span class="token punctuation">,</span><span class="token string-property property">"localfile"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"localkeyfile"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"securitymode"</span><span class="token operator">:</span><span class="token string">"None"</span><span class="token punctuation">,</span><span class="token string-property property">"securitypolicy"</span><span class="token operator">:</span><span class="token string">"None"</span><span class="token punctuation">,</span><span class="token string-property property">"folderName4PKI"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"useTransport"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"maxChunkCount"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"maxMessageSize"</span><span class="token operator">:</span><span class="token number">8192</span><span class="token punctuation">,</span><span class="token string-property property">"receiveBufferSize"</span><span class="token operator">:</span><span class="token number">8192</span><span class="token punctuation">,</span><span class="token string-property property">"sendBufferSize"</span><span class="token operator">:</span><span class="token number">8192</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Write MyLevel"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">700</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1540</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"19c427f70d0ed845"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"b1eeba37b0d982ef"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Call OPC UA Item"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">450</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1440</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"01153fddbbb2cd73"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"b1eeba37b0d982ef"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Write OPC UA Item to Client"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">720</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1440</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"d60c2dfabc359e22"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_group"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Barcode Scanner"</span><span class="token punctuation">,</span><span class="token string-property property">"tab"</span><span class="token operator">:</span><span class="token string">"b7603898c5b527e4"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token string-property property">"disp"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token string">"12"</span><span class="token punctuation">,</span><span class="token string-property property">"collapse"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"53f4394dbf12c6b7"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"OpcUa-Endpoint"</span><span class="token punctuation">,</span><span class="token string-property property">"endpoint"</span><span class="token operator">:</span><span class="token string">"opc.tcp://192.168.0.141:53530/OPCUA/SimulationServer"</span><span class="token punctuation">,</span><span class="token string-property property">"secpol"</span><span class="token operator">:</span><span class="token string">"None"</span><span class="token punctuation">,</span><span class="token string-property property">"secmode"</span><span class="token operator">:</span><span class="token string">"None"</span><span class="token punctuation">,</span><span class="token string-property property">"none"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"login"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"usercert"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"usercertificate"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"userprivatekey"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"b7603898c5b527e4"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_tab"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Camera"</span><span class="token punctuation">,</span><span class="token string-property property">"icon"</span><span class="token operator">:</span><span class="token string">"camera"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">5</span><span class="token punctuation">,</span><span class="token string-property property">"disabled"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"hidden"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">}</span><span class="token punctuation">]</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-217" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>We have two values to write, a boolean value corresponding to the node object <code>MySwitch</code>, and an integer value corresponding to the object <code>MyLevel</code>. Therefore, we will use a toggle switch to toggle the <code>MySwitch</code>, and a slider to modify <code>MyLevel</code>.</p>
<p>There’s no need to modify the toggle switch properties, other than giving it a name. The slider needs to have the range modified to match the range of the level, which is 0-100%.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/level-range-exaL1QwQLR-650.avif 650w, https://flowfuse.com/img/level-range-exaL1QwQLR-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/level-range-exaL1QwQLR-650.webp 650w, https://flowfuse.com/img/level-range-exaL1QwQLR-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/level-range-exaL1QwQLR-650.jpeg 650w, https://flowfuse.com/img/level-range-exaL1QwQLR-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="level-range.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/level-range-exaL1QwQLR-650.jpeg" width="1300" height="489" /></picture>
For the <code>OpcUa-Item</code> nodes, copy the <code>NodeId</code> corresponding to each device,</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/copy-node-id-gvbKOWOD1W-650.avif 650w, https://flowfuse.com/img/copy-node-id-gvbKOWOD1W-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/copy-node-id-gvbKOWOD1W-650.webp 650w, https://flowfuse.com/img/copy-node-id-gvbKOWOD1W-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/copy-node-id-gvbKOWOD1W-650.jpeg 650w, https://flowfuse.com/img/copy-node-id-gvbKOWOD1W-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="copy-node-id.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/copy-node-id-gvbKOWOD1W-650.jpeg" width="1300" height="324" /></picture>
and paste it into <code>OpcUa-Item</code> node. You must also ensure the data-type matches with the value you’re writing to.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/opcua-item-NMw9sxkqdz-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/opcua-item-NMw9sxkqdz-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="opcua-item.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/opcua-item-NMw9sxkqdz-650.jpeg" width="650" height="437" /></picture>
The <code>Opc-Ua-Client</code> needs to have an endpoint and the action changed to <code>WRITE</code>.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/client-node-Mcbyiq-uwV-650.avif 650w, https://flowfuse.com/img/client-node-Mcbyiq-uwV-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/client-node-Mcbyiq-uwV-650.webp 650w, https://flowfuse.com/img/client-node-Mcbyiq-uwV-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/client-node-Mcbyiq-uwV-650.jpeg 650w, https://flowfuse.com/img/client-node-Mcbyiq-uwV-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="client-node.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/client-node-Mcbyiq-uwV-650.jpeg" width="1300" height="797" /></picture>
The process is the same for <code>MySwitch</code> and <code>MyLevel</code>, the only difference being what <code>NodeId</code> is referenced in the <code>OpcUa-Item</code> node.</p>
<p>When deployed, you can confirm values are being written to from the client to the server from the dashboard.</p>
<video width="560" height="315" controls="">
<source src="https://website-data.s3.eu-west-1.amazonaws.com/opc-write.mp4" type="video/mp4" />
</video>
<h2 id="read-alarms-%26-events-from-opc-ua-server-using-opcua-event-and-opc-ua-client-nodes" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/how-to-build-a-opc-client-dashboard-in-node-red/#read-alarms-%26-events-from-opc-ua-server-using-opcua-event-and-opc-ua-client-nodes"># </a> Read Alarms & Events from OPC UA Server Using OpcUa-Event and Opc-Ua-Client Nodes</h2>
<p>Our last flow we’ll show how to read OPC UA Alarms & Events.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/opc-event-flow-m_JiU7yphR-650.avif 650w, https://flowfuse.com/img/opc-event-flow-m_JiU7yphR-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/opc-event-flow-m_JiU7yphR-650.webp 650w, https://flowfuse.com/img/opc-event-flow-m_JiU7yphR-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/opc-event-flow-m_JiU7yphR-650.jpeg 650w, https://flowfuse.com/img/opc-event-flow-m_JiU7yphR-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="opc-event-flow.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/opc-event-flow-m_JiU7yphR-650.jpeg" width="1300" height="334" /></picture>
You can import this flow into Node-RED using the code below:</p>
<div style="position: relative">
<pre class="language-javascript"><code id="code-249" class="language-javascript"><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"3013af7593f2847b"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"group"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Read Alarms & Events From OPC UA Server"</span><span class="token punctuation">,</span><span class="token string-property property">"style"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"color"</span><span class="token operator">:</span><span class="token string">"#000000"</span><span class="token punctuation">,</span><span class="token string-property property">"fill"</span><span class="token operator">:</span><span class="token string">"#ffffff"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token string-property property">"nodes"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"bd95b96ed77a621c"</span><span class="token punctuation">,</span><span class="token string">"26b7db518e4ac448"</span><span class="token punctuation">,</span><span class="token string">"05b98e27c8317489"</span><span class="token punctuation">,</span><span class="token string">"67aa6d2ecee3895b"</span><span class="token punctuation">,</span><span class="token string">"bfb585c5777dfeca"</span><span class="token punctuation">,</span><span class="token string">"4c47ed5a65160149"</span><span class="token punctuation">,</span><span class="token string">"b6d318d3372e149f"</span><span class="token punctuation">,</span><span class="token string">"8d36820730690d7d"</span><span class="token punctuation">,</span><span class="token string">"87eb7ad331a15823"</span><span class="token punctuation">,</span><span class="token string">"fd228940746d2e4c"</span><span class="token punctuation">,</span><span class="token string">"564212f76a83ce5e"</span><span class="token punctuation">,</span><span class="token string">"8a06f75c33593dc1"</span><span class="token punctuation">,</span><span class="token string">"6ba832b756579002"</span><span class="token punctuation">,</span><span class="token string">"be911708a19728b0"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">54</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1639</span><span class="token punctuation">,</span><span class="token string-property property">"w"</span><span class="token operator">:</span><span class="token number">1332</span><span class="token punctuation">,</span><span class="token string-property property">"h"</span><span class="token operator">:</span><span class="token number">282</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"bd95b96ed77a621c"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3013af7593f2847b"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Call OPC UA Item"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">430</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1780</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"26b7db518e4ac448"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"OpcUa-Event"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3013af7593f2847b"</span><span class="token punctuation">,</span><span class="token string-property property">"root"</span><span class="token operator">:</span><span class="token string">"ns=6;s=MyLevel.Alarm"</span><span class="token punctuation">,</span><span class="token string-property property">"activatecustomevent"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"eventtype"</span><span class="token operator">:</span><span class="token string">"i=2041"</span><span class="token punctuation">,</span><span class="token string-property property">"customeventtype"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"MyLevel Alarms"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">460</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1820</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"67aa6d2ecee3895b"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"05b98e27c8317489"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3013af7593f2847b"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Trigger Alarm Event Capture"</span><span class="token punctuation">,</span><span class="token string-property property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"topic"</span><span class="token punctuation">,</span><span class="token string-property property">"vt"</span><span class="token operator">:</span><span class="token string">"str"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"repeat"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"once"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"onceDelay"</span><span class="token operator">:</span><span class="token number">0.1</span><span class="token punctuation">,</span><span class="token string-property property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"payload"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"payloadType"</span><span class="token operator">:</span><span class="token string">"date"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">220</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1820</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"26b7db518e4ac448"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"67aa6d2ecee3895b"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"OpcUa-Client"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3013af7593f2847b"</span><span class="token punctuation">,</span><span class="token string-property property">"endpoint"</span><span class="token operator">:</span><span class="token string">"53f4394dbf12c6b7"</span><span class="token punctuation">,</span><span class="token string-property property">"action"</span><span class="token operator">:</span><span class="token string">"events"</span><span class="token punctuation">,</span><span class="token string-property property">"deadbandtype"</span><span class="token operator">:</span><span class="token string">"a"</span><span class="token punctuation">,</span><span class="token string-property property">"deadbandvalue"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"time"</span><span class="token operator">:</span><span class="token number">10</span><span class="token punctuation">,</span><span class="token string-property property">"timeUnit"</span><span class="token operator">:</span><span class="token string">"s"</span><span class="token punctuation">,</span><span class="token string-property property">"certificate"</span><span class="token operator">:</span><span class="token string">"n"</span><span class="token punctuation">,</span><span class="token string-property property">"localfile"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"localkeyfile"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"securitymode"</span><span class="token operator">:</span><span class="token string">"None"</span><span class="token punctuation">,</span><span class="token string-property property">"securitypolicy"</span><span class="token operator">:</span><span class="token string">"None"</span><span class="token punctuation">,</span><span class="token string-property property">"folderName4PKI"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"useTransport"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"maxChunkCount"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"maxMessageSize"</span><span class="token operator">:</span><span class="token number">8192</span><span class="token punctuation">,</span><span class="token string-property property">"receiveBufferSize"</span><span class="token operator">:</span><span class="token number">8192</span><span class="token punctuation">,</span><span class="token string-property property">"sendBufferSize"</span><span class="token operator">:</span><span class="token number">8192</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Get MyLevel Events"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">680</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1820</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"4c47ed5a65160149"</span><span class="token punctuation">,</span><span class="token string">"8d36820730690d7d"</span><span class="token punctuation">,</span><span class="token string">"87eb7ad331a15823"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"bfb585c5777dfeca"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_text"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3013af7593f2847b"</span><span class="token punctuation">,</span><span class="token string-property property">"group"</span><span class="token operator">:</span><span class="token string">"b095aee62f84e514"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">5</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token string">"Latest MyLevel Event"</span><span class="token punctuation">,</span><span class="token string-property property">"format"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"layout"</span><span class="token operator">:</span><span class="token string">"col-center"</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"style"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"font"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"fontSize"</span><span class="token operator">:</span><span class="token number">16</span><span class="token punctuation">,</span><span class="token string-property property">"color"</span><span class="token operator">:</span><span class="token string">"#000000"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1180</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1780</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"4c47ed5a65160149"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3013af7593f2847b"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Event Text"</span><span class="token punctuation">,</span><span class="token string-property property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload.Message.text"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">950</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1760</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"bfb585c5777dfeca"</span><span class="token punctuation">,</span><span class="token string">"564212f76a83ce5e"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"b6d318d3372e149f"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_text"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3013af7593f2847b"</span><span class="token punctuation">,</span><span class="token string-property property">"group"</span><span class="token operator">:</span><span class="token string">"b095aee62f84e514"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">7</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token string">"Latest MyLevel Event Timestamp"</span><span class="token punctuation">,</span><span class="token string-property property">"format"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"layout"</span><span class="token operator">:</span><span class="token string">"col-center"</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"style"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"font"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"fontSize"</span><span class="token operator">:</span><span class="token number">16</span><span class="token punctuation">,</span><span class="token string-property property">"color"</span><span class="token operator">:</span><span class="token string">"#000000"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1220</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1820</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"8d36820730690d7d"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3013af7593f2847b"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Event Time"</span><span class="token punctuation">,</span><span class="token string-property property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload.Time"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">950</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1820</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"b6d318d3372e149f"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"87eb7ad331a15823"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3013af7593f2847b"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Event Severity"</span><span class="token punctuation">,</span><span class="token string-property property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload.Severity"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">960</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1880</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"fd228940746d2e4c"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"fd228940746d2e4c"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_text"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3013af7593f2847b"</span><span class="token punctuation">,</span><span class="token string-property property">"group"</span><span class="token operator">:</span><span class="token string">"b095aee62f84e514"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">6</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token string">"Latest MyLevel Event Severity"</span><span class="token punctuation">,</span><span class="token string-property property">"format"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"layout"</span><span class="token operator">:</span><span class="token string">"col-center"</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"style"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"font"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"fontSize"</span><span class="token operator">:</span><span class="token number">16</span><span class="token punctuation">,</span><span class="token string-property property">"color"</span><span class="token operator">:</span><span class="token string">"#000000"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1210</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1880</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"564212f76a83ce5e"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_toast"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3013af7593f2847b"</span><span class="token punctuation">,</span><span class="token string-property property">"position"</span><span class="token operator">:</span><span class="token string">"top right"</span><span class="token punctuation">,</span><span class="token string-property property">"displayTime"</span><span class="token operator">:</span><span class="token string">"3"</span><span class="token punctuation">,</span><span class="token string-property property">"highlight"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"sendall"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"outputs"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"ok"</span><span class="token operator">:</span><span class="token string">"OK"</span><span class="token punctuation">,</span><span class="token string-property property">"cancel"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"raw"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Event Notification"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1170</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1720</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"8a06f75c33593dc1"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3013af7593f2847b"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Parse Event Dataset"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">950</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1720</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"6ba832b756579002"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3013af7593f2847b"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Get OPC Events from Client"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">680</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1780</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"be911708a19728b0"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3013af7593f2847b"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Display Events on Dashboard"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1200</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1680</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"53f4394dbf12c6b7"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"OpcUa-Endpoint"</span><span class="token punctuation">,</span><span class="token string-property property">"endpoint"</span><span class="token operator">:</span><span class="token string">"opc.tcp://192.168.0.141:53530/OPCUA/SimulationServer"</span><span class="token punctuation">,</span><span class="token string-property property">"secpol"</span><span class="token operator">:</span><span class="token string">"None"</span><span class="token punctuation">,</span><span class="token string-property property">"secmode"</span><span class="token operator">:</span><span class="token string">"None"</span><span class="token punctuation">,</span><span class="token string-property property">"none"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"login"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"usercert"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"usercertificate"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"userprivatekey"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"b095aee62f84e514"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_group"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"MyDevice Status & Control"</span><span class="token punctuation">,</span><span class="token string-property property">"tab"</span><span class="token operator">:</span><span class="token string">"0113eb87060106be"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">4</span><span class="token punctuation">,</span><span class="token string-property property">"disp"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token string">"6"</span><span class="token punctuation">,</span><span class="token string-property property">"collapse"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"0113eb87060106be"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_tab"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"OPC UA"</span><span class="token punctuation">,</span><span class="token string-property property">"icon"</span><span class="token operator">:</span><span class="token string">"dashboard"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">7</span><span class="token punctuation">,</span><span class="token string-property property">"disabled"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"hidden"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">}</span><span class="token punctuation">]</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-249" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>We use an inject node to trigger the <code>OpcUa-Event</code> node. In the properties of the event node, we get the <code>NodeId</code> from the <code>MyLevelAlarm</code> event from the OPC Server -</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/mylevel-event-DAdiz8agx3-650.avif 650w, https://flowfuse.com/img/mylevel-event-DAdiz8agx3-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/mylevel-event-DAdiz8agx3-650.webp 650w, https://flowfuse.com/img/mylevel-event-DAdiz8agx3-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/mylevel-event-DAdiz8agx3-650.jpeg 650w, https://flowfuse.com/img/mylevel-event-DAdiz8agx3-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="mylevel-event.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/mylevel-event-DAdiz8agx3-650.jpeg" width="1300" height="517" /></picture>
And copy that <code>NodeId</code> into the <code>OpcUa-Event</code> node. Event type will be <code>BaseEvent (all)</code>.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/event-node-properties-wyPltii_R4-650.avif 650w, https://flowfuse.com/img/event-node-properties-wyPltii_R4-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/event-node-properties-wyPltii_R4-650.webp 650w, https://flowfuse.com/img/event-node-properties-wyPltii_R4-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/event-node-properties-wyPltii_R4-650.jpeg 650w, https://flowfuse.com/img/event-node-properties-wyPltii_R4-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="event-node-properties.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/event-node-properties-wyPltii_R4-650.jpeg" width="1300" height="877" /></picture>
In the <code>Opc-Ua-Client</code> node, we set the <code>Action</code> to <code>EVENTS</code>.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/client-events-4jRajoWxwS-650.avif 650w, https://flowfuse.com/img/client-events-4jRajoWxwS-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/client-events-4jRajoWxwS-650.webp 650w, https://flowfuse.com/img/client-events-4jRajoWxwS-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/client-events-4jRajoWxwS-650.jpeg 650w, https://flowfuse.com/img/client-events-4jRajoWxwS-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="client-events.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/client-events-4jRajoWxwS-650.jpeg" width="1300" height="1233" /></picture>
If we stick a debug node on the output of the client event, we can see how the OPC Server annunciates events.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/event-debug-tlQeoRlzL5-650.avif 650w, https://flowfuse.com/img/event-debug-tlQeoRlzL5-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/event-debug-tlQeoRlzL5-650.webp 650w, https://flowfuse.com/img/event-debug-tlQeoRlzL5-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/event-debug-tlQeoRlzL5-650.jpeg 650w, https://flowfuse.com/img/event-debug-tlQeoRlzL5-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="event-debug.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/event-debug-tlQeoRlzL5-650.jpeg" width="1300" height="596" /></picture>
Every time <code>MyLevel</code> exceeds certain thresholds (10%, 30%, 70% and 90%) it will flag a <code>Level Exceeded</code> alarm. The event is timestamped and assigned a severity level, which we will record and put onto the dashboard.</p>
<p>To make things simple, we’ll only track the last event. But in a production system, you’d likely want to store these events in a relational database (historian) to keep an alarm history. We’ll also include a notification pop-up when an alarm occurs to notify someone monitoring the dashboard a new alarm has occurred.</p>
<p>Adding alarms and events to our dashboard creates the following result -</p>
<p><picture><source type="image/gif" srcset="https://flowfuse.com/img/opc-event-MKkNLxwh24-650.gif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="opc-event.gif" loading="lazy" decoding="async" src="https://flowfuse.com/img/opc-event-MKkNLxwh24-650.webp" width="650" height="365" /></picture></p>
<h2 id="conclusion" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/how-to-build-a-opc-client-dashboard-in-node-red/#conclusion"># </a> Conclusion</h2>
<p>In this final article, we went over building a OPC UA Client dashboard that can browse the address space, read values from an OPC Server, write values to an OPC Server, and get events from an OPC Server.</p>
<p>This flow provides examples that can serve as a foundation for an interactive OPC Client application built in Node-RED. This now concludes the OPC UA Series.</p>
<p>full source code for this project -</p>
<div style="position: relative">
<pre class="language-javascript"><code id="code-286" class="language-javascript"><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"tab"</span><span class="token punctuation">,</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token string">"Prosys OPC UA Client Example"</span><span class="token punctuation">,</span><span class="token string-property property">"disabled"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"env"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"3e09b7a420dd81d2"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"group"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Browse Hierarchical Address Space Structure & Display on Dashboard"</span><span class="token punctuation">,</span><span class="token string-property property">"style"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"stroke"</span><span class="token operator">:</span><span class="token string">"#a4a4a4"</span><span class="token punctuation">,</span><span class="token string-property property">"color"</span><span class="token operator">:</span><span class="token string">"#000000"</span><span class="token punctuation">,</span><span class="token string-property property">"fill"</span><span class="token operator">:</span><span class="token string">"#ffffff"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token string-property property">"nodes"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"6b17b2da2b942bb4"</span><span class="token punctuation">,</span><span class="token string">"61797eccf2785257"</span><span class="token punctuation">,</span><span class="token string">"4d92d940177b6ee3"</span><span class="token punctuation">,</span><span class="token string">"68a113d5893b7c01"</span><span class="token punctuation">,</span><span class="token string">"98560994a7884f15"</span><span class="token punctuation">,</span><span class="token string">"4dd13685c3c2879e"</span><span class="token punctuation">,</span><span class="token string">"a29358cca5c1c12a"</span><span class="token punctuation">,</span><span class="token string">"d0c969b6a59fac3a"</span><span class="token punctuation">,</span><span class="token string">"639da01fc957e547"</span><span class="token punctuation">,</span><span class="token string">"29437ca7222d9a64"</span><span class="token punctuation">,</span><span class="token string">"49983d5da0958bf2"</span><span class="token punctuation">,</span><span class="token string">"49040d0cf1144f0a"</span><span class="token punctuation">,</span><span class="token string">"e7c55f412ef86543"</span><span class="token punctuation">,</span><span class="token string">"7b53b798a025f1d8"</span><span class="token punctuation">,</span><span class="token string">"71512a0d602095a0"</span><span class="token punctuation">,</span><span class="token string">"9c3b0c36d69c05cf"</span><span class="token punctuation">,</span><span class="token string">"de21b7ad98a05833"</span><span class="token punctuation">,</span><span class="token string">"2d56e9a431c21a3b"</span><span class="token punctuation">,</span><span class="token string">"ac95bd0e2b304eec"</span><span class="token punctuation">,</span><span class="token string">"6fdabcc2950ccf4e"</span><span class="token punctuation">,</span><span class="token string">"1c49fa5142d2cf17"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">54</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">19</span><span class="token punctuation">,</span><span class="token string-property property">"w"</span><span class="token operator">:</span><span class="token number">1172</span><span class="token punctuation">,</span><span class="token string-property property">"h"</span><span class="token operator">:</span><span class="token number">422</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"ab8e5ebe8c14819d"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"group"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Read Simulation Values & Display on Dashboard"</span><span class="token punctuation">,</span><span class="token string-property property">"style"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token string-property property">"stroke"</span><span class="token operator">:</span><span class="token string">"#a4a4a4"</span><span class="token punctuation">,</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"color"</span><span class="token operator">:</span><span class="token string">"#001f60"</span><span class="token punctuation">,</span><span class="token string-property property">"fill"</span><span class="token operator">:</span><span class="token string">"#ffffff"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token string-property property">"nodes"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"482da272d75f9fc9"</span><span class="token punctuation">,</span><span class="token string">"36b93ad2d6b4b695"</span><span class="token punctuation">,</span><span class="token string">"1819591e5ebae68d"</span><span class="token punctuation">,</span><span class="token string">"740c976dd5aca65a"</span><span class="token punctuation">,</span><span class="token string">"8d671460beac82d8"</span><span class="token punctuation">,</span><span class="token string">"80e5270d14633586"</span><span class="token punctuation">,</span><span class="token string">"de478581d1839a70"</span><span class="token punctuation">,</span><span class="token string">"0128582021fb3fbc"</span><span class="token punctuation">,</span><span class="token string">"454fe6a32820dbc9"</span><span class="token punctuation">,</span><span class="token string">"5e955dbca478356f"</span><span class="token punctuation">,</span><span class="token string">"57da7c9808e5fa56"</span><span class="token punctuation">,</span><span class="token string">"5658b05beada4467"</span><span class="token punctuation">,</span><span class="token string">"8f866373ed32349c"</span><span class="token punctuation">,</span><span class="token string">"35f53fe496f4f68a"</span><span class="token punctuation">,</span><span class="token string">"c9e043783aeaf0fa"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">54</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">479</span><span class="token punctuation">,</span><span class="token string-property property">"w"</span><span class="token operator">:</span><span class="token number">1372</span><span class="token punctuation">,</span><span class="token string-property property">"h"</span><span class="token operator">:</span><span class="token number">302</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"23696c742b062ee0"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"group"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Read StaticData Values & Display on Dashboard"</span><span class="token punctuation">,</span><span class="token string-property property">"style"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token string-property property">"stroke"</span><span class="token operator">:</span><span class="token string">"#a4a4a4"</span><span class="token punctuation">,</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"color"</span><span class="token operator">:</span><span class="token string">"#000000"</span><span class="token punctuation">,</span><span class="token string-property property">"fill"</span><span class="token operator">:</span><span class="token string">"#ffffff"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token string-property property">"nodes"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"e573ccc34fdcde6e"</span><span class="token punctuation">,</span><span class="token string">"cf673bdce7b5b77a"</span><span class="token punctuation">,</span><span class="token string">"eb9263b229ec4811"</span><span class="token punctuation">,</span><span class="token string">"551d276aed309e6e"</span><span class="token punctuation">,</span><span class="token string">"9c84f8d19ae7ea45"</span><span class="token punctuation">,</span><span class="token string">"bf9e5ad82b0f9a0e"</span><span class="token punctuation">,</span><span class="token string">"14eaeb56e3922c6a"</span><span class="token punctuation">,</span><span class="token string">"12be1bc3729ee611"</span><span class="token punctuation">,</span><span class="token string">"d9f2b147a2519719"</span><span class="token punctuation">,</span><span class="token string">"09882f19a74faff8"</span><span class="token punctuation">,</span><span class="token string">"d89e22654946066d"</span><span class="token punctuation">,</span><span class="token string">"9c5762fc7fdbae59"</span><span class="token punctuation">,</span><span class="token string">"a5981d515cfadb55"</span><span class="token punctuation">,</span><span class="token string">"a736c876b46c763f"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">54</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">819</span><span class="token punctuation">,</span><span class="token string-property property">"w"</span><span class="token operator">:</span><span class="token number">1372</span><span class="token punctuation">,</span><span class="token string-property property">"h"</span><span class="token operator">:</span><span class="token number">202</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"38f43e1ab70fe0cf"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"group"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Read MyDevice Values & Display on Dashboard"</span><span class="token punctuation">,</span><span class="token string-property property">"style"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"color"</span><span class="token operator">:</span><span class="token string">"#000000"</span><span class="token punctuation">,</span><span class="token string-property property">"fill"</span><span class="token operator">:</span><span class="token string">"#ffffff"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token string-property property">"nodes"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"513d07a651243e9e"</span><span class="token punctuation">,</span><span class="token string">"96294bbf031d67e8"</span><span class="token punctuation">,</span><span class="token string">"3140b66e39039a37"</span><span class="token punctuation">,</span><span class="token string">"8eda44307f47c12f"</span><span class="token punctuation">,</span><span class="token string">"cb0a56243f0a6b5e"</span><span class="token punctuation">,</span><span class="token string">"d6d60ff6a933ad1d"</span><span class="token punctuation">,</span><span class="token string">"7de0892e28c6fea9"</span><span class="token punctuation">,</span><span class="token string">"13c6bf381ff0d8b2"</span><span class="token punctuation">,</span><span class="token string">"8b48799434be36cf"</span><span class="token punctuation">,</span><span class="token string">"e29a74ea9a1de0ef"</span><span class="token punctuation">,</span><span class="token string">"a27699b4e9697558"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">54</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1059</span><span class="token punctuation">,</span><span class="token string-property property">"w"</span><span class="token operator">:</span><span class="token number">1292</span><span class="token punctuation">,</span><span class="token string-property property">"h"</span><span class="token operator">:</span><span class="token number">182</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"b1eeba37b0d982ef"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"group"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Write MyDevice Values to OPC UA Server"</span><span class="token punctuation">,</span><span class="token string-property property">"style"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"color"</span><span class="token operator">:</span><span class="token string">"#000000"</span><span class="token punctuation">,</span><span class="token string-property property">"fill"</span><span class="token operator">:</span><span class="token string">"#ffffff"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token string-property property">"nodes"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"2cb01ef75f8b5f39"</span><span class="token punctuation">,</span><span class="token string">"36daedb0c2a5295d"</span><span class="token punctuation">,</span><span class="token string">"f6d73ab104914017"</span><span class="token punctuation">,</span><span class="token string">"16224a3eefb5184e"</span><span class="token punctuation">,</span><span class="token string">"711c6f36547b4efb"</span><span class="token punctuation">,</span><span class="token string">"cb0e16ceab421d58"</span><span class="token punctuation">,</span><span class="token string">"968a8b27d03f6372"</span><span class="token punctuation">,</span><span class="token string">"19c427f70d0ed845"</span><span class="token punctuation">,</span><span class="token string">"01153fddbbb2cd73"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">54</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1279</span><span class="token punctuation">,</span><span class="token string-property property">"w"</span><span class="token operator">:</span><span class="token number">792</span><span class="token punctuation">,</span><span class="token string-property property">"h"</span><span class="token operator">:</span><span class="token number">182</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"3013af7593f2847b"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"group"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Read Alarms & Events From OPC UA Server"</span><span class="token punctuation">,</span><span class="token string-property property">"style"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"color"</span><span class="token operator">:</span><span class="token string">"#000000"</span><span class="token punctuation">,</span><span class="token string-property property">"fill"</span><span class="token operator">:</span><span class="token string">"#ffffff"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token string-property property">"nodes"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"bd95b96ed77a621c"</span><span class="token punctuation">,</span><span class="token string">"26b7db518e4ac448"</span><span class="token punctuation">,</span><span class="token string">"05b98e27c8317489"</span><span class="token punctuation">,</span><span class="token string">"67aa6d2ecee3895b"</span><span class="token punctuation">,</span><span class="token string">"bfb585c5777dfeca"</span><span class="token punctuation">,</span><span class="token string">"4c47ed5a65160149"</span><span class="token punctuation">,</span><span class="token string">"b6d318d3372e149f"</span><span class="token punctuation">,</span><span class="token string">"8d36820730690d7d"</span><span class="token punctuation">,</span><span class="token string">"87eb7ad331a15823"</span><span class="token punctuation">,</span><span class="token string">"fd228940746d2e4c"</span><span class="token punctuation">,</span><span class="token string">"564212f76a83ce5e"</span><span class="token punctuation">,</span><span class="token string">"8a06f75c33593dc1"</span><span class="token punctuation">,</span><span class="token string">"6ba832b756579002"</span><span class="token punctuation">,</span><span class="token string">"be911708a19728b0"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">54</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1499</span><span class="token punctuation">,</span><span class="token string-property property">"w"</span><span class="token operator">:</span><span class="token number">1332</span><span class="token punctuation">,</span><span class="token string-property property">"h"</span><span class="token operator">:</span><span class="token number">282</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"6b17b2da2b942bb4"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"OpcUa-Browser"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3e09b7a420dd81d2"</span><span class="token punctuation">,</span><span class="token string-property property">"endpoint"</span><span class="token operator">:</span><span class="token string">"53f4394dbf12c6b7"</span><span class="token punctuation">,</span><span class="token string-property property">"item"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"datatype"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"items"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"OPC Client Namespace Browse"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">510</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">160</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"4d92d940177b6ee3"</span><span class="token punctuation">,</span><span class="token string">"d0c969b6a59fac3a"</span><span class="token punctuation">,</span><span class="token string">"639da01fc957e547"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"1c49fa5142d2cf17"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3e09b7a420dd81d2"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Global Address Space Folder Browse"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">390</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">120</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"61797eccf2785257"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3e09b7a420dd81d2"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Get Base Folder Structure"</span><span class="token punctuation">,</span><span class="token string-property property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"topic"</span><span class="token punctuation">,</span><span class="token string-property property">"vt"</span><span class="token operator">:</span><span class="token string">"str"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"repeat"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"once"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"onceDelay"</span><span class="token operator">:</span><span class="token string">"0.3"</span><span class="token punctuation">,</span><span class="token string-property property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"payload"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"payloadType"</span><span class="token operator">:</span><span class="token string">"date"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">240</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">160</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"6b17b2da2b942bb4"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"4d92d940177b6ee3"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3e09b7a420dd81d2"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Simulation Folder"</span><span class="token punctuation">,</span><span class="token string-property property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"Objects.Simulation.nodeId"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"flow"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload[2].item.nodeId"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload[2].item.browseName.name"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">790</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">100</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"98560994a7884f15"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"68a113d5893b7c01"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3e09b7a420dd81d2"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Display on Dashboard"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1100</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">60</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"98560994a7884f15"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_text"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3e09b7a420dd81d2"</span><span class="token punctuation">,</span><span class="token string-property property">"group"</span><span class="token operator">:</span><span class="token string">"4340b56a2335c304"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token string-property property">"height"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Simulation"</span><span class="token punctuation">,</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token string">"Namespace 3"</span><span class="token punctuation">,</span><span class="token string-property property">"format"</span><span class="token operator">:</span><span class="token string">" <i class=\"fa fa-folder\" aria-hidden=\"true\"></i>"</span><span class="token punctuation">,</span><span class="token string-property property">"layout"</span><span class="token operator">:</span><span class="token string">"col-center"</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"style"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"font"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"fontSize"</span><span class="token operator">:</span><span class="token number">16</span><span class="token punctuation">,</span><span class="token string-property property">"color"</span><span class="token operator">:</span><span class="token string">"#000000"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1070</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">100</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"482da272d75f9fc9"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"OpcUa-Browser"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"ab8e5ebe8c14819d"</span><span class="token punctuation">,</span><span class="token string-property property">"endpoint"</span><span class="token operator">:</span><span class="token string">"53f4394dbf12c6b7"</span><span class="token punctuation">,</span><span class="token string-property property">"item"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"datatype"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"items"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"OPC Client Namespace Browse"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">530</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">640</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"80e5270d14633586"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"36b93ad2d6b4b695"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"ab8e5ebe8c14819d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Update Simulation Values @ 1 second"</span><span class="token punctuation">,</span><span class="token string-property property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"topic"</span><span class="token punctuation">,</span><span class="token string-property property">"v"</span><span class="token operator">:</span><span class="token string">"Objects.Simulation.nodeId"</span><span class="token punctuation">,</span><span class="token string-property property">"vt"</span><span class="token operator">:</span><span class="token string">"flow"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"repeat"</span><span class="token operator">:</span><span class="token string">"1"</span><span class="token punctuation">,</span><span class="token string-property property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"once"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"onceDelay"</span><span class="token operator">:</span><span class="token number">0.1</span><span class="token punctuation">,</span><span class="token string-property property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"payload"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"payloadType"</span><span class="token operator">:</span><span class="token string">"date"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">260</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">640</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"482da272d75f9fc9"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"1819591e5ebae68d"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"ab8e5ebe8c14819d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Read Simulation Values"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">420</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">600</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"740c976dd5aca65a"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"ab8e5ebe8c14819d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Get Counter Value"</span><span class="token punctuation">,</span><span class="token string-property property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload[1].item.value"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1030</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">560</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"8d671460beac82d8"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"8d671460beac82d8"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_gauge"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"ab8e5ebe8c14819d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"group"</span><span class="token operator">:</span><span class="token string">"825fe3323bd36ae6"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token string">"0"</span><span class="token punctuation">,</span><span class="token string-property property">"height"</span><span class="token operator">:</span><span class="token string">"0"</span><span class="token punctuation">,</span><span class="token string-property property">"gtype"</span><span class="token operator">:</span><span class="token string">"gage"</span><span class="token punctuation">,</span><span class="token string-property property">"title"</span><span class="token operator">:</span><span class="token string">"Counter"</span><span class="token punctuation">,</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token string">"units"</span><span class="token punctuation">,</span><span class="token string-property property">"format"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"min"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"max"</span><span class="token operator">:</span><span class="token string">"30"</span><span class="token punctuation">,</span><span class="token string-property property">"colors"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"#00b500"</span><span class="token punctuation">,</span><span class="token string">"#e6e600"</span><span class="token punctuation">,</span><span class="token string">"#ca3838"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"seg1"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"seg2"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"diff"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1280</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">560</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"80e5270d14633586"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"switch"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"ab8e5ebe8c14819d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"empty check"</span><span class="token punctuation">,</span><span class="token string-property property">"property"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token string-property property">"propertyType"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"nempty"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"checkall"</span><span class="token operator">:</span><span class="token string">"true"</span><span class="token punctuation">,</span><span class="token string-property property">"repair"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"outputs"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">750</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">640</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"740c976dd5aca65a"</span><span class="token punctuation">,</span><span class="token string">"de478581d1839a70"</span><span class="token punctuation">,</span><span class="token string">"454fe6a32820dbc9"</span><span class="token punctuation">,</span><span class="token string">"57da7c9808e5fa56"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"de478581d1839a70"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"ab8e5ebe8c14819d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Get Random Number Value"</span><span class="token punctuation">,</span><span class="token string-property property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload[2].item.value"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1060</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">620</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"0128582021fb3fbc"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"0128582021fb3fbc"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_text"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"ab8e5ebe8c14819d"</span><span class="token punctuation">,</span><span class="token string-property property">"group"</span><span class="token operator">:</span><span class="token string">"825fe3323bd36ae6"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">7</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token string">"Random Number"</span><span class="token punctuation">,</span><span class="token string-property property">"format"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"layout"</span><span class="token operator">:</span><span class="token string">"col-center"</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"style"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"font"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"fontSize"</span><span class="token operator">:</span><span class="token number">16</span><span class="token punctuation">,</span><span class="token string-property property">"color"</span><span class="token operator">:</span><span class="token string">"#000000"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1310</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">620</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"4dd13685c3c2879e"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_text"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3e09b7a420dd81d2"</span><span class="token punctuation">,</span><span class="token string-property property">"group"</span><span class="token operator">:</span><span class="token string">"4340b56a2335c304"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token string-property property">"height"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"StaticData"</span><span class="token punctuation">,</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token string">"Namespace 5"</span><span class="token punctuation">,</span><span class="token string-property property">"format"</span><span class="token operator">:</span><span class="token string">" <i class=\"fa fa-folder\" aria-hidden=\"true\"></i> <i class=\"fa fa-sort-desc\" aria-hidden=\"true\"></i>"</span><span class="token punctuation">,</span><span class="token string-property property">"layout"</span><span class="token operator">:</span><span class="token string">"col-center"</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"style"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"font"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"fontSize"</span><span class="token operator">:</span><span class="token number">16</span><span class="token punctuation">,</span><span class="token string-property property">"color"</span><span class="token operator">:</span><span class="token string">"#000000"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1070</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">160</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"a29358cca5c1c12a"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_text"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3e09b7a420dd81d2"</span><span class="token punctuation">,</span><span class="token string-property property">"group"</span><span class="token operator">:</span><span class="token string">"4340b56a2335c304"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">9</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token string-property property">"height"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"MyObjects"</span><span class="token punctuation">,</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token string">"Namespace 6"</span><span class="token punctuation">,</span><span class="token string-property property">"format"</span><span class="token operator">:</span><span class="token string">" <i class=\"fa fa-folder\" aria-hidden=\"true\"></i> <i class=\"fa fa-sort-desc\" aria-hidden=\"true\"></i>"</span><span class="token punctuation">,</span><span class="token string-property property">"layout"</span><span class="token operator">:</span><span class="token string">"col-center"</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"style"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"font"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"fontSize"</span><span class="token operator">:</span><span class="token number">16</span><span class="token punctuation">,</span><span class="token string-property property">"color"</span><span class="token operator">:</span><span class="token string">"#000000"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1070</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">220</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"d0c969b6a59fac3a"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3e09b7a420dd81d2"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"MyObjects Folder"</span><span class="token punctuation">,</span><span class="token string-property property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"Objects.MyObjects.nodeId"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"flow"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload[4].item.nodeId"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload[4].item.browseName.name"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">790</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">220</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"a29358cca5c1c12a"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"454fe6a32820dbc9"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"ab8e5ebe8c14819d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Get Sawtooth Value"</span><span class="token punctuation">,</span><span class="token string-property property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload[3].item.value"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1040</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">680</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"5e955dbca478356f"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"5e955dbca478356f"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_chart"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"ab8e5ebe8c14819d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"group"</span><span class="token operator">:</span><span class="token string">"825fe3323bd36ae6"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">8</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token string">"Sawtooth"</span><span class="token punctuation">,</span><span class="token string-property property">"chartType"</span><span class="token operator">:</span><span class="token string">"line"</span><span class="token punctuation">,</span><span class="token string-property property">"legend"</span><span class="token operator">:</span><span class="token string">"false"</span><span class="token punctuation">,</span><span class="token string-property property">"xformat"</span><span class="token operator">:</span><span class="token string">"HH:mm:ss"</span><span class="token punctuation">,</span><span class="token string-property property">"interpolate"</span><span class="token operator">:</span><span class="token string">"linear"</span><span class="token punctuation">,</span><span class="token string-property property">"nodata"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"dot"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"ymin"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"ymax"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"removeOlder"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"removeOlderPoints"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"removeOlderUnit"</span><span class="token operator">:</span><span class="token string">"60"</span><span class="token punctuation">,</span><span class="token string-property property">"cutout"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"useOneColor"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"useUTC"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"colors"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"#1f77b4"</span><span class="token punctuation">,</span><span class="token string">"#aec7e8"</span><span class="token punctuation">,</span><span class="token string">"#ff7f0e"</span><span class="token punctuation">,</span><span class="token string">"#2ca02c"</span><span class="token punctuation">,</span><span class="token string">"#98df8a"</span><span class="token punctuation">,</span><span class="token string">"#d62728"</span><span class="token punctuation">,</span><span class="token string">"#ff9896"</span><span class="token punctuation">,</span><span class="token string">"#9467bd"</span><span class="token punctuation">,</span><span class="token string">"#c5b0d5"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"outputs"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"useDifferentColor"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1280</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">680</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"57da7c9808e5fa56"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"ab8e5ebe8c14819d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Get Sawtooth Value"</span><span class="token punctuation">,</span><span class="token string-property property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload[4].item.value"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1040</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">740</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"5658b05beada4467"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"5658b05beada4467"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_chart"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"ab8e5ebe8c14819d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"group"</span><span class="token operator">:</span><span class="token string">"825fe3323bd36ae6"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">9</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token string">"Sinusoid"</span><span class="token punctuation">,</span><span class="token string-property property">"chartType"</span><span class="token operator">:</span><span class="token string">"line"</span><span class="token punctuation">,</span><span class="token string-property property">"legend"</span><span class="token operator">:</span><span class="token string">"false"</span><span class="token punctuation">,</span><span class="token string-property property">"xformat"</span><span class="token operator">:</span><span class="token string">"HH:mm:ss"</span><span class="token punctuation">,</span><span class="token string-property property">"interpolate"</span><span class="token operator">:</span><span class="token string">"linear"</span><span class="token punctuation">,</span><span class="token string-property property">"nodata"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"dot"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"ymin"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"ymax"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"removeOlder"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"removeOlderPoints"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"removeOlderUnit"</span><span class="token operator">:</span><span class="token string">"60"</span><span class="token punctuation">,</span><span class="token string-property property">"cutout"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"useOneColor"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"useUTC"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"colors"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"#1f77b4"</span><span class="token punctuation">,</span><span class="token string">"#aec7e8"</span><span class="token punctuation">,</span><span class="token string">"#ff7f0e"</span><span class="token punctuation">,</span><span class="token string">"#2ca02c"</span><span class="token punctuation">,</span><span class="token string">"#98df8a"</span><span class="token punctuation">,</span><span class="token string">"#d62728"</span><span class="token punctuation">,</span><span class="token string">"#ff9896"</span><span class="token punctuation">,</span><span class="token string">"#9467bd"</span><span class="token punctuation">,</span><span class="token string">"#c5b0d5"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"outputs"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"useDifferentColor"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1280</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">740</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"e573ccc34fdcde6e"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"OpcUa-Browser"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"23696c742b062ee0"</span><span class="token punctuation">,</span><span class="token string-property property">"endpoint"</span><span class="token operator">:</span><span class="token string">"53f4394dbf12c6b7"</span><span class="token punctuation">,</span><span class="token string-property property">"item"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"datatype"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"items"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"OPC Client Namespace Browse"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">590</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">900</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"9c84f8d19ae7ea45"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"cf673bdce7b5b77a"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"23696c742b062ee0"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Update AnalogItemArrays Values @ 1 second"</span><span class="token punctuation">,</span><span class="token string-property property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"topic"</span><span class="token punctuation">,</span><span class="token string-property property">"v"</span><span class="token operator">:</span><span class="token string">"Objects.StaticData.AnalogItemArrays.nodeId"</span><span class="token punctuation">,</span><span class="token string-property property">"vt"</span><span class="token operator">:</span><span class="token string">"flow"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"repeat"</span><span class="token operator">:</span><span class="token string">"1"</span><span class="token punctuation">,</span><span class="token string-property property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"once"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"onceDelay"</span><span class="token operator">:</span><span class="token number">0.1</span><span class="token punctuation">,</span><span class="token string-property property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"payload"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"payloadType"</span><span class="token operator">:</span><span class="token string">"date"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">280</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">900</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"e573ccc34fdcde6e"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"eb9263b229ec4811"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"23696c742b062ee0"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Read StaticData Values"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">480</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">860</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"551d276aed309e6e"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"23696c742b062ee0"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Get ByteAnalogItemArray Value"</span><span class="token punctuation">,</span><span class="token string-property property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload[0].item.value"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1030</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">900</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"bf9e5ad82b0f9a0e"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"9c84f8d19ae7ea45"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"switch"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"23696c742b062ee0"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"empty check"</span><span class="token punctuation">,</span><span class="token string-property property">"property"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token string-property property">"propertyType"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"nempty"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"checkall"</span><span class="token operator">:</span><span class="token string">"true"</span><span class="token punctuation">,</span><span class="token string-property property">"repair"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"outputs"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">790</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">900</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"551d276aed309e6e"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"639da01fc957e547"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3e09b7a420dd81d2"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"StaticData Folder"</span><span class="token punctuation">,</span><span class="token string-property property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"Objects.StaticData.nodeId"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"flow"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload[3].item.nodeId"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload[3].item.browseName.name"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">790</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">160</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"4dd13685c3c2879e"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"29437ca7222d9a64"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"OpcUa-Browser"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3e09b7a420dd81d2"</span><span class="token punctuation">,</span><span class="token string-property property">"endpoint"</span><span class="token operator">:</span><span class="token string">"53f4394dbf12c6b7"</span><span class="token punctuation">,</span><span class="token string-property property">"item"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"datatype"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"items"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"OPC Client Namespace Browse"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">510</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">320</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"49040d0cf1144f0a"</span><span class="token punctuation">,</span><span class="token string">"e7c55f412ef86543"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"49983d5da0958bf2"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3e09b7a420dd81d2"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Get StaticData Folder Structure"</span><span class="token punctuation">,</span><span class="token string-property property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"topic"</span><span class="token punctuation">,</span><span class="token string-property property">"v"</span><span class="token operator">:</span><span class="token string">"Objects.StaticData.nodeId"</span><span class="token punctuation">,</span><span class="token string-property property">"vt"</span><span class="token operator">:</span><span class="token string">"flow"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"repeat"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"once"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"onceDelay"</span><span class="token operator">:</span><span class="token string">"0.3"</span><span class="token punctuation">,</span><span class="token string-property property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"payload"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"payloadType"</span><span class="token operator">:</span><span class="token string">"date"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">230</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">320</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"29437ca7222d9a64"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"49040d0cf1144f0a"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3e09b7a420dd81d2"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"AnalogItemArrays Folder"</span><span class="token punctuation">,</span><span class="token string-property property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"Objects.StaticData.AnalogItemArrays.nodeId"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"flow"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload[1].item.nodeId"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload[1].item.browseName.name"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">810</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">340</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"7b53b798a025f1d8"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"e7c55f412ef86543"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3e09b7a420dd81d2"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"StaticArrayVariables Folder"</span><span class="token punctuation">,</span><span class="token string-property property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"Objects.StaticData.StaticArrayVariables.nodeId"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"flow"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload[6].item.nodeId"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload[6].item.browseName.name"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">820</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">280</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"71512a0d602095a0"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"7b53b798a025f1d8"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_text"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3e09b7a420dd81d2"</span><span class="token punctuation">,</span><span class="token string-property property">"group"</span><span class="token operator">:</span><span class="token string">"4340b56a2335c304"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">8</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token number">4</span><span class="token punctuation">,</span><span class="token string-property property">"height"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"AnalogItemArrays"</span><span class="token punctuation">,</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"format"</span><span class="token operator">:</span><span class="token string">"<i class=\"fa fa-folder\" aria-hidden=\"true\"></i> "</span><span class="token punctuation">,</span><span class="token string-property property">"layout"</span><span class="token operator">:</span><span class="token string">"col-center"</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"style"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"font"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"fontSize"</span><span class="token operator">:</span><span class="token number">16</span><span class="token punctuation">,</span><span class="token string-property property">"color"</span><span class="token operator">:</span><span class="token string">"#000000"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1090</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">340</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"71512a0d602095a0"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_text"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3e09b7a420dd81d2"</span><span class="token punctuation">,</span><span class="token string-property property">"group"</span><span class="token operator">:</span><span class="token string">"4340b56a2335c304"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">6</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token number">4</span><span class="token punctuation">,</span><span class="token string-property property">"height"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"StaticArrayVariables"</span><span class="token punctuation">,</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"format"</span><span class="token operator">:</span><span class="token string">" <i class=\"fa fa-folder\" aria-hidden=\"true\"></i> "</span><span class="token punctuation">,</span><span class="token string-property property">"layout"</span><span class="token operator">:</span><span class="token string">"col-center"</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"style"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"font"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"fontSize"</span><span class="token operator">:</span><span class="token number">16</span><span class="token punctuation">,</span><span class="token string-property property">"color"</span><span class="token operator">:</span><span class="token string">"#000000"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1100</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">280</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"bf9e5ad82b0f9a0e"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_text"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"23696c742b062ee0"</span><span class="token punctuation">,</span><span class="token string-property property">"group"</span><span class="token operator">:</span><span class="token string">"92444e82445bab62"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token string">"ByteAnalogItemArray"</span><span class="token punctuation">,</span><span class="token string-property property">"format"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"layout"</span><span class="token operator">:</span><span class="token string">"col-center"</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"style"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"font"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"fontSize"</span><span class="token operator">:</span><span class="token number">16</span><span class="token punctuation">,</span><span class="token string-property property">"color"</span><span class="token operator">:</span><span class="token string">"#000000"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1300</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">900</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"14eaeb56e3922c6a"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"OpcUa-Browser"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"23696c742b062ee0"</span><span class="token punctuation">,</span><span class="token string-property property">"endpoint"</span><span class="token operator">:</span><span class="token string">"53f4394dbf12c6b7"</span><span class="token punctuation">,</span><span class="token string-property property">"item"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"datatype"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"items"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"OPC Client Namespace Browse"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">590</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">980</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"09882f19a74faff8"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"12be1bc3729ee611"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"23696c742b062ee0"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Update StaticArrayVariables Values @1 second"</span><span class="token punctuation">,</span><span class="token string-property property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"topic"</span><span class="token punctuation">,</span><span class="token string-property property">"v"</span><span class="token operator">:</span><span class="token string">"Objects.StaticData.StaticArrayVariables.nodeId"</span><span class="token punctuation">,</span><span class="token string-property property">"vt"</span><span class="token operator">:</span><span class="token string">"flow"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"repeat"</span><span class="token operator">:</span><span class="token string">"1"</span><span class="token punctuation">,</span><span class="token string-property property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"once"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"onceDelay"</span><span class="token operator">:</span><span class="token number">0.1</span><span class="token punctuation">,</span><span class="token string-property property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"payload"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"payloadType"</span><span class="token operator">:</span><span class="token string">"date"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">280</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">980</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"14eaeb56e3922c6a"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"d9f2b147a2519719"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"23696c742b062ee0"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Get BooleanArray Value"</span><span class="token punctuation">,</span><span class="token string-property property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload[0].item.value"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1010</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">980</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"d89e22654946066d"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"09882f19a74faff8"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"switch"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"23696c742b062ee0"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"empty check"</span><span class="token punctuation">,</span><span class="token string-property property">"property"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token string-property property">"propertyType"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"nempty"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"checkall"</span><span class="token operator">:</span><span class="token string">"true"</span><span class="token punctuation">,</span><span class="token string-property property">"repair"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"outputs"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">790</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">980</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"d9f2b147a2519719"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"d89e22654946066d"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_text"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"23696c742b062ee0"</span><span class="token punctuation">,</span><span class="token string-property property">"group"</span><span class="token operator">:</span><span class="token string">"92444e82445bab62"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token string">"BooleanArray"</span><span class="token punctuation">,</span><span class="token string-property property">"format"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"layout"</span><span class="token operator">:</span><span class="token string">"col-center"</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"style"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"font"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"fontSize"</span><span class="token operator">:</span><span class="token number">16</span><span class="token punctuation">,</span><span class="token string-property property">"color"</span><span class="token operator">:</span><span class="token string">"#000000"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1280</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">980</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"513d07a651243e9e"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"OpcUa-Browser"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"38f43e1ab70fe0cf"</span><span class="token punctuation">,</span><span class="token string-property property">"endpoint"</span><span class="token operator">:</span><span class="token string">"53f4394dbf12c6b7"</span><span class="token punctuation">,</span><span class="token string-property property">"item"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"datatype"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"items"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"OPC Client Namespace Browse"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">550</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1160</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"cb0a56243f0a6b5e"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"96294bbf031d67e8"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"38f43e1ab70fe0cf"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Read MyDevice Values @ 1 second"</span><span class="token punctuation">,</span><span class="token string-property property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"topic"</span><span class="token punctuation">,</span><span class="token string-property property">"v"</span><span class="token operator">:</span><span class="token string">"Objects.MyObjects.MyDevice.nodeId"</span><span class="token punctuation">,</span><span class="token string-property property">"vt"</span><span class="token operator">:</span><span class="token string">"flow"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"repeat"</span><span class="token operator">:</span><span class="token string">"1"</span><span class="token punctuation">,</span><span class="token string-property property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"once"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"onceDelay"</span><span class="token operator">:</span><span class="token number">0.1</span><span class="token punctuation">,</span><span class="token string-property property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"payload"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"payloadType"</span><span class="token operator">:</span><span class="token string">"date"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">250</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1160</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"513d07a651243e9e"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"3140b66e39039a37"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"38f43e1ab70fe0cf"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Read MyDevice"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">440</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1120</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"8eda44307f47c12f"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"38f43e1ab70fe0cf"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Get MyLevel Value"</span><span class="token punctuation">,</span><span class="token string-property property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload[0].item.value"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">990</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1140</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"7de0892e28c6fea9"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"cb0a56243f0a6b5e"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"switch"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"38f43e1ab70fe0cf"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"empty check"</span><span class="token punctuation">,</span><span class="token string-property property">"property"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token string-property property">"propertyType"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"nempty"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"checkall"</span><span class="token operator">:</span><span class="token string">"true"</span><span class="token punctuation">,</span><span class="token string-property property">"repair"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"outputs"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">770</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1160</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"8eda44307f47c12f"</span><span class="token punctuation">,</span><span class="token string">"d6d60ff6a933ad1d"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"d6d60ff6a933ad1d"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"38f43e1ab70fe0cf"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Get MySwitch Value"</span><span class="token punctuation">,</span><span class="token string-property property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload[4].item.value"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1000</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1200</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"13c6bf381ff0d8b2"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"9c3b0c36d69c05cf"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_text"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3e09b7a420dd81d2"</span><span class="token punctuation">,</span><span class="token string-property property">"group"</span><span class="token operator">:</span><span class="token string">"4340b56a2335c304"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">12</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token number">4</span><span class="token punctuation">,</span><span class="token string-property property">"height"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"MyDevice"</span><span class="token punctuation">,</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"format"</span><span class="token operator">:</span><span class="token string">"<i class=\"fa fa-cube\" aria-hidden=\"true\"></i> "</span><span class="token punctuation">,</span><span class="token string-property property">"layout"</span><span class="token operator">:</span><span class="token string">"col-center"</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"style"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"font"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"fontSize"</span><span class="token operator">:</span><span class="token number">16</span><span class="token punctuation">,</span><span class="token string-property property">"color"</span><span class="token operator">:</span><span class="token string">"#000000"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1060</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">400</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"de21b7ad98a05833"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3e09b7a420dd81d2"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"MyDevice Object"</span><span class="token punctuation">,</span><span class="token string-property property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"Objects.MyObjects.MyDevice.nodeId"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"flow"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload[0].item.nodeId"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload[0].item.browseName.name"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">790</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">400</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"9c3b0c36d69c05cf"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"2d56e9a431c21a3b"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3e09b7a420dd81d2"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Get MyObjects Object Structure"</span><span class="token punctuation">,</span><span class="token string-property property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"topic"</span><span class="token punctuation">,</span><span class="token string-property property">"v"</span><span class="token operator">:</span><span class="token string">"Objects.MyObjects.nodeId"</span><span class="token punctuation">,</span><span class="token string-property property">"vt"</span><span class="token operator">:</span><span class="token string">"flow"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"repeat"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"once"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"onceDelay"</span><span class="token operator">:</span><span class="token string">"0.5"</span><span class="token punctuation">,</span><span class="token string-property property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"payload"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"payloadType"</span><span class="token operator">:</span><span class="token string">"date"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">230</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">400</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"ac95bd0e2b304eec"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"ac95bd0e2b304eec"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"OpcUa-Browser"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3e09b7a420dd81d2"</span><span class="token punctuation">,</span><span class="token string-property property">"endpoint"</span><span class="token operator">:</span><span class="token string">"53f4394dbf12c6b7"</span><span class="token punctuation">,</span><span class="token string-property property">"item"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"datatype"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"items"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"OPC Client Namespace Browse"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">510</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">400</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"de21b7ad98a05833"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"7de0892e28c6fea9"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_gauge"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"38f43e1ab70fe0cf"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"group"</span><span class="token operator">:</span><span class="token string">"b095aee62f84e514"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">4</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token string">"0"</span><span class="token punctuation">,</span><span class="token string-property property">"height"</span><span class="token operator">:</span><span class="token string">"0"</span><span class="token punctuation">,</span><span class="token string-property property">"gtype"</span><span class="token operator">:</span><span class="token string">"wave"</span><span class="token punctuation">,</span><span class="token string-property property">"title"</span><span class="token operator">:</span><span class="token string">"MyLevel"</span><span class="token punctuation">,</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token string">"%"</span><span class="token punctuation">,</span><span class="token string-property property">"format"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"min"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"max"</span><span class="token operator">:</span><span class="token string">"100"</span><span class="token punctuation">,</span><span class="token string-property property">"colors"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"#00b500"</span><span class="token punctuation">,</span><span class="token string">"#e6e600"</span><span class="token punctuation">,</span><span class="token string">"#ca3838"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"seg1"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"seg2"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"diff"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1220</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1140</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"13c6bf381ff0d8b2"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_led"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"38f43e1ab70fe0cf"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token string-property property">"group"</span><span class="token operator">:</span><span class="token string">"b095aee62f84e514"</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token string">"MySwitch"</span><span class="token punctuation">,</span><span class="token string-property property">"labelPlacement"</span><span class="token operator">:</span><span class="token string">"left"</span><span class="token punctuation">,</span><span class="token string-property property">"labelAlignment"</span><span class="token operator">:</span><span class="token string">"left"</span><span class="token punctuation">,</span><span class="token string-property property">"colorForValue"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"color"</span><span class="token operator">:</span><span class="token string">"#ff0000"</span><span class="token punctuation">,</span><span class="token string-property property">"value"</span><span class="token operator">:</span><span class="token string">"false"</span><span class="token punctuation">,</span><span class="token string-property property">"valueType"</span><span class="token operator">:</span><span class="token string">"bool"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"color"</span><span class="token operator">:</span><span class="token string">"#008000"</span><span class="token punctuation">,</span><span class="token string-property property">"value"</span><span class="token operator">:</span><span class="token string">"true"</span><span class="token punctuation">,</span><span class="token string-property property">"valueType"</span><span class="token operator">:</span><span class="token string">"bool"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"allowColorForValueInMessage"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"shape"</span><span class="token operator">:</span><span class="token string">"circle"</span><span class="token punctuation">,</span><span class="token string-property property">"showGlow"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1210</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1200</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"2cb01ef75f8b5f39"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_switch"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"b1eeba37b0d982ef"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token string">"Toggle MySwitch"</span><span class="token punctuation">,</span><span class="token string-property property">"tooltip"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"group"</span><span class="token operator">:</span><span class="token string">"b095aee62f84e514"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"passthru"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"decouple"</span><span class="token operator">:</span><span class="token string">"false"</span><span class="token punctuation">,</span><span class="token string-property property">"topic"</span><span class="token operator">:</span><span class="token string">"topic"</span><span class="token punctuation">,</span><span class="token string-property property">"topicType"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"style"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"onvalue"</span><span class="token operator">:</span><span class="token string">"true"</span><span class="token punctuation">,</span><span class="token string-property property">"onvalueType"</span><span class="token operator">:</span><span class="token string">"bool"</span><span class="token punctuation">,</span><span class="token string-property property">"onicon"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"oncolor"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"offvalue"</span><span class="token operator">:</span><span class="token string">"false"</span><span class="token punctuation">,</span><span class="token string-property property">"offvalueType"</span><span class="token operator">:</span><span class="token string">"bool"</span><span class="token punctuation">,</span><span class="token string-property property">"officon"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"offcolor"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"animate"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">170</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1360</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"36daedb0c2a5295d"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"36daedb0c2a5295d"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"OpcUa-Item"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"b1eeba37b0d982ef"</span><span class="token punctuation">,</span><span class="token string-property property">"item"</span><span class="token operator">:</span><span class="token string">"ns=6;s=MySwitch"</span><span class="token punctuation">,</span><span class="token string-property property">"datatype"</span><span class="token operator">:</span><span class="token string">"Boolean"</span><span class="token punctuation">,</span><span class="token string-property property">"value"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Toggle MySwitch"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">430</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1360</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"f6d73ab104914017"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"f6d73ab104914017"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"OpcUa-Client"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"b1eeba37b0d982ef"</span><span class="token punctuation">,</span><span class="token string-property property">"endpoint"</span><span class="token operator">:</span><span class="token string">"53f4394dbf12c6b7"</span><span class="token punctuation">,</span><span class="token string-property property">"action"</span><span class="token operator">:</span><span class="token string">"write"</span><span class="token punctuation">,</span><span class="token string-property property">"deadbandtype"</span><span class="token operator">:</span><span class="token string">"a"</span><span class="token punctuation">,</span><span class="token string-property property">"deadbandvalue"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"time"</span><span class="token operator">:</span><span class="token number">10</span><span class="token punctuation">,</span><span class="token string-property property">"timeUnit"</span><span class="token operator">:</span><span class="token string">"s"</span><span class="token punctuation">,</span><span class="token string-property property">"certificate"</span><span class="token operator">:</span><span class="token string">"n"</span><span class="token punctuation">,</span><span class="token string-property property">"localfile"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"localkeyfile"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"securitymode"</span><span class="token operator">:</span><span class="token string">"None"</span><span class="token punctuation">,</span><span class="token string-property property">"securitypolicy"</span><span class="token operator">:</span><span class="token string">"None"</span><span class="token punctuation">,</span><span class="token string-property property">"folderName4PKI"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"useTransport"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"maxChunkCount"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"maxMessageSize"</span><span class="token operator">:</span><span class="token number">8192</span><span class="token punctuation">,</span><span class="token string-property property">"receiveBufferSize"</span><span class="token operator">:</span><span class="token number">8192</span><span class="token punctuation">,</span><span class="token string-property property">"sendBufferSize"</span><span class="token operator">:</span><span class="token number">8192</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Write MySwitch"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">680</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1360</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"16224a3eefb5184e"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"b1eeba37b0d982ef"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Dashboard Input"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">160</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1320</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"8b48799434be36cf"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"38f43e1ab70fe0cf"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Display on Dashboard"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1220</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1100</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"bd95b96ed77a621c"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3013af7593f2847b"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Call OPC UA Item"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">430</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1640</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"26b7db518e4ac448"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"OpcUa-Event"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3013af7593f2847b"</span><span class="token punctuation">,</span><span class="token string-property property">"root"</span><span class="token operator">:</span><span class="token string">"ns=6;s=MyLevel.Alarm"</span><span class="token punctuation">,</span><span class="token string-property property">"activatecustomevent"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"eventtype"</span><span class="token operator">:</span><span class="token string">"i=2041"</span><span class="token punctuation">,</span><span class="token string-property property">"customeventtype"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"MyLevel Alarms"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">460</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1680</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"67aa6d2ecee3895b"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"05b98e27c8317489"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3013af7593f2847b"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Trigger Alarm Event Capture"</span><span class="token punctuation">,</span><span class="token string-property property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"topic"</span><span class="token punctuation">,</span><span class="token string-property property">"vt"</span><span class="token operator">:</span><span class="token string">"str"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"repeat"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"once"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"onceDelay"</span><span class="token operator">:</span><span class="token number">0.1</span><span class="token punctuation">,</span><span class="token string-property property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"payload"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"payloadType"</span><span class="token operator">:</span><span class="token string">"date"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">220</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1680</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"26b7db518e4ac448"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"67aa6d2ecee3895b"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"OpcUa-Client"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3013af7593f2847b"</span><span class="token punctuation">,</span><span class="token string-property property">"endpoint"</span><span class="token operator">:</span><span class="token string">"53f4394dbf12c6b7"</span><span class="token punctuation">,</span><span class="token string-property property">"action"</span><span class="token operator">:</span><span class="token string">"events"</span><span class="token punctuation">,</span><span class="token string-property property">"deadbandtype"</span><span class="token operator">:</span><span class="token string">"a"</span><span class="token punctuation">,</span><span class="token string-property property">"deadbandvalue"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"time"</span><span class="token operator">:</span><span class="token number">10</span><span class="token punctuation">,</span><span class="token string-property property">"timeUnit"</span><span class="token operator">:</span><span class="token string">"s"</span><span class="token punctuation">,</span><span class="token string-property property">"certificate"</span><span class="token operator">:</span><span class="token string">"n"</span><span class="token punctuation">,</span><span class="token string-property property">"localfile"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"localkeyfile"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"securitymode"</span><span class="token operator">:</span><span class="token string">"None"</span><span class="token punctuation">,</span><span class="token string-property property">"securitypolicy"</span><span class="token operator">:</span><span class="token string">"None"</span><span class="token punctuation">,</span><span class="token string-property property">"folderName4PKI"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"useTransport"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"maxChunkCount"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"maxMessageSize"</span><span class="token operator">:</span><span class="token number">8192</span><span class="token punctuation">,</span><span class="token string-property property">"receiveBufferSize"</span><span class="token operator">:</span><span class="token number">8192</span><span class="token punctuation">,</span><span class="token string-property property">"sendBufferSize"</span><span class="token operator">:</span><span class="token number">8192</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Get MyLevel Events"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">680</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1680</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"4c47ed5a65160149"</span><span class="token punctuation">,</span><span class="token string">"8d36820730690d7d"</span><span class="token punctuation">,</span><span class="token string">"87eb7ad331a15823"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"711c6f36547b4efb"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_slider"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"b1eeba37b0d982ef"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token string">"Modify MyLevel"</span><span class="token punctuation">,</span><span class="token string-property property">"tooltip"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"group"</span><span class="token operator">:</span><span class="token string">"b095aee62f84e514"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"passthru"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"outs"</span><span class="token operator">:</span><span class="token string">"all"</span><span class="token punctuation">,</span><span class="token string-property property">"topic"</span><span class="token operator">:</span><span class="token string">"topic"</span><span class="token punctuation">,</span><span class="token string-property property">"topicType"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"min"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"max"</span><span class="token operator">:</span><span class="token string">"100"</span><span class="token punctuation">,</span><span class="token string-property property">"step"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">160</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1420</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"cb0e16ceab421d58"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"cb0e16ceab421d58"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"OpcUa-Item"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"b1eeba37b0d982ef"</span><span class="token punctuation">,</span><span class="token string-property property">"item"</span><span class="token operator">:</span><span class="token string">"ns=6;s=MyLevel"</span><span class="token punctuation">,</span><span class="token string-property property">"datatype"</span><span class="token operator">:</span><span class="token string">"Double"</span><span class="token punctuation">,</span><span class="token string-property property">"value"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Modify MyLevel"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">420</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1420</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"968a8b27d03f6372"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"968a8b27d03f6372"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"OpcUa-Client"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"b1eeba37b0d982ef"</span><span class="token punctuation">,</span><span class="token string-property property">"endpoint"</span><span class="token operator">:</span><span class="token string">"53f4394dbf12c6b7"</span><span class="token punctuation">,</span><span class="token string-property property">"action"</span><span class="token operator">:</span><span class="token string">"write"</span><span class="token punctuation">,</span><span class="token string-property property">"deadbandtype"</span><span class="token operator">:</span><span class="token string">"a"</span><span class="token punctuation">,</span><span class="token string-property property">"deadbandvalue"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"time"</span><span class="token operator">:</span><span class="token number">10</span><span class="token punctuation">,</span><span class="token string-property property">"timeUnit"</span><span class="token operator">:</span><span class="token string">"s"</span><span class="token punctuation">,</span><span class="token string-property property">"certificate"</span><span class="token operator">:</span><span class="token string">"n"</span><span class="token punctuation">,</span><span class="token string-property property">"localfile"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"localkeyfile"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"securitymode"</span><span class="token operator">:</span><span class="token string">"None"</span><span class="token punctuation">,</span><span class="token string-property property">"securitypolicy"</span><span class="token operator">:</span><span class="token string">"None"</span><span class="token punctuation">,</span><span class="token string-property property">"folderName4PKI"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"useTransport"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"maxChunkCount"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"maxMessageSize"</span><span class="token operator">:</span><span class="token number">8192</span><span class="token punctuation">,</span><span class="token string-property property">"receiveBufferSize"</span><span class="token operator">:</span><span class="token number">8192</span><span class="token punctuation">,</span><span class="token string-property property">"sendBufferSize"</span><span class="token operator">:</span><span class="token number">8192</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Write MyLevel"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">680</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1420</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"bfb585c5777dfeca"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_text"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3013af7593f2847b"</span><span class="token punctuation">,</span><span class="token string-property property">"group"</span><span class="token operator">:</span><span class="token string">"b095aee62f84e514"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">5</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token string">"Latest MyLevel Event"</span><span class="token punctuation">,</span><span class="token string-property property">"format"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"layout"</span><span class="token operator">:</span><span class="token string">"col-center"</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"style"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"font"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"fontSize"</span><span class="token operator">:</span><span class="token number">16</span><span class="token punctuation">,</span><span class="token string-property property">"color"</span><span class="token operator">:</span><span class="token string">"#000000"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1180</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1640</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"4c47ed5a65160149"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3013af7593f2847b"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Event Text"</span><span class="token punctuation">,</span><span class="token string-property property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload.Message.text"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">950</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1620</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"bfb585c5777dfeca"</span><span class="token punctuation">,</span><span class="token string">"564212f76a83ce5e"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"b6d318d3372e149f"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_text"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3013af7593f2847b"</span><span class="token punctuation">,</span><span class="token string-property property">"group"</span><span class="token operator">:</span><span class="token string">"b095aee62f84e514"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">7</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token string">"Latest MyLevel Event Timestamp"</span><span class="token punctuation">,</span><span class="token string-property property">"format"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"layout"</span><span class="token operator">:</span><span class="token string">"col-center"</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"style"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"font"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"fontSize"</span><span class="token operator">:</span><span class="token number">16</span><span class="token punctuation">,</span><span class="token string-property property">"color"</span><span class="token operator">:</span><span class="token string">"#000000"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1220</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1680</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"8d36820730690d7d"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3013af7593f2847b"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Event Time"</span><span class="token punctuation">,</span><span class="token string-property property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload.Time"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">950</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1680</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"b6d318d3372e149f"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"87eb7ad331a15823"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3013af7593f2847b"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Event Severity"</span><span class="token punctuation">,</span><span class="token string-property property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload.Severity"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">960</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1740</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"fd228940746d2e4c"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"fd228940746d2e4c"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_text"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3013af7593f2847b"</span><span class="token punctuation">,</span><span class="token string-property property">"group"</span><span class="token operator">:</span><span class="token string">"b095aee62f84e514"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">6</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token string">"Latest MyLevel Event Severity"</span><span class="token punctuation">,</span><span class="token string-property property">"format"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"layout"</span><span class="token operator">:</span><span class="token string">"col-center"</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"style"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"font"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"fontSize"</span><span class="token operator">:</span><span class="token number">16</span><span class="token punctuation">,</span><span class="token string-property property">"color"</span><span class="token operator">:</span><span class="token string">"#000000"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1210</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1740</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"564212f76a83ce5e"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_toast"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3013af7593f2847b"</span><span class="token punctuation">,</span><span class="token string-property property">"position"</span><span class="token operator">:</span><span class="token string">"top right"</span><span class="token punctuation">,</span><span class="token string-property property">"displayTime"</span><span class="token operator">:</span><span class="token string">"3"</span><span class="token punctuation">,</span><span class="token string-property property">"highlight"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"sendall"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"outputs"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token string-property property">"ok"</span><span class="token operator">:</span><span class="token string">"OK"</span><span class="token punctuation">,</span><span class="token string-property property">"cancel"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"raw"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Event Notification"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1170</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1580</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"6fdabcc2950ccf4e"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3e09b7a420dd81d2"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Store & Parse nodeId & browseName"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">810</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">60</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"8f866373ed32349c"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"ab8e5ebe8c14819d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Discard Empty Datasets"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">740</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">600</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"35f53fe496f4f68a"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"ab8e5ebe8c14819d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Parse Simulation Values"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1030</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">520</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"c9e043783aeaf0fa"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"ab8e5ebe8c14819d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Display on Dashboard"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1300</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">520</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"9c5762fc7fdbae59"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"23696c742b062ee0"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Discard Empty Datasets"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">780</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">860</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"a5981d515cfadb55"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"23696c742b062ee0"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Parse StaticData Values"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1030</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">860</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"a736c876b46c763f"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"23696c742b062ee0"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Display on Dashboard"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1300</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">860</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"e29a74ea9a1de0ef"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"38f43e1ab70fe0cf"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Parse MyDevice Values"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1000</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1100</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"a27699b4e9697558"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"38f43e1ab70fe0cf"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Discard Empty Datasets"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">760</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1120</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"8a06f75c33593dc1"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3013af7593f2847b"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Parse Event Dataset"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">950</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1580</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"19c427f70d0ed845"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"b1eeba37b0d982ef"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Call OPC UA Item"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">430</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1320</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"01153fddbbb2cd73"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"b1eeba37b0d982ef"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Write OPC UA Item to Client"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">700</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1320</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"6ba832b756579002"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3013af7593f2847b"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Get OPC Events from Client"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">680</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1640</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"be911708a19728b0"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"g"</span><span class="token operator">:</span><span class="token string">"3013af7593f2847b"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Display Events on Dashboard"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">1200</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">1540</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"475336420d03d64d"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_spacer"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"spacer"</span><span class="token punctuation">,</span><span class="token string-property property">"group"</span><span class="token operator">:</span><span class="token string">"4340b56a2335c304"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token number">4</span><span class="token punctuation">,</span><span class="token string-property property">"height"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"b062bda097966b0d"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_spacer"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"spacer"</span><span class="token punctuation">,</span><span class="token string-property property">"group"</span><span class="token operator">:</span><span class="token string">"4340b56a2335c304"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">4</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token number">4</span><span class="token punctuation">,</span><span class="token string-property property">"height"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"bca4de20b077c6a7"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_spacer"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"spacer"</span><span class="token punctuation">,</span><span class="token string-property property">"group"</span><span class="token operator">:</span><span class="token string">"4340b56a2335c304"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">5</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token string-property property">"height"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"943c46d47e94a1cb"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_spacer"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"spacer"</span><span class="token punctuation">,</span><span class="token string-property property">"group"</span><span class="token operator">:</span><span class="token string">"4340b56a2335c304"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">7</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token string-property property">"height"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"f97ba8b89dda4ec8"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_spacer"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"spacer"</span><span class="token punctuation">,</span><span class="token string-property property">"group"</span><span class="token operator">:</span><span class="token string">"4340b56a2335c304"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">10</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token number">4</span><span class="token punctuation">,</span><span class="token string-property property">"height"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"751daf8eaa27f30b"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_spacer"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"58c0065ebdc1d89d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"spacer"</span><span class="token punctuation">,</span><span class="token string-property property">"group"</span><span class="token operator">:</span><span class="token string">"4340b56a2335c304"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">11</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token string-property property">"height"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"53f4394dbf12c6b7"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"OpcUa-Endpoint"</span><span class="token punctuation">,</span><span class="token string-property property">"endpoint"</span><span class="token operator">:</span><span class="token string">"opc.tcp://192.168.0.141:53530/OPCUA/SimulationServer"</span><span class="token punctuation">,</span><span class="token string-property property">"secpol"</span><span class="token operator">:</span><span class="token string">"None"</span><span class="token punctuation">,</span><span class="token string-property property">"secmode"</span><span class="token operator">:</span><span class="token string">"None"</span><span class="token punctuation">,</span><span class="token string-property property">"none"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"login"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"usercert"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"usercertificate"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"userprivatekey"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"4340b56a2335c304"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_group"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Address Space Structure"</span><span class="token punctuation">,</span><span class="token string-property property">"tab"</span><span class="token operator">:</span><span class="token string">"0113eb87060106be"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token string-property property">"disp"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token string">"7"</span><span class="token punctuation">,</span><span class="token string-property property">"collapse"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"825fe3323bd36ae6"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_group"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Simulation Values"</span><span class="token punctuation">,</span><span class="token string-property property">"tab"</span><span class="token operator">:</span><span class="token string">"0113eb87060106be"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token string-property property">"disp"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token string">"6"</span><span class="token punctuation">,</span><span class="token string-property property">"collapse"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"92444e82445bab62"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_group"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"StaticData Values"</span><span class="token punctuation">,</span><span class="token string-property property">"tab"</span><span class="token operator">:</span><span class="token string">"0113eb87060106be"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token string-property property">"disp"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token string">"6"</span><span class="token punctuation">,</span><span class="token string-property property">"collapse"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"b095aee62f84e514"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_group"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"MyDevice Status & Control"</span><span class="token punctuation">,</span><span class="token string-property property">"tab"</span><span class="token operator">:</span><span class="token string">"0113eb87060106be"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">4</span><span class="token punctuation">,</span><span class="token string-property property">"disp"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"width"</span><span class="token operator">:</span><span class="token string">"6"</span><span class="token punctuation">,</span><span class="token string-property property">"collapse"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"0113eb87060106be"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"ui_tab"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"OPC UA"</span><span class="token punctuation">,</span><span class="token string-property property">"icon"</span><span class="token operator">:</span><span class="token string">"dashboard"</span><span class="token punctuation">,</span><span class="token string-property property">"order"</span><span class="token operator">:</span><span class="token number">7</span><span class="token punctuation">,</span><span class="token string-property property">"disabled"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"hidden"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">}</span><span class="token punctuation">]</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-286" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
https://flowfuse.com/blog/2023/07/dashboard-0-1-release/First Pre-Alpha Release of the new Node-RED DashboardIntroducing v0.0.1 – An Initial Glimpse at the Future of Dashboarding in Node-RED2023-07-27T00:00:00ZJoe PavittMarian Demme<p>Just weeks ago, we at FlowFuse <a href="https://flowfuse.com/blog/2023/06/dashboard-announcement">announced our plan</a> to develop a successor to the Node-RED Dashboard. Today, we're excited to reveal the pre-alpha release of this highly anticipated project, bringing us one step closer to a new era of data visualization in Node-RED.</p>
<!--more-->
<h2 id="sneak-peek-into-the-new-node-red-dashboard" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/dashboard-0-1-release/#sneak-peek-into-the-new-node-red-dashboard"># </a> Sneak Peek into the New Node-RED Dashboard</h2>
<!-- ![](./images/placeholder.png "new Node-RED Dashboard Overview")-->
<p>The Node-RED Dashboard successor is now available for install as an npm package under the name <a href="https://www.npmjs.com/package/@flowforge/node-red-dashboard">@flowforge/node-red-dashboard</a> in your Node-RED palette manager.</p>
<p>This pre-alpha version includes the first set of Vue.js-based elements familiar to Node-RED Dashboard users:</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/nr-dashboard-screenshot-SXRsRfVGhg-650.avif 650w, https://flowfuse.com/img/nr-dashboard-screenshot-SXRsRfVGhg-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/nr-dashboard-screenshot-SXRsRfVGhg-650.webp 650w, https://flowfuse.com/img/nr-dashboard-screenshot-SXRsRfVGhg-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/nr-dashboard-screenshot-SXRsRfVGhg-650.jpeg 650w, https://flowfuse.com/img/nr-dashboard-screenshot-SXRsRfVGhg-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="new Node-RED Dashboard Elements" alt="" loading="lazy" decoding="async" src="https://flowfuse.com/img/nr-dashboard-screenshot-SXRsRfVGhg-650.jpeg" width="1300" height="759" /></picture></p>
<p>This is but a hint of what's to come. The objective of these pre-alpha releases is to provide early access to the current status.</p>
<p>The strength of the project comes from the community. Your insights, suggestions and contributions play a significant role in shaping the future of this dashboard. Keep them coming through our <a href="https://github.com/FlowFuse/node-red-dashboard">Github page</a>.</p>
<h2 id="current-status-and-next-steps" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/dashboard-0-1-release/#current-status-and-next-steps"># </a> Current Status and Next Steps</h2>
<p>As of now, we've implemented the following Dashboard Widgets:</p>
<ul>
<li>UI Text (<a href="https://github.com/FlowFuse/node-red-dashboard/issues/38">ui-text Widget</a>)</li>
<li>Text Input (<a href="https://github.com/FlowFuse/node-red-dashboard/issues/39">ui-text-input Widget</a>)</li>
<li>Range Slider (<a href="https://github.com/FlowFuse/node-red-dashboard/issues/47">ui-slider Widget</a>)</li>
<li>Dropdown/Select (<a href="https://github.com/FlowFuse/node-red-dashboard/issues/45">ui-dropdown Widget</a>)</li>
</ul>
<p>We've also introduced a new widget:</p>
<ul>
<li>Markdown (<a href="https://github.com/FlowFuse/node-red-dashboard/issues/62">ui-markdown Widget</a>)</li>
</ul>
<p>Not yet part of the first Pre-Alpha Release:</p>
<ul>
<li>Toggle Switch (<a href="https://github.com/FlowFuse/node-red-dashboard/issues/42">ui-switch Widget</a>)</li>
<li>Colour Picker (<a href="https://github.com/FlowFuse/node-red-dashboard/issues/46">ui-color-picker Widget</a>)</li>
<li>Number Input (<a href="https://github.com/FlowFuse/node-red-dashboard/issues/41">ui-numeric Widget</a>)</li>
<li>Form (<a href="https://github.com/FlowFuse/node-red-dashboard/issues/49">ui-form Widget</a>)</li>
<li>Date selector (<a href="https://github.com/FlowFuse/node-red-dashboard/issues/32">ui-date-picker</a>)</li>
</ul>
<p>Our immediate focus is to continue adding the missing elements from the original Node-RED Dashboard, releasing each as soon as they're fully developed. This will significantly increase the frequency of our releases in the upcoming weeks.</p>
<p>In addition to these releases, we plan to publish regular blog posts titled "What's New in Node-RED Dashboard". These posts will keep you informed of all the latest features, updates, and improvements.</p>
https://flowfuse.com/blog/2023/07/images-in-node-red-dashboards/How to add images to Node-RED dashboards when using FlowFuseImport your images into your Node-RED dashboards, wherever you are running your instances2023-07-21T00:00:00ZRob Marcer<p>Using images in your Node-RED dashboards can significantly improve your users' experience. The most common method to add images to dashboards, is to store them within the filesystem of an Node-RED instance but sometimes that's not an option. How can you easily use images when working in a containerised environment such as Docker, Kubernetes, or FlowFuse?</p>
<!--more-->
<p>When designing a dashboard, images allow you to significantly enrich your content. Some examples include:</p>
<ul>
<li>
<p>displaying maps to guide engineers to a problem which needs resolving.</p>
</li>
<li>
<p>displaying pictures of specific hardware on a factory-floor which needs to be checked.</p>
</li>
<li>
<p>displaying physical tools which should be used to resolve a problem.</p>
</li>
</ul>
<h2 id="why-not-just-store-them-in-node-red's-host-operating-system%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/images-in-node-red-dashboards/#why-not-just-store-them-in-node-red's-host-operating-system%3F"># </a> Why not just store them in Node-RED's host operating system?</h2>
<p>Storing images locally can work well when you can access and edit the images on an operating system, but that approach doesn't scale if you are moving instances through a DevOps pipeline. It can also not work well when deploying to environments where you don't have easy access to the host operating system.</p>
<p>How can we include images in dashboards, and be confident that a given build of an application will show the correct images, no matter where your Node-RED instances are hosted?</p>
<h2 id="inspiration" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/images-in-node-red-dashboards/#inspiration"># </a> Inspiration</h2>
<p>There are various solutions to this problem, I wanted to share one I came across when working with a FlowFuse customer recently. I've modified the flows to make them more general in design, but the underlying principal is the same. I asked if I was OK to credit the customer but they said there was no need. Thanks for the inspiration, kind customer!</p>
<h2 id="solution-explanation" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/images-in-node-red-dashboards/#solution-explanation"># </a> Solution explanation</h2>
<p>There are three key sections to this solution:</p>
<ol>
<li>
<p>Pull the images we need from URLs</p>
</li>
<li>
<p>Store those images in the temporary filesystem of Node-RED</p>
</li>
<li>
<p>Serve up those images as needed in the dashboard</p>
</li>
</ol>
<p>It is possible for us to skip step 2, but I wanted to have the images stored locally, in the Node-RED instance. storing the images locally will improve the loading times of the dashboard. This is especially beneficial when your dashboard is dynamically displaying relevant images, e.g. to show an image of a specific machine which needs to be attended to.</p>
<p>The key benefit of pulling the images from URLs this way is, no matter where you are running Node-RED, the correct images will be shown in your dashboard.</p>
<h2 id="file-and-file-in-nodes" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/images-in-node-red-dashboards/#file-and-file-in-nodes"># </a> File and file-in nodes</h2>
<p>I've included the flows as json below so you can try them out yourself. Please note, I'm using FlowFuse's own <a href="https://flowfuse.com/docs/user/filenodes/">file and file-in nodes</a> in these examples. If you want to use these flows on hosting other than FlowFuse, you will need to replace the nodes with the standard Node-RED file and file-in nodes.</p>
<h2 id="custom-nodes-used" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/images-in-node-red-dashboards/#custom-nodes-used"># </a> Custom nodes used</h2>
<p>These flows use a few very useful custom nodes which you will need to add manually via the palette manager, they are:</p>
<ul>
<li><a href="https://flows.nodered.org/node/node-red-contrib-calc">node-red-contrib-calc</a> - "A Node-Red node to perform basic mathematical calculations".</li>
<li><a href="https://flows.nodered.org/node/node-red-contrib-image-output">node-red-contrib-image-output</a> - "Easy way of previewing and examining images in your flows".</li>
<li><a href="https://flows.nodered.org/node/node-red-contrib-os">node-red-contrib-os</a> - "Node-Red nodes for obtaining cpu system information".</li>
<li><a href="https://flows.nodered.org/node/node-red-contrib-string">node-red-contrib-string</a> - "Provides a string manipulation node with a chainable UI based on the concise and lightweight stringjs.com".</li>
<li><a href="https://flows.nodered.org/node/node-red-dashboard">node-red-dashboard</a> - "A set of dashboard nodes for Node-RED".</li>
<li><a href="https://flows.nodered.org/node/node-red-node-base64">node-red-node-base64</a> - "A Node-RED node to pack and unpack objects to base64 format".</li>
</ul>
<h2 id="the-flows" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/images-in-node-red-dashboards/#the-flows"># </a> The flows</h2>
<p>The first flow takes image URLs in an array, each image is downloaded, processed, then saved to the local file storage. Let's take a look at the flow:</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/save-images-to-disk-sYtc2bMRo_-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/save-images-to-disk-sYtc2bMRo_-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Download the images and save them to disk" alt="Download the images and save them to disk" loading="lazy" decoding="async" src="https://flowfuse.com/img/save-images-to-disk-sYtc2bMRo_-650.jpeg" width="650" height="285" /></picture></p>
<p>You can import this flow into Node-RED using the code below:</p>
<div style="position: relative">
<pre class="language-json"><code id="code-124" class="language-json"><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"6b8059f703d0f574"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"group"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Write the images to disk from the URLs"</span><span class="token punctuation">,</span><span class="token property">"style"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token property">"label"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token property">"nodes"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"04fb6911559797a0"</span><span class="token punctuation">,</span><span class="token string">"8a3c077f0f85a905"</span><span class="token punctuation">,</span><span class="token string">"22c5026dd58e418b"</span><span class="token punctuation">,</span><span class="token string">"6fcca5cfee2bcb89"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">38</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">53</span><span class="token punctuation">,</span><span class="token property">"w"</span><span class="token operator">:</span><span class="token number">1004</span><span class="token punctuation">,</span><span class="token property">"h"</span><span class="token operator">:</span><span class="token number">434</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"04fb6911559797a0"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"group"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"6b8059f703d0f574"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Inject the image URLs to download"</span><span class="token punctuation">,</span><span class="token property">"style"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token property">"label"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token property">"nodes"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"e635ceb0577a86d5"</span><span class="token punctuation">,</span><span class="token string">"29fe40a054be5b2b"</span><span class="token punctuation">,</span><span class="token string">"1e81a35c27aae6ad"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">74</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">79</span><span class="token punctuation">,</span><span class="token property">"w"</span><span class="token operator">:</span><span class="token number">502</span><span class="token punctuation">,</span><span class="token property">"h"</span><span class="token operator">:</span><span class="token number">82</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"e635ceb0577a86d5"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"04fb6911559797a0"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Send in image URLs as an array"</span><span class="token punctuation">,</span><span class="token property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"repeat"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"once"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"onceDelay"</span><span class="token operator">:</span><span class="token number">0.1</span><span class="token punctuation">,</span><span class="token property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"payload"</span><span class="token operator">:</span><span class="token string">"[\"https://openjsf.org/wp-content/uploads/sites/84/2023/02/ff-logo-wordmark-light_4x.png\",\"https://nodered.org/images/nr-image-1.png\",\"/img/screen-pseudo-overview-2QvTVle3Mr-384.avif\"]"</span><span class="token punctuation">,</span><span class="token property">"payloadType"</span><span class="token operator">:</span><span class="token string">"json"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">250</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">120</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"29fe40a054be5b2b"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"29fe40a054be5b2b"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"split"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"04fb6911559797a0"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"splt"</span><span class="token operator">:</span><span class="token string">"\\n"</span><span class="token punctuation">,</span><span class="token property">"spltType"</span><span class="token operator">:</span><span class="token string">"str"</span><span class="token punctuation">,</span><span class="token property">"arraySplt"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"arraySpltType"</span><span class="token operator">:</span><span class="token string">"len"</span><span class="token punctuation">,</span><span class="token property">"stream"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"addname"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">450</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">120</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"1e81a35c27aae6ad"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"1e81a35c27aae6ad"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"link out"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"04fb6911559797a0"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"link out 3"</span><span class="token punctuation">,</span><span class="token property">"mode"</span><span class="token operator">:</span><span class="token string">"link"</span><span class="token punctuation">,</span><span class="token property">"links"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"f582702ec222069c"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">535</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">120</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"8a3c077f0f85a905"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"group"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"6b8059f703d0f574"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Download the images"</span><span class="token punctuation">,</span><span class="token property">"style"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token property">"label"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token property">"nodes"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"453f3b9d7d312bd2"</span><span class="token punctuation">,</span><span class="token string">"ecbd7b1a410ecd9d"</span><span class="token punctuation">,</span><span class="token string">"4d650baa2118036e"</span><span class="token punctuation">,</span><span class="token string">"f582702ec222069c"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">84</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">179</span><span class="token punctuation">,</span><span class="token property">"w"</span><span class="token operator">:</span><span class="token number">532</span><span class="token punctuation">,</span><span class="token property">"h"</span><span class="token operator">:</span><span class="token number">82</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"453f3b9d7d312bd2"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"http request"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"8a3c077f0f85a905"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Get the image"</span><span class="token punctuation">,</span><span class="token property">"method"</span><span class="token operator">:</span><span class="token string">"GET"</span><span class="token punctuation">,</span><span class="token property">"ret"</span><span class="token operator">:</span><span class="token string">"bin"</span><span class="token punctuation">,</span><span class="token property">"paytoqs"</span><span class="token operator">:</span><span class="token string">"ignore"</span><span class="token punctuation">,</span><span class="token property">"url"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"tls"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"persist"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"proxy"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"insecureHTTPParser"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"authType"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"senderr"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"headers"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">460</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">220</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"4d650baa2118036e"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"ecbd7b1a410ecd9d"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"8a3c077f0f85a905"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Set URL to download"</span><span class="token punctuation">,</span><span class="token property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"t"</span><span class="token operator">:</span><span class="token string">"move"</span><span class="token punctuation">,</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">"url"</span><span class="token punctuation">,</span><span class="token property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">260</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">220</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"453f3b9d7d312bd2"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"4d650baa2118036e"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"link out"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"8a3c077f0f85a905"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"link out 1"</span><span class="token punctuation">,</span><span class="token property">"mode"</span><span class="token operator">:</span><span class="token string">"link"</span><span class="token punctuation">,</span><span class="token property">"links"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"8bc38803dec97185"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">575</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">220</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"f582702ec222069c"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"link in"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"8a3c077f0f85a905"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"link in 3"</span><span class="token punctuation">,</span><span class="token property">"links"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"1e81a35c27aae6ad"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">125</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">220</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"ecbd7b1a410ecd9d"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"22c5026dd58e418b"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"group"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"6b8059f703d0f574"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Save the images to the local storage"</span><span class="token punctuation">,</span><span class="token property">"style"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token property">"label"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token property">"nodes"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"95c819560d22f394"</span><span class="token punctuation">,</span><span class="token string">"0fe7f013b6356c5d"</span><span class="token punctuation">,</span><span class="token string">"7edc6cb2b0d243db"</span><span class="token punctuation">,</span><span class="token string">"829bfc8e6e293ada"</span><span class="token punctuation">,</span><span class="token string">"8bc38803dec97185"</span><span class="token punctuation">,</span><span class="token string">"98980d88013c6e12"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">84</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">279</span><span class="token punctuation">,</span><span class="token property">"w"</span><span class="token operator">:</span><span class="token number">932</span><span class="token punctuation">,</span><span class="token property">"h"</span><span class="token operator">:</span><span class="token number">82</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"95c819560d22f394"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"base64"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"22c5026dd58e418b"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"convert to base64"</span><span class="token punctuation">,</span><span class="token property">"action"</span><span class="token operator">:</span><span class="token string">"str"</span><span class="token punctuation">,</span><span class="token property">"property"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">250</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">320</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"829bfc8e6e293ada"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"0fe7f013b6356c5d"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"file"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"22c5026dd58e418b"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Write file to storage"</span><span class="token punctuation">,</span><span class="token property">"filename"</span><span class="token operator">:</span><span class="token string">"filename"</span><span class="token punctuation">,</span><span class="token property">"filenameType"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"appendNewline"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"createDir"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"overwriteFile"</span><span class="token operator">:</span><span class="token string">"true"</span><span class="token punctuation">,</span><span class="token property">"encoding"</span><span class="token operator">:</span><span class="token string">"none"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">850</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">320</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"98980d88013c6e12"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"7edc6cb2b0d243db"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"string"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"22c5026dd58e418b"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Get filename from the URL"</span><span class="token punctuation">,</span><span class="token property">"methods"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"getRightMost"</span><span class="token punctuation">,</span><span class="token property">"params"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"str"</span><span class="token punctuation">,</span><span class="token property">"value"</span><span class="token operator">:</span><span class="token string">"/"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"prop"</span><span class="token operator">:</span><span class="token string">"responseUrl"</span><span class="token punctuation">,</span><span class="token property">"propout"</span><span class="token operator">:</span><span class="token string">"filename"</span><span class="token punctuation">,</span><span class="token property">"object"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"objectout"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">620</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">320</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"0fe7f013b6356c5d"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"829bfc8e6e293ada"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"image"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"22c5026dd58e418b"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"preview"</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token string">"150"</span><span class="token punctuation">,</span><span class="token property">"data"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"dataType"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"thumbnail"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"active"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"pass"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"outputs"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">420</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">320</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"7edc6cb2b0d243db"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"8bc38803dec97185"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"link in"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"22c5026dd58e418b"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"link in 1"</span><span class="token punctuation">,</span><span class="token property">"links"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"4d650baa2118036e"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">125</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">320</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"95c819560d22f394"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"98980d88013c6e12"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"link out"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"22c5026dd58e418b"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"link out 2"</span><span class="token punctuation">,</span><span class="token property">"mode"</span><span class="token operator">:</span><span class="token string">"link"</span><span class="token punctuation">,</span><span class="token property">"links"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"1e94b5bab542830a"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">975</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">320</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"6fcca5cfee2bcb89"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"group"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"6b8059f703d0f574"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Output a debug once all images have been processed"</span><span class="token punctuation">,</span><span class="token property">"style"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token property">"label"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token property">"nodes"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"d1a6feea3ac829c6"</span><span class="token punctuation">,</span><span class="token string">"119f8008752bc4fb"</span><span class="token punctuation">,</span><span class="token string">"1e94b5bab542830a"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">64</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">379</span><span class="token punctuation">,</span><span class="token property">"w"</span><span class="token operator">:</span><span class="token number">382</span><span class="token punctuation">,</span><span class="token property">"h"</span><span class="token operator">:</span><span class="token number">82</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"d1a6feea3ac829c6"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"debug"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"6fcca5cfee2bcb89"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"debug 140"</span><span class="token punctuation">,</span><span class="token property">"active"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"tosidebar"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"console"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"tostatus"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"complete"</span><span class="token operator">:</span><span class="token string">"true"</span><span class="token punctuation">,</span><span class="token property">"targetType"</span><span class="token operator">:</span><span class="token string">"full"</span><span class="token punctuation">,</span><span class="token property">"statusVal"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"statusType"</span><span class="token operator">:</span><span class="token string">"auto"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">330</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">420</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"119f8008752bc4fb"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"join"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"6fcca5cfee2bcb89"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"mode"</span><span class="token operator">:</span><span class="token string">"auto"</span><span class="token punctuation">,</span><span class="token property">"build"</span><span class="token operator">:</span><span class="token string">"object"</span><span class="token punctuation">,</span><span class="token property">"property"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"propertyType"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"key"</span><span class="token operator">:</span><span class="token string">"topic"</span><span class="token punctuation">,</span><span class="token property">"joiner"</span><span class="token operator">:</span><span class="token string">"\\n"</span><span class="token punctuation">,</span><span class="token property">"joinerType"</span><span class="token operator">:</span><span class="token string">"str"</span><span class="token punctuation">,</span><span class="token property">"accumulate"</span><span class="token operator">:</span><span class="token string">"false"</span><span class="token punctuation">,</span><span class="token property">"timeout"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"count"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"reduceRight"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">190</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">420</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"d1a6feea3ac829c6"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"1e94b5bab542830a"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"link in"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"6fcca5cfee2bcb89"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"link in 2"</span><span class="token punctuation">,</span><span class="token property">"links"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"98980d88013c6e12"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">105</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">420</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"119f8008752bc4fb"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">]</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-124" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>We've now downloaded the images we need, and saved them to our local storage, to make them load more quickly when a user views them in the dashboard.</p>
<p>Onto the second flow, which will get the images from the local storage and then load them into the dashboard. Let's take a look at it:</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/load-images-from-disk-and-show-in-dashboard-LV9FMxbbNB-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/load-images-from-disk-and-show-in-dashboard-LV9FMxbbNB-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Get the images from the local storage and place them in a dashboard" alt="Get the images from the local storage and place them in a dashboard" loading="lazy" decoding="async" src="https://flowfuse.com/img/load-images-from-disk-and-show-in-dashboard-LV9FMxbbNB-650.jpeg" width="650" height="448" /></picture></p>
<p>You can import this flow into Node-RED using the code below:</p>
<div style="position: relative">
<pre class="language-json"><code id="code-137" class="language-json"><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"c0f2a076e4449f10"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"group"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Get the images from the filestore and display in the Dashboard"</span><span class="token punctuation">,</span><span class="token property">"style"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token property">"label"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token property">"nodes"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"a671e373b7ca0be8"</span><span class="token punctuation">,</span><span class="token string">"767590694c5a17f7"</span><span class="token punctuation">,</span><span class="token string">"fb1ce2ca6b73d950"</span><span class="token punctuation">,</span><span class="token string">"fee0b4a8fff9f4aa"</span><span class="token punctuation">,</span><span class="token string">"c9930135726cf256"</span><span class="token punctuation">,</span><span class="token string">"806b98a5bdf7ceea"</span><span class="token punctuation">,</span><span class="token string">"b58daed1ee453873"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">48</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">513</span><span class="token punctuation">,</span><span class="token property">"w"</span><span class="token operator">:</span><span class="token number">954</span><span class="token punctuation">,</span><span class="token property">"h"</span><span class="token operator">:</span><span class="token number">654</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"a671e373b7ca0be8"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"junction"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"c0f2a076e4449f10"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">320</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">560</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"767590694c5a17f7"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"junction"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"c0f2a076e4449f10"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">320</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">640</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"fb1ce2ca6b73d950"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"group"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"c0f2a076e4449f10"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Get the images from the local storage"</span><span class="token punctuation">,</span><span class="token property">"style"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token property">"label"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token property">"nodes"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"924666bcda6c633b"</span><span class="token punctuation">,</span><span class="token string">"e6f985ed4ff557b5"</span><span class="token punctuation">,</span><span class="token string">"bee4039410549ec8"</span><span class="token punctuation">,</span><span class="token string">"83477da8696ae6e7"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">84</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">679</span><span class="token punctuation">,</span><span class="token property">"w"</span><span class="token operator">:</span><span class="token number">492</span><span class="token punctuation">,</span><span class="token property">"h"</span><span class="token operator">:</span><span class="token number">82</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"924666bcda6c633b"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"image"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"fb1ce2ca6b73d950"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"preview"</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token string">"150"</span><span class="token punctuation">,</span><span class="token property">"data"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"dataType"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"thumbnail"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"active"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"pass"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"outputs"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">440</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">720</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"83477da8696ae6e7"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"e6f985ed4ff557b5"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"file in"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"fb1ce2ca6b73d950"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Read file from storage"</span><span class="token punctuation">,</span><span class="token property">"filename"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"filenameType"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"format"</span><span class="token operator">:</span><span class="token string">"utf8"</span><span class="token punctuation">,</span><span class="token property">"chunk"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"sendError"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"encoding"</span><span class="token operator">:</span><span class="token string">"none"</span><span class="token punctuation">,</span><span class="token property">"allProps"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">260</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">720</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"924666bcda6c633b"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"bee4039410549ec8"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"link in"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"fb1ce2ca6b73d950"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"link in 4"</span><span class="token punctuation">,</span><span class="token property">"links"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"b669ea3caf594f9a"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">125</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">720</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"e6f985ed4ff557b5"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"83477da8696ae6e7"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"link out"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"fb1ce2ca6b73d950"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"link out 5"</span><span class="token punctuation">,</span><span class="token property">"mode"</span><span class="token operator">:</span><span class="token string">"link"</span><span class="token punctuation">,</span><span class="token property">"links"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"044af6d97af553e4"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">535</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">720</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"fee0b4a8fff9f4aa"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"group"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"c0f2a076e4449f10"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Prepare each image to be shown in the dashboard"</span><span class="token punctuation">,</span><span class="token property">"style"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token property">"label"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token property">"nodes"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"8cb8c95c2f5a1591"</span><span class="token punctuation">,</span><span class="token string">"6eabd7a88e3863d3"</span><span class="token punctuation">,</span><span class="token string">"044af6d97af553e4"</span><span class="token punctuation">,</span><span class="token string">"264eb6e2f10c1ab5"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">84</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">779</span><span class="token punctuation">,</span><span class="token property">"w"</span><span class="token operator">:</span><span class="token number">832</span><span class="token punctuation">,</span><span class="token property">"h"</span><span class="token operator">:</span><span class="token number">82</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"8cb8c95c2f5a1591"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"fee0b4a8fff9f4aa"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Add the file type to the mimetype, add to image content"</span><span class="token punctuation">,</span><span class="token property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"mimetype"</span><span class="token punctuation">,</span><span class="token property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">"\"data:image/\"&msg.filetype&\";base64,\""</span><span class="token punctuation">,</span><span class="token property">"tot"</span><span class="token operator">:</span><span class="token string">"jsonata"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"output"</span><span class="token punctuation">,</span><span class="token property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">"msg.mimetype&msg.payload"</span><span class="token punctuation">,</span><span class="token property">"tot"</span><span class="token operator">:</span><span class="token string">"jsonata"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"t"</span><span class="token operator">:</span><span class="token string">"move"</span><span class="token punctuation">,</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"output"</span><span class="token punctuation">,</span><span class="token property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">630</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">820</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"264eb6e2f10c1ab5"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"6eabd7a88e3863d3"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"string"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"fee0b4a8fff9f4aa"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Get file type from file name"</span><span class="token punctuation">,</span><span class="token property">"methods"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"getRightMost"</span><span class="token punctuation">,</span><span class="token property">"params"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"str"</span><span class="token punctuation">,</span><span class="token property">"value"</span><span class="token operator">:</span><span class="token string">"."</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"prop"</span><span class="token operator">:</span><span class="token string">"filename"</span><span class="token punctuation">,</span><span class="token property">"propout"</span><span class="token operator">:</span><span class="token string">"filetype"</span><span class="token punctuation">,</span><span class="token property">"object"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"objectout"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">280</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">820</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"8cb8c95c2f5a1591"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"044af6d97af553e4"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"link in"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"fee0b4a8fff9f4aa"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"link in 5"</span><span class="token punctuation">,</span><span class="token property">"links"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"83477da8696ae6e7"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">125</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">820</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"6eabd7a88e3863d3"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"264eb6e2f10c1ab5"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"link out"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"fee0b4a8fff9f4aa"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"link out 6"</span><span class="token punctuation">,</span><span class="token property">"mode"</span><span class="token operator">:</span><span class="token string">"link"</span><span class="token punctuation">,</span><span class="token property">"links"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"e95c6d9464521102"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">875</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">820</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"c9930135726cf256"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"group"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"c0f2a076e4449f10"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Send the images to the correct section of the dashboard"</span><span class="token punctuation">,</span><span class="token property">"style"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token property">"label"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token property">"nodes"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"ecf3cb2b1bc5096e"</span><span class="token punctuation">,</span><span class="token string">"0629532fdd62fd03"</span><span class="token punctuation">,</span><span class="token string">"3a790fd52e77cb43"</span><span class="token punctuation">,</span><span class="token string">"3613df20a3a361e2"</span><span class="token punctuation">,</span><span class="token string">"e95c6d9464521102"</span><span class="token punctuation">,</span><span class="token string">"2728c1ee286a404b"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">84</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">879</span><span class="token punctuation">,</span><span class="token property">"w"</span><span class="token operator">:</span><span class="token number">892</span><span class="token punctuation">,</span><span class="token property">"h"</span><span class="token operator">:</span><span class="token number">162</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"ecf3cb2b1bc5096e"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_template"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"c9930135726cf256"</span><span class="token punctuation">,</span><span class="token property">"group"</span><span class="token operator">:</span><span class="token string">"8c5b99709c90620a"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Display the image on the Dashboard"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"format"</span><span class="token operator">:</span><span class="token string">"<!DOCTYPE html>\n<html>\n<head>\n<style>\ndiv.parent {\n position: relative;\n height: 200px ;\n //width: 600px;\n}\ndiv.absolute {\n position: absolute;\n width: 100%;\n bottom: 0px;\n} \nimg{\n border-radius: 10px;\n}\n\n</style>\n</head>\n<body>\n <div class=\"parent\">\n <div class=\"relative\" >\n \n <img src= \"\" alt=\"Image loaded from the filestore\" style=\"width:100%\"><br>\n </div>\n </div>\n</body>\n</html>\n\n"</span><span class="token punctuation">,</span><span class="token property">"storeOutMessages"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"fwdInMessages"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"resendOnRefresh"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"templateScope"</span><span class="token operator">:</span><span class="token string">"local"</span><span class="token punctuation">,</span><span class="token property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">750</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">920</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"2728c1ee286a404b"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"0629532fdd62fd03"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_template"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"c9930135726cf256"</span><span class="token punctuation">,</span><span class="token property">"group"</span><span class="token operator">:</span><span class="token string">"8c5b99709c90620a"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Display the image on the Dashboard"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token number">4</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token property">"height"</span><span class="token operator">:</span><span class="token number">4</span><span class="token punctuation">,</span><span class="token property">"format"</span><span class="token operator">:</span><span class="token string">"<!DOCTYPE html>\n<html>\n<head>\n<style>\ndiv.parent {\n position: relative;\n height: 200px ;\n //width: 600px;\n}\ndiv.absolute {\n position: absolute;\n width: 100%;\n bottom: 0px;\n} \nimg{\n border-radius: 10px;\n}\n\n</style>\n</head>\n<body>\n <div class=\"parent\">\n <div class=\"relative\" >\n \n <img src= \"\" alt=\"Image loaded from the filestore\" style=\"width:100%\"><br>\n </div>\n </div>\n</body>\n</html>\n\n"</span><span class="token punctuation">,</span><span class="token property">"storeOutMessages"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"fwdInMessages"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"resendOnRefresh"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"templateScope"</span><span class="token operator">:</span><span class="token string">"local"</span><span class="token punctuation">,</span><span class="token property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">750</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">960</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"2728c1ee286a404b"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"3a790fd52e77cb43"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_template"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"c9930135726cf256"</span><span class="token punctuation">,</span><span class="token property">"group"</span><span class="token operator">:</span><span class="token string">"8c5b99709c90620a"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Display the image on the Dashboard"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token number">5</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token property">"height"</span><span class="token operator">:</span><span class="token number">4</span><span class="token punctuation">,</span><span class="token property">"format"</span><span class="token operator">:</span><span class="token string">"<!DOCTYPE html>\n<html>\n<head>\n<style>\ndiv.parent {\n position: relative;\n height: 200px ;\n //width: 600px;\n}\ndiv.absolute {\n position: absolute;\n width: 100%;\n bottom: 0px;\n} \nimg{\n border-radius: 10px;\n}\n\n</style>\n</head>\n<body>\n <div class=\"parent\">\n <div class=\"relative\" >\n \n <img src= \"\" alt=\"Image loaded from the filestore\" style=\"width:100%\"><br>\n </div>\n </div>\n</body>\n</html>\n\n"</span><span class="token punctuation">,</span><span class="token property">"storeOutMessages"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"fwdInMessages"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"resendOnRefresh"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"templateScope"</span><span class="token operator">:</span><span class="token string">"local"</span><span class="token punctuation">,</span><span class="token property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">750</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">1000</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"2728c1ee286a404b"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"3613df20a3a361e2"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"switch"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"c9930135726cf256"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Send the image to the correct section of the dashboard"</span><span class="token punctuation">,</span><span class="token property">"property"</span><span class="token operator">:</span><span class="token string">"filename"</span><span class="token punctuation">,</span><span class="token property">"propertyType"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"t"</span><span class="token operator">:</span><span class="token string">"eq"</span><span class="token punctuation">,</span><span class="token property">"v"</span><span class="token operator">:</span><span class="token string">"ff-logo-wordmark-light_4x.png"</span><span class="token punctuation">,</span><span class="token property">"vt"</span><span class="token operator">:</span><span class="token string">"str"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"t"</span><span class="token operator">:</span><span class="token string">"eq"</span><span class="token punctuation">,</span><span class="token property">"v"</span><span class="token operator">:</span><span class="token string">"screen-pseudo-overview-2QvTVle3Mr-384.avif"</span><span class="token punctuation">,</span><span class="token property">"vt"</span><span class="token operator">:</span><span class="token string">"str"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"t"</span><span class="token operator">:</span><span class="token string">"eq"</span><span class="token punctuation">,</span><span class="token property">"v"</span><span class="token operator">:</span><span class="token string">"nr-image-1.png"</span><span class="token punctuation">,</span><span class="token property">"vt"</span><span class="token operator">:</span><span class="token string">"str"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"checkall"</span><span class="token operator">:</span><span class="token string">"true"</span><span class="token punctuation">,</span><span class="token property">"repair"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"outputs"</span><span class="token operator">:</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">370</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">960</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"ecf3cb2b1bc5096e"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token punctuation">[</span><span class="token string">"0629532fdd62fd03"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token punctuation">[</span><span class="token string">"3a790fd52e77cb43"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"e95c6d9464521102"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"link in"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"c9930135726cf256"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"link in 6"</span><span class="token punctuation">,</span><span class="token property">"links"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"264eb6e2f10c1ab5"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">125</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">960</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"3613df20a3a361e2"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"2728c1ee286a404b"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"link out"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"c9930135726cf256"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"link out 7"</span><span class="token punctuation">,</span><span class="token property">"mode"</span><span class="token operator">:</span><span class="token string">"link"</span><span class="token punctuation">,</span><span class="token property">"links"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"d4c41d5c9f332ba4"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">935</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">960</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"8c5b99709c90620a"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_group"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Default"</span><span class="token punctuation">,</span><span class="token property">"tab"</span><span class="token operator">:</span><span class="token string">"4c70ce602964b5fb"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"disp"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token string">"6"</span><span class="token punctuation">,</span><span class="token property">"collapse"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"4c70ce602964b5fb"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_tab"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Home"</span><span class="token punctuation">,</span><span class="token property">"icon"</span><span class="token operator">:</span><span class="token string">"dashboard"</span><span class="token punctuation">,</span><span class="token property">"disabled"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"hidden"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"806b98a5bdf7ceea"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"group"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"c0f2a076e4449f10"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Output a debug once all images have been processed"</span><span class="token punctuation">,</span><span class="token property">"style"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token property">"label"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token property">"nodes"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"d4c41d5c9f332ba4"</span><span class="token punctuation">,</span><span class="token string">"b40f5d5e5df0074d"</span><span class="token punctuation">,</span><span class="token string">"f2f386a2615e5698"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">74</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">1059</span><span class="token punctuation">,</span><span class="token property">"w"</span><span class="token operator">:</span><span class="token number">392</span><span class="token punctuation">,</span><span class="token property">"h"</span><span class="token operator">:</span><span class="token number">82</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"d4c41d5c9f332ba4"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"link in"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"806b98a5bdf7ceea"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"link in 7"</span><span class="token punctuation">,</span><span class="token property">"links"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"2728c1ee286a404b"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">115</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">1100</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"b40f5d5e5df0074d"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"b40f5d5e5df0074d"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"join"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"806b98a5bdf7ceea"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"mode"</span><span class="token operator">:</span><span class="token string">"auto"</span><span class="token punctuation">,</span><span class="token property">"build"</span><span class="token operator">:</span><span class="token string">"object"</span><span class="token punctuation">,</span><span class="token property">"property"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"propertyType"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"key"</span><span class="token operator">:</span><span class="token string">"topic"</span><span class="token punctuation">,</span><span class="token property">"joiner"</span><span class="token operator">:</span><span class="token string">"\\n"</span><span class="token punctuation">,</span><span class="token property">"joinerType"</span><span class="token operator">:</span><span class="token string">"str"</span><span class="token punctuation">,</span><span class="token property">"accumulate"</span><span class="token operator">:</span><span class="token string">"false"</span><span class="token punctuation">,</span><span class="token property">"timeout"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"count"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"reduceRight"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">200</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">1100</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"f2f386a2615e5698"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"f2f386a2615e5698"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"debug"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"806b98a5bdf7ceea"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"debug 141"</span><span class="token punctuation">,</span><span class="token property">"active"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"tosidebar"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"console"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"tostatus"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"complete"</span><span class="token operator">:</span><span class="token string">"false"</span><span class="token punctuation">,</span><span class="token property">"statusVal"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"statusType"</span><span class="token operator">:</span><span class="token string">"auto"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">350</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">1100</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"b58daed1ee453873"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"group"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"c0f2a076e4449f10"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Inject the image files' names"</span><span class="token punctuation">,</span><span class="token property">"style"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token property">"label"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token property">"nodes"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"9cf7532041d938d2"</span><span class="token punctuation">,</span><span class="token string">"0ec6e6d3e7b31ad7"</span><span class="token punctuation">,</span><span class="token string">"b669ea3caf594f9a"</span><span class="token punctuation">,</span><span class="token string">"bca6faef579bc33d"</span><span class="token punctuation">,</span><span class="token string">"89abee9a3f6cd7e5"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">74</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">539</span><span class="token punctuation">,</span><span class="token property">"w"</span><span class="token operator">:</span><span class="token number">782</span><span class="token punctuation">,</span><span class="token property">"h"</span><span class="token operator">:</span><span class="token number">122</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"9cf7532041d938d2"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"b58daed1ee453873"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Inject"</span><span class="token punctuation">,</span><span class="token property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"repeat"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"once"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"onceDelay"</span><span class="token operator">:</span><span class="token string">"1"</span><span class="token punctuation">,</span><span class="token property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">170</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">580</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"89abee9a3f6cd7e5"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"0ec6e6d3e7b31ad7"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"split"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"b58daed1ee453873"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"splt"</span><span class="token operator">:</span><span class="token string">"\\n"</span><span class="token punctuation">,</span><span class="token property">"spltType"</span><span class="token operator">:</span><span class="token string">"str"</span><span class="token punctuation">,</span><span class="token property">"arraySplt"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"arraySpltType"</span><span class="token operator">:</span><span class="token string">"len"</span><span class="token punctuation">,</span><span class="token property">"stream"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"addname"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">730</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">580</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"b669ea3caf594f9a"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"b669ea3caf594f9a"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"link out"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"b58daed1ee453873"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"link out 4"</span><span class="token punctuation">,</span><span class="token property">"mode"</span><span class="token operator">:</span><span class="token string">"link"</span><span class="token punctuation">,</span><span class="token property">"links"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"bee4039410549ec8"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">815</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">580</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"bca6faef579bc33d"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_ui_control"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"b58daed1ee453873"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Update images on dashboard open"</span><span class="token punctuation">,</span><span class="token property">"events"</span><span class="token operator">:</span><span class="token string">"connect"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">240</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">620</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"89abee9a3f6cd7e5"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"89abee9a3f6cd7e5"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"b58daed1ee453873"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Image file names as an array"</span><span class="token punctuation">,</span><span class="token property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">"[\"ff-logo-wordmark-light_4x.png\",\"screen-pseudo-overview-2QvTVle3Mr-384.avif\",\"nr-image-1.png\"]"</span><span class="token punctuation">,</span><span class="token property">"tot"</span><span class="token operator">:</span><span class="token string">"json"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">540</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">580</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"0ec6e6d3e7b31ad7"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"c65a9370f1fec257"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"group"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Chart showing CPU load"</span><span class="token punctuation">,</span><span class="token property">"style"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token property">"label"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token property">"nodes"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"4b5271c11b0b1bba"</span><span class="token punctuation">,</span><span class="token string">"5bf4c21f882eccd0"</span><span class="token punctuation">,</span><span class="token string">"775403922e7c51f4"</span><span class="token punctuation">,</span><span class="token string">"3789d7b7f40e8596"</span><span class="token punctuation">,</span><span class="token string">"3be771b04a805b19"</span><span class="token punctuation">,</span><span class="token string">"96a1d087230c4631"</span><span class="token punctuation">,</span><span class="token string">"b82cd8fb933d1f1b"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">54</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">1179</span><span class="token punctuation">,</span><span class="token property">"w"</span><span class="token operator">:</span><span class="token number">1012</span><span class="token punctuation">,</span><span class="token property">"h"</span><span class="token operator">:</span><span class="token number">122</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"4b5271c11b0b1bba"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"c65a9370f1fec257"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"topic"</span><span class="token punctuation">,</span><span class="token property">"vt"</span><span class="token operator">:</span><span class="token string">"str"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"repeat"</span><span class="token operator">:</span><span class="token string">"1"</span><span class="token punctuation">,</span><span class="token property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"once"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"onceDelay"</span><span class="token operator">:</span><span class="token number">0.1</span><span class="token punctuation">,</span><span class="token property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"payload"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"payloadType"</span><span class="token operator">:</span><span class="token string">"date"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">170</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">1220</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"775403922e7c51f4"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"5bf4c21f882eccd0"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_chart"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"c65a9370f1fec257"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"group"</span><span class="token operator">:</span><span class="token string">"8c5b99709c90620a"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token property">"height"</span><span class="token operator">:</span><span class="token number">4</span><span class="token punctuation">,</span><span class="token property">"label"</span><span class="token operator">:</span><span class="token string">"CPU Load %"</span><span class="token punctuation">,</span><span class="token property">"chartType"</span><span class="token operator">:</span><span class="token string">"line"</span><span class="token punctuation">,</span><span class="token property">"legend"</span><span class="token operator">:</span><span class="token string">"false"</span><span class="token punctuation">,</span><span class="token property">"xformat"</span><span class="token operator">:</span><span class="token string">"HH:mm:ss"</span><span class="token punctuation">,</span><span class="token property">"interpolate"</span><span class="token operator">:</span><span class="token string">"linear"</span><span class="token punctuation">,</span><span class="token property">"nodata"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"dot"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"ymin"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"ymax"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"removeOlder"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"removeOlderPoints"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"removeOlderUnit"</span><span class="token operator">:</span><span class="token string">"60"</span><span class="token punctuation">,</span><span class="token property">"cutout"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"useOneColor"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"useUTC"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"colors"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"#1f77b4"</span><span class="token punctuation">,</span><span class="token string">"#aec7e8"</span><span class="token punctuation">,</span><span class="token string">"#ff7f0e"</span><span class="token punctuation">,</span><span class="token string">"#2ca02c"</span><span class="token punctuation">,</span><span class="token string">"#98df8a"</span><span class="token punctuation">,</span><span class="token string">"#d62728"</span><span class="token punctuation">,</span><span class="token string">"#ff9896"</span><span class="token punctuation">,</span><span class="token string">"#9467bd"</span><span class="token punctuation">,</span><span class="token string">"#c5b0d5"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"outputs"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"useDifferentColor"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">790</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">1220</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"3789d7b7f40e8596"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"775403922e7c51f4"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"Loadavg"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"c65a9370f1fec257"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">320</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">1220</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"3be771b04a805b19"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"3789d7b7f40e8596"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"debug"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"c65a9370f1fec257"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"debug 142"</span><span class="token punctuation">,</span><span class="token property">"active"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"tosidebar"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"console"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"tostatus"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"complete"</span><span class="token operator">:</span><span class="token string">"false"</span><span class="token punctuation">,</span><span class="token property">"statusVal"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"statusType"</span><span class="token operator">:</span><span class="token string">"auto"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">950</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">1220</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"3be771b04a805b19"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"c65a9370f1fec257"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">"payload.loadavg[0]"</span><span class="token punctuation">,</span><span class="token property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">480</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">1220</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"b82cd8fb933d1f1b"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"96a1d087230c4631"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_gauge"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"c65a9370f1fec257"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"group"</span><span class="token operator">:</span><span class="token string">"8c5b99709c90620a"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token property">"height"</span><span class="token operator">:</span><span class="token number">4</span><span class="token punctuation">,</span><span class="token property">"gtype"</span><span class="token operator">:</span><span class="token string">"gage"</span><span class="token punctuation">,</span><span class="token property">"title"</span><span class="token operator">:</span><span class="token string">"CPU Load"</span><span class="token punctuation">,</span><span class="token property">"label"</span><span class="token operator">:</span><span class="token string">"units"</span><span class="token punctuation">,</span><span class="token property">"format"</span><span class="token operator">:</span><span class="token string">"%"</span><span class="token punctuation">,</span><span class="token property">"min"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"max"</span><span class="token operator">:</span><span class="token string">"100"</span><span class="token punctuation">,</span><span class="token property">"colors"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"#00b500"</span><span class="token punctuation">,</span><span class="token string">"#e6e600"</span><span class="token punctuation">,</span><span class="token string">"#ca3838"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"seg1"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"seg2"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"diff"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">790</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">1260</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"b82cd8fb933d1f1b"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"calculator"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"c6f2a894be05d857"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"c65a9370f1fec257"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"inputMsgField"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"outputMsgField"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"operation"</span><span class="token operator">:</span><span class="token string">"mult"</span><span class="token punctuation">,</span><span class="token property">"constant"</span><span class="token operator">:</span><span class="token string">"100"</span><span class="token punctuation">,</span><span class="token property">"round"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"decimals"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">640</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">1220</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"96a1d087230c4631"</span><span class="token punctuation">,</span><span class="token string">"5bf4c21f882eccd0"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">]</span><br /></code></pre>
<button class="code-copy " data-clipboard-target="#code-137" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>I have also included some simple dashboard elements you can view alongside the images. Let's take a look at the dashboard:</p>
<p><picture><source type="image/gif" srcset="https://flowfuse.com/img/the-dashboard-Kv1WJp4RqL-646.gif 646w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="The dashboard showing our images alongside other standard elements" alt="The dashboard showing our images alongside other standard elements" loading="lazy" decoding="async" src="https://flowfuse.com/img/the-dashboard-Kv1WJp4RqL-646.webp" width="646" height="656" /></picture></p>
<p>If you import these flows into Node-RED, you should see the images automatically loaded into the dashboard when you view it. You can also replace the URLs and file paths to try using some different images if you'd like to.</p>
<h2 id="more-things-to-try" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/images-in-node-red-dashboards/#more-things-to-try"># </a> More things to try</h2>
<p>In this example, the images are static but it's simple to load images depending on the state of the flow. As mentioned in this article's introduction, you could display context aware images guiding the user of the dashboard to a specific location on a map, to complete a maintenance task. If you're interested in seeing examples of dynamic image loading please comment below.</p>
<h2 id="conclusion" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/images-in-node-red-dashboards/#conclusion"># </a> Conclusion</h2>
<p>Images can add a lot of value to dashboards, but depending on how you host a given Node-RED instance it can be challenging to ensure the correct images are shown, especially when working with your flows in a DevOps pipeline. The techniques I've discussed above allow you to use images in dashboards, even in containerised environments.</p>
<p>I'd love to hear your comments and suggestions on this article. please tell us what you think about this article, and how you might use these techniques in the comments section below.</p>
https://flowfuse.com/blog/2023/07/flowforge-1-9-3-release/FlowFuse 1.9.3 and Device Agent 1.9.5 releasedA maintenance release to improve the Device Agent editor experience2023-07-21T00:00:00ZNick O'Leary<p>FlowFuse and the Device Agent both received updates yesterday that bring improvements to the Device Agent editor experience, making it more resilient to network issues.</p>
<!--more-->
<h2 id="improving-the-device-agent-editor-experience" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/flowforge-1-9-3-release/#improving-the-device-agent-editor-experience"># </a> Improving the Device Agent editor experience</h2>
<p>The ability to remotely edit flows running the Device Agent has been warmly welcomed by many users on the platform. Along with that comes great feedback we can use to continue improving the user experience.</p>
<p>Some early feedback identified issues with the resilience of the tunnel we connect between the Device Agent and the platform. If the tunnel was interrupted for any reason, the user would have to manually set it up again.</p>
<p>With the FlowFuse 1.9.3 release, now running FlowFuse Cloud, along with the latest version of the Device Agent, we have made the tunnel much more resilient. It can now restablish itself without any intervention from the user - making for a much more seamless experience.</p>
<ul>
<li><a href="https://github.com/FlowFuse/flowfuse/pull/2488">#2488</a></li>
<li><a href="https://github.com/FlowFuse/flowfuse/pull/2507">#2507</a></li>
</ul>
<h2 id="other-new-features-and-bug-fixes" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/flowforge-1-9-3-release/#other-new-features-and-bug-fixes"># </a> Other New Features and Bug Fixes</h2>
<ul>
<li>Fixes incorrect 'start-failed' notifications when restarting an instance <a href="https://github.com/FlowFuse/flowfuse/pull/2505">#2505</a> The system log now includes more information about the callingThe FlowFuse device agent is now supported on Windows <a href="https://github.com/FlowFuse/device-agent/issues/78">#78</a></li>
<li>Ensures the system logging captures the proper source IP address of requests <a href="https://github.com/FlowFuse/flowfuse/pull/2503">#2505</a></li>
<li>A few documentation updates, including a clarfication on how to run the Device Agent under docker <a href="https://github.com/FlowFuse/flowfuse/pull/2498">#2498</a></li>
</ul>
<h2 id="what's-next%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/flowforge-1-9-3-release/#what's-next%3F"># </a> What's next?</h2>
<p>We're always working to enhance your experience with FlowFuse. Here's how you can stay informed and contribute:</p>
<ul>
<li><strong>Roadmap Overview</strong>: Check out our <a href="https://flowfuse.com/product/roadmap/">Product Roadmap Page</a> to see what we're planning for future updates.</li>
<li><strong>Entire Roadmap</strong>: Visit our <a href="https://github.com/orgs/FlowFuse/projects/5">Roadmap on GitHub</a> to follow our progress and contribute your ideas.</li>
<li><strong>Feedback</strong>: We're interested in your thoughts about FlowFuse. Your feedback is crucial to us, and we'd love to hear about your experiences with the new features and improvements. Please share your thoughts, suggestions, or report any <a href="https://github.com/FlowFuse/flowfuse/issues/new/choose">issues on GitHub</a>.</li>
</ul>
<p>Together, we can make FlowFuse better with each release!</p>
<h2 id="try-it-out" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/flowforge-1-9-3-release/#try-it-out"># </a> Try it out</h2>
<p>We're confident you can have self managed FlowFuse running locally in under 30 minutes.
You can install our <a href="https://flowfuse.com/docs/install/local/">local build</a>, use <a href="https://flowfuse.com/docs/install/docker/">Docker</a>, or <a href="https://flowfuse.com/docs/install/kubernetes/">Kubernetes</a>.</p>
<p>If you'd rather use our hosted offering: <a href="https://app.flowfuse.com/account/create">Get started for free</a> on FlowFuse Cloud.</p>
<h2 id="upgrading-flowfuse" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/flowforge-1-9-3-release/#upgrading-flowfuse"># </a> Upgrading FlowFuse</h2>
<p><a href="https://app.flowfuse.com/">FlowFuse Cloud</a> is already running 1.9.3.</p>
<p>If you installed a previous version of FlowFuse and want to upgrade, our documentation provides a
guide for <a href="https://flowfuse.com/docs/upgrade/">upgrading your FlowFuse instance</a>.</p>
<h2 id="getting-help" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/flowforge-1-9-3-release/#getting-help"># </a> Getting help</h2>
<p>Please check FlowFuse's <a href="https://flowfuse.com/docs/">documentation</a> as the answers to many questions are covered there. Additionally you can go the the <a href="https://discourse.nodered.org/c/vendors/flowfuse/24">community forum</a> if you have
any feedback or feature requests.</p>
https://flowfuse.com/blog/2023/07/how-to-build-a-secure-opc-ua-server-for-plcs-in-node-red/How to Build a Secure OPC-UA Server for PLCs in Node-REDOPC-UA Server Information Modeling in Node-RED - part 22023-07-19T00:00:00Z<p>This article is the second part of a series of OPC-UA content. In <a href="https://flowfuse.com/blog/2023/07/how-to-deploy-a-basic-opc-ua-server-in-node-red/">part one</a>,
we explained some basic concepts of OPC-UA as they apply to building a server in Node-RED, then walked through how to deploy an example OPC-UA Server. In this article, we will build on the foundation of our previous article and create a fully custom secure OPC-UA Server that creates an information model based on data coming from a PLC.</p>
<!--more-->
<h2 id="table-of-contents" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/how-to-build-a-secure-opc-ua-server-for-plcs-in-node-red/#table-of-contents"># </a> Table of contents</h2>
<ol>
<li><a href="https://flowfuse.com/blog/2023/07/how-to-build-a-secure-opc-ua-server-for-plcs-in-node-red/#introduction">Introduction</a></li>
<li><a href="https://flowfuse.com/blog/2023/07/how-to-build-a-secure-opc-ua-server-for-plcs-in-node-red/#plc-to-opcua-arch">PLC to OPC-UA Server Architecture Overview</a></li>
<li><a href="https://flowfuse.com/blog/2023/07/how-to-build-a-secure-opc-ua-server-for-plcs-in-node-red/#install-custom-nodes">Install Custom Nodes</a></li>
<li><a href="https://flowfuse.com/blog/2023/07/how-to-build-a-secure-opc-ua-server-for-plcs-in-node-red/#set-up-eth-ip">Set Up Ethernet/IP Data</a></li>
<li><a href="https://flowfuse.com/blog/2023/07/how-to-build-a-secure-opc-ua-server-for-plcs-in-node-red/#object-for-storing-plc-data">Create Object For Storing PLC Data In Flow Context Memory</a></li>
<li><a href="https://flowfuse.com/blog/2023/07/how-to-build-a-secure-opc-ua-server-for-plcs-in-node-red/#program-opc-addres-space">Program the OPC UA Server Address Space</a>
<ol>
<li><a href="https://flowfuse.com/blog/2023/07/how-to-build-a-secure-opc-ua-server-for-plcs-in-node-red/#context-variables">Bring In Context Variables</a></li>
<li><a href="https://flowfuse.com/blog/2023/07/how-to-build-a-secure-opc-ua-server-for-plcs-in-node-red/#custom-folder-structure">Create Custom Folder Structure</a></li>
<li><a href="https://flowfuse.com/blog/2023/07/how-to-build-a-secure-opc-ua-server-for-plcs-in-node-red/#define-opc-nodes">Define OPC UA Nodes</a></li>
<li><a href="https://flowfuse.com/blog/2023/07/how-to-build-a-secure-opc-ua-server-for-plcs-in-node-red/#define-browser-views">Define Browser Views</a></li>
</ol>
</li>
<li><a href="https://flowfuse.com/blog/2023/07/how-to-build-a-secure-opc-ua-server-for-plcs-in-node-red/#wrap-up-server-config">Wrap Up Server Configuration</a></li>
<li><a href="https://flowfuse.com/blog/2023/07/how-to-build-a-secure-opc-ua-server-for-plcs-in-node-red/#security-optional">Security (Optional)</a></li>
<li><a href="https://flowfuse.com/blog/2023/07/how-to-build-a-secure-opc-ua-server-for-plcs-in-node-red/#opc-ua-client-configuration-and-testing">OPC UA Client Configuration and Testing</a></li>
<li><a href="https://flowfuse.com/blog/2023/07/how-to-build-a-secure-opc-ua-server-for-plcs-in-node-red/#summary">Summary</a></li>
</ol>
<h2 id="introduction" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/how-to-build-a-secure-opc-ua-server-for-plcs-in-node-red/#introduction"># </a> Introduction <a name="introduction"></a></h2>
<p>While it's typical to find PLCs that have built-in OPC-UA server capabilities, such as Omron and Siemens, this is not an industry-wide practice. One notable exception is Allen Bradley PLCs. For Allen Bradley, you have to buy FactoryTalk Linx Gateway (formally RSLinx Enterprise) for OPC-UA Server capability, or you need to employ a 3rd party OPC-UA Server. This article will guide you through the process of using Node-RED as a 3rd party OPC-UA Server for Allen Bradley, by creating a custom Information Model for the PLC data, publishing it, then securing the server with SSL to make it production-ready.</p>
<h2 id="plc-to-opc-ua-server-architecture-overview" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/how-to-build-a-secure-opc-ua-server-for-plcs-in-node-red/#plc-to-opc-ua-server-architecture-overview"># </a> PLC to OPC-UA Server Architecture Overview <a name="plc-to-opcua-arch"></a></h2>
<p>A visual representation of our PLC to OPC-UA Server architecture is shown in the drawing below, consisting of 6 major parts.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/PLC-Information-Model-1-WEAWXpHzFQ-650.avif 650w, https://flowfuse.com/img/PLC-Information-Model-1-WEAWXpHzFQ-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/PLC-Information-Model-1-WEAWXpHzFQ-650.webp 650w, https://flowfuse.com/img/PLC-Information-Model-1-WEAWXpHzFQ-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/PLC-Information-Model-1-WEAWXpHzFQ-650.jpeg 650w, https://flowfuse.com/img/PLC-Information-Model-1-WEAWXpHzFQ-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="PLC-Information-Model-1.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/PLC-Information-Model-1-WEAWXpHzFQ-650.jpeg" width="1300" height="823" /></picture></p>
<ol>
<li>Set up the PLC tags to be sent to the OPC Server</li>
<li>Read the PLC tags into Node-RED</li>
<li>Copy the PLC tags into Node-RED context memory</li>
<li>Program the OPC Server address space</li>
<li>Encrypt the OPC Server with SSL</li>
<li>Set up the OPC Client</li>
</ol>
<p>The PLC is an Allen Bradley, and an instance of Node-RED running on the same OT network as the PLC will act as the OPC UA Server. In our Allen Bradley PLC, we will re-use an example from a <a href="https://flowfuse.com/blog/2023/06/node-red-as-a-no-code-ethernet_ip-to-s7-protocol-converter/">previous article</a> where the PLC is simulating a conveyor line, called <em>Line 4 PLC,</em> depicted as number 1 architecture drawing above. The tags below represent the data to be transferred from the Line 4 PLC to the Node-RED OPC UA server, depicted as number 2 in the architecture drawing.</p>
<table>
<thead>
<tr>
<th><strong>Tag</strong></th>
<th><strong>Data Type</strong></th>
<th><strong>Description</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>Conveyor_RTS</td>
<td>BOOL</td>
<td>Conveyor Ready to Start</td>
</tr>
<tr>
<td>Robot_RTS</td>
<td>BOOL</td>
<td>Conveyor Robot Ready to Start</td>
</tr>
<tr>
<td>Robot_Position</td>
<td>REAL</td>
<td>Robot Arm position (degrees)</td>
</tr>
<tr>
<td>Conveyor_Running</td>
<td>BOOL</td>
<td>Conveyor is running</td>
</tr>
<tr>
<td>Line4_State</td>
<td>DINT</td>
<td>Line 4 Machine State</td>
</tr>
<tr>
<td>Line4_Fault</td>
<td>BOOL</td>
<td>Line 4 is faulted</td>
</tr>
</tbody>
</table>
<p>A simple ladder application has been built in the PLC to simulate our conveyor values.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/image-20230717-212515-qAwoNJhKkB-650.avif 650w, https://flowfuse.com/img/image-20230717-212515-qAwoNJhKkB-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/image-20230717-212515-qAwoNJhKkB-650.webp 650w, https://flowfuse.com/img/image-20230717-212515-qAwoNJhKkB-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/image-20230717-212515-qAwoNJhKkB-650.jpeg 650w, https://flowfuse.com/img/image-20230717-212515-qAwoNJhKkB-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="image-20230717-212515.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/image-20230717-212515-qAwoNJhKkB-650.jpeg" width="1300" height="936" /></picture>
The Line 4 PLC tags will be read by Node-RED using an Ethernet/IP driver, with each PLC tag copied to flow context memory as part of an object named <code>conveyorData</code>, depicted in number 3 of the architecture drawing. Using the <code>node-red-contrib-opcua-server</code> node, the <code>conveyorData</code> object will become part of a hierarchical OPA UA Information Model representing the Line 4 PLC conveyor data, and stored into the <em>OPC UA Server Address Space,</em> depicted as number 4 in the architecture drawing. The OPC Server will publish the Line 4 PLC conveyor data, implementing a self-signed SSL certificate to encrypt the OPC traffic and establish a secure connection with an OPC Client application, depicted as number 5 in the architecture drawing.</p>
<ul>
<li>note - if you prefer not to secure the server, you can skip this step and still connect to the server anonymously for testing purposes.</li>
</ul>
<p>The OPC client will be a windows-based <a href="https://www.prosysopc.com/products/opc-ua-browser/">Prosys OPC UA Browser</a>, depicted on the far right as number 6 in our architecture drawing.</p>
<p>Now that we have laid out a concept for our application, let’s build it.</p>
<h2 id="install-custom-nodes" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/how-to-build-a-secure-opc-ua-server-for-plcs-in-node-red/#install-custom-nodes"># </a> Install Custom Nodes <a name="install-custom-nodes"></a></h2>
<p>First, we need to add three custom nodes that will allow Node-RED to read Ethernet/IP data and add OPC UA Server functionality.</p>
<p>Click the hamburger icon → manage palette</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/flow-manage-palette-Yso6QhXb4l-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/flow-manage-palette-Yso6QhXb4l-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="flow-manage-palette.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/flow-manage-palette-Yso6QhXb4l-650.jpeg" width="650" height="1009" /></picture></p>
<p>On the <code>install</code> tab, search for <code>ethernet</code> and install the <code>node-red-contrib-cip-ethernet-ip</code> node, which will be used to read the Ethernet/IP fieldbus data from our Allen Bradley PLC.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/install-eth-ip-node-pqnVSLL27Y-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/install-eth-ip-node-pqnVSLL27Y-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="install-eth-ip-node.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/install-eth-ip-node-pqnVSLL27Y-650.jpeg" width="650" height="321" /></picture>
Next, search for <code>opc</code> and install <code>node-red-contrib-opcua</code> and <code>node-red-contrib-opc-ua-server</code>. These nodes take a particularly long time to install, as they require a lot of dependencies. Expect anywhere from 2 to 10 minutes to complete installation, depending on the speed of your system. You will not be able to track the progress of the installation unless you are monitoring the logs on the back-end, so just be patient.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/opc-nodes-install-oj4fT30eaA-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/opc-nodes-install-oj4fT30eaA-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="opc-nodes-install.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/opc-nodes-install-oj4fT30eaA-650.jpeg" width="650" height="587" /></picture>
Go to the <code>Nodes</code> tab and confirm the 3 custom nodes have been properly installed.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/custom-nodes-installed-AO2-UAwsAB-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/custom-nodes-installed-AO2-UAwsAB-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="custom-nodes-installed.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/custom-nodes-installed-AO2-UAwsAB-650.jpeg" width="650" height="702" /></picture></p>
<h2 id="set-up-ethernet%2Fip-data" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/how-to-build-a-secure-opc-ua-server-for-plcs-in-node-red/#set-up-ethernet%2Fip-data"># </a> Set Up Ethernet/IP Data <a name="set-up-eth-ip"></a></h2>
<p>Note: this process is largely a recap from the first part of a previous article where <a href="https://flowfuse.com/blog/2023/06/node-red-as-a-no-code-ethernet_ip-to-s7-protocol-converter/">Node-RED is used as an Ethernet/IP to S7 protocol converter</a>.</p>
<p>Let’s start by dragging a <code>eth-ip in</code> node onto the palette. Then add a new endpoint, which will point to our Line4 PLC.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/eth-ip-in-palette-UT4daifFRZ-650.avif 650w, https://flowfuse.com/img/eth-ip-in-palette-UT4daifFRZ-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/eth-ip-in-palette-UT4daifFRZ-650.webp 650w, https://flowfuse.com/img/eth-ip-in-palette-UT4daifFRZ-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/eth-ip-in-palette-UT4daifFRZ-650.jpeg 650w, https://flowfuse.com/img/eth-ip-in-palette-UT4daifFRZ-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="eth-ip-in-palette.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/eth-ip-in-palette-UT4daifFRZ-650.jpeg" width="1300" height="667" /></picture>
In the endpoint <code>Connection</code> properties, the connection information must match the PLC, so set the IP address and CPU slot number appropriately. Also, the default cycle time is 500ms. Depending on your application, polling the CPU at 500ms may be appropriate. But for our OPC UA application, we will change it to 1000ms, which is a more appropriate polling rate for this type of application.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/ethip-node-connection-seH_aIH7b2-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/ethip-node-connection-seH_aIH7b2-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="ethip-node-connection.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/ethip-node-connection-seH_aIH7b2-650.jpeg" width="650" height="439" /></picture>
On the <code>Tags</code> tab, populate the tag information to match our Allen Bradley PLC. Then select <code>Update</code> to complete configuration of the <code>eth-ip endpoint</code>.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/eth-ip-endpoint-tags-242Kc1telm-650.avif 650w, https://flowfuse.com/img/eth-ip-endpoint-tags-242Kc1telm-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/eth-ip-endpoint-tags-242Kc1telm-650.webp 650w, https://flowfuse.com/img/eth-ip-endpoint-tags-242Kc1telm-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/eth-ip-endpoint-tags-242Kc1telm-650.jpeg 650w, https://flowfuse.com/img/eth-ip-endpoint-tags-242Kc1telm-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="eth-ip-endpoint-tags.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/eth-ip-endpoint-tags-242Kc1telm-650.jpeg" width="1300" height="468" /></picture>
Now that we have our endpoint, let’s finish configuring the <code>eth-ip in</code> node.</p>
<ol>
<li>select the endpoint we just created</li>
<li>Change <code>Mode</code> To <code>All tags</code></li>
<li>Give the node a descriptive name.</li>
</ol>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/eth-ip-in-properties-HNyxFuKNwe-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/eth-ip-in-properties-HNyxFuKNwe-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="eth-ip-in-properties.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/eth-ip-in-properties-HNyxFuKNwe-650.jpeg" width="650" height="384" /></picture>
As configured, the node is going to read all PLC tags any time a value is changed. Press done to complete the configuration.</p>
<p>Before we deploy this flow, let’s wire a <code>debug</code> node to our <code>eth-ip in</code> node to confirm Node-RED can read the tags from our PLC.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/eth-ip-debug-D6XtG51DUb-650.avif 650w, https://flowfuse.com/img/eth-ip-debug-D6XtG51DUb-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/eth-ip-debug-D6XtG51DUb-650.webp 650w, https://flowfuse.com/img/eth-ip-debug-D6XtG51DUb-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/eth-ip-debug-D6XtG51DUb-650.jpeg 650w, https://flowfuse.com/img/eth-ip-debug-D6XtG51DUb-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="eth-ip-debug.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/eth-ip-debug-D6XtG51DUb-650.jpeg" width="1300" height="767" /></picture>
Deploy the flow.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/deploy-flow-pVchkIdV8D-644.avif 644w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/deploy-flow-pVchkIdV8D-644.webp 644w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="deploy-flow.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/deploy-flow-pVchkIdV8D-644.jpeg" width="644" height="221" /></picture>
Click the <code>debug</code> tab and confirm data is flowing in from our PLC.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/debug-data-FLCRIC7N1B-589.avif 589w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/debug-data-FLCRIC7N1B-589.webp 589w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="debug-data.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/debug-data-FLCRIC7N1B-589.jpeg" width="589" height="926" /></picture>
We can see that all tags are being read from the PLC in one message as a key/value hash table, or dict.</p>
<p>After confirming the PLC data acquisition is working, we can remove the <code>debug</code> node and continue building the rest of our flow. Referring back to our architecture drawing, we’ve now taken care of the first 2 objectives of our application.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/PLC-Information-Model-2-of-6-1-Xw5nh2dQHn-650.avif 650w, https://flowfuse.com/img/PLC-Information-Model-2-of-6-1-Xw5nh2dQHn-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/PLC-Information-Model-2-of-6-1-Xw5nh2dQHn-650.webp 650w, https://flowfuse.com/img/PLC-Information-Model-2-of-6-1-Xw5nh2dQHn-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/PLC-Information-Model-2-of-6-1-Xw5nh2dQHn-650.jpeg 650w, https://flowfuse.com/img/PLC-Information-Model-2-of-6-1-Xw5nh2dQHn-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="PLC-Information-Model-2-of-6-1.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/PLC-Information-Model-2-of-6-1-Xw5nh2dQHn-650.jpeg" width="1300" height="827" /></picture></p>
<p><input type="checkbox" checked="" /> Set up the PLC tags to be sent to the OPC Server<br />
<input type="checkbox" checked="" /> Read the PLC tags into Node-RED<br /></p>
<p>Let’s move on to objective 3.</p>
<h2 id="store-the-plc-data-in-flow-context-memory" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/how-to-build-a-secure-opc-ua-server-for-plcs-in-node-red/#store-the-plc-data-in-flow-context-memory"># </a> Store the PLC Data In Flow Context Memory <a name="object-for-storing-plc-data"></a></h2>
<p>Drag a <code>change</code> node onto the palette and wire it to the <code>eth-ip in</code> node.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/change-node-palette-PK9c4oGsdV-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/change-node-palette-PK9c4oGsdV-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="change-node-palette.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/change-node-palette-PK9c4oGsdV-650.jpeg" width="650" height="363" /></picture></p>
<p>We’re going move the data from the PLC into flow context memory, by setting each element of the outgoing <code>msg.payload</code> to <code>flow.conveyorData</code>. To do this, refer back to the structure of the <code>msg.payload</code> from the <code>debug</code> node we connected to the <code>eth-ip in</code> node earlier -
<picture><source type="image/avif" srcset="https://flowfuse.com/img/msg-payload-ZkRbPDqz9q-497.avif 497w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/msg-payload-ZkRbPDqz9q-497.webp 497w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="msg-payload.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/msg-payload-ZkRbPDqz9q-497.jpeg" width="497" height="342" /></picture></p>
<p>Now open up the change node, and press the <code>+add</code> button to add a rule for each PLC tag in our <code>msg.payload</code> object (6), and <code>set</code> each rule so that you're setting a <code>flow</code> value to a <code>msg</code> value. Then populate each rule as shown -
<picture><source type="image/avif" srcset="https://flowfuse.com/img/change-node-properties-kv1WWZ6gtL-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/change-node-properties-kv1WWZ6gtL-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="change-node-properties.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/change-node-properties-kv1WWZ6gtL-650.jpeg" width="650" height="1207" /></picture></p>
<p>We've now configured the <code>change</code> node to move the data from our PLC into a dict called <code>conveyorData</code>, stored in flow context memory.</p>
<p>Give the node an appripriate name, hit done and deploy the flow.</p>
<p>Our flow should now look like below -
<picture><source type="image/avif" srcset="https://flowfuse.com/img/flow-with-change-palette-UCj5aNpj_A-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/flow-with-change-palette-UCj5aNpj_A-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="flow-with-change-palette.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/flow-with-change-palette-UCj5aNpj_A-650.jpeg" width="650" height="135" /></picture></p>
<p>Let’s look at the flow context memory to confirm the data from our PLC is being written to the <code>conveyorData</code> object we created.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/context-data-1-0nkKpv86ic-571.avif 571w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/context-data-1-0nkKpv86ic-571.webp 571w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="context-data-1.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/context-data-1-0nkKpv86ic-571.jpeg" width="571" height="445" /></picture>
<picture><source type="image/avif" srcset="https://flowfuse.com/img/context-refresh-JTyOrzCd07-623.avif 623w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/context-refresh-JTyOrzCd07-623.webp 623w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="context-refresh.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/context-refresh-JTyOrzCd07-623.jpeg" width="623" height="766" /></picture>
Every time we hit refresh, the values in <code>conveyorData</code> change as the value in the PLC changes, confirming things are working as expected.</p>
<p>Looking back at the application architecture we laid out, we’ve achieved 3 out of the 6 objectives.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/PLC-Information-Model-3-of-6-1-zjcVf77Yei-650.avif 650w, https://flowfuse.com/img/PLC-Information-Model-3-of-6-1-zjcVf77Yei-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/PLC-Information-Model-3-of-6-1-zjcVf77Yei-650.webp 650w, https://flowfuse.com/img/PLC-Information-Model-3-of-6-1-zjcVf77Yei-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/PLC-Information-Model-3-of-6-1-zjcVf77Yei-650.jpeg 650w, https://flowfuse.com/img/PLC-Information-Model-3-of-6-1-zjcVf77Yei-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="PLC-Information-Model-3-of-6-1.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/PLC-Information-Model-3-of-6-1-zjcVf77Yei-650.jpeg" width="1300" height="821" /></picture></p>
<p><input type="checkbox" checked="" /> Set up the PLC tags to be sent to the OPC Server<br />
<input type="checkbox" checked="" /> Read the PLC tags into Node-RED<br />
<input type="checkbox" checked="" /> Copy the PLC tags into Node-RED context memory<br /></p>
<p>Let’s now tackle the OPC Server address space.</p>
<h2 id="program-the-opc-ua-server-address-space" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/how-to-build-a-secure-opc-ua-server-for-plcs-in-node-red/#program-the-opc-ua-server-address-space"># </a> Program the OPC UA Server Address Space <a name="program-opc-addres-space"></a></h2>
<p>To make our lives significantly easier, we’re going to start from a template, the same template used in <a href="https://flowfuse.com/blog/2023/07/how-to-deploy-a-basic-opc-ua-server-in-node-red/">part 1 of our OPC UA Series</a>.</p>
<p>Copy the content of the <a href="https://github.com/BiancoRoyal/node-red-contrib-opcua-server/blob/master/examples/server-with-context.json">example template</a>, then paste it into Node-RED to import it.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/import-tj45nhvHWu-476.avif 476w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/import-tj45nhvHWu-476.webp 476w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="import.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/import-tj45nhvHWu-476.jpeg" width="476" height="454" /></picture>
<picture><source type="image/avif" srcset="https://flowfuse.com/img/import-context-QgpSuIUKyK-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/import-context-QgpSuIUKyK-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="import-context.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/import-context-QgpSuIUKyK-650.jpeg" width="650" height="553" /></picture>
You end up with a new flow that looks like the one below.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/example-flow-1qGNKbasJk-650.avif 650w, https://flowfuse.com/img/example-flow-1qGNKbasJk-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/example-flow-1qGNKbasJk-650.webp 650w, https://flowfuse.com/img/example-flow-1qGNKbasJk-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/example-flow-1qGNKbasJk-650.jpeg 650w, https://flowfuse.com/img/example-flow-1qGNKbasJk-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="example-flow.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/example-flow-1qGNKbasJk-650.jpeg" width="1300" height="336" /></picture>
All we care about here is the <code>Compact-Server</code> node. In fact, we’ll just copy that node and paste it into the current flow we’ve been building. Once we’ve copied the server node into our custom flow, we can discard the example flow. The whole purpose of this was to simply populate the <code>address space</code> of the <code>Compact-Server</code> node with template code that will trivialize the programming for our custom application.</p>
<p>Our custom flow should now look something like this.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/flow-with-compact-server-6PSto8Qut1-650.avif 650w, https://flowfuse.com/img/flow-with-compact-server-6PSto8Qut1-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/flow-with-compact-server-6PSto8Qut1-650.webp 650w, https://flowfuse.com/img/flow-with-compact-server-6PSto8Qut1-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/flow-with-compact-server-6PSto8Qut1-650.jpeg 650w, https://flowfuse.com/img/flow-with-compact-server-6PSto8Qut1-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="flow-with-compact-server.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/flow-with-compact-server-6PSto8Qut1-650.jpeg" width="1300" height="204" /></picture></p>
<ul>
<li>note - I’ve added some comments to make the flow even easier to follow. Similar to commenting code, commenting flows is good practice.</li>
</ul>
<p>Open up the <code>Compact-Server</code> node and jump straight to the address space.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/compact-server-node-address-space-u11KgCcHLd-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/compact-server-node-address-space-u11KgCcHLd-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="compact-server-node-address-space.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/compact-server-node-address-space-u11KgCcHLd-650.jpeg" width="650" height="604" /></picture></p>
<ul>
<li>note - we won’t go into detail on what the address space actually is in this article, or the details of the <code>Compact-Server</code> node, as it was covered in <a href="https://flowfuse.com/blog/2023/07/how-to-deploy-a-basic-opc-ua-server-in-node-red/">part 1 of this OPC UA series</a>. Please read that article if you are unfamiliar with it.</li>
</ul>
<p>There are 4 key things we’ll modify in the address space template code -</p>
<ol>
<li>Bring in our <code>conveyorData</code> context variables</li>
<li>create our custom folder structure</li>
<li>define our context variables as OPC UA nodes</li>
<li>create custom browser views for our nodes</li>
</ol>
<h3 id="bring-in-context-variables" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/how-to-build-a-secure-opc-ua-server-for-plcs-in-node-red/#bring-in-context-variables"># </a> Bring in Context Variables <a name="context-variables"></a></h3>
<p>Starting from the section of code where it’s bringing in the context variables defined in the example, delete that code</p>
<div style="position: relative">
<pre class="language-javascript"><code id="code-433" class="language-javascript"> <span class="token keyword">this</span><span class="token punctuation">.</span>sandboxFlowContext<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">"isoInput1"</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setInterval</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> flexServerInternals<span class="token punctuation">.</span>sandboxFlowContext<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><br /> <span class="token string">"isoInput1"</span><span class="token punctuation">,</span><br /> Math<span class="token punctuation">.</span><span class="token function">random</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token number">50.0</span><br /> <span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">500</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span>sandboxFlowContext<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">"isoInput2"</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token operator">...</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span>sandboxFlowContext<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">"isoOutput8"</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-433" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>and replace it with our <code>conveyorData</code> context variables.</p>
<div style="position: relative">
<pre class="language-javascript"><code id="code-437" class="language-javascript"> <span class="token keyword">this</span><span class="token punctuation">.</span>sandboxFlowContext<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">"conveyorData.Conveyor_RTS"</span><span class="token punctuation">,</span> <span class="token boolean">false</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span>sandboxFlowContext<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">"conveyorData.Robot_RTS"</span><span class="token punctuation">,</span> <span class="token boolean">false</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span>sandboxFlowContext<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">"conveyorData.Robot_Position"</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span>sandboxFlowContext<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">"conveyorData.Conveyor_Running"</span><span class="token punctuation">,</span> <span class="token boolean">false</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span>sandboxFlowContext<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">"conveyorData.Line4_State"</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span>sandboxFlowContext<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">"conveyorData.Line4_Fault"</span><span class="token punctuation">,</span> <span class="token boolean">false</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-437" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<h3 id="create-custom-folder-structure" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/how-to-build-a-secure-opc-ua-server-for-plcs-in-node-red/#create-custom-folder-structure"># </a> Create Custom Folder Structure <a name="custom-folder-structure"></a></h3>
<p>Starting from the section of code where the example folder structure is defined, delete it and replace it with our custom folder structure defined in our architecture -</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/opc-folder-structure-c3P4MztkbZ-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/opc-folder-structure-c3P4MztkbZ-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="opc-folder-structure.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/opc-folder-structure-c3P4MztkbZ-650.jpeg" width="650" height="887" /></picture>
Delete the section of code starting from here -</p>
<div style="position: relative">
<pre class="language-javascript"><code id="code-447" class="language-javascript"> <span class="token keyword">const</span> myDevice <span class="token operator">=</span> namespace<span class="token punctuation">.</span><span class="token function">addFolder</span><span class="token punctuation">(</span>rootFolder<span class="token punctuation">.</span>objects<span class="token punctuation">,</span> <span class="token punctuation">{</span><br /> <span class="token string-property property">"browseName"</span><span class="token operator">:</span> <span class="token string">"RaspberryPI-Zero-WLAN"</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">const</span> gpioFolder <span class="token operator">=</span> namespace<span class="token punctuation">.</span><span class="token function">addFolder</span><span class="token punctuation">(</span>myDevice<span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token string-property property">"browseName"</span><span class="token operator">:</span> <span class="token string">"GPIO"</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">const</span> isoInputs <span class="token operator">=</span> namespace<span class="token punctuation">.</span><span class="token function">addFolder</span><span class="token punctuation">(</span>gpioFolder<span class="token punctuation">,</span> <span class="token punctuation">{</span><br /> <span class="token string-property property">"browseName"</span><span class="token operator">:</span> <span class="token string">"Inputs"</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">const</span> isoOutputs <span class="token operator">=</span> namespace<span class="token punctuation">.</span><span class="token function">addFolder</span><span class="token punctuation">(</span>gpioFolder<span class="token punctuation">,</span> <span class="token punctuation">{</span><br /> <span class="token string-property property">"browseName"</span><span class="token operator">:</span> <span class="token string">"Outputs"</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-447" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>and replace it with the folder structure shown above -</p>
<div style="position: relative">
<pre class="language-javascript"><code id="code-451" class="language-javascript"> <span class="token keyword">const</span> myDevice <span class="token operator">=</span> namespace<span class="token punctuation">.</span><span class="token function">addFolder</span><span class="token punctuation">(</span>rootFolder<span class="token punctuation">.</span>objects<span class="token punctuation">,</span> <span class="token punctuation">{</span><br /> <span class="token string-property property">"browseName"</span><span class="token operator">:</span> <span class="token string">"Line 4 PLC"</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">const</span> conveyorFolder <span class="token operator">=</span> namespace<span class="token punctuation">.</span><span class="token function">addFolder</span><span class="token punctuation">(</span>myDevice<span class="token punctuation">,</span> <span class="token punctuation">{</span> <br /> <span class="token string-property property">"browseName"</span><span class="token operator">:</span> <span class="token string">"Conveyor"</span> <br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">const</span> conveyorBools <span class="token operator">=</span> namespace<span class="token punctuation">.</span><span class="token function">addFolder</span><span class="token punctuation">(</span>conveyorFolder<span class="token punctuation">,</span> <span class="token punctuation">{</span><br /> <span class="token string-property property">"browseName"</span><span class="token operator">:</span> <span class="token string">"Bools"</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">const</span> conveyorDINTs <span class="token operator">=</span> namespace<span class="token punctuation">.</span><span class="token function">addFolder</span><span class="token punctuation">(</span>conveyorFolder<span class="token punctuation">,</span> <span class="token punctuation">{</span><br /> <span class="token string-property property">"browseName"</span><span class="token operator">:</span> <span class="token string">"DINTs"</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">const</span> conveyorFloats <span class="token operator">=</span> namespace<span class="token punctuation">.</span><span class="token function">addFolder</span><span class="token punctuation">(</span>conveyorFolder<span class="token punctuation">,</span> <span class="token punctuation">{</span><br /> <span class="token string-property property">"browseName"</span><span class="token operator">:</span> <span class="token string">"Floats"</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-451" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<h3 id="define-opc-ua-nodes" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/how-to-build-a-secure-opc-ua-server-for-plcs-in-node-red/#define-opc-ua-nodes"># </a> Define OPC UA Nodes <a name="define-opc-nodes"></a></h3>
<p>Now we can construct the nodes for each context variable.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/opc-nodes-1AVGAgKfwW-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/opc-nodes-1AVGAgKfwW-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="opc-nodes.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/opc-nodes-1AVGAgKfwW-650.jpeg" width="650" height="837" /></picture></p>
<p>Delete the section of code defining the nodes for <code>isoInput1</code> through <code>isoOutput8</code> -</p>
<div style="position: relative">
<pre class="language-javascript"><code id="code-464" class="language-javascript"> <span class="token keyword">const</span> gpioDI1 <span class="token operator">=</span> namespace<span class="token punctuation">.</span><span class="token function">addVariable</span><span class="token punctuation">(</span><span class="token punctuation">{</span><br /> <span class="token string-property property">"organizedBy"</span><span class="token operator">:</span> isoInputs<span class="token punctuation">,</span><br /> <span class="token string-property property">"browseName"</span><span class="token operator">:</span> <span class="token string">"I1"</span><span class="token punctuation">,</span><br /> <span class="token string-property property">"nodeId"</span><span class="token operator">:</span> <span class="token string">"ns=1;s=Isolated_Input1"</span><span class="token punctuation">,</span><br /> <span class="token string-property property">"dataType"</span><span class="token operator">:</span> <span class="token string">"Double"</span><span class="token punctuation">,</span><br /> <span class="token string-property property">"value"</span><span class="token operator">:</span> <span class="token punctuation">{</span><br /> <span class="token operator">...</span><br /> <span class="token string-property property">"set"</span><span class="token operator">:</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">variant</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> flexServerInternals<span class="token punctuation">.</span>sandboxFlowContext<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><br /> <span class="token string">"isoOutput8"</span><span class="token punctuation">,</span><br /> <span class="token function">parseFloat</span><span class="token punctuation">(</span>variant<span class="token punctuation">.</span>value<span class="token punctuation">)</span><br /> <span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">return</span> opcua<span class="token punctuation">.</span>StatusCodes<span class="token punctuation">.</span>Good<span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /> <span class="token punctuation">}</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> </code></pre>
<button class="code-copy " data-clipboard-target="#code-464" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>And replace it with our custom nodes, paying respect to the folder structure we defined in our architecture -</p>
<div style="position: relative">
<pre class="language-javascript"><code id="code-468" class="language-javascript"> <span class="token comment">// Construct Nodes</span><br /> <span class="token keyword">const</span> Conveyor_RTS <span class="token operator">=</span> namespace<span class="token punctuation">.</span><span class="token function">addVariable</span><span class="token punctuation">(</span><span class="token punctuation">{</span><br /> <span class="token string-property property">"organizedBy"</span><span class="token operator">:</span> conveyorBools<span class="token punctuation">,</span><br /> <span class="token string-property property">"browseName"</span><span class="token operator">:</span> <span class="token string">"Conveyor Ready to Start"</span><span class="token punctuation">,</span><br /> <span class="token string-property property">"nodeId"</span><span class="token operator">:</span> <span class="token string">"ns=1;s=Conveyor_RTS"</span><span class="token punctuation">,</span><br /> <span class="token string-property property">"dataType"</span><span class="token operator">:</span> <span class="token string">"Boolean"</span><span class="token punctuation">,</span><br /> <span class="token string-property property">"value"</span><span class="token operator">:</span> <span class="token punctuation">{</span><br /> <span class="token string-property property">"get"</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Variant</span><span class="token punctuation">(</span><span class="token punctuation">{</span><br /> <span class="token string-property property">"dataType"</span><span class="token operator">:</span> DataType<span class="token punctuation">.</span>Boolean<span class="token punctuation">,</span><br /> <span class="token string-property property">"value"</span><span class="token operator">:</span> flexServerInternals<span class="token punctuation">.</span>sandboxFlowContext<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">"conveyorData.Conveyor_RTS"</span><span class="token punctuation">)</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token string-property property">"set"</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">variant</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> flexServerInternals<span class="token punctuation">.</span>sandboxFlowContext<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><br /> <span class="token string">"conveyorData.Conveyor_RTS"</span><span class="token punctuation">,</span><br /> variant<span class="token punctuation">.</span>value<br /> <span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">return</span> opcua<span class="token punctuation">.</span>StatusCodes<span class="token punctuation">.</span>Good<span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /> <span class="token punctuation">}</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /> <span class="token keyword">const</span> Robot_RTS <span class="token operator">=</span> namespace<span class="token punctuation">.</span><span class="token function">addVariable</span><span class="token punctuation">(</span><span class="token punctuation">{</span><br /> <span class="token string-property property">"organizedBy"</span><span class="token operator">:</span> conveyorBools<span class="token punctuation">,</span><br /> <span class="token string-property property">"browseName"</span><span class="token operator">:</span> <span class="token string">"Robot Ready to Start"</span><span class="token punctuation">,</span><br /> <span class="token string-property property">"nodeId"</span><span class="token operator">:</span> <span class="token string">"ns=1;s=Robot_RTS"</span><span class="token punctuation">,</span><br /> <span class="token string-property property">"dataType"</span><span class="token operator">:</span> <span class="token string">"Boolean"</span><span class="token punctuation">,</span><br /> <span class="token string-property property">"value"</span><span class="token operator">:</span> <span class="token punctuation">{</span><br /> <span class="token string-property property">"get"</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Variant</span><span class="token punctuation">(</span><span class="token punctuation">{</span><br /> <span class="token string-property property">"dataType"</span><span class="token operator">:</span> DataType<span class="token punctuation">.</span>Boolean<span class="token punctuation">,</span><br /> <span class="token string-property property">"value"</span><span class="token operator">:</span> flexServerInternals<span class="token punctuation">.</span>sandboxFlowContext<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">"conveyorData.Robot_RTS"</span><span class="token punctuation">)</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token string-property property">"set"</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">variant</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> flexServerInternals<span class="token punctuation">.</span>sandboxFlowContext<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><br /> <span class="token string">"conveyorData.Robot_RTS"</span><span class="token punctuation">,</span><br /> variant<span class="token punctuation">.</span>value<br /> <span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">return</span> opcua<span class="token punctuation">.</span>StatusCodes<span class="token punctuation">.</span>Good<span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /> <span class="token punctuation">}</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /> <span class="token keyword">const</span> Conveyor_Running <span class="token operator">=</span> namespace<span class="token punctuation">.</span><span class="token function">addVariable</span><span class="token punctuation">(</span><span class="token punctuation">{</span><br /> <span class="token string-property property">"organizedBy"</span><span class="token operator">:</span> conveyorBools<span class="token punctuation">,</span><br /> <span class="token string-property property">"browseName"</span><span class="token operator">:</span> <span class="token string">"Conveyor Running"</span><span class="token punctuation">,</span><br /> <span class="token string-property property">"nodeId"</span><span class="token operator">:</span> <span class="token string">"ns=1;s=Conveyor_Running"</span><span class="token punctuation">,</span><br /> <span class="token string-property property">"dataType"</span><span class="token operator">:</span> <span class="token string">"Boolean"</span><span class="token punctuation">,</span><br /> <span class="token string-property property">"value"</span><span class="token operator">:</span> <span class="token punctuation">{</span><br /> <span class="token string-property property">"get"</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Variant</span><span class="token punctuation">(</span><span class="token punctuation">{</span><br /> <span class="token string-property property">"dataType"</span><span class="token operator">:</span> DataType<span class="token punctuation">.</span>Boolean<span class="token punctuation">,</span><br /> <span class="token string-property property">"value"</span><span class="token operator">:</span> flexServerInternals<span class="token punctuation">.</span>sandboxFlowContext<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">"conveyorData.Conveyor_Running"</span><span class="token punctuation">)</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token string-property property">"set"</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">variant</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> flexServerInternals<span class="token punctuation">.</span>sandboxFlowContext<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><br /> <span class="token string">"conveyorData.Conveyor_Running"</span><span class="token punctuation">,</span><br /> variant<span class="token punctuation">.</span>value<br /> <span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">return</span> opcua<span class="token punctuation">.</span>StatusCodes<span class="token punctuation">.</span>Good<span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /> <span class="token punctuation">}</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /> <span class="token keyword">const</span> Line4_Fault <span class="token operator">=</span> namespace<span class="token punctuation">.</span><span class="token function">addVariable</span><span class="token punctuation">(</span><span class="token punctuation">{</span><br /> <span class="token string-property property">"organizedBy"</span><span class="token operator">:</span> conveyorBools<span class="token punctuation">,</span><br /> <span class="token string-property property">"browseName"</span><span class="token operator">:</span> <span class="token string">"Line 4 Faulted"</span><span class="token punctuation">,</span><br /> <span class="token string-property property">"nodeId"</span><span class="token operator">:</span> <span class="token string">"ns=1;s=Line4_Fault"</span><span class="token punctuation">,</span><br /> <span class="token string-property property">"dataType"</span><span class="token operator">:</span> <span class="token string">"Boolean"</span><span class="token punctuation">,</span><br /> <span class="token string-property property">"value"</span><span class="token operator">:</span> <span class="token punctuation">{</span><br /> <span class="token string-property property">"get"</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Variant</span><span class="token punctuation">(</span><span class="token punctuation">{</span><br /> <span class="token string-property property">"dataType"</span><span class="token operator">:</span> DataType<span class="token punctuation">.</span>Boolean<span class="token punctuation">,</span><br /> <span class="token string-property property">"value"</span><span class="token operator">:</span> flexServerInternals<span class="token punctuation">.</span>sandboxFlowContext<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">"conveyorData.Line4_Fault"</span><span class="token punctuation">)</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token string-property property">"set"</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">variant</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> flexServerInternals<span class="token punctuation">.</span>sandboxFlowContext<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><br /> <span class="token string">"conveyorData.Line4_Fault"</span><span class="token punctuation">,</span><br /> variant<span class="token punctuation">.</span>value<br /> <span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">return</span> opcua<span class="token punctuation">.</span>StatusCodes<span class="token punctuation">.</span>Good<span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /> <span class="token punctuation">}</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /> <span class="token keyword">const</span> Line4_State <span class="token operator">=</span> namespace<span class="token punctuation">.</span><span class="token function">addVariable</span><span class="token punctuation">(</span><span class="token punctuation">{</span><br /> <span class="token string-property property">"organizedBy"</span><span class="token operator">:</span> conveyorDINTs<span class="token punctuation">,</span><br /> <span class="token string-property property">"browseName"</span><span class="token operator">:</span> <span class="token string">"Line 4 State"</span><span class="token punctuation">,</span><br /> <span class="token string-property property">"nodeId"</span><span class="token operator">:</span> <span class="token string">"ns=1;s=Line4_State"</span><span class="token punctuation">,</span><br /> <span class="token string-property property">"dataType"</span><span class="token operator">:</span> <span class="token string">"Int32"</span><span class="token punctuation">,</span><br /> <span class="token string-property property">"value"</span><span class="token operator">:</span> <span class="token punctuation">{</span><br /> <span class="token string-property property">"get"</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Variant</span><span class="token punctuation">(</span><span class="token punctuation">{</span><br /> <span class="token string-property property">"dataType"</span><span class="token operator">:</span> DataType<span class="token punctuation">.</span>Int32<span class="token punctuation">,</span><br /> <span class="token string-property property">"value"</span><span class="token operator">:</span> flexServerInternals<span class="token punctuation">.</span>sandboxFlowContext<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">"conveyorData.Line4_State"</span><span class="token punctuation">)</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token string-property property">"set"</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">variant</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> flexServerInternals<span class="token punctuation">.</span>sandboxFlowContext<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><br /> <span class="token string">"conveyorData.Line4_State"</span><span class="token punctuation">,</span><br /> variant<span class="token punctuation">.</span>value<br /> <span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">return</span> opcua<span class="token punctuation">.</span>StatusCodes<span class="token punctuation">.</span>Good<span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /> <span class="token punctuation">}</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /> <span class="token keyword">const</span> Robot_Position <span class="token operator">=</span> namespace<span class="token punctuation">.</span><span class="token function">addVariable</span><span class="token punctuation">(</span><span class="token punctuation">{</span><br /> <span class="token string-property property">"organizedBy"</span><span class="token operator">:</span> conveyorFloats<span class="token punctuation">,</span><br /> <span class="token string-property property">"browseName"</span><span class="token operator">:</span> <span class="token string">"Robot Axis A1 Position"</span><span class="token punctuation">,</span><br /> <span class="token string-property property">"nodeId"</span><span class="token operator">:</span> <span class="token string">"ns=1;s=Robot_Position"</span><span class="token punctuation">,</span><br /> <span class="token string-property property">"dataType"</span><span class="token operator">:</span> <span class="token string">"Float"</span><span class="token punctuation">,</span><br /> <span class="token string-property property">"value"</span><span class="token operator">:</span> <span class="token punctuation">{</span><br /> <span class="token string-property property">"get"</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Variant</span><span class="token punctuation">(</span><span class="token punctuation">{</span><br /> <span class="token string-property property">"dataType"</span><span class="token operator">:</span> DataType<span class="token punctuation">.</span>Float<span class="token punctuation">,</span><br /> <span class="token string-property property">"value"</span><span class="token operator">:</span> flexServerInternals<span class="token punctuation">.</span>sandboxFlowContext<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">"conveyorData.Robot_Position"</span><span class="token punctuation">)</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token string-property property">"set"</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">variant</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> flexServerInternals<span class="token punctuation">.</span>sandboxFlowContext<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><br /> <span class="token string">"conveyorData.Robot_Position"</span><span class="token punctuation">,</span><br /> <span class="token function">parseFloat</span><span class="token punctuation">(</span>variant<span class="token punctuation">.</span>value<span class="token punctuation">)</span><br /> <span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">return</span> opcua<span class="token punctuation">.</span>StatusCodes<span class="token punctuation">.</span>Good<span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /> <span class="token punctuation">}</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-468" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<h3 id="define-browser-views" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/how-to-build-a-secure-opc-ua-server-for-plcs-in-node-red/#define-browser-views"># </a> Define Browser Views <a name="define-browser-views"></a></h3>
<p>Last, let’s create some custom views. Delete the code starting from -</p>
<div style="position: relative">
<pre class="language-javascript"><code id="code-475" class="language-javascript"> <span class="token comment">//------------------------------------------------------------------------------</span><br /> <span class="token comment">// Add a view</span><br /> <span class="token comment">//------------------------------------------------------------------------------</span><br /> <span class="token keyword">const</span> viewDI <span class="token operator">=</span> namespace<span class="token punctuation">.</span><span class="token function">addView</span><span class="token punctuation">(</span><span class="token punctuation">{</span><br /> <span class="token string-property property">"organizedBy"</span><span class="token operator">:</span> rootFolder<span class="token punctuation">.</span>views<span class="token punctuation">,</span><br /> <span class="token string-property property">"browseName"</span><span class="token operator">:</span> <span class="token string">"RPIW0-Digital-Ins"</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token operator">...</span><br /> viewDO<span class="token punctuation">.</span><span class="token function">addReference</span><span class="token punctuation">(</span><span class="token punctuation">{</span><br /> <span class="token string-property property">"referenceType"</span><span class="token operator">:</span> <span class="token string">"Organizes"</span><span class="token punctuation">,</span><br /> <span class="token string-property property">"nodeId"</span><span class="token operator">:</span> gpioDO8<span class="token punctuation">.</span>nodeId<br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-475" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>And replace with a custom view of your choice. I’ve defined a view that splits the bools, DINTs, and Reals.</p>
<div style="position: relative">
<pre class="language-javascript"><code id="code-479" class="language-javascript"> <span class="token keyword">const</span> viewBools <span class="token operator">=</span> namespace<span class="token punctuation">.</span><span class="token function">addView</span><span class="token punctuation">(</span><span class="token punctuation">{</span><br /> <span class="token string-property property">"organizedBy"</span><span class="token operator">:</span> rootFolder<span class="token punctuation">.</span>views<span class="token punctuation">,</span><br /> <span class="token string-property property">"browseName"</span><span class="token operator">:</span> <span class="token string">"Line 4 Conveyor Bools"</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /> <span class="token keyword">const</span> viewDINTs <span class="token operator">=</span> namespace<span class="token punctuation">.</span><span class="token function">addView</span><span class="token punctuation">(</span><span class="token punctuation">{</span><br /> <span class="token string-property property">"organizedBy"</span><span class="token operator">:</span> rootFolder<span class="token punctuation">.</span>views<span class="token punctuation">,</span><br /> <span class="token string-property property">"browseName"</span><span class="token operator">:</span> <span class="token string">"Line4 Conveyor DINTs"</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /> <span class="token keyword">const</span> viewFloats <span class="token operator">=</span> namespace<span class="token punctuation">.</span><span class="token function">addView</span><span class="token punctuation">(</span><span class="token punctuation">{</span><br /> <span class="token string-property property">"organizedBy"</span><span class="token operator">:</span> rootFolder<span class="token punctuation">.</span>views<span class="token punctuation">,</span><br /> <span class="token string-property property">"browseName"</span><span class="token operator">:</span> <span class="token string">"Line4 Conveyor Floats"</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /> viewBools<span class="token punctuation">.</span><span class="token function">addReference</span><span class="token punctuation">(</span><span class="token punctuation">{</span><br /> <span class="token string-property property">"referenceType"</span><span class="token operator">:</span> <span class="token string">"Organizes"</span><span class="token punctuation">,</span><br /> <span class="token string-property property">"nodeId"</span><span class="token operator">:</span> Conveyor_RTS<span class="token punctuation">.</span>nodeId<br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /> viewBools<span class="token punctuation">.</span><span class="token function">addReference</span><span class="token punctuation">(</span><span class="token punctuation">{</span><br /> <span class="token string-property property">"referenceType"</span><span class="token operator">:</span> <span class="token string">"Organizes"</span><span class="token punctuation">,</span><br /> <span class="token string-property property">"nodeId"</span><span class="token operator">:</span> Robot_RTS<span class="token punctuation">.</span>nodeId<br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /> viewBools<span class="token punctuation">.</span><span class="token function">addReference</span><span class="token punctuation">(</span><span class="token punctuation">{</span><br /> <span class="token string-property property">"referenceType"</span><span class="token operator">:</span> <span class="token string">"Organizes"</span><span class="token punctuation">,</span><br /> <span class="token string-property property">"nodeId"</span><span class="token operator">:</span> Conveyor_Running<span class="token punctuation">.</span>nodeId<br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /> viewBools<span class="token punctuation">.</span><span class="token function">addReference</span><span class="token punctuation">(</span><span class="token punctuation">{</span><br /> <span class="token string-property property">"referenceType"</span><span class="token operator">:</span> <span class="token string">"Organizes"</span><span class="token punctuation">,</span><br /> <span class="token string-property property">"nodeId"</span><span class="token operator">:</span> Line4_Fault<span class="token punctuation">.</span>nodeId<br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /><br /> viewDINTs<span class="token punctuation">.</span><span class="token function">addReference</span><span class="token punctuation">(</span><span class="token punctuation">{</span><br /> <span class="token string-property property">"referenceType"</span><span class="token operator">:</span> <span class="token string">"Organizes"</span><span class="token punctuation">,</span><br /> <span class="token string-property property">"nodeId"</span><span class="token operator">:</span> Line4_State<span class="token punctuation">.</span>nodeId<br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /> viewFloats<span class="token punctuation">.</span><span class="token function">addReference</span><span class="token punctuation">(</span><span class="token punctuation">{</span><br /> <span class="token string-property property">"referenceType"</span><span class="token operator">:</span> <span class="token string">"Organizes"</span><span class="token punctuation">,</span><br /> <span class="token string-property property">"nodeId"</span><span class="token operator">:</span> Robot_Position<span class="token punctuation">.</span>nodeId<br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-479" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>We’ve now completed the address space, so all that’s left is to define the OPC UA endpoint.</p>
<h2 id="wrap-up-server-configuration" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/how-to-build-a-secure-opc-ua-server-for-plcs-in-node-red/#wrap-up-server-configuration"># </a> Wrap Up Server Configuration <a name="wrap-up-server-config"></a></h2>
<p>Go to the discovery tab and define an endpoint following the convention below, with the ip address matching the ip address of your Node-RED instance.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/image-20230718-155245-ZpIumQ5oXj-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/image-20230718-155245-ZpIumQ5oXj-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="image-20230718-155245.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/image-20230718-155245-ZpIumQ5oXj-650.jpeg" width="650" height="314" /></picture></p>
<p>Now, our OPC UA Server is set up and ready to be browsable by an OPC UA Client.</p>
<p>Deploy the changes and make sure the <code>Compact-Server</code> is reporting <code>active</code>.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/compact-server-active-q63DTQLrFO-626.avif 626w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/compact-server-active-q63DTQLrFO-626.webp 626w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="compact-server-active.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/compact-server-active-q63DTQLrFO-626.jpeg" width="626" height="268" /></picture>
If not, go back and check your code for errors. The Node-RED logfiles will come in handy to track down issues if your server isn’t activating.</p>
<p>This wraps up the 4th objective of our application.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/PLC-Information-Model-4-of-6-1-hufAV2-CcW-650.avif 650w, https://flowfuse.com/img/PLC-Information-Model-4-of-6-1-hufAV2-CcW-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/PLC-Information-Model-4-of-6-1-hufAV2-CcW-650.webp 650w, https://flowfuse.com/img/PLC-Information-Model-4-of-6-1-hufAV2-CcW-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/PLC-Information-Model-4-of-6-1-hufAV2-CcW-650.jpeg 650w, https://flowfuse.com/img/PLC-Information-Model-4-of-6-1-hufAV2-CcW-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="PLC-Information-Model-4-of-6-1.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/PLC-Information-Model-4-of-6-1-hufAV2-CcW-650.jpeg" width="1300" height="832" /></picture></p>
<p><input type="checkbox" checked="" /> Set up the PLC tags to be sent to the OPC Server<br />
<input type="checkbox" checked="" /> Read the PLC tags into Node-RED<br />
<input type="checkbox" checked="" /> Copy the PLC tags into Node-RED context memory<br />
<input type="checkbox" checked="" /> Program the OPC Server address space<br /></p>
<h2 id="security-(optional)" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/how-to-build-a-secure-opc-ua-server-for-plcs-in-node-red/#security-(optional)"># </a> Security (Optional) <a name="security-optional"></a></h2>
<p>At this point, our OPC UA Server will accept a client connection, but it won’t be secure, so we should take the extra step and encrypt our OPC UA traffic.</p>
<p>To do this, go to the <code>Security</code> tab of the <code>Compact-Server</code> properties.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/security-tab-default-iMrz0fsq0N-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/security-tab-default-iMrz0fsq0N-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="security-tab-default.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/security-tab-default-iMrz0fsq0N-650.jpeg" width="650" height="462" /></picture>
By default, the server is using no security, and allowing anonymous connections. Let’s fix that by unchecking <code>Allow Anonymous</code> , and checking <code>Use invididual Certificate Files</code>.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/individual-cert-file-option-7xokCW3LdO-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/individual-cert-file-option-7xokCW3LdO-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="individual-cert-file-option.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/individual-cert-file-option-7xokCW3LdO-650.jpeg" width="650" height="454" /></picture>
The node gives us some clues on how we can populate this section. When <code>node-red-contrib-opcua-server</code> was installed, it created self-signed ssl certificates that are bound to our host system. Let’s make use of them.</p>
<p>navigate to <code>./node-red-contrib-opcua-server/certificates</code> folder, where the node-red instance has installed the node-red module.</p>
<ul>
<li>I have Node-RED installed in the root path of my server, so my full path to the certs folder is <code>/root/.node-red/node_modules/node-red-contrib-opcua-server/certificates</code></li>
<li>If you’re having trouble finding the directory, do a search for the file <code>server_selfsigned_cert_2048.pem</code>.</li>
</ul>
<p>Once you’ve navigated to the correct directory, it should be full of various cert files.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/cert-list-b0EmIY9RbS-650.avif 650w, https://flowfuse.com/img/cert-list-b0EmIY9RbS-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/cert-list-b0EmIY9RbS-650.webp 650w, https://flowfuse.com/img/cert-list-b0EmIY9RbS-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/cert-list-b0EmIY9RbS-650.jpeg 650w, https://flowfuse.com/img/cert-list-b0EmIY9RbS-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="cert-list.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/cert-list-b0EmIY9RbS-650.jpeg" width="1300" height="859" /></picture>
The two cert files we care about, which were already pre-defined in the node, are <code>server_selfsigned_cert_2048.pem</code>, which is the public cert file, and <code>server_key_2048.pem</code>, which is the private cert file.</p>
<p>Go back to the node configuration and populate the <code>Security</code> tab with the <em>full absolute path</em> to the files.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/cert-tab-filled-ntD5EUsMUs-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/cert-tab-filled-ntD5EUsMUs-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="cert-tab-filled.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/cert-tab-filled-ntD5EUsMUs-650.jpeg" width="650" height="261" /></picture>
Hit done and redeploy the node. Make sure the server reports <code>active</code>. If not, check the cert paths and try again.</p>
<p>You may also run into file permission issues, depending on how you set up your Node-RED instance, so make sure Node-RED also has read access to the files.</p>
<p>We’re not done yet. The server is happy, but the OPC Client will need access to these cert files as well. So copy the files to a location that will make the two cert files accessible to the OPC Client. In my case, the OPC Client is being ran on a personal Windows machine on the same network. So I copied the cert files to a nas, which both my Node-RED instance and my Windows machine have access to.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/copy-certs--12hvjU8RS-650.avif 650w, https://flowfuse.com/img/copy-certs--12hvjU8RS-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/copy-certs--12hvjU8RS-650.webp 650w, https://flowfuse.com/img/copy-certs--12hvjU8RS-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/copy-certs--12hvjU8RS-650.jpeg 650w, https://flowfuse.com/img/copy-certs--12hvjU8RS-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="copy-certs.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/copy-certs--12hvjU8RS-650.jpeg" width="1300" height="91" /></picture>
<picture><source type="image/avif" srcset="https://flowfuse.com/img/copied-certs-1EAH3aSGso-650.avif 650w, https://flowfuse.com/img/copied-certs-1EAH3aSGso-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/copied-certs-1EAH3aSGso-650.webp 650w, https://flowfuse.com/img/copied-certs-1EAH3aSGso-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/copied-certs-1EAH3aSGso-650.jpeg 650w, https://flowfuse.com/img/copied-certs-1EAH3aSGso-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="copied-certs.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/copied-certs-1EAH3aSGso-650.jpeg" width="1300" height="399" /></picture>
Now we can move on to OPC Client Configuration. We’ve achieved 5 out of 6 objectives.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/PLC-Information-Model-5-of-6-1-f8D6dGim07-650.avif 650w, https://flowfuse.com/img/PLC-Information-Model-5-of-6-1-f8D6dGim07-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/PLC-Information-Model-5-of-6-1-f8D6dGim07-650.webp 650w, https://flowfuse.com/img/PLC-Information-Model-5-of-6-1-f8D6dGim07-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/PLC-Information-Model-5-of-6-1-f8D6dGim07-650.jpeg 650w, https://flowfuse.com/img/PLC-Information-Model-5-of-6-1-f8D6dGim07-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="PLC-Information-Model-5-of-6-1.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/PLC-Information-Model-5-of-6-1-f8D6dGim07-650.jpeg" width="1300" height="827" /></picture></p>
<p><input type="checkbox" checked="" /> Set up the PLC tags to be sent to the OPC Server<br />
<input type="checkbox" checked="" /> Read the PLC tags into Node-RED<br />
<input type="checkbox" checked="" /> Copy the PLC tags into Node-RED context memory<br />
<input type="checkbox" checked="" /> Program the OPC Server address space<br />
<input type="checkbox" checked="" /> Encrypt the OPC Server with SSL<br /></p>
<h2 id="opc-ua-client-configuration-and-testing" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/how-to-build-a-secure-opc-ua-server-for-plcs-in-node-red/#opc-ua-client-configuration-and-testing"># </a> OPC UA Client Configuration and Testing <a name="opc-ua-client-configuration-and-testing"></a></h2>
<p>To connect to our Node-RED OPC server, enter the endpoint url and press “connect to server”.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/opc-client-connect-PiEc8hBVCA-650.avif 650w, https://flowfuse.com/img/opc-client-connect-PiEc8hBVCA-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/opc-client-connect-PiEc8hBVCA-650.webp 650w, https://flowfuse.com/img/opc-client-connect-PiEc8hBVCA-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/opc-client-connect-PiEc8hBVCA-650.jpeg 650w, https://flowfuse.com/img/opc-client-connect-PiEc8hBVCA-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="opc-client-connect.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/opc-client-connect-PiEc8hBVCA-650.jpeg" width="1300" height="79" /></picture>
Security settings are displayed.</p>
<p>We’re going to select <code>Sign & Encrypt</code> and change the security policy to <code>Aes128Sha256RsaOaep</code></p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/sign&encrypt-uXWBFLft01-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/sign&encrypt-uXWBFLft01-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="sign&encrypt.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/sign&encrypt-uXWBFLft01-650.jpeg" width="650" height="524" /></picture>
When we try to connect, our connection to the server is rejected, because we haven’t pointed the client to our ssl cert files. Press Okay to acknowledge the error and we can fix that problem.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/connect-rejected-fzyBADJZVT-627.avif 627w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/connect-rejected-fzyBADJZVT-627.webp 627w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="connect-rejected.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/connect-rejected-fzyBADJZVT-627.jpeg" width="627" height="417" /></picture>
When you acknowledge the connection error, you are taken to the <code>User Authentication</code> properties. Select <code>Certificate and Private key</code>. We need to point to our certificate and private key files.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/client-cert-path-glKn4ylwZW-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/client-cert-path-glKn4ylwZW-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="client-cert-path.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/client-cert-path-glKn4ylwZW-650.jpeg" width="650" height="418" /></picture>
When we browse for our certificate file, the client software tells us it’s expecting a <code>*.der</code> file, which we don’t have yet.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/der-file-RG85pbcL3_-369.avif 369w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/der-file-RG85pbcL3_-369.webp 369w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="der-file.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/der-file-RG85pbcL3_-369.jpeg" width="369" height="147" /></picture>
However, we can create one from our existing cert file using <code>openssl</code>.</p>
<p>If you don’t already have openssl installed, <a href="https://www.openssl.org/">install it</a>.</p>
<p>Then from a command prompt, run the following command in the directory where your client-side cert files are stored -</p>
<div style="position: relative">
<pre><code>openssl x509 -in server_selfsigned_cert_2048.pem -out server_selfsigned_cert_2048.der -outform DER
</code></pre>
<button class="code-copy " data-clipboard-target="#code-597" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/ssl-pub-keygen-W6AdxsTStU-650.avif 650w, https://flowfuse.com/img/ssl-pub-keygen-W6AdxsTStU-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/ssl-pub-keygen-W6AdxsTStU-650.webp 650w, https://flowfuse.com/img/ssl-pub-keygen-W6AdxsTStU-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/ssl-pub-keygen-W6AdxsTStU-650.jpeg 650w, https://flowfuse.com/img/ssl-pub-keygen-W6AdxsTStU-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="ssl-pub-keygen.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/ssl-pub-keygen-W6AdxsTStU-650.jpeg" width="1300" height="58" /></picture>
This command will generate the .der file the opc client is expecting to see.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/copied-certs-with-pubkey-p8eIlqiCSQ-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/copied-certs-with-pubkey-p8eIlqiCSQ-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="copied-certs-with-pubkey.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/copied-certs-with-pubkey-p8eIlqiCSQ-650.jpeg" width="650" height="249" /></picture>
Now we can go back and point to the public key file, which is the <code>server_selfsigned_cert_2048.der</code> file, and the private key file, which is the <code>server_key_2048.pem</code> file.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/client-cert-path-filled-EFOxkSZ3tV-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/client-cert-path-filled-EFOxkSZ3tV-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="client-cert-path-filled.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/client-cert-path-filled-EFOxkSZ3tV-650.jpeg" width="650" height="383" /></picture>
The first time you do this, you will be asked to accept the server certificate.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/opc-client-accept-cert-rEX63UqEGb-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/opc-client-accept-cert-rEX63UqEGb-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="opc-client-accept-cert.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/opc-client-accept-cert-rEX63UqEGb-650.jpeg" width="650" height="413" /></picture>
If you choose accept permanently, you won’t see this prompt again. You should now have access to browse the OPC Server.</p>
<p>As can be seen, our OPC Client sees the data from our PLC matching our OPC Information Model we defined in our Node-RED server address space.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/image-20230718-164326-IpEhnQ4JWe-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/image-20230718-164326-IpEhnQ4JWe-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="image-20230718-164326.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/image-20230718-164326-IpEhnQ4JWe-650.jpeg" width="650" height="672" /></picture>
We’ve now achieved all of our design objectives.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/PLC-Information-Model-6-of-6-1-i7wQab9_ea-650.avif 650w, https://flowfuse.com/img/PLC-Information-Model-6-of-6-1-i7wQab9_ea-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/PLC-Information-Model-6-of-6-1-i7wQab9_ea-650.webp 650w, https://flowfuse.com/img/PLC-Information-Model-6-of-6-1-i7wQab9_ea-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/PLC-Information-Model-6-of-6-1-i7wQab9_ea-650.jpeg 650w, https://flowfuse.com/img/PLC-Information-Model-6-of-6-1-i7wQab9_ea-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="PLC-Information-Model-6-of-6-1.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/PLC-Information-Model-6-of-6-1-i7wQab9_ea-650.jpeg" width="1300" height="822" /></picture></p>
<p><input type="checkbox" checked="" /> Set up the PLC tags to be sent to the OPC Server<br />
<input type="checkbox" checked="" /> Read the PLC tags into Node-RED<br />
<input type="checkbox" checked="" /> Copy the PLC tags into Node-RED context memory<br />
<input type="checkbox" checked="" /> Program the OPC Server address space<br />
<input type="checkbox" checked="" /> Encrypt the OPC Server with SSL<br />
<input type="checkbox" checked="" /> Set up the OPC Client<br /></p>
<p>Our custom OPC UA application is complete and production-ready.</p>
<p>Test the application by confirming values changed in the PLC are reflected in the OPC UA Client.</p>
<p>In my PLC code, I created a sine wave generator that changes the <code>Robot Axis A1 Position</code> value continuously, so the value is always changing, making it easy to confirm that the server is passing OPC traffic correctly.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/sine-wave-gen-bR2S_0hyb5-603.avif 603w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/sine-wave-gen-bR2S_0hyb5-603.webp 603w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="sine-wave-gen.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/sine-wave-gen-bR2S_0hyb5-603.jpeg" width="603" height="635" /></picture></p>
<h2 id="summary" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/how-to-build-a-secure-opc-ua-server-for-plcs-in-node-red/#summary"># </a> Summary <a name="summary"></a></h2>
<p>In this article, we covered in detail how to create an OPC UA application that pulls data from an Allen Bradley PLC over Ethernet/IP, store the PLC data in Node-RED context memory, then publish the PLC data from context memory onto a ssl secured OPC UA Server. An OPC Client can subscribe to the OPC UA Server over an encrypted connection, making the application deployable in a production environment, including in the cloud if desired.</p>
<p>With the foundation laid in this article, you can customize the application to fit your individual needs, with an understanding of what is going on “under the hood” of an OPC UA Server. This application only scratches the surface of what features OPC UA has available. Refer to the <a href="https://node-opcua.github.io/">NodeOPCUA sdk</a> and experiment by building on top of this example if you desire to learn more or want to add features this application is lacking.</p>
<p>In the next article of the OPC UA series, we will establish how to create an OPC UA Client application in Node-RED.</p>
<p>Source code for flow used in this article -</p>
<div style="position: relative">
<pre class="language-javascript"><code id="code-649" class="language-javascript"><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"2e8c7f5c.ab73d"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"tab"</span><span class="token punctuation">,</span><span class="token string-property property">"label"</span><span class="token operator">:</span><span class="token string">"OPC-UA Custom Context Server"</span><span class="token punctuation">,</span><span class="token string-property property">"disabled"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"38ce10de.7d8c"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"opcua-compact-server"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"2e8c7f5c.ab73d"</span><span class="token punctuation">,</span><span class="token string-property property">"port"</span><span class="token operator">:</span><span class="token string">"54845"</span><span class="token punctuation">,</span><span class="token string-property property">"endpoint"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"productUri"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"acceptExternalCommands"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"maxAllowedSessionNumber"</span><span class="token operator">:</span><span class="token string">"10"</span><span class="token punctuation">,</span><span class="token string-property property">"maxConnectionsPerEndpoint"</span><span class="token operator">:</span><span class="token string">"10"</span><span class="token punctuation">,</span><span class="token string-property property">"maxAllowedSubscriptionNumber"</span><span class="token operator">:</span><span class="token string">"100"</span><span class="token punctuation">,</span><span class="token string-property property">"alternateHostname"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"showStatusActivities"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"showErrors"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"allowAnonymous"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"individualCerts"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"isAuditing"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"serverDiscovery"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token string-property property">"users"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"xmlsetsOPCUA"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"publicCertificateFile"</span><span class="token operator">:</span><span class="token string">"/root/.node-red/node_modules/node-red-contrib-opcua-server/certificates/server_selfsigned_cert_2048.pem"</span><span class="token punctuation">,</span><span class="token string-property property">"privateCertificateFile"</span><span class="token operator">:</span><span class="token string">"/root/.node-red/node_modules/node-red-contrib-opcua-server/certificates/server_key_2048.pem"</span><span class="token punctuation">,</span><span class="token string-property property">"registerServerMethod"</span><span class="token operator">:</span><span class="token string">"1"</span><span class="token punctuation">,</span><span class="token string-property property">"discoveryServerEndpointUrl"</span><span class="token operator">:</span><span class="token string">"opc.tcp://192.168.0.114:54845"</span><span class="token punctuation">,</span><span class="token string-property property">"capabilitiesForMDNS"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"maxNodesPerRead"</span><span class="token operator">:</span><span class="token number">1000</span><span class="token punctuation">,</span><span class="token string-property property">"maxNodesPerWrite"</span><span class="token operator">:</span><span class="token number">1000</span><span class="token punctuation">,</span><span class="token string-property property">"maxNodesPerHistoryReadData"</span><span class="token operator">:</span><span class="token number">100</span><span class="token punctuation">,</span><span class="token string-property property">"maxNodesPerBrowse"</span><span class="token operator">:</span><span class="token number">3000</span><span class="token punctuation">,</span><span class="token string-property property">"maxBrowseContinuationPoints"</span><span class="token operator">:</span><span class="token string">"10"</span><span class="token punctuation">,</span><span class="token string-property property">"maxHistoryContinuationPoints"</span><span class="token operator">:</span><span class="token string">"10"</span><span class="token punctuation">,</span><span class="token string-property property">"delayToInit"</span><span class="token operator">:</span><span class="token string">"1000"</span><span class="token punctuation">,</span><span class="token string-property property">"delayToClose"</span><span class="token operator">:</span><span class="token string">"200"</span><span class="token punctuation">,</span><span class="token string-property property">"serverShutdownTimeout"</span><span class="token operator">:</span><span class="token string">"100"</span><span class="token punctuation">,</span><span class="token string-property property">"addressSpaceScript"</span><span class="token operator">:</span><span class="token string">"function constructAlarmAddressSpace(server, addressSpace, eventObjects, done) {\n // server = the created node-opcua server\n // addressSpace = address space of the node-opcua server\n // eventObjects = add event variables here to hold them in memory from this script\n\n // internal sandbox objects are:\n // node = the compact server node,\n // coreServer = core compact server object for debug and access to NodeOPCUA\n // this.sandboxNodeContext = node context node-red\n // this.sandboxFlowContext = flow context node-red\n // this.sandboxGlobalContext = global context node-red\n // this.sandboxEnv = env variables\n // timeout and interval functions as expected from nodejs\n\n const opcua = coreServer.choreCompact.opcua;\n const LocalizedText = opcua.LocalizedText;\n const namespace = addressSpace.getOwnNamespace();\n\n const Variant = opcua.Variant;\n const DataType = opcua.DataType;\n const DataValue = opcua.DataValue;\n\n var flexServerInternals = this;\n\n this.sandboxFlowContext.set(\"conveyorData.Conveyor_RTS\", false);\n this.sandboxFlowContext.set(\"conveyorData.Robot_RTS\", false);\n this.sandboxFlowContext.set(\"conveyorData.Robot_Position\", 0);\n this.sandboxFlowContext.set(\"conveyorData.Conveyor_Running\", false);\n this.sandboxFlowContext.set(\"conveyorData.Line4_State\", 0);\n this.sandboxFlowContext.set(\"conveyorData.Line4_Fault\", false);\n\n // this.sandboxFlowContext.set(\"isoInput1\", 0);\n // this.setInterval(() => {\n // flexServerInternals.sandboxFlowContext.set(\n // \"isoInput1\",\n // Math.random() + 50.0\n // );\n // }, 500);\n // this.sandboxFlowContext.set(\"isoInput2\", 0);\n // this.sandboxFlowContext.set(\"isoInput3\", 0);\n // this.sandboxFlowContext.set(\"isoInput4\", 0);\n // this.sandboxFlowContext.set(\"isoInput5\", 0);\n // this.sandboxFlowContext.set(\"isoInput6\", 0);\n // this.sandboxFlowContext.set(\"isoInput7\", 0);\n // this.sandboxFlowContext.set(\"isoInput8\", 0);\n // this.sandboxFlowContext.set(\"isoOutput1\", 0);\n // this.setInterval(() => {\n // flexServerInternals.sandboxFlowContext.set(\n // \"isoOutput1\",\n // Math.random() + 10.0\n // );\n // }, 500);\n\n // this.sandboxFlowContext.set(\"isoOutput2\", 0);\n // this.sandboxFlowContext.set(\"isoOutput3\", 0);\n // this.sandboxFlowContext.set(\"isoOutput4\", 0);\n // this.sandboxFlowContext.set(\"isoOutput5\", 0);\n // this.sandboxFlowContext.set(\"isoOutput6\", 0);\n // this.sandboxFlowContext.set(\"isoOutput7\", 0);\n // this.sandboxFlowContext.set(\"isoOutput8\", 0);\n\n coreServer.debugLog(\"init dynamic address space\");\n const rootFolder = addressSpace.findNode(\"RootFolder\");\n\n node.warn(\"construct new address space for OPC UA\");\n\n const myDevice = namespace.addFolder(rootFolder.objects, {\n \"browseName\": \"Line 4 PLC\"\n });\n const conveyorFolder = namespace.addFolder(myDevice, { \"browseName\": \"Conveyor\" });\n const conveyorBools = namespace.addFolder(conveyorFolder, {\n \"browseName\": \"Bools\"\n });\n const conveyorDINTs = namespace.addFolder(conveyorFolder, {\n \"browseName\": \"DINTs\"\n });\n const conveyorFloats = namespace.addFolder(conveyorFolder, {\n \"browseName\": \"Floats\"\n });\n\n // Construct Nodes\n const Conveyor_RTS = namespace.addVariable({\n \"organizedBy\": conveyorBools,\n \"browseName\": \"Conveyor Ready to Start\",\n \"nodeId\": \"ns=1;s=Conveyor_RTS\",\n \"dataType\": \"Boolean\",\n \"value\": {\n \"get\": function () {\n return new Variant({\n \"dataType\": DataType.Boolean,\n \"value\": flexServerInternals.sandboxFlowContext.get(\"conveyorData.Conveyor_RTS\")\n });\n },\n \"set\": function (variant) {\n flexServerInternals.sandboxFlowContext.set(\n \"conveyorData.Conveyor_RTS\",\n variant.value\n );\n return opcua.StatusCodes.Good;\n }\n }\n });\n\n const Robot_RTS = namespace.addVariable({\n \"organizedBy\": conveyorBools,\n \"browseName\": \"Robot Ready to Start\",\n \"nodeId\": \"ns=1;s=Robot_RTS\",\n \"dataType\": \"Boolean\",\n \"value\": {\n \"get\": function () {\n return new Variant({\n \"dataType\": DataType.Boolean,\n \"value\": flexServerInternals.sandboxFlowContext.get(\"conveyorData.Robot_RTS\")\n });\n },\n \"set\": function (variant) {\n flexServerInternals.sandboxFlowContext.set(\n \"conveyorData.Robot_RTS\",\n variant.value\n );\n return opcua.StatusCodes.Good;\n }\n }\n });\n\n const Conveyor_Running = namespace.addVariable({\n \"organizedBy\": conveyorBools,\n \"browseName\": \"Conveyor Running\",\n \"nodeId\": \"ns=1;s=Conveyor_Running\",\n \"dataType\": \"Boolean\",\n \"value\": {\n \"get\": function () {\n return new Variant({\n \"dataType\": DataType.Boolean,\n \"value\": flexServerInternals.sandboxFlowContext.get(\"conveyorData.Conveyor_Running\")\n });\n },\n \"set\": function (variant) {\n flexServerInternals.sandboxFlowContext.set(\n \"conveyorData.Conveyor_Running\",\n variant.value\n );\n return opcua.StatusCodes.Good;\n }\n }\n });\n\n const Line4_Fault = namespace.addVariable({\n \"organizedBy\": conveyorBools,\n \"browseName\": \"Line 4 Faulted\",\n \"nodeId\": \"ns=1;s=Line4_Fault\",\n \"dataType\": \"Boolean\",\n \"value\": {\n \"get\": function () {\n return new Variant({\n \"dataType\": DataType.Boolean,\n \"value\": flexServerInternals.sandboxFlowContext.get(\"conveyorData.Line4_Fault\")\n });\n },\n \"set\": function (variant) {\n flexServerInternals.sandboxFlowContext.set(\n \"conveyorData.Line4_Fault\",\n variant.value\n );\n return opcua.StatusCodes.Good;\n }\n }\n });\n\n const Line4_State = namespace.addVariable({\n \"organizedBy\": conveyorDINTs,\n \"browseName\": \"Line 4 State\",\n \"nodeId\": \"ns=1;s=Line4_State\",\n \"dataType\": \"Int32\",\n \"value\": {\n \"get\": function () {\n return new Variant({\n \"dataType\": DataType.Int32,\n \"value\": flexServerInternals.sandboxFlowContext.get(\"conveyorData.Line4_State\")\n });\n },\n \"set\": function (variant) {\n flexServerInternals.sandboxFlowContext.set(\n \"conveyorData.Line4_State\",\n variant.value\n );\n return opcua.StatusCodes.Good;\n }\n }\n });\n\n const Robot_Position = namespace.addVariable({\n \"organizedBy\": conveyorFloats,\n \"browseName\": \"Robot Axis A1 Position\",\n \"nodeId\": \"ns=1;s=Robot_Position\",\n \"dataType\": \"Float\",\n \"value\": {\n \"get\": function () {\n return new Variant({\n \"dataType\": DataType.Float,\n \"value\": flexServerInternals.sandboxFlowContext.get(\"conveyorData.Robot_Position\")\n });\n },\n \"set\": function (variant) {\n flexServerInternals.sandboxFlowContext.set(\n \"conveyorData.Robot_Position\",\n parseFloat(variant.value)\n );\n return opcua.StatusCodes.Good;\n }\n }\n });\n\n //------------------------------------------------------------------------------\n // Add a view\n //------------------------------------------------------------------------------\n const viewBools = namespace.addView({\n \"organizedBy\": rootFolder.views,\n \"browseName\": \"Line 4 Conveyor Bools\"\n });\n\n const viewDINTs = namespace.addView({\n \"organizedBy\": rootFolder.views,\n \"browseName\": \"Line4 Conveyor DINTs\"\n });\n\n const viewFloats = namespace.addView({\n \"organizedBy\": rootFolder.views,\n \"browseName\": \"Line4 Conveyor Floats\"\n });\n\n viewBools.addReference({\n \"referenceType\": \"Organizes\",\n \"nodeId\": Conveyor_RTS.nodeId\n });\n\n viewBools.addReference({\n \"referenceType\": \"Organizes\",\n \"nodeId\": Robot_RTS.nodeId\n });\n\n viewBools.addReference({\n \"referenceType\": \"Organizes\",\n \"nodeId\": Conveyor_Running.nodeId\n });\n\n viewBools.addReference({\n \"referenceType\": \"Organizes\",\n \"nodeId\": Line4_Fault.nodeId\n });\n\n\n viewDINTs.addReference({\n \"referenceType\": \"Organizes\",\n \"nodeId\": Line4_State.nodeId\n });\n\n viewFloats.addReference({\n \"referenceType\": \"Organizes\",\n \"nodeId\": Robot_Position.nodeId\n });\n coreServer.debugLog(\"create dynamic address space done\");\n node.warn(\"construction of new address space for OPC UA done\");\n\n done();\n}\n"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">960</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">600</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"7ae89f134415c51e"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"eth-ip in"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"2e8c7f5c.ab73d"</span><span class="token punctuation">,</span><span class="token string-property property">"endpoint"</span><span class="token operator">:</span><span class="token string">"f012042b75173b77"</span><span class="token punctuation">,</span><span class="token string-property property">"mode"</span><span class="token operator">:</span><span class="token string">"all"</span><span class="token punctuation">,</span><span class="token string-property property">"variable"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"program"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Read Line4 Conveyor tags"</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">150</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">600</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"0c51f44baa08a3b2"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"a0592280baea975b"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"2e8c7f5c.ab73d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"read data from PLC & store in conveyorData context flow memory"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">350</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">540</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"b411a5ce4749fa61"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"2e8c7f5c.ab73d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Secure OPC UA Server Publishing PLC conveyorData"</span><span class="token punctuation">,</span><span class="token string-property property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">980</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">540</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"0c51f44baa08a3b2"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token string-property property">"z"</span><span class="token operator">:</span><span class="token string">"2e8c7f5c.ab73d"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"store PLC Data in flow context memory"</span><span class="token punctuation">,</span><span class="token string-property property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"conveyorData.Conveyor_RTS"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"flow"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload.Conveyor_RTS"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"conveyorData.Conveyor_Running"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"flow"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload.Conveyor_Running"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"conveyorData.Line4_Fault"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"flow"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload.Line4_Fault"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"conveyorData.Line4_State"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"flow"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload.Line4_State"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"conveyorData.Robot_Position"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"flow"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload.Robot_Position"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token string-property property">"p"</span><span class="token operator">:</span><span class="token string">"conveyorData.Robot_RTS"</span><span class="token punctuation">,</span><span class="token string-property property">"pt"</span><span class="token operator">:</span><span class="token string">"flow"</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">"payload.Robot_RTS"</span><span class="token punctuation">,</span><span class="token string-property property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string-property property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token string-property property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token string-property property">"x"</span><span class="token operator">:</span><span class="token number">530</span><span class="token punctuation">,</span><span class="token string-property property">"y"</span><span class="token operator">:</span><span class="token number">600</span><span class="token punctuation">,</span><span class="token string-property property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token string-property property">"id"</span><span class="token operator">:</span><span class="token string">"f012042b75173b77"</span><span class="token punctuation">,</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"eth-ip endpoint"</span><span class="token punctuation">,</span><span class="token string-property property">"address"</span><span class="token operator">:</span><span class="token string">"192.168.0.5"</span><span class="token punctuation">,</span><span class="token string-property property">"slot"</span><span class="token operator">:</span><span class="token string">"0"</span><span class="token punctuation">,</span><span class="token string-property property">"cycletime"</span><span class="token operator">:</span><span class="token string">"1000"</span><span class="token punctuation">,</span><span class="token string-property property">"name"</span><span class="token operator">:</span><span class="token string">"Line 4 PLC"</span><span class="token punctuation">,</span><span class="token string-property property">"vartable"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token string-property property">""</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token string-property property">"Conveyor_RTS"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"BOOL"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token string-property property">"Conveyor_Running"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"BOOL"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token string-property property">"Line4_Fault"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"BOOL"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token string-property property">"Line4_State"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"DINT"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token string-property property">"Robot_Position"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"REAL"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token string-property property">"Robot_RTS"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token string-property property">"type"</span><span class="token operator">:</span><span class="token string">"BOOL"</span><span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token punctuation">]</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-649" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
https://flowfuse.com/blog/2023/07/influxdb-historical-data/Creating a Historical Data Dashboard with InfluxDB and Node-REDDetailed instructions on how to create a Node-RED dashboard that shows historical data.2023-07-18T00:00:00Z<p>Every new dashboard is met with the fast-following request, “can we save this data and somehow look back on it?” Yes, you can, and let’s use InfluxDB to make it happen!</p>
<!--more-->
<p>Edge devices are often polling sensors at regular intervals and are a perfect candidate to be paired with a database purpose-built for time-series data, like InfluxDB. Let’s capture some data, create a live chart, store the data, and then create a GUI for retrieving the data.</p>
<p>Here’s a screenshot of the dashboard we will create, which is divided into two sections. The first section displays live data, while the second section consists of fields that enable users to query the database and retrieve historical data. Looking at the live data, the chart depicts a sinusoidal graph that represents the scale measurements used for quality assurance in the aggregate production process at an automated mining operation. The graph showcases fluctuations in weight over time, indicating variations in the samples being weighed. This monitoring process ensures the quality and consistency of the aggregates being produced. The historical data shows a snippet of this information that was retrieved from InfluxDB.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/dashboard-1-SVwKifqDBJ-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/dashboard-1-SVwKifqDBJ-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Dashboard" alt="alt_text" loading="lazy" decoding="async" src="https://flowfuse.com/img/dashboard-1-SVwKifqDBJ-650.jpeg" width="650" height="598" /></picture></p>
<br />
<p>Here is a screenshot of the simple Node-RED flow to create that dashboard. We will dive into the details through this article, and, by the end, you will be able to create this flow yourself.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/flow-2-0_I_1b9Zd8-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/flow-2-0_I_1b9Zd8-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Final Flow" alt="alt_text" loading="lazy" decoding="async" src="https://flowfuse.com/img/flow-2-0_I_1b9Zd8-650.jpeg" width="650" height="184" /></picture></p>
<h2 id="capturing-serial-port-data" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/influxdb-historical-data/#capturing-serial-port-data"># </a> Capturing serial port data</h2>
<p>The live view is fed by data coming from a simple scale with a serial interface. This <a href="https://www.brecknellscales.com/wp-content/uploads/2022/09/LPS-Series_u_en_fr_501724-1.pdf">Brecknell LPS-150</a> scale will auto power-on, remembers the last tare setting, and continuously sends its reading via RS-232, so it is a great unit to use for unattended IoT projects.</p>
<p>On the Node-RED side, a serial node can be configured to capture this incoming data. If your device running Node-RED doesn’t have an RS-232 port, there are many variations of RS-232-to-USB cables to help you connect. This scale is sending data at a very high-speed interval so it is important to use a “delay” node before the rest of your flow gets bogged down.</p>
<p>Below, I have configured the serial port node with the same settings that were used to set up the scale. These settings are commonly documented as "9600 8N1" in shorthand. In serial communication it is necessary for the two devices to have the exact same settings or the data becomes garbled. The incoming stream of ASCII text is divided using the hex value 0x0D, which corresponds to the return character. This character is used as a delimiter to separate the individual chunks of text within the incoming data stream.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/serial-port-node-3-DwwNQyF5ba-517.avif 517w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/serial-port-node-3-DwwNQyF5ba-517.webp 517w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Serial Port Node" alt="alt_text" loading="lazy" decoding="async" src="https://flowfuse.com/img/serial-port-node-3-DwwNQyF5ba-517.jpeg" width="517" height="679" /></picture></p>
<br />
<p>With this “delay” node, we now have a new message from the scale at a rate of 1 msg per 5 seconds</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/delay-4-827GfWRy4f-510.avif 510w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/delay-4-827GfWRy4f-510.webp 510w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Delay Node" alt="alt_text" loading="lazy" decoding="async" src="https://flowfuse.com/img/delay-4-827GfWRy4f-510.jpeg" width="510" height="411" /></picture></p>
<br />
<p>The debugger allows us to see the raw data as it is captured.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/debugger-5-btWET_2zcA-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/debugger-5-btWET_2zcA-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Debugger" alt="alt_text" loading="lazy" decoding="async" src="https://flowfuse.com/img/debugger-5-btWET_2zcA-650.jpeg" width="650" height="102" /></picture></p>
<br />
<p>Unfortunately, these values are not in a friendly form to work with. Ideally, we want our payload to just be a number, not this string with odd characters, extra spaces, and the units.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/change-node-6-k6vBLGukV1-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/change-node-6-k6vBLGukV1-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Node-RED Change Node" alt="alt_text" loading="lazy" decoding="async" src="https://flowfuse.com/img/change-node-6-k6vBLGukV1-650.jpeg" width="650" height="304" /></picture></p>
<br />
<p>We need to extract the numeric part of the string using a regular expression with a “change” node and the JSONata expression $number($match(msg.payload, /-?(\d+(.\d+)?)/ , 10).match). “$match” and “/-?(\d+(.\d+)?)/” help the function pull out the numeric components of the string and “$number” parses these components to be an actual number data type.</p>
<p>Here are the properties of the “change” node.</p>
<p>When we look in the debugger we see the payload specified as a “number” and the value displayed in blue, both indications that we have successfully extracted the weight as the correct data type.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/number-7-VUKjxQoGRn-191.avif 191w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/number-7-VUKjxQoGRn-191.webp 191w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Debug Output" alt="alt_text" loading="lazy" decoding="async" src="https://flowfuse.com/img/number-7-VUKjxQoGRn-191.jpeg" width="191" height="69" /></picture></p>
<h2 id="setting-up-serverless-influxdb-in-the-cloud" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/influxdb-historical-data/#setting-up-serverless-influxdb-in-the-cloud"># </a> Setting up serverless InfluxDB in the cloud</h2>
<p>Now we have some live data, let’s store it using InfluxDB. Below are the steps to set up an account with the InfluxDB free service. Navigate to <a href="https://www.influxdata.com/products/influxdb-overview/">https://www.influxdata.com/products/influxdb-overview/</a> and let’s begin. Click on “Get Started for Free” under Cloud, InfluxDB Cloud Serverless.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/run-influxdb-8-dCr8iG20ob-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/run-influxdb-8-dCr8iG20ob-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="InfluxDB" alt="alt_text" loading="lazy" decoding="async" src="https://flowfuse.com/img/run-influxdb-8-dCr8iG20ob-650.jpeg" width="650" height="284" /></picture></p>
<p>For this example the Free plan will work fine.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/free-influxdb-9-LrJdk7HLOv-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/free-influxdb-9-LrJdk7HLOv-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Free InfluxDB" alt="alt_text" loading="lazy" decoding="async" src="https://flowfuse.com/img/free-influxdb-9-LrJdk7HLOv-650.jpeg" width="650" height="526" /></picture></p>
<p>Create a bucket to store the data.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/bucket-influxdb-10-s9YjBmiFiT-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/bucket-influxdb-10-s9YjBmiFiT-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Create Bucket" alt="alt_text" loading="lazy" decoding="async" src="https://flowfuse.com/img/bucket-influxdb-10-s9YjBmiFiT-650.jpeg" width="650" height="482" /></picture></p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/load-data-influxdb-11-BwVzC3khYr-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/load-data-influxdb-11-BwVzC3khYr-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Create Bucket" alt="alt_text" loading="lazy" decoding="async" src="https://flowfuse.com/img/load-data-influxdb-11-BwVzC3khYr-650.jpeg" width="650" height="187" /></picture></p>
<p>Generate a token to direct the calls from Node-RED to your InfluxDB account when they hit the InfluxDB server:</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/token-influxdb-12-1qA96B6gb_-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/token-influxdb-12-1qA96B6gb_-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Token" alt="alt_text" loading="lazy" decoding="async" src="https://flowfuse.com/img/token-influxdb-12-1qA96B6gb_-650.jpeg" width="650" height="183" /></picture></p>
<p>I selected “Generate All Access API Token,” but eventually you will want a custom, more restricted approach.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/generate-token-influxdb-13-3sTzWsuJkc-387.avif 387w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/generate-token-influxdb-13-3sTzWsuJkc-387.webp 387w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="image_tooltip" alt="alt_text" loading="lazy" decoding="async" src="https://flowfuse.com/img/generate-token-influxdb-13-3sTzWsuJkc-387.jpeg" width="387" height="269" /></picture></p>
<p>Copy your token and do not share it! (mine will be deleted later)</p>
<h2 id="connecting-node-red-to-influxdb" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/influxdb-historical-data/#connecting-node-red-to-influxdb"># </a> Connecting Node-RED to InfluxDB</h2>
<p>Navigate to “Manage Palette” in the Node-RED hamburger menu in the upper right corner of the flow editor. I did a search for InfluxDB and selected the most popular one, “node-red-contrib-influxdb” by looking at the number of downloads per week at <a href="https://flows.nodered.org/node/node-red-contrib-influxdb">https://flows.nodered.org/node/node-red-contrib-influxdb</a>. When you are just starting out, it can be a smart decision to go with the popular option. The popularity indicates a level of trust and adoption within the community, making it a reliable choice for beginners</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/install-contrib-influxdb-14-5-FBdn33Ve-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/install-contrib-influxdb-14-5-FBdn33Ve-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="InfluxDB Nodes" alt="alt_text" loading="lazy" decoding="async" src="https://flowfuse.com/img/install-contrib-influxdb-14-5-FBdn33Ve-650.jpeg" width="650" height="294" /></picture></p>
<br />
<p>After installing this package you will see three new nodes in your flow editor.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/influxdb-nodes-15-YhCM5CENmp-157.avif 157w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/influxdb-nodes-15-YhCM5CENmp-157.webp 157w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="InfluxDB Nodes" alt="alt_text" loading="lazy" decoding="async" src="https://flowfuse.com/img/influxdb-nodes-15-YhCM5CENmp-157.jpeg" width="157" height="143" /></picture></p>
<p>Drag and drop the “influxdb out” node into your flow, double click on it, and start filling out the needed fields. The naming convention of “test<<THING>>” works well for initial setups to make it clear what names should go where.</THING></p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/influxdb-out-node-16-BgiF3koLh3-517.avif 517w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/influxdb-out-node-16-BgiF3koLh3-517.webp 517w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="InfluxDB Out Node" alt="alt_text" loading="lazy" decoding="async" src="https://flowfuse.com/img/influxdb-out-node-16-BgiF3koLh3-517.jpeg" width="517" height="442" /></picture></p>
<br />
<p>It was a little unclear what URL to use with this serverless option, but I guessed it was the same as the URL for the InfluxDB resource center account page, “<a href="https://us-east-1-1.aws.cloud2.influxdata.com/">https://us-east-1-1.aws.cloud2.influxdata.com/</a>” and it worked. Then, enter the API token that was generated earlier.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/influxdb-node-17-tbU6XJNq3x-507.avif 507w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/influxdb-node-17-tbU6XJNq3x-507.webp 507w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="image_tooltip" alt="alt_text" loading="lazy" decoding="async" src="https://flowfuse.com/img/influxdb-node-17-tbU6XJNq3x-507.jpeg" width="507" height="362" /></picture></p>
<br />
<p>The “influxdb out” node is now ready to start storing payloads. The documentation for the InfluxDB nodes at <a href="https://flows.nodered.org/node/node-red-contrib-influxdb">https://flows.nodered.org/node/node-red-contrib-influxdb</a> gives more detail as to extra options, such as tags, that you might want to attach to your data being stored. In this simple example, we are just going to send the “influxdb out” node a number via the msg.payload.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/flow-influxdb-out-18-sKUXhxd6sq-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/flow-influxdb-out-18-sKUXhxd6sq-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Out Flow" alt="alt_text" loading="lazy" decoding="async" src="https://flowfuse.com/img/flow-influxdb-out-18-sKUXhxd6sq-650.jpeg" width="650" height="79" /></picture></p>
<br />
<p>Here is a chart of the live data which is also being stored.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/live-data-chart-19-qkB3uPxcvV-322.avif 322w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/live-data-chart-19-qkB3uPxcvV-322.webp 322w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Live Data" alt="alt_text" loading="lazy" decoding="async" src="https://flowfuse.com/img/live-data-chart-19-qkB3uPxcvV-322.jpeg" width="322" height="271" /></picture></p>
<br />
<p>The InfluxDB Data Explorer helps you create a SQL call and allows you to run it right in the browser so you can verify that your data is being stored correctly.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/influxdb-explorer-20-OXsksNsMfz-650.avif 650w, https://flowfuse.com/img/influxdb-explorer-20-OXsksNsMfz-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/influxdb-explorer-20-OXsksNsMfz-650.webp 650w, https://flowfuse.com/img/influxdb-explorer-20-OXsksNsMfz-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/influxdb-explorer-20-OXsksNsMfz-650.jpeg 650w, https://flowfuse.com/img/influxdb-explorer-20-OXsksNsMfz-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="InfluxDB Explorer" alt="alt_text" loading="lazy" decoding="async" src="https://flowfuse.com/img/influxdb-explorer-20-OXsksNsMfz-650.jpeg" width="1300" height="705" /></picture></p>
<br />
<h2 id="creating-a-historical-data-gui" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/influxdb-historical-data/#creating-a-historical-data-gui"># </a> Creating a historical data GUI</h2>
<p>Now we have our data being stored, but we aren’t quite finished. We still want an easy way to pull this information up and for it to be presented in a chart, just like the live data.</p>
<p>Here is the Dashboard group we will create for this GUI.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/historical-data-21-0AcJTMFOcD-320.avif 320w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/historical-data-21-0AcJTMFOcD-320.webp 320w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Historical Data" alt="alt_text" loading="lazy" decoding="async" src="https://flowfuse.com/img/historical-data-21-0AcJTMFOcD-320.jpeg" width="320" height="600" /></picture></p>
<p>And here is the flow to create it.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/data-flow-22-x9hE0kmJsf-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/data-flow-22-x9hE0kmJsf-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Data Flow" alt="alt_text" loading="lazy" decoding="async" src="https://flowfuse.com/img/data-flow-22-x9hE0kmJsf-650.jpeg" width="650" height="116" /></picture></p>
<p>A “template” node creates a convenient way to create a plain text output with variable properties within. Below you can see that msg.query is created from a string of text with “rangeStart” and “rangeEnd” dynamically inserted using the “mustache” syntax. More information about how to query InfluxDB can be found here: <a href="https://docs.influxdata.com/influxdb/v2.0/query-data/get-started/query-influxdb/">https://docs.influxdata.com/influxdb/v2.0/query-data/get-started/query-influxdb/</a>.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/template-node-23-ZzMWqGgjt8-640.avif 640w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/template-node-23-ZzMWqGgjt8-640.webp 640w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Template Node" alt="alt_text" loading="lazy" decoding="async" src="https://flowfuse.com/img/template-node-23-ZzMWqGgjt8-640.jpeg" width="640" height="667" /></picture></p>
<br />
<p>Using the "Form" dashboard node is an easy way to collect all the required information for our query. We need to be able to enter in a date and time to start gathering the data, and a window to know how long a range of values to pull.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/form-node-24-gM4bqn-p2V-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/form-node-24-gM4bqn-p2V-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Form Node" alt="alt_text" loading="lazy" decoding="async" src="https://flowfuse.com/img/form-node-24-gM4bqn-p2V-650.jpeg" width="650" height="563" /></picture></p>
<p>Here is the code from the “time/date” function node. A bit of juggling of local time versus UTC time is needed to allow the user to intuitively query the correct data for their timezone.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/function-node-25-0bAZwBvHvW-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/function-node-25-0bAZwBvHvW-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Function Node" alt="alt_text" loading="lazy" decoding="async" src="https://flowfuse.com/img/function-node-25-0bAZwBvHvW-650.jpeg" width="650" height="466" /></picture></p>
<br />
<p>Here is the “change” node used to create the msg.rangeEnd. The JSONatta expression is $fromMillis($toMillis(msg.rangeStart) + msg.payload.window * 60 * 1000). The expression combines the milliseconds from the msg.rangeStart with the calculated milliseconds in the “Window (minutes)” from the GUI.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/change-node-26-tzOj3AJFAa-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/change-node-26-tzOj3AJFAa-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Change Node" alt="alt_text" loading="lazy" decoding="async" src="https://flowfuse.com/img/change-node-26-tzOj3AJFAa-650.jpeg" width="650" height="391" /></picture></p>
<br />
<p>Now that the query is coming back from InfluxDB, let’s break down how to transform this data object into one that can be read by the “chart” node. Below, we see on the left column what the object looks like from InfluxDB and on the right we see how it must be structured to be viewed in the chart.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/data-format-27-OFKpV992TT-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/data-format-27-OFKpV992TT-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Data Format" alt="alt_text" loading="lazy" decoding="async" src="https://flowfuse.com/img/data-format-27-OFKpV992TT-650.jpeg" width="650" height="579" /></picture></p>
<p>Rob Marcer has a great article on working with persistent chart data found here: <a href="https://flowfuse.com/blog/2023/05/persisting-chart-data-in-node-red/">/blog/2023/05/persisting-chart-data-in-node-red/</a>.</p>
<p>We can use a series of nodes from the Node-RED core package to transform this data.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/transform-data-28-SUZ7P-iTlR-529.avif 529w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/transform-data-28-SUZ7P-iTlR-529.webp 529w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Flwo to transform data" alt="alt_text" loading="lazy" decoding="async" src="https://flowfuse.com/img/transform-data-28-SUZ7P-iTlR-529.jpeg" width="529" height="269" /></picture></p>
<br />
<p>First, a “switch” node is used to determine if the response InfluxDB contains any data so that we can either format the data properly, or clear the chart and indicate “No Data.”</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/switch-node-28-oyYAuKY4zP-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/switch-node-28-oyYAuKY4zP-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Switch Node" alt="alt_text" loading="lazy" decoding="async" src="https://flowfuse.com/img/switch-node-28-oyYAuKY4zP-650.jpeg" width="650" height="606" /></picture></p>
<br />
<p>The “Label” field in the “chart” node can also be dynamically created with the mustache syntax.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/chart-node-29-8PODDPN9UY-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/chart-node-29-8PODDPN9UY-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Chart Node" alt="alt_text" loading="lazy" decoding="async" src="https://flowfuse.com/img/chart-node-29-8PODDPN9UY-650.jpeg" width="650" height="428" /></picture></p>
<br />
<p>If the “is not empty” “switch” node sees an empty payload, this “change” node sets the payload to an empty array, clearing the chart, and sets the msg.title to “No Data” so users know their query, though successful, returned an empty set of values.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/change-node-30-r1fwGZMnTs-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/change-node-30-r1fwGZMnTs-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Change Node" alt="alt_text" loading="lazy" decoding="async" src="https://flowfuse.com/img/change-node-30-r1fwGZMnTs-650.jpeg" width="650" height="606" /></picture></p>
<br />
<p>The parameters for the “split” node can be left as-is.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/split-node-31-IQf-ZExcu2-608.avif 608w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/split-node-31-IQf-ZExcu2-608.webp 608w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Split Node" alt="alt_text" loading="lazy" decoding="async" src="https://flowfuse.com/img/split-node-31-IQf-ZExcu2-608.jpeg" width="608" height="480" /></picture></p>
<br />
<p>In the “chartData” “change” node, will pull out the two values we need for the chart, milliseconds since the UNIX epoch for the x-value and the measurement from the scale for the y-value. A simple JSONatta expression helps us transform the date from a string to milliseconds for the x-value.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/change-node-32-smuQTyksre-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/change-node-32-smuQTyksre-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Chnage Node" alt="alt_text" loading="lazy" decoding="async" src="https://flowfuse.com/img/change-node-32-smuQTyksre-650.jpeg" width="650" height="486" /></picture></p>
<br />
<p>The “join” node just needs to be set to “Combine each” msg.chartData object and configured “to create” an array.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/join-node-33-55a-Ouf-0x-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/join-node-33-55a-Ouf-0x-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Join Node" alt="alt_text" loading="lazy" decoding="async" src="https://flowfuse.com/img/join-node-33-55a-Ouf-0x-650.jpeg" width="650" height="426" /></picture></p>
<br />
<p>The final “change” node, “format,” is where we prescribe the format needed for the “chart” node, [{"series":[""],"data":[[]],"labels":[""]}], and finally we insert our msg.chartData array into that structure. Notice msg.title is now set to “Data Received.”</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/change-node-33-gUhHgghB58-595.avif 595w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/change-node-33-gUhHgghB58-595.webp 595w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Change Node" alt="alt_text" loading="lazy" decoding="async" src="https://flowfuse.com/img/change-node-33-gUhHgghB58-595.jpeg" width="595" height="451" /></picture></p>
<br />
<p>And, there you have it. You can query the same range of data found on the live chart to ensure the code is working and then you can use the dashboard to pull up historical data, way in the past from what is shown on the live chart.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/final-dashboard-34-k8pk61PD73-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/final-dashboard-34-k8pk61PD73-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="image_tooltip" alt="alt_text" loading="lazy" decoding="async" src="https://flowfuse.com/img/final-dashboard-34-k8pk61PD73-650.jpeg" width="650" height="604" /></picture></p>
<h2 id="final-thoughts" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/influxdb-historical-data/#final-thoughts"># </a> Final Thoughts</h2>
<p>This was a data-driven journey, capturing values from a scale for comprehensive testing. We were able to develop a simple, yet powerful dashboard that visualizes this live data while using InfluxDB as a reliable storage solution. We also designed an intuitive interface for efficient data querying to generate charts to analyze historical data.</p>
<p>InfluxDB's capabilities go beyond these initial achievements. It can be deployed locally, has the ability to handle high sample rates, can apply data scrubbing functions, and store this filtered data to enhance data quality and accessibility. Most importantly, this data visualization enables us to spot trends effortlessly and gain valuable predictive insights by examining historical data leading up to specific events. We are empowered to uncover meaningful patterns, make informed decisions, and drive innovation in data management and analysis.</p>
https://flowfuse.com/blog/2023/07/how-to-deploy-a-basic-opc-ua-server-in-node-red/How to Deploy a Basic OPC-UA Server in Node-RED - Part 1OPC-UA Server Information Modeling in Node-RED2023-07-13T00:00:00Z<p>This article is the first part of a series of OPC-UA content. Here, we will explain some basic concepts of OPC-UA as they apply to building a server in Node-RED, then walk through and deploy an example OPC-UA Server.</p>
<!--more-->
<h2 id="what-is-opc-ua%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/how-to-deploy-a-basic-opc-ua-server-in-node-red/#what-is-opc-ua%3F"># </a> What is OPC-UA?</h2>
<p>Open Platform Communications Unified Architecture (OPC UA) is an open, platform independent communication framework frequently utilized in industrial automation, and is considered one of the key protocol standards for Industry 4.0 and Industrial IoT (IIoT). The standard is developed and maintained by a consortium called the OPC Foundation, with recognizable industry names such as Siemens, Honeywell, Microsoft, Beckhoff, SAP, Yokogawa, ABB, Rockwell, and Schneider Electric.</p>
<p>Because of OPC-UA’s wide industry acceptance, it is increasingly becoming natively supported on devices and systems spanning the entirety of the automation pyramid.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/automation-pyramid-6xEWe3SHv7-650.avif 650w, https://flowfuse.com/img/automation-pyramid-6xEWe3SHv7-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/automation-pyramid-6xEWe3SHv7-650.webp 650w, https://flowfuse.com/img/automation-pyramid-6xEWe3SHv7-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/automation-pyramid-6xEWe3SHv7-650.jpeg 650w, https://flowfuse.com/img/automation-pyramid-6xEWe3SHv7-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Automation Pyramid" loading="lazy" decoding="async" src="https://flowfuse.com/img/automation-pyramid-6xEWe3SHv7-650.jpeg" width="1300" height="934" /></picture>
<em>Image reference - <a href="https://www.motioncontroltips.com/what-is-opc-ua-and-how-does-it-compare-with-industrial-ethernet/">imagecontroltips.com</a></em></p>
<h2 id="fieldbus-model-vs-opc-ua-information-model" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/how-to-deploy-a-basic-opc-ua-server-in-node-red/#fieldbus-model-vs-opc-ua-information-model"># </a> Fieldbus Model vs OPC-UA Information Model</h2>
<p>As of today, industrial ethernet fieldbuses dominate the field/device-level (level 0) and controller/PLC-level (level 1) of the automation pyramid.
<picture><source type="image/avif" srcset="https://flowfuse.com/img/OPC-UA-pyramid-2-tU8VywnGaC-630.avif 630w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/OPC-UA-pyramid-2-tU8VywnGaC-630.webp 630w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="OPC-UA Pyramid" loading="lazy" decoding="async" src="https://flowfuse.com/img/OPC-UA-pyramid-2-tU8VywnGaC-630.jpeg" width="630" height="460" /></picture>
<em>Image reference - <a href="https://www.mdpi.com/1424-8220/21/14/4656">mdpi.com</a></em></p>
<p>Fieldbuses such as Profinet, Ethernet/IP, and EtherCAT, employ deterministic, real-time communication, which is essential for mission-critical and safety-oriented automation tasks. OPC-UA is most commonly encountered at the SCADA level and above (level 2-4). However, with the inclusion of <a href="https://www.tttech-industrial.com/resource-library/blog-posts/opc-ua-fx">Time Sensitive Networking (TSN) into the OPC-UA technology stack</a>, OPC-UA can be feasibly used for real-time communication all the way down to the device level.</p>
<p>Traditionally, fieldbus protocols transmit only raw data from field devices (ie, a float to represent a pressure, or a boolean to represent the position of a switch). The fieldbus data gets pushed up the automation stack layer by layer, where eventually it will be converted to a format suitable for IT systems to consume (such as OPC-UA).</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/fieldbus-model-NtyAEOfJEA-650.avif 650w, https://flowfuse.com/img/fieldbus-model-NtyAEOfJEA-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/fieldbus-model-NtyAEOfJEA-650.webp 650w, https://flowfuse.com/img/fieldbus-model-NtyAEOfJEA-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/fieldbus-model-NtyAEOfJEA-650.jpeg 650w, https://flowfuse.com/img/fieldbus-model-NtyAEOfJEA-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Fieldbus Model.png" loading="lazy" decoding="async" src="https://flowfuse.com/img/fieldbus-model-NtyAEOfJEA-650.jpeg" width="1300" height="654" /></picture></p>
<p>In contrast to fieldbus protocols, OPC-UA represents automation data in the form of nodes. The framework for constructing nodes is referred to as the <a href="lhttps://reference.opcfoundation.org/Core/Part5/v104/docs/">OPC Information model</a>, and consists of pre-defined classes and methods that are programmed in the OPC Server address space.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/opc-information-model-78prN7R6B0-650.avif 650w, https://flowfuse.com/img/opc-information-model-78prN7R6B0-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/opc-information-model-78prN7R6B0-650.webp 650w, https://flowfuse.com/img/opc-information-model-78prN7R6B0-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/opc-information-model-78prN7R6B0-650.jpeg 650w, https://flowfuse.com/img/opc-information-model-78prN7R6B0-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="OPC Information Model" loading="lazy" decoding="async" src="https://flowfuse.com/img/opc-information-model-78prN7R6B0-650.jpeg" width="1300" height="790" /></picture>
Devices can be described as objects that give a holistic view of the device, beyond simply the raw value. To construct a device object, we can take different individual attributes associated with a device, such as the transmitter raw value, transmitter fault flag, alarm setpoint, and combine them, similar to how user-defined datatypes (UDTs) are objects used to represent devices in PLCs. The information model also defines a folder structure, to allow devices information to reside in a structured hierarchy. Using the example temperature transmitter above, an example folder structure can be constructed as follows:</p>
<p><code>/Root/Objects/Calcinator 1 PLC/Temperature Transmitters/Tank 1 Temperature/Transmitter Value</code></p>
<p>This folder structure will be exposed via the OPC Client browser, allowing end-users to easily “drill down” to individual node information in a logical manner.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/opc-client-browser-xaVrhfTOIm-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/opc-client-browser-xaVrhfTOIm-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="OPC Client Browser" loading="lazy" decoding="async" src="https://flowfuse.com/img/opc-client-browser-xaVrhfTOIm-650.jpeg" width="650" height="485" /></picture>
In summary, OPC-UA represents a trade-off between complex information modeling, with the versatility for that data to be consumed by devices and systems all the way up the automation pyramid layers. The data does not have to pass through subsequent automation layers on the way up, nor does the data need to undergo any conversion along the way.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/OPC-UA-distributed-model-t4CxB7ZRBs-525.avif 525w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/OPC-UA-distributed-model-t4CxB7ZRBs-525.webp 525w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="OPC-UA Distributed Model" loading="lazy" decoding="async" src="https://flowfuse.com/img/OPC-UA-distributed-model-t4CxB7ZRBs-525.jpeg" width="525" height="350" /></picture>
<em>Image reference - <a href="https://ifr.org/post/faster-robot-communication-through-the-opc-robotics-companion-specification">ifr.org</a></em></p>
<p>The OPC client simply needs to subscribe to the OPC Server endpoint url (ex. opc.tcp://server.address), and the client will be able to browse the structured OPC data as it’s modeled in the server. Any client will receive the information in the same manner, regardless if it’s a PLC, SCADA, MES, or ERP system. This opens the possibility for horizontal and vertical system integration in a standardized manner. Additionally, the more information that is exposed about a device, the easier it is to track, and use said data to autonomously reconfigure, or pre-emptively take maintenance actions.</p>
<h2 id="deploying-an-example-opc-ua-server-in-node-red" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/how-to-deploy-a-basic-opc-ua-server-in-node-red/#deploying-an-example-opc-ua-server-in-node-red"># </a> Deploying an Example OPC-UA Server in Node-RED</h2>
<p>With some background on OPC-UA and how information is modeled in mind, we can take a look at the <a href="https://flows.nodered.org/node/node-red-contrib-opcua-server">node-red-contrib-opcua-server</a> node, which is merely a compact version of the <a href="https://flows.nodered.org/node/node-red-contrib-opcua">node-red-contrib-opcua</a> node that only focuses on the OPC-UA server and hence requires less dependencies.</p>
<p>An <a href="https://github.com/BiancoRoyal/node-red-contrib-opcua-server/blob/master/examples/server-with-context.json">example flow</a> is provided on github that can serve as a basis for understanding how a OPC-UA server is constructed. Let’s get the example server up and running.</p>
<p>Deploying the example flow yields the following result -</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/compact-server-flow-vnx5mwUMDT-650.avif 650w, https://flowfuse.com/img/compact-server-flow-vnx5mwUMDT-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/compact-server-flow-vnx5mwUMDT-650.webp 650w, https://flowfuse.com/img/compact-server-flow-vnx5mwUMDT-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/compact-server-flow-vnx5mwUMDT-650.jpeg 650w, https://flowfuse.com/img/compact-server-flow-vnx5mwUMDT-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Compact Server Flow" loading="lazy" decoding="async" src="https://flowfuse.com/img/compact-server-flow-vnx5mwUMDT-650.jpeg" width="1300" height="199" /></picture></p>
<ul>
<li>an inject node is trigging the function <code>set flow context Inputs</code> at a one second interval, which creates 7 randomly generated float values and stores them as flow context variables, <code>isoInput2</code> - <code>isoInput8</code> (isolated inputs). The values will change to a new random number each time the node is injected.</li>
</ul>
<div style="position: relative">
<pre class="language-javascript"><code id="code-74" class="language-javascript">flow<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">'isoInput2'</span><span class="token punctuation">,</span> Math<span class="token punctuation">.</span><span class="token function">random</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token number">12.0</span><span class="token punctuation">)</span><br />flow<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">'isoInput3'</span><span class="token punctuation">,</span> Math<span class="token punctuation">.</span><span class="token function">random</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token number">13.0</span><span class="token punctuation">)</span><br />flow<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">'isoInput4'</span><span class="token punctuation">,</span> Math<span class="token punctuation">.</span><span class="token function">random</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token number">14.0</span><span class="token punctuation">)</span><br />flow<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">'isoInput5'</span><span class="token punctuation">,</span> Math<span class="token punctuation">.</span><span class="token function">random</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token number">15.0</span><span class="token punctuation">)</span><br />flow<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">'isoInput6'</span><span class="token punctuation">,</span> Math<span class="token punctuation">.</span><span class="token function">random</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token number">16.0</span><span class="token punctuation">)</span><br />flow<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">'isoInput7'</span><span class="token punctuation">,</span> Math<span class="token punctuation">.</span><span class="token function">random</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token number">17.0</span><span class="token punctuation">)</span><br />flow<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">'isoInput8'</span><span class="token punctuation">,</span> Math<span class="token punctuation">.</span><span class="token function">random</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token number">18.0</span><span class="token punctuation">)</span><br /><br /><span class="token operator">...</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-74" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<ul>
<li>another inject node is triggering the function <code>set flow context Outputs</code>, also at a one second interval, which creates another set of 7 randomly generated float values and stores them as flow context variables, <code>isoOutput2</code> - <code>isoOutput8</code> (isolated inputs). The values will change to a new random number each time the node is injected.</li>
</ul>
<div style="position: relative">
<pre class="language-javascript"><code id="code-82" class="language-javascript">flow<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">'isoOutput2'</span><span class="token punctuation">,</span> Math<span class="token punctuation">.</span><span class="token function">random</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token number">2.0</span><span class="token punctuation">)</span><br />flow<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">'isoOutput3'</span><span class="token punctuation">,</span> Math<span class="token punctuation">.</span><span class="token function">random</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token number">3.0</span><span class="token punctuation">)</span><br />flow<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">'isoOutput4'</span><span class="token punctuation">,</span> Math<span class="token punctuation">.</span><span class="token function">random</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token number">4.0</span><span class="token punctuation">)</span><br />flow<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">'isoOutput5'</span><span class="token punctuation">,</span> Math<span class="token punctuation">.</span><span class="token function">random</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token number">5.0</span><span class="token punctuation">)</span><br />flow<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">'isoOutput6'</span><span class="token punctuation">,</span> Math<span class="token punctuation">.</span><span class="token function">random</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token number">6.0</span><span class="token punctuation">)</span><br />flow<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">'isoOutput7'</span><span class="token punctuation">,</span> Math<span class="token punctuation">.</span><span class="token function">random</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token number">7.0</span><span class="token punctuation">)</span><br />flow<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">'isoOutput8'</span><span class="token punctuation">,</span> Math<span class="token punctuation">.</span><span class="token function">random</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token number">8.0</span><span class="token punctuation">)</span><br /><br /><span class="token operator">...</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-82" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>We can confirm the values are being stored in memory by checking the flow context data and pressing the refresh button.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/context-data-1-IczPgYP8Hd-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/context-data-1-IczPgYP8Hd-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Context Data 1" loading="lazy" decoding="async" src="https://flowfuse.com/img/context-data-1-IczPgYP8Hd-650.jpeg" width="650" height="433" /></picture>
<picture><source type="image/avif" srcset="https://flowfuse.com/img/context-data-2-wZaRYwhx8v-617.avif 617w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/context-data-2-wZaRYwhx8v-617.webp 617w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Context Data 2" loading="lazy" decoding="async" src="https://flowfuse.com/img/context-data-2-wZaRYwhx8v-617.jpeg" width="617" height="1504" /></picture>
Each time we hit refresh, the values change, confirming that the values are randomly changing every second.</p>
<p>The last, and most important part of the flow, is the <code>Compact-Server</code> node, which actually stands alone without any incoming or outgoing connections.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/compact-server-node-FczbW0zSos-384.avif 384w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/compact-server-node-FczbW0zSos-384.webp 384w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Compact Server Node" loading="lazy" decoding="async" src="https://flowfuse.com/img/compact-server-node-FczbW0zSos-384.jpeg" width="384" height="203" /></picture>
In the <code>Compact-Server</code> node properties, the first tab is <code>Settings</code>, and the two important properties here are <code>Port</code> and <code>Show Errors</code>. As can be seen in the node screenshot above, the node is reporting <code>active</code>, which means the server is configured correctly.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/settings-tab-dggoF-GT-9-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/settings-tab-dggoF-GT-9-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Settings Tab" loading="lazy" decoding="async" src="https://flowfuse.com/img/settings-tab-dggoF-GT-9-650.jpeg" width="650" height="763" /></picture></p>
<p>The <code>Limits</code> tab specifies some default limits that we can configure if we like, but are not necessary to be modified for test purposes.</p>
<p>The <code>Security</code> tab has one important option, <code>Allow Anonymous</code>. By default, anonymous access is enabled.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/security-tab-1iBS79iJLd-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/security-tab-1iBS79iJLd-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Security Tab" loading="lazy" decoding="async" src="https://flowfuse.com/img/security-tab-1iBS79iJLd-650.jpeg" width="650" height="462" /></picture>
For a production system, we will want to enable security, but for test purposes, we will leave anonymous access enabled.</p>
<p><code>Users & Sets</code> tab is related to security and permissions. We can leave this empty for testing.</p>
<p>The <code>Address Space</code> tab is where our server OPC Information Model is constructed, using classes and methods from the <a href="https://node-opcua.github.io/">node-opcua sdk</a>.</p>
<p>Breaking down the provided example code for further context, it starts with a function that is responsible for invoking the OPC-UA server,</p>
<div style="position: relative">
<pre class="language-javascript"><code id="code-116" class="language-javascript"> <span class="token keyword">const</span> opcua <span class="token operator">=</span> coreServer<span class="token punctuation">.</span>choreCompact<span class="token punctuation">.</span>opcua<span class="token punctuation">;</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-116" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>and then the namespace is created.</p>
<div style="position: relative">
<pre class="language-javascript"><code id="code-120" class="language-javascript"><span class="token keyword">const</span> namespace <span class="token operator">=</span> addressSpace<span class="token punctuation">.</span><span class="token function">getOwnNamespace</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-120" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>Further down, the variables that will be published by the server (which are our <code>isoInput</code> & <code>isoOutput</code> flow context variables) are initialized,</p>
<div style="position: relative">
<pre class="language-javascript"><code id="code-124" class="language-javascript"> <span class="token keyword">this</span><span class="token punctuation">.</span>sandboxFlowContext<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">"isoInput1"</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setInterval</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> flexServerInternals<span class="token punctuation">.</span>sandboxFlowContext<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><br /> <span class="token string">"isoInput1"</span><span class="token punctuation">,</span><br /> Math<span class="token punctuation">.</span><span class="token function">random</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token number">50.0</span><br /> <span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">500</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span>sandboxFlowContext<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">"isoInput2"</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">this</span><span class="token punctuation">.</span>sandboxFlowContext<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">"isoInput3"</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token operator">...</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-124" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>and an OPC folder structure is defined.</p>
<div style="position: relative">
<pre class="language-javascript"><code id="code-128" class="language-javascript"> coreServer<span class="token punctuation">.</span><span class="token function">debugLog</span><span class="token punctuation">(</span><span class="token string">"init dynamic address space"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">const</span> rootFolder <span class="token operator">=</span> addressSpace<span class="token punctuation">.</span><span class="token function">findNode</span><span class="token punctuation">(</span><span class="token string">"RootFolder"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /> node<span class="token punctuation">.</span><span class="token function">warn</span><span class="token punctuation">(</span><span class="token string">"construct new address space for OPC UA"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /> <span class="token keyword">const</span> myDevice <span class="token operator">=</span> namespace<span class="token punctuation">.</span><span class="token function">addFolder</span><span class="token punctuation">(</span>rootFolder<span class="token punctuation">.</span>objects<span class="token punctuation">,</span> <span class="token punctuation">{</span><br /> <span class="token string-property property">"browseName"</span><span class="token operator">:</span> <span class="token string">"RaspberryPI-Zero-WLAN"</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token operator">...</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-128" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>Then, with our variables and folder structure defined, nodes are added to the namespace for each context variable.</p>
<div style="position: relative">
<pre class="language-javascript"><code id="code-132" class="language-javascript"> <span class="token keyword">const</span> gpioDI1 <span class="token operator">=</span> namespace<span class="token punctuation">.</span><span class="token function">addVariable</span><span class="token punctuation">(</span><span class="token punctuation">{</span><br /> <span class="token string-property property">"organizedBy"</span><span class="token operator">:</span> isoInputs<span class="token punctuation">,</span><br /> <span class="token string-property property">"browseName"</span><span class="token operator">:</span> <span class="token string">"I1"</span><span class="token punctuation">,</span><br /> <span class="token string-property property">"nodeId"</span><span class="token operator">:</span> <span class="token string">"ns=1;s=Isolated_Input1"</span><span class="token punctuation">,</span><br /> <span class="token string-property property">"dataType"</span><span class="token operator">:</span> <span class="token string">"Double"</span><span class="token punctuation">,</span><br /> <span class="token string-property property">"value"</span><span class="token operator">:</span> <span class="token punctuation">{</span><br /> <span class="token string-property property">"get"</span><span class="token operator">:</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Variant</span><span class="token punctuation">(</span><span class="token punctuation">{</span><br /> <span class="token string-property property">"dataType"</span><span class="token operator">:</span> DataType<span class="token punctuation">.</span>Double<span class="token punctuation">,</span><br /> <span class="token string-property property">"value"</span><span class="token operator">:</span> flexServerInternals<span class="token punctuation">.</span>sandboxFlowContext<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">"isoInput1"</span><span class="token punctuation">)</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token string-property property">"set"</span><span class="token operator">:</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">variant</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> flexServerInternals<span class="token punctuation">.</span>sandboxFlowContext<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><br /> <span class="token string">"isoInput1"</span><span class="token punctuation">,</span><br /> <span class="token function">parseFloat</span><span class="token punctuation">(</span>variant<span class="token punctuation">.</span>value<span class="token punctuation">)</span><br /> <span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">return</span> opcua<span class="token punctuation">.</span>StatusCodes<span class="token punctuation">.</span>Good<span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /> <span class="token punctuation">}</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /><span class="token operator">...</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-132" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>Last, OPC views are defined. Views create custom hierarchies our OPC Client can browse as an alternative to the default folder structure.</p>
<div style="position: relative">
<pre class="language-javascript"><code id="code-136" class="language-javascript"> <span class="token keyword">const</span> viewDI <span class="token operator">=</span> namespace<span class="token punctuation">.</span><span class="token function">addView</span><span class="token punctuation">(</span><span class="token punctuation">{</span><br /> <span class="token string-property property">"organizedBy"</span><span class="token operator">:</span> rootFolder<span class="token punctuation">.</span>views<span class="token punctuation">,</span><br /> <span class="token string-property property">"browseName"</span><span class="token operator">:</span> <span class="token string">"RPIW0-Digital-Ins"</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /> <span class="token keyword">const</span> viewDO <span class="token operator">=</span> namespace<span class="token punctuation">.</span><span class="token function">addView</span><span class="token punctuation">(</span><span class="token punctuation">{</span><br /> <span class="token string-property property">"organizedBy"</span><span class="token operator">:</span> rootFolder<span class="token punctuation">.</span>views<span class="token punctuation">,</span><br /> <span class="token string-property property">"browseName"</span><span class="token operator">:</span> <span class="token string">"RPIW0-Digital-Outs"</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /> viewDI<span class="token punctuation">.</span><span class="token function">addReference</span><span class="token punctuation">(</span><span class="token punctuation">{</span><br /> <span class="token string-property property">"referenceType"</span><span class="token operator">:</span> <span class="token string">"Organizes"</span><span class="token punctuation">,</span><br /> <span class="token string-property property">"nodeId"</span><span class="token operator">:</span> gpioDI1<span class="token punctuation">.</span>nodeId<br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /><span class="token operator">...</span><br /></code></pre>
<button class="code-copy " data-clipboard-target="#code-136" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>Finally, on the <code>Discovery</code> tab, we must define an endpoint for an OPC Client to subscribe to.</p>
<p>The <code>Endpoint Url</code> follows the format <code>opc.tcp://<address>:port</code>. Our port was defined on the <code>Settings</code> tab, which by default, is port <code>54845</code>. The address will be either the url or ip address of your Node-RED instance. In my case, it’s 192.168.0.114. So my Endpoint Url = <code>opc.tcp://192.168.0.114:54845</code></p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/discovery-tab-IZqHlj2fy9-650.avif 650w, https://flowfuse.com/img/discovery-tab-IZqHlj2fy9-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/discovery-tab-IZqHlj2fy9-650.webp 650w, https://flowfuse.com/img/discovery-tab-IZqHlj2fy9-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/discovery-tab-IZqHlj2fy9-650.jpeg 650w, https://flowfuse.com/img/discovery-tab-IZqHlj2fy9-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Discovery Tab" loading="lazy" decoding="async" src="https://flowfuse.com/img/discovery-tab-IZqHlj2fy9-650.jpeg" width="1300" height="624" /></picture>
Once the endpoint url is added, deploy the flow, and confirm the server is reporting “active”.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/compact-server-active-i9AeSVwBwT-427.avif 427w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/compact-server-active-i9AeSVwBwT-427.webp 427w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Compact Server Active" loading="lazy" decoding="async" src="https://flowfuse.com/img/compact-server-active-i9AeSVwBwT-427.jpeg" width="427" height="230" /></picture></p>
<h2 id="connect-to-example-opc-server-using-opc-ua-browser" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/how-to-deploy-a-basic-opc-ua-server-in-node-red/#connect-to-example-opc-server-using-opc-ua-browser"># </a> Connect to Example OPC-Server Using OPC-UA Browser</h2>
<p>To connect to our OPC endpoint, we need an OPC Client. Prosys provides a <a href="https://www.prosysopc.com/products/opc-ua-browser/">free OPC-UA Browser </a>that supports Windows, Linux, and Mac OS. To test our Server, the Windows version of Prosys OPC-UA Browser will be utilized.</p>
<p>To connect to our Node-RED OPC server, enter the endpoint url and press “connect to server”.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/opc-client-connect-rB-AxlG9NI-650.avif 650w, https://flowfuse.com/img/opc-client-connect-rB-AxlG9NI-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/opc-client-connect-rB-AxlG9NI-650.webp 650w, https://flowfuse.com/img/opc-client-connect-rB-AxlG9NI-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/opc-client-connect-rB-AxlG9NI-650.jpeg 650w, https://flowfuse.com/img/opc-client-connect-rB-AxlG9NI-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="OPC Client Connect" loading="lazy" decoding="async" src="https://flowfuse.com/img/opc-client-connect-rB-AxlG9NI-650.jpeg" width="1300" height="150" /></picture>
It will ask for security. Remember that we allowed anonymous access, so the default security mode of <code>None</code> is the correct option.</p>
<p>Once connected, we can browse our OPC Server.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/opc-client-ui-Z0GIgYvSCm-650.avif 650w, https://flowfuse.com/img/opc-client-ui-Z0GIgYvSCm-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/opc-client-ui-Z0GIgYvSCm-650.webp 650w, https://flowfuse.com/img/opc-client-ui-Z0GIgYvSCm-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/opc-client-ui-Z0GIgYvSCm-650.jpeg 650w, https://flowfuse.com/img/opc-client-ui-Z0GIgYvSCm-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="OPC Client UI" loading="lazy" decoding="async" src="https://flowfuse.com/img/opc-client-ui-Z0GIgYvSCm-650.jpeg" width="1300" height="814" /></picture>
If we navigate to <code>Objects → RaspberryPI-Zero-WLAN → GPIO → Inputs</code>, we can see a list of inputs that correspond to the <code>isoInput</code> context variables defined in the example flow, which are randomly generated numbers.</p>
<p>Clicking <code>I1</code> we can see the value in real-time, along with some additional properties.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/opc-client-node-PEU8njC0YQ-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/opc-client-node-PEU8njC0YQ-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="OPC Client Node" loading="lazy" decoding="async" src="https://flowfuse.com/img/opc-client-node-PEU8njC0YQ-650.jpeg" width="650" height="466" /></picture>
If we go to <code>Views</code>, we can see the custom hierarchy defined in the example server, which divides the data by Digital-Ins and Digital-Outs.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/opc-client-view-g1n1EAuaf5-472.avif 472w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/opc-client-view-g1n1EAuaf5-472.webp 472w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="OPC Client View" loading="lazy" decoding="async" src="https://flowfuse.com/img/opc-client-view-g1n1EAuaf5-472.jpeg" width="472" height="683" /></picture></p>
<h2 id="summary" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/how-to-deploy-a-basic-opc-ua-server-in-node-red/#summary"># </a> Summary</h2>
<p>In this article, we compare OPC-UA to traditional fieldbus protocols, explain the importance of the OPC UA Information Model to understand how data is modeled in the address space of an OPC Server, and then walk through and deploy an example compact OPC-UA Server flow.</p>
<p>In our next article, we will build a custom OPC-UA Server in Node-RED with data pulled from an Allen Bradley PLC over Ethernet/IP, using the PLC data to develop a custom OPC UA Information Model programmed in the OPC server address space.</p>
https://flowfuse.com/blog/2023/07/community-news-07/Community News July 2023Your monthly update for the FlowFuse and Node-RED communities2023-07-12T00:00:00Z<p>Welcome to the FlowFuse newsletter for July 2023, a monthly roundup of what’s been happening with FlowFuse and the wider Node-RED community.</p>
<!--more-->
<h2 id="new-release" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/community-news-07/#new-release"># </a> New Release</h2>
<p>Last week we released FlowFuse 1.9, featuring new API documentation available in the Swagger UI and the ability to customize Node-RED palettes.</p>
<p>Read about the details of FlowFuse 1.9 in our <a href="https://flowfuse.com/blog/2023/07/flowforge-1-9-release/">release announcement</a>.</p>
<h2 id="upcoming-events" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/community-news-07/#upcoming-events"># </a> Upcoming events</h2>
<h3 id="how-to-deploy-node-red-to-hundreds-of-plcs-and-iot-edge-devices" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/community-news-07/#how-to-deploy-node-red-to-hundreds-of-plcs-and-iot-edge-devices"># </a> How to deploy Node-RED to hundreds of PLCs and IoT edge devices</h3>
<p>Our next webinar will be focused on the device management capabilities in the FlowFuse platform. Lots of companies are deploying Node-RED to PLCs and IIoT edge computers. FlowFuse allows these companies to scale and manage Node-RED deployment out to hundreds of these types of devices. Discover how during our next webinar.</p>
<p><a href="https://flowfuse.com/webinars/2023/flowforge-device-management/">Sign-up today</a> to join us on July 27.</p>
<h2 id="from-our-blog" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/community-news-07/#from-our-blog"># </a> From our Blog</h2>
<ul>
<li>
<p><a href="https://flowfuse.com/blog/2023/06/dashboard-announcement/">The Next Step in Data Visualization - Announcing the Successor to the Node-RED Dashboard</a> - FlowFuse announces plans to develop the next version of the Node-RED Dashboard project.</p>
</li>
<li>
<p><a href="https://flowfuse.com/blog/2023/06/node-red-as-a-no-code-ethernet_ip-to-s7-protocol-converter/">Node-RED as a No-Code Ethernet/IP to S7 Protocol Converter</a> - A guide to using Node-RED for converting ethernet IP data to Siemens S7. Also a <a href="https://youtu.be/dteXgcBXUnk">video version</a> of the same content.</p>
</li>
<li>
<p><a href="https://flowfuse.com/blog/2023/06/connect-to-hivemq-in-flowforge/">MQTT and its Role in IoT and Industrial IoT</a> - A practical explainer on the role of MQTT in IoT use cases and how to connect with an MQTT broker in Node-RED.</p>
</li>
<li>
<p>Two new Node-RED Nodes Explained articles</p>
<ul>
<li><a href="https://flowfuse.com/node-red/core-nodes/split/">Nodes explained: Split</a></li>
<li><a href="https://flowfuse.com/node-red/core-nodes/rbe/">Nodes explained: Filter</a></li>
</ul>
</li>
</ul>
<h2 id="from-the-community" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/community-news-07/#from-the-community"># </a> From the Community</h2>
<ul>
<li>
<p><a href="https://youtu.be/1GKkXJOQMhU">Node-RED & Industry 4.0: The Future is Now</a> - An informative panel discussion led by Walker Reynolds on the role of Node-RED in the future of Industry 4.0.</p>
</li>
<li>
<p><a href="http://blog.openmindmap.org/blog/node-red-terminology">Node-RED Terminology</a> - An explanation of the different Node-RED terminology.</p>
</li>
</ul>
<h2 id="join-our-team" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/community-news-07/#join-our-team"># </a> Join Our Team</h2>
<p>FlowFuse is expanding our team. Check out the current openings:</p>
<ul>
<li><a href="https://boards.greenhouse.io/flowfuse/jobs/4911532004">Contract Front-End Engineer – Node-RED Dashboard</a></li>
</ul>
https://flowfuse.com/blog/2023/07/connect-node-red-to-influxdb/Send data from your Node-RED flows into InfluxDBA Guide to Connecting InfluxDB with Node-RED2023-07-11T00:00:00ZRob Marcer<p>InfluxDB is a time series database that is commonly used for storing and analysing IoT data. Node-RED is a visual programming tool that makes it easy to connect different data sources and create flows that automate tasks.</p>
<!--more-->
<p>In this blog article, we will show you how to write data to InfluxDB from a Node-RED flow. We will also provide you with a few tips for writing data to InfluxDB effectively.</p>
<h2 id="step-1%3A-install-the-influxdb-node-red-package" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/connect-node-red-to-influxdb/#step-1%3A-install-the-influxdb-node-red-package"># </a> Step 1: Install the InfluxDB Node-RED package</h2>
<p>The first step is to install the InfluxDB Node-RED package. You can do this by opening the Node-RED editor and clicking on the Manage Palette button. In the search bar, type InfluxDB and select the package called node-red-contrib-influxdb.</p>
<h2 id="step-2%3A-configure-the-influxdb-node" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/connect-node-red-to-influxdb/#step-2%3A-configure-the-influxdb-node"># </a> Step 2: Configure the InfluxDB node</h2>
<p>Once you have installed the InfluxDB node, you need to configure it. Drag an instance of 'influxdb out' onto your canvas and select 'Add new influxdb'. Follow the steps below to configure your connection.</p>
<ul>
<li>Version: The version of InfluxDB you are using (we're using 2.0).</li>
<li>URL: The URL of your InfluxDB server.</li>
<li>Token: Your token to access your InfluxDB database.</li>
</ul>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/config-connection-C6d9qeHiT3-550.avif 550w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/config-connection-C6d9qeHiT3-550.webp 550w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="configuring the influxdb node step 1" alt="configuring the influxdb node step 1" loading="lazy" decoding="async" src="https://flowfuse.com/img/config-connection-C6d9qeHiT3-550.jpeg" width="550" height="357" /></picture></p>
<p>We can now configure the database.</p>
<ul>
<li>Organisation name.</li>
<li>Bucket (database) name.</li>
<li>Measurement (table) name.</li>
</ul>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/config-database-YMPVNV7s2W-522.avif 522w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/config-database-YMPVNV7s2W-522.webp 522w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="configuring the influxdb node step 2" alt="configuring the influxdb node step 2" loading="lazy" decoding="async" src="https://flowfuse.com/img/config-database-YMPVNV7s2W-522.jpeg" width="522" height="416" /></picture></p>
<h2 id="step-3%3A-create-a-data-point" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/connect-node-red-to-influxdb/#step-3%3A-create-a-data-point"># </a> Step 3: Create a data point</h2>
<p>A data point is a single piece of data that is written to InfluxDB. A data point consists of a measurement, a set of fields, and a set of tags.</p>
<p>The measurement is the name of the data that you are writing. We've set it in the configuration of the InfluxDB above so we don't need to pass it in with each payload.</p>
<p>The fields are the individual pieces of data that you are writing. The tags are used to categorise the data.</p>
<p>You can import the flow below into Node-RED to see an example of a payload which will write all the required values to create a data point in InfluxDB:</p>
<div style="position: relative">
<pre class="language-json"><code id="code-77" class="language-json"><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"cb3b0ecc762dbf93"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"4542482476b9c71d"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"repeat"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"once"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"onceDelay"</span><span class="token operator">:</span><span class="token number">0.1</span><span class="token punctuation">,</span><span class="token property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"payload"</span><span class="token operator">:</span><span class="token string">"[{\"time\":1688718546,\"temperature\":24},{\"device\":\"dQBgXeWLRE\",\"deviceType\":\"Pi4\",\"deviceName\":\"demo-pi-rob\"}]"</span><span class="token punctuation">,</span><span class="token property">"payloadType"</span><span class="token operator">:</span><span class="token string">"json"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">450</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">420</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"87166c0dafdeea33"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"87166c0dafdeea33"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"debug"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"4542482476b9c71d"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"debug 31"</span><span class="token punctuation">,</span><span class="token property">"active"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"tosidebar"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"console"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"tostatus"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"complete"</span><span class="token operator">:</span><span class="token string">"true"</span><span class="token punctuation">,</span><span class="token property">"targetType"</span><span class="token operator">:</span><span class="token string">"full"</span><span class="token punctuation">,</span><span class="token property">"statusVal"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"statusType"</span><span class="token operator">:</span><span class="token string">"auto"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">600</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">420</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">]</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-77" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>In this example, the time & temperature fields are hard coded, you will need to overwrite the values stored in <code>payload[0].time</code> & <code>payload[0].temperature</code> with real data if you were to connect this flow to a real IOT thermometer.</p>
<h2 id="step-4%3A-write-the-data-point-to-influxdb" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/connect-node-red-to-influxdb/#step-4%3A-write-the-data-point-to-influxdb"># </a> Step 4: Write the data point to InfluxDB</h2>
<p>Once you have created a data point, you can write it to InfluxDB by using the InfluxDB node.</p>
<ul>
<li>Data: The data point that you want to write.</li>
<li>Options: The configuration options for the InfluxDB node.</li>
</ul>
<p>This is an example valid payload:</p>
<div style="position: relative">
<pre class="language-json"><code id="code-102" class="language-json"><span class="token punctuation">[</span><br /> <span class="token punctuation">{</span><br /> <span class="token property">"time"</span><span class="token operator">:</span> <span class="token number">1688987984</span><span class="token punctuation">,</span><br /> <span class="token property">"temperature"</span><span class="token operator">:</span> <span class="token number">24</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token punctuation">{</span><br /> <span class="token property">"device"</span><span class="token operator">:</span> <span class="token string">"dQBgXeWLRE"</span><span class="token punctuation">,</span><br /> <span class="token property">"deviceType"</span><span class="token operator">:</span> <span class="token string">"Pi4"</span><span class="token punctuation">,</span><br /> <span class="token property">"deviceName"</span><span class="token operator">:</span> <span class="token string">"demo-pi-rob"</span><br /> <span class="token punctuation">}</span><br /><span class="token punctuation">]</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-102" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>You can import a demo, including the demo payload flow using the code below:</p>
<div style="position: relative">
<pre class="language-json"><code id="code-106" class="language-json"><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"ecbb02face30cbcd"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"influxdb out"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"4542482476b9c71d"</span><span class="token punctuation">,</span><span class="token property">"influxdb"</span><span class="token operator">:</span><span class="token string">"1c1a5edef41716e3"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"InfluxDB"</span><span class="token punctuation">,</span><span class="token property">"measurement"</span><span class="token operator">:</span><span class="token string">"temperature"</span><span class="token punctuation">,</span><span class="token property">"precision"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"retentionPolicy"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"database"</span><span class="token operator">:</span><span class="token string">"database"</span><span class="token punctuation">,</span><span class="token property">"precisionV18FluxV20"</span><span class="token operator">:</span><span class="token string">"s"</span><span class="token punctuation">,</span><span class="token property">"retentionPolicyV18Flux"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"org"</span><span class="token operator">:</span><span class="token string">"organisation"</span><span class="token punctuation">,</span><span class="token property">"bucket"</span><span class="token operator">:</span><span class="token string">"my_data"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">360</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">220</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"de83c2b49ba249fd"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"4542482476b9c71d"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"measurement"</span><span class="token punctuation">,</span><span class="token property">"v"</span><span class="token operator">:</span><span class="token string">"temperature"</span><span class="token punctuation">,</span><span class="token property">"vt"</span><span class="token operator">:</span><span class="token string">"str"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"repeat"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"once"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"onceDelay"</span><span class="token operator">:</span><span class="token number">0.1</span><span class="token punctuation">,</span><span class="token property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"payload"</span><span class="token operator">:</span><span class="token string">"[{\"time\":1688987984,\"temperature\":24},{\"device\":\"dQBgXeWLRE\",\"deviceType\":\"Pi4\",\"deviceName\":\"demo-pi-rob\"}]"</span><span class="token punctuation">,</span><span class="token property">"payloadType"</span><span class="token operator">:</span><span class="token string">"json"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">190</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">160</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"aad6353f2f00333e"</span><span class="token punctuation">,</span><span class="token string">"ecbb02face30cbcd"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"aad6353f2f00333e"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"debug"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"4542482476b9c71d"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"debug 31"</span><span class="token punctuation">,</span><span class="token property">"active"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"tosidebar"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"console"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"tostatus"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"complete"</span><span class="token operator">:</span><span class="token string">"true"</span><span class="token punctuation">,</span><span class="token property">"targetType"</span><span class="token operator">:</span><span class="token string">"full"</span><span class="token punctuation">,</span><span class="token property">"statusVal"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"statusType"</span><span class="token operator">:</span><span class="token string">"auto"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">360</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">160</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"1c1a5edef41716e3"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"influxdb"</span><span class="token punctuation">,</span><span class="token property">"hostname"</span><span class="token operator">:</span><span class="token string">"127.0.0.1"</span><span class="token punctuation">,</span><span class="token property">"port"</span><span class="token operator">:</span><span class="token string">"8086"</span><span class="token punctuation">,</span><span class="token property">"protocol"</span><span class="token operator">:</span><span class="token string">"http"</span><span class="token punctuation">,</span><span class="token property">"database"</span><span class="token operator">:</span><span class="token string">"my_data"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"usetls"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"tls"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"influxdbVersion"</span><span class="token operator">:</span><span class="token string">"2.0"</span><span class="token punctuation">,</span><span class="token property">"url"</span><span class="token operator">:</span><span class="token string">"https://localhost"</span><span class="token punctuation">,</span><span class="token property">"rejectUnauthorized"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">}</span><span class="token punctuation">]</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-106" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>Bear in mind that you will need to edit the server and database details in your influxdb node for this demo to work.</p>
<h2 id="step-5%3A-test-your-flow" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/connect-node-red-to-influxdb/#step-5%3A-test-your-flow"># </a> Step 5: Test your flow</h2>
<p>You should now be ready to test your flow is writing data to InfluxDB correctly. There is no output in Node-RED to confirm you data was written, so you will need to check directly on InfluxDB.</p>
<p><picture><source type="image/gif" srcset="https://flowfuse.com/img/data_in_influx-pFGVOWDtEO-650.gif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Checking the data has arrived in InfluxDB" alt="Checking the data has arrived in InfluxDB" loading="lazy" decoding="async" src="https://flowfuse.com/img/data_in_influx-pFGVOWDtEO-650.webp" width="650" height="470" /></picture></p>
<p>Great, our data has arrived correctly and is ready to be used.</p>
<h2 id="5-tips-for-writing-data-to-node-red-from-influxdb-effectively" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/connect-node-red-to-influxdb/#5-tips-for-writing-data-to-node-red-from-influxdb-effectively"># </a> 5 Tips for writing data to Node-RED from InfluxDB effectively</h2>
<ol>
<li>Choose the correct InfluxDB node. There are two InfluxDB nodes available in Node-RED: the 'influxdb out' node and the 'influx batch' node. The influxdb out node writes data to InfluxDB one point at a time, while the influx batch node writes data to InfluxDB in batches. The best node to use depends on the amount of data you are writing and the performance requirements of your application. If you are just getting started with InfluxDB, we suggest starting with influxdb out.</li>
<li>Set the correct measurement name. The measurement name is the name of the table in InfluxDB where the data will be stored. It is important to choose a meaningful measurement name that will help you to easily identify the data later.</li>
<li>Set the correct tags and fields. Tags are used to identify the data points, while fields are used to store the actual data values. It is important to set the correct tags and fields for your data so that you can easily query and analyse it later.</li>
<li>Set the correct timestamp. The timestamp is the time at which the data point was recorded. It is important to set the correct timestamp so that you can track the evolution of your data over time.</li>
<li>Use the correct precision. The precision is the number of decimal places that are stored for each data value. It is important to use the correct precision so that your data is easy to use.</li>
</ol>
<h2 id="conclusion" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/connect-node-red-to-influxdb/#conclusion"># </a> Conclusion</h2>
<p>In this blog article, we showed you how to write data to InfluxDB from a Node-RED flow. We also provided you with a few tips for writing data to InfluxDB effectively. If you'd like to learn more about using InfluxDB with Node-RED, checkout the <a href="https://www.influxdata.com/resources/build-an-edge-to-cloud-solution-with-the-ming-stack/">webinar</a> we created with InfluxData.</p>
https://flowfuse.com/blog/2023/07/flowforge-1-9-release/FlowFuse now offers API Documentation with Swagger UIFlowFuse 1.9 adds new features to make it easier to administer FlowFuse2023-07-06T00:00:00Z<p>FlowFuse 1.9 adds new features to make it easier to administer FlowFuse platform deployments, including new API documentation and the ability to create customized Node-RED palettes.</p>
<!--more-->
<h2 id="api-documentation" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/flowforge-1-9-release/#api-documentation"># </a> API Documentation</h2>
<p>FlowFuse API allows developers to programmatically interact with the FlowFuse platform. This makes it possible to integrate FlowFuse into different infrastructure technologies, create scripts to automate specific FlowFuse tasks and embed FlowFuse into other applications.</p>
<p>In the 1.9 release we are now publishing our <a href="https://flowfuse.com/docs/api/">API documentation</a> using the <a href="https://swagger.io/specification/">OpenAPI specification</a> and making it viewable with the Swagger UI. Both these industrial standards will make using the FlowFuse API easier to use and understand.</p>
<h2 id="customize-node-red-palettes-%232002" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/flowforge-1-9-release/#customize-node-red-palettes-%232002"># </a> Customize Node-RED Palettes <a href="https://github.com/FlowFuse/flowfuse/issues/2002">#2002</a></h2>
<p>FlowFuse platform adminstrators are now able to create customized Node-RED palettes that will be used when a Node-RED instance is created. An adminstator can create pre-defined templates to specify the nodes that should be included in the palette. This makes it easier for FlowFuse teams to standardized on Node-RED usage across an organization.</p>
<p>Note: this feature is not available for FlowFuse cloud users since they do not have administrator access.</p>
<h2 id="new-rbac-role-for-dashboard-users-%232292" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/flowforge-1-9-release/#new-rbac-role-for-dashboard-users-%232292"># </a> New RBAC Role for Dashboard users <a href="https://github.com/FlowFuse/flowfuse/issues/1924">#2292</a></h2>
<p>A new FlowFuse user role has been created to view Node-RED dashboards. This allows for users to view Nod-RED dashboards without access to the Node-RED editor or requiring separate login credentials.</p>
<h2 id="other-new-features" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/flowforge-1-9-release/#other-new-features"># </a> Other New Features</h2>
<ul>
<li>FlowFuse device agent is now supported on Windows <a href="https://github.com/FlowFuse/device-agent/issues/78">#78</a></li>
<li>Allow local configuration of https/httpStatic on a device <a href="https://github.com/FlowFuse/device-agent/issues/110">#110</a></li>
<li>Implementing custom certificate settings for device configuration <a href="https://github.com/FlowFuse/flowfuse/issues/2257">#2257</a></li>
<li>Allow devices to access the "Snapshot ID" and the "Snapshot Name" running on them <a href="https://github.com/FlowFuse/device-agent/issues/94">#94</a></li>
<li>High Availability logging enhanced: Individual Node-RED Instance replica querying and filtering <a href="https://github.com/FlowFuse/flowfuse/issues/2260">#2260</a></li>
<li>High Availability is now generally available <a href="https://github.com/FlowFuse/flowfuse/issues/2412">#2414</a></li>
</ul>
<h2 id="bug-fixes" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/flowforge-1-9-release/#bug-fixes"># </a> Bug Fixes</h2>
<ul>
<li>Can not promote NR instance in DevOps Pipeline <a href="https://github.com/FlowFuse/flowfuse/issues/2363">#2363</a></li>
<li>Billing team menu item missing on first page load <a href="https://github.com/FlowFuse/flowfuse/issues/2398">#2398</a></li>
<li>Duplicate labels in Instance Import dialog <a href="https://github.com/FlowFuse/flowfuse/issues/2200">#2200</a></li>
<li>Broken littie animations <a href="https://github.com/FlowFuse/flowfuse/issues/2354">#2354</a></li>
<li>Instance Logs page doesn't handle errors well <a href="https://github.com/FlowFuse/flowfuse/issues/1083">#1083</a></li>
<li>Device continues to run edited flows once taken out of dev mode <a href="https://github.com/FlowFuse/flowfuse/issues/2323">#2323</a></li>
<li>Device Editor cannot pickup FF theme <a href="https://github.com/FlowFuse/device-agent/issues/89">#89</a></li>
</ul>
<h2 id="community-contributions" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/flowforge-1-9-release/#community-contributions"># </a> Community Contributions</h2>
<p>Thanks to our community members for their contributions to this release.</p>
<ul>
<li>sumitshinde-84 - make Instance and application names in delete popup easily selectable <a href="https://github.com/FlowFuse/flowfuse/pull/2291">#2291</a></li>
<li>biancode - Fixed typo in doc <a href="https://github.com/FlowFuse/flowfuse/pull/2327">#2327</a></li>
</ul>
<h2 id="what's-next%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/flowforge-1-9-release/#what's-next%3F"># </a> What's next?</h2>
<p>We're always working to enhance your experience with FlowFuse. Here's how you can stay informed and contribute:</p>
<ul>
<li><strong>Roadmap Overview</strong>: Check out our <a href="https://flowfuse.com/product/roadmap/">Product Roadmap Page</a> to see what we're planning for future updates.</li>
<li><strong>Entire Roadmap</strong>: Visit our <a href="https://github.com/orgs/FlowFuse/projects/5">Roadmap on GitHub</a> to follow our progress and contribute your ideas.</li>
<li><strong>Feedback</strong>: We're interested in your thoughts about FlowFuse. Your feedback is crucial to us, and we'd love to hear about your experiences with the new features and improvements. Please share your thoughts, suggestions, or report any <a href="https://github.com/FlowFuse/flowfuse/issues/new/choose">issues on GitHub</a>.</li>
</ul>
<p>Together, we can make FlowFuse better with each release!</p>
<h2 id="try-it-out" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/flowforge-1-9-release/#try-it-out"># </a> Try it out</h2>
<p>We're confident you can have self managed FlowFuse running locally in under 30 minutes.
You can install our <a href="https://flowfuse.com/docs/install/local/">local build</a>, use <a href="https://flowfuse.com/docs/install/docker/">Docker</a>, or <a href="https://flowfuse.com/docs/install/kubernetes/">Kubernetes</a>.</p>
<p>If you'd rather use our hosted offering: <a href="https://app.flowfuse.com/account/create">Get started for free</a> on FlowFuse Cloud.</p>
<h2 id="upgrading-flowfuse" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/flowforge-1-9-release/#upgrading-flowfuse"># </a> Upgrading FlowFuse</h2>
<p><a href="https://app.flowfuse.com/">FlowFuse Cloud</a> is already running 1.9.</p>
<p>If you installed a previous version of FlowFuse and want to upgrade, our documentation provides a
guide for <a href="https://flowfuse.com/docs/upgrade/">upgrading your FlowFuse instance</a>.</p>
<h2 id="getting-help" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/07/flowforge-1-9-release/#getting-help"># </a> Getting help</h2>
<p>Please check FlowFuse's <a href="https://flowfuse.com/docs/">documentation</a> as the answers to many questions are covered there. Additionally you can go the the <a href="https://discourse.nodered.org/c/vendors/flowfuse/24">community forum</a> if you have
any feedback or feature requests.</p>
https://flowfuse.com/blog/2023/06/dashboard-announcement/The Next Step in Data Visualization - Announcing the Successor to the Node-RED DashboardFlowFuse's Journey Towards a New Node-RED Dashboard2023-06-21T00:00:00ZJoe PavittMarian Demme<p>For the past several years, the Node-RED Dashboard has been an indispensable tool for many Node-RED users. It has offered a seamless way to create live dashboards, enabling the quick and intuitive creation of user interfaces for Node-RED flows. However, as the saying goes, "all good things must come to an end."</p>
<!--more-->
<p>We at FlowFuse have identified a significant need for a modern, interactive data visualization and dashboard solution. Having evaluated a wide range of options, we've decided to embark on an exciting journey: the creation of what we hope becomes the official successor to the Node-RED Dashboard.</p>
<h2 id="the-problem-at-hand" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/dashboard-announcement/#the-problem-at-hand"># </a> The Problem at Hand</h2>
<p>The original Node-RED Dashboard is based on Angular v1, which is no longer maintained. Although small patches have been and will continue to be applied on a "best can do" basis, there will be no major feature upgrades. The lack of ongoing maintenance and updates has the potential to lead to underlying security breakages, a risk we are not comfortable taking. We have recognized the need to innovate and adapt, which is why we are creating a completely new project to replace the existing Node-RED Dashboard.</p>
<h2 id="the-solution" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/dashboard-announcement/#the-solution"># </a> The Solution</h2>
<p>The successor to the Node-RED Dashboard will be a completely new project, published as a separate package. This new project will take the reins from the old dashboard and guide us into the future with the support and blessing of the existing dashboard maintainers. The Node-RED community can rest assured that the project will stay under the Apache 2.0 licence and keep intact the core principles of open-source and community-driven development.</p>
<h2 id="community-involvement-and-open-source-contribution" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/dashboard-announcement/#community-involvement-and-open-source-contribution"># </a> Community Involvement and Open Source Contribution</h2>
<p>We believe in the power of the community, and we want your feedback. If there are features you'd like to see or improvements you think can be made, we invite you to open a <a href="https://github.com/FlowFuse/node-red-dashboard/issues/new/choose">Github issue</a>. Your insights and suggestions will be invaluable in shaping the future of this project. Contributions from the community are not just welcome, but highly encouraged. We believe that the strength of a project is proportional to the strength of its community.</p>
<p>In our commitment to transparency and collaboration, we will be documenting all major decision-making processes and sharing the details here in our blog as they become available. By working closely with additional Node-RED key figures like Dave Conway-Jones, and by making our development process as open and collaborative as possible, we aim to ensure that the successor to the Node-RED Dashboard lives up to the high standards set by the original, while also introducing innovative features and enhancements.</p>
<h2 id="join-the-team" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/dashboard-announcement/#join-the-team"># </a> Join the Team</h2>
<p>Are you a developer looking for a new challenge? We are searching for a freelancer to help us with the development of the first version of the new dashboard. This is a 2-3 month project that provides an exciting opportunity to contribute to the future of data visualization and Node-RED. If you're interested, <a href="https://boards.greenhouse.io/flowfuse/jobs/4911532004">we'd love to hear from you.</a></p>
<h2 id="charting-the-course" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/dashboard-announcement/#charting-the-course"># </a> Charting the Course</h2>
<p>As we embark on this new journey, we are excited about the potential of the successor to the Node-RED Dashboard. The road ahead will be filled with challenges, but we are confident that with the help of the community, and a dedicated team, we will create a tool that surpasses its predecessor in every way.</p>
<p>Join us on this exciting journey as we innovate, create, and redefine the future of data visualization with the successor to the Node-RED Dashboard.</p>
https://flowfuse.com/blog/2023/06/node-red-as-a-no-code-ethernet_ip-to-s7-protocol-converter/Node-RED as a No-Code Ethernet/IP to S7 Protocol ConverterBeginner tutorial for using Node-RED as free industrial protocol converter2023-06-20T00:00:00Z<p>Frequently in industrial automation, there's a need for two devices that use different protocols to communicate with each other, requiring protocol conversion.<br />
In this tutorial, we present a mock scenario where Node-RED is used to enable an Allen Bradley PLC, which uses ethernet/IP, to communicate with a Siemens PLC, which uses S7, using a no-code solution. This example is geared toward beginners and assumes that the end-user knows how to use PLCs, but may be using FlowFuse or Node-RED for the first time.</p>
<!--more-->
<h2 id="premise" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/node-red-as-a-no-code-ethernet_ip-to-s7-protocol-converter/#premise"># </a> Premise</h2>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/e-to-p-1-mVvCWo0rYL-650.avif 650w, https://flowfuse.com/img/e-to-p-1-mVvCWo0rYL-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/e-to-p-1-mVvCWo0rYL-650.webp 650w, https://flowfuse.com/img/e-to-p-1-mVvCWo0rYL-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/e-to-p-1-mVvCWo0rYL-650.jpeg 650w, https://flowfuse.com/img/e-to-p-1-mVvCWo0rYL-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="FlowFuse Mock production facility" alt="Mock production facility" loading="lazy" decoding="async" src="https://flowfuse.com/img/e-to-p-1-mVvCWo0rYL-650.jpeg" width="1300" height="1077" /></picture></p>
<p>The figure above shows the layout of a mock production facility. Inside this facility, operations suggested adding stack lights as an extra visual aid for operators to get a quick status of its 4 conveyor lines, avoiding the need to constantly monitor the HMI/SCADA displays.<br />
Engineering has suggested adding a siemens S7 1200 PLC with an IO link connection to 4 stacklights, with each line PLC sending basic status information to the stacklight PLC to control the stack light outputs.<br />
Line 1-3 PLCs are Siemens-based, and can communicate with the stacklight PLC natively over S7. But line 4 is an Allen Bradley PLC that uses ethernet/IP, and can't communicate with the stacklight PLC without some form of protocol conversion.<br />
Traditionally, we'd use protocol gateway hardware, like Anybus or Red Lion, to convert ethernet/IP to S7.<br />
But for this application, we will instead use FlowFuse, a pure software-based approach, to convert ethernet/IP to S7. Let's walk through the process.</p>
<h2 id="pre-requisites-and-set-up" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/node-red-as-a-no-code-ethernet_ip-to-s7-protocol-converter/#pre-requisites-and-set-up"># </a> Pre-Requisites and Set Up</h2>
<h3 id="flowfuse" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/node-red-as-a-no-code-ethernet_ip-to-s7-protocol-converter/#flowfuse"># </a> FlowFuse</h3>
<p>In addition to our two PLCs, we’ll be using FlowFuse software to serve our Node-RED instance. You can either self-host, on-premise or in the cloud. Or use the managed service <a href="https://app.flowfuse.com/">FlowFuse Cloud</a>.</p>
<p>In this example, we will be using a self-hosted FlowFuse instance running on <a href="https://flowfuse.com/docs/install/docker/">Docker</a>.</p>
<h3 id="data-treatment-on-ethernet%2Fip-plc" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/node-red-as-a-no-code-ethernet_ip-to-s7-protocol-converter/#data-treatment-on-ethernet%2Fip-plc"># </a> Data Treatment on Ethernet/IP PLC</h3>
<p>In our Allen Bradley line 4 PLC, we will send some arbitrary tags of various datatypes to the stacklight PLC for illustrative purposes, described in table 1 below -</p>
<table>
<thead>
<tr>
<th><strong>Tag</strong></th>
<th><strong>Data Type</strong></th>
<th><strong>Description</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>Conveyor_RTS</td>
<td>BOOL</td>
<td>Conveyor Ready to Start</td>
</tr>
<tr>
<td>Robot_RTS</td>
<td>BOOL</td>
<td>Robot is Ready to Start</td>
</tr>
<tr>
<td>Robot_Position</td>
<td>REAL</td>
<td>Robot Arm position (degrees)</td>
</tr>
<tr>
<td>Conveyor_Running</td>
<td>BOOL</td>
<td>Conveyor is running</td>
</tr>
<tr>
<td>Line4_State</td>
<td>DINT</td>
<td>Line 4 Machine State</td>
</tr>
<tr>
<td>Line4_Fault</td>
<td>BOOL</td>
<td>Line 4 is faulted</td>
</tr>
</tbody>
</table>
<p>Table 1 - Line 4 Tags to be sent to Stacklight PLC</p>
<p>We can send any atomic data type we want, but it must be globally (controller) scoped.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/e-to-p-2-B85UrCEqqF-650.avif 650w, https://flowfuse.com/img/e-to-p-2-B85UrCEqqF-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/e-to-p-2-B85UrCEqqF-650.webp 650w, https://flowfuse.com/img/e-to-p-2-B85UrCEqqF-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/e-to-p-2-B85UrCEqqF-650.jpeg 650w, https://flowfuse.com/img/e-to-p-2-B85UrCEqqF-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="AB Controller Tags" loading="lazy" decoding="async" src="https://flowfuse.com/img/e-to-p-2-B85UrCEqqF-650.jpeg" width="1300" height="613" /></picture></p>
<p>Each tag must also have external read/write access enabled.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/e-to-p-3-S-KK4bZRbG-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/e-to-p-3-S-KK4bZRbG-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="AB Tag Properties" loading="lazy" decoding="async" src="https://flowfuse.com/img/e-to-p-3-S-KK4bZRbG-650.jpeg" width="650" height="800" /></picture></p>
<h3 id="data-treatment-on-s7-plc" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/node-red-as-a-no-code-ethernet_ip-to-s7-protocol-converter/#data-treatment-on-s7-plc"># </a> Data Treatment on S7 PLC</h3>
<p>In the Siemens PLC, we have a DB for the data from the Line 4 PLC to be written to.</p>
<ul>
<li>
<p>In the DBs attributes, “optimized block access” must be disabled.</p>
</li>
<li>
<p>The tags must be writeable and accessible</p>
</li>
<li>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/e-to-p-4-gTapN2Dmcp-650.avif 650w, https://flowfuse.com/img/e-to-p-4-gTapN2Dmcp-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/e-to-p-4-gTapN2Dmcp-650.webp 650w, https://flowfuse.com/img/e-to-p-4-gTapN2Dmcp-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/e-to-p-4-gTapN2Dmcp-650.jpeg 650w, https://flowfuse.com/img/e-to-p-4-gTapN2Dmcp-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Siemens Tag DB Properties" loading="lazy" decoding="async" src="https://flowfuse.com/img/e-to-p-4-gTapN2Dmcp-650.jpeg" width="1300" height="814" /></picture></p>
<p>“No protection” must be set in the CPU properties</p>
</li>
<li>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/e-to-p-5-bHnio1WobD-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/e-to-p-5-bHnio1WobD-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Siemens CPU Properties" loading="lazy" decoding="async" src="https://flowfuse.com/img/e-to-p-5-bHnio1WobD-650.jpeg" width="650" height="730" /></picture></p>
</li>
</ul>
<h2 id="create-the-flow" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/node-red-as-a-no-code-ethernet_ip-to-s7-protocol-converter/#create-the-flow"># </a> Create The Flow</h2>
<p>With both PLCs up and running and properly set up to send/receive remote data, we can now create a flow to act as our protocol converter.</p>
<h3 id="install-custom-nodes" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/node-red-as-a-no-code-ethernet_ip-to-s7-protocol-converter/#install-custom-nodes"># </a> Install Custom Nodes</h3>
<p>First, we need to add two custom nodes that will give node-red the ability to read/write ethernet/IP and S7 data.</p>
<p>Click the hamburger icon → manage pallette</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/e-to-p-6-Yso6QhXb4l-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/e-to-p-6-Yso6QhXb4l-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="FlowFuse Properties" loading="lazy" decoding="async" src="https://flowfuse.com/img/e-to-p-6-Yso6QhXb4l-650.jpeg" width="650" height="1009" /></picture></p>
<p>On the <code>install</code> tab, search for <code>s7</code> and install the <code>node-red-contrib-s7</code> node.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/e-to-p-7-sV8cneyMtr-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/e-to-p-7-sV8cneyMtr-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Install S7 S7 Node" loading="lazy" decoding="async" src="https://flowfuse.com/img/e-to-p-7-sV8cneyMtr-650.jpeg" width="650" height="663" /></picture></p>
<p>Next, search for <code>ethernet</code> and install the <code>node-red-contrib-cip-ethernet-ip</code> node.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/e-to-p-8-pqnVSLL27Y-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/e-to-p-8-pqnVSLL27Y-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Install EthernetIP Node" loading="lazy" decoding="async" src="https://flowfuse.com/img/e-to-p-8-pqnVSLL27Y-650.jpeg" width="650" height="321" /></picture>
Go to the <code>nodes</code> tab and confirm both custom nodes have been properly installed.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/e-to-p-9-QFBNDpXbSp-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/e-to-p-9-QFBNDpXbSp-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Nodes Installed List" loading="lazy" decoding="async" src="https://flowfuse.com/img/e-to-p-9-QFBNDpXbSp-650.jpeg" width="650" height="547" /></picture></p>
<h3 id="set-up-ethernet%2Fip-data" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/node-red-as-a-no-code-ethernet_ip-to-s7-protocol-converter/#set-up-ethernet%2Fip-data"># </a> Set Up Ethernet/IP Data</h3>
<p>Let’s start by dragging a <code>eth-ip in</code> node onto the pallette. Then add a new endpoint, which will point to our Line4 PLC.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/e-to-p-10-UT4daifFRZ-650.avif 650w, https://flowfuse.com/img/e-to-p-10-UT4daifFRZ-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/e-to-p-10-UT4daifFRZ-650.webp 650w, https://flowfuse.com/img/e-to-p-10-UT4daifFRZ-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/e-to-p-10-UT4daifFRZ-650.jpeg 650w, https://flowfuse.com/img/e-to-p-10-UT4daifFRZ-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="eth-ip Setup" loading="lazy" decoding="async" src="https://flowfuse.com/img/e-to-p-10-UT4daifFRZ-650.jpeg" width="1300" height="667" /></picture></p>
<p>In the endpoint <code>connection</code> properties, the connection information must match the PLC, so set the IP address and CPU slot number appropriately. Also, the default cycle time is 500ms. Depending on your application, polling the CPU at 500ms may be appropriate. But being that this is a simple stacklight, 500ms is unnecessarily fast. So we will change it to 1000ms, which is a more appropriate polling rate for this type of application.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/e-to-p-11-UlU_bU60W4-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/e-to-p-11-UlU_bU60W4-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="eth-ip Endpoint Connection" loading="lazy" decoding="async" src="https://flowfuse.com/img/e-to-p-11-UlU_bU60W4-650.jpeg" width="650" height="365" /></picture></p>
<p>On the <code>Tags</code> tab, populate the tag information to match our Allen Bradley PLC. Then select <code>Update</code> to complete configuration of the <code>eth-ip endpoint</code>.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/e-to-p-12-242Kc1telm-650.avif 650w, https://flowfuse.com/img/e-to-p-12-242Kc1telm-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/e-to-p-12-242Kc1telm-650.webp 650w, https://flowfuse.com/img/e-to-p-12-242Kc1telm-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/e-to-p-12-242Kc1telm-650.jpeg 650w, https://flowfuse.com/img/e-to-p-12-242Kc1telm-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="eth-ip Endpoint Tags" loading="lazy" decoding="async" src="https://flowfuse.com/img/e-to-p-12-242Kc1telm-650.jpeg" width="1300" height="468" /></picture></p>
<p>Now that we have our endpoint, let’s finish configuring the <code>eth-ip in</code> node.</p>
<ol>
<li>
<p>select the endpoint we just created</p>
</li>
<li>
<p>select the first tag in the drop-down</p>
</li>
<li>
<p>give the node a descriptive name</p>
</li>
</ol>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/e-to-p-13-v5YoDA9smq-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/e-to-p-13-v5YoDA9smq-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="eth-ip in Node Config" loading="lazy" decoding="async" src="https://flowfuse.com/img/e-to-p-13-v5YoDA9smq-650.jpeg" width="650" height="526" /></picture></p>
<p>Now let’s set up a quick test to confirm our PLC connection is valid by adding a <code>debug</code> node to the <code>eth-ip in</code> node. Then hit <code>deploy</code>.</p>
<ul>
<li>note - you can see we also have a <code>comment</code> above the nodes that describes what is happening. This is optional but good practice to help organize and understand your flow.</li>
</ul>
<p>The output of the debug console did not report any errors so communication appears to be okay.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/e-to-p-14-0DtND9Gl9G-650.avif 650w, https://flowfuse.com/img/e-to-p-14-0DtND9Gl9G-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/e-to-p-14-0DtND9Gl9G-650.webp 650w, https://flowfuse.com/img/e-to-p-14-0DtND9Gl9G-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/e-to-p-14-0DtND9Gl9G-650.jpeg 650w, https://flowfuse.com/img/e-to-p-14-0DtND9Gl9G-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="eth-ip in Debug" loading="lazy" decoding="async" src="https://flowfuse.com/img/e-to-p-14-0DtND9Gl9G-650.jpeg" width="1300" height="311" /></picture></p>
<p>But just to confirm, let’s toggle the value and see if comes through.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/e-to-p-15-lpwdxRuF3e-650.avif 650w, https://flowfuse.com/img/e-to-p-15-lpwdxRuF3e-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/e-to-p-15-lpwdxRuF3e-650.webp 650w, https://flowfuse.com/img/e-to-p-15-lpwdxRuF3e-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/e-to-p-15-lpwdxRuF3e-650.jpeg 650w, https://flowfuse.com/img/e-to-p-15-lpwdxRuF3e-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="eth-ip in Debug Toggle" loading="lazy" decoding="async" src="https://flowfuse.com/img/e-to-p-15-lpwdxRuF3e-650.jpeg" width="1300" height="153" /></picture></p>
<p>So by toggling the value and see the result, here we confirmed 2 things:</p>
<ul>
<li>
<p>We can detect changes in value</p>
</li>
<li>
<p>the <code>eth-ip in</code> node only sends a message when the value changes, also known as Report by Exception.</p>
</li>
</ul>
<p>Because the <code>eth-ip in</code> node implicitly uses report by exception, and the protocol doesn't rely on contiguous data consistency (unlike modbus, for instance), we can receive our data one tag at a time to keep our flow simple.</p>
<p>Now we can remove the debug node and add the additional <code>eth-ip in</code> nodes to receive the remaining tags from our Line 4 PLC.</p>
<p>Here’s how the the flow should look at this point.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/e-to-p-16-l4vLc4wh8V-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/e-to-p-16-l4vLc4wh8V-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Line 4 PLC Nodes" loading="lazy" decoding="async" src="https://flowfuse.com/img/e-to-p-16-l4vLc4wh8V-650.jpeg" width="650" height="1115" /></picture></p>
<h3 id="set-up-s7-data" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/node-red-as-a-no-code-ethernet_ip-to-s7-protocol-converter/#set-up-s7-data"># </a> Set Up S7 Data</h3>
<p>Now we’ll set up the S7 endpoint, using an <code>s7 out</code> node.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/e-to-p-17-LDUD1atLR_-650.avif 650w, https://flowfuse.com/img/e-to-p-17-LDUD1atLR_-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/e-to-p-17-LDUD1atLR_-650.webp 650w, https://flowfuse.com/img/e-to-p-17-LDUD1atLR_-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/e-to-p-17-LDUD1atLR_-650.jpeg 650w, https://flowfuse.com/img/e-to-p-17-LDUD1atLR_-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="s7 out Node on Pallette" loading="lazy" decoding="async" src="https://flowfuse.com/img/e-to-p-17-LDUD1atLR_-650.jpeg" width="1300" height="723" /></picture></p>
<p>Populate the connection properties to match your hardware. The cycle time is updated to 1000ms to match the cycle time of our <code>eth-ip in</code> nodes. You can adjust this value to match your intended application.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/e-to-p-18-RgthciB-S8-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/e-to-p-18-RgthciB-S8-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="S7 endpoint Connection" loading="lazy" decoding="async" src="https://flowfuse.com/img/e-to-p-18-RgthciB-S8-650.jpeg" width="650" height="541" /></picture></p>
<p>On the <code>Variables</code> tab, some special formatting is required to point to the absolute reference of the tag DB location in the S7 PLC.</p>
<p>For information on how to format S7 absolute tag references in a way the <code>s7 endpoint</code> node is expecting, refer to the <a href="https://flows.nodered.org/node/node-red-contrib-s7">node documentation</a> for further information.</p>
<p>For reference, here is an example of how we set the tags in our stacklight PLC example and how it looks in our <code>s7 endpoint</code>.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/e-to-p-19-TFcKvI7Jm2-650.avif 650w, https://flowfuse.com/img/e-to-p-19-TFcKvI7Jm2-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/e-to-p-19-TFcKvI7Jm2-650.webp 650w, https://flowfuse.com/img/e-to-p-19-TFcKvI7Jm2-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/e-to-p-19-TFcKvI7Jm2-650.jpeg 650w, https://flowfuse.com/img/e-to-p-19-TFcKvI7Jm2-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="s7 endpoint Variables" loading="lazy" decoding="async" src="https://flowfuse.com/img/e-to-p-19-TFcKvI7Jm2-650.jpeg" width="1300" height="812" /></picture></p>
<p>Once the tags are populated we can select our configured endpoint from the dropdown list, point to our first variable, <code>Conveyor_RTS</code>, and give the node a name.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/e-to-p-20-4kgUIRd_TZ-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/e-to-p-20-4kgUIRd_TZ-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="S7 out Config" loading="lazy" decoding="async" src="https://flowfuse.com/img/e-to-p-20-4kgUIRd_TZ-650.jpeg" width="650" height="380" /></picture></p>
<p>Repeat this process for the remaining tags.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/e-to-p-21-IaLyrhvyX7-650.avif 650w, https://flowfuse.com/img/e-to-p-21-IaLyrhvyX7-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/e-to-p-21-IaLyrhvyX7-650.webp 650w, https://flowfuse.com/img/e-to-p-21-IaLyrhvyX7-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/e-to-p-21-IaLyrhvyX7-650.jpeg 650w, https://flowfuse.com/img/e-to-p-21-IaLyrhvyX7-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Stacklight PLC Nodes" loading="lazy" decoding="async" src="https://flowfuse.com/img/e-to-p-21-IaLyrhvyX7-650.jpeg" width="1300" height="1103" /></picture></p>
<h2 id="test-the-conversion" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/node-red-as-a-no-code-ethernet_ip-to-s7-protocol-converter/#test-the-conversion"># </a> Test the Conversion</h2>
<p>The only thing remaining is to simply wire the nodes together, and confirm the values pass through.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/e-to-p-22-El6qhMN6fv-650.avif 650w, https://flowfuse.com/img/e-to-p-22-El6qhMN6fv-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/e-to-p-22-El6qhMN6fv-650.webp 650w, https://flowfuse.com/img/e-to-p-22-El6qhMN6fv-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/e-to-p-22-El6qhMN6fv-650.jpeg 650w, https://flowfuse.com/img/e-to-p-22-El6qhMN6fv-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Complete Flow with Live Data" loading="lazy" decoding="async" src="https://flowfuse.com/img/e-to-p-22-El6qhMN6fv-650.jpeg" width="1300" height="541" /></picture></p>
<p>Manipulate the incoming values and confirm the data passes through as expected. Because of the report by exception nature of the <code>eth-ip in</code> node, tag changes should be near instantaneous on the receiving PLC.</p>
<p>We can stop here, but we can improve this flow by adding a <code>filter</code> node on our REAL data-type, <code>Robot_Position</code>.</p>
<h3 id="add-filter-to-real-data" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/node-red-as-a-no-code-ethernet_ip-to-s7-protocol-converter/#add-filter-to-real-data"># </a> Add Filter to REAL data</h3>
<p>Depending on how noisy the REAL data is, which is common with unfiltered 4-20mA field transmitters, and how much granularity you need to capture, it is good practice to add a filter on REAL data to reduce FieldBus traffic coming out of our soft protocol converter.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/e-to-p-23-okXk3CiZ2--650.avif 650w, https://flowfuse.com/img/e-to-p-23-okXk3CiZ2--1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/e-to-p-23-okXk3CiZ2--650.webp 650w, https://flowfuse.com/img/e-to-p-23-okXk3CiZ2--1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/e-to-p-23-okXk3CiZ2--650.jpeg 650w, https://flowfuse.com/img/e-to-p-23-okXk3CiZ2--1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Filter node Configuration" loading="lazy" decoding="async" src="https://flowfuse.com/img/e-to-p-23-okXk3CiZ2--650.jpeg" width="1300" height="566" /></picture></p>
<p>In the example above, we arbitrarily applied a 3% <a href="https://flowfuse.com/node-red/core-nodes/rbe/#deadband-mode">deadband</a>
to the <code>Robot_Position</code> value, which means that the value must change by greater than or equal to 3% compared to the last input value, or else the data will be discarded before being sent to the stacklight PLC.</p>
<p>You can adjust the deadband to find the right balance for your particular application.</p>
<p>We can see the effect the deadband filter had by adding debug nodes before and after the filter.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/e-to-p-24-FmsWDsCm9d-650.avif 650w, https://flowfuse.com/img/e-to-p-24-FmsWDsCm9d-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/e-to-p-24-FmsWDsCm9d-650.webp 650w, https://flowfuse.com/img/e-to-p-24-FmsWDsCm9d-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/e-to-p-24-FmsWDsCm9d-650.jpeg 650w, https://flowfuse.com/img/e-to-p-24-FmsWDsCm9d-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Filter Node Debug" loading="lazy" decoding="async" src="https://flowfuse.com/img/e-to-p-24-FmsWDsCm9d-650.jpeg" width="1300" height="285" /></picture></p>
<p>As shown above, when <code>Robot_Position</code> changed from 15.6 to 15.6999..., the value was captured on the input of the filter, but was discarded on the output.</p>
<p>When the <code>Robot_Position</code> went from 15.6999 to 18, the filter allowed it to pass as it exceeded the deadband limit we had set.</p>
<p>Use filters to optimize your fieldbus converter network performance, especially if dealing with noisy signals or large quantities of REAL datatypes.</p>
<h2 id="conclusion" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/node-red-as-a-no-code-ethernet_ip-to-s7-protocol-converter/#conclusion"># </a> Conclusion</h2>
<p>In this tutorial, we demonstrated how to use Node-RED as a free Ethernet/IP to S7 protocol converter using a simple no-code approach. We showed how to configure PLC tags to be sent remotely using Ethernet/IP, how to configure PLC tags to be received remotely using S7, and how to create the flow to use Node-RED to seamlessly convert incoming PLC data between the two protocols using <code>node-red-contrib-cip-ethernet-ip</code> and <code>node-red-contrib-s7</code> custom nodes. We also took things one step further and added a <code>filter</code> node to optimize FieldBus network traffic by putting a deadband on REAL data being sent to the receiving PLC.</p>
<p>The end result is a simple to set up, free and performant industrial protocol converter that requires minimal PLC configuration, which allows this application to be applied in non-mission critical production systems with minimal, if any downtime. Additionally, the protocol traffic can be visually observed in real-time for easy trouble-shooting and fault analysis by simply accessing the Node-RED UI.</p>
<p>In later tutorials, we can show ways this simple flow can be extended to add additional capabilities not normally available in traditional off-the-shelf protocol gateways. If you found this tutorial helpful, or have any questions or comments, please leave us a comment and let us know your thoughts.</p>
<p>JSON source code for the flow used in this tutorial is provided below -</p>
<div style="position: relative">
<pre class="language-json"><code id="code-385" class="language-json"><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"ad7b17411c8e83aa"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"tab"</span><span class="token punctuation">,</span><span class="token property">"label"</span><span class="token operator">:</span><span class="token string">"Line 4 to Stacklight PLC"</span><span class="token punctuation">,</span><span class="token property">"disabled"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"env"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"c97a4c9bd1981757"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"ad7b17411c8e83aa"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"AB EIP/CIP - Line 4 PLC"</span><span class="token punctuation">,</span><span class="token property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">190</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">140</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"2cc5227ef6a90814"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"eth-ip in"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"ad7b17411c8e83aa"</span><span class="token punctuation">,</span><span class="token property">"endpoint"</span><span class="token operator">:</span><span class="token string">"4ab2910b66e16220"</span><span class="token punctuation">,</span><span class="token property">"mode"</span><span class="token operator">:</span><span class="token string">"single"</span><span class="token punctuation">,</span><span class="token property">"variable"</span><span class="token operator">:</span><span class="token string">"Conveyor_RTS"</span><span class="token punctuation">,</span><span class="token property">"program"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Read Conveyor_RTS"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">200</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">200</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"fe18ef80f9e18c13"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"9308dcbda17274c7"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"comment"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"ad7b17411c8e83aa"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Siemens S7 - Stacklight PLC"</span><span class="token punctuation">,</span><span class="token property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">620</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">140</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"fe18ef80f9e18c13"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"s7 out"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"ad7b17411c8e83aa"</span><span class="token punctuation">,</span><span class="token property">"endpoint"</span><span class="token operator">:</span><span class="token string">"a1bec25858c6f3ef"</span><span class="token punctuation">,</span><span class="token property">"variable"</span><span class="token operator">:</span><span class="token string">"Conveyor_RTS"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Write Conveyor_RTS"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">620</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">200</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"94fe6b73efa1c56b"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"eth-ip in"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"ad7b17411c8e83aa"</span><span class="token punctuation">,</span><span class="token property">"endpoint"</span><span class="token operator">:</span><span class="token string">"4ab2910b66e16220"</span><span class="token punctuation">,</span><span class="token property">"mode"</span><span class="token operator">:</span><span class="token string">"single"</span><span class="token punctuation">,</span><span class="token property">"variable"</span><span class="token operator">:</span><span class="token string">"Robot_RTS"</span><span class="token punctuation">,</span><span class="token property">"program"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Read Robot_RTS"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">180</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">280</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"7774d6ce188c288c"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"7e9564cd59e3d0a2"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"eth-ip in"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"ad7b17411c8e83aa"</span><span class="token punctuation">,</span><span class="token property">"endpoint"</span><span class="token operator">:</span><span class="token string">"4ab2910b66e16220"</span><span class="token punctuation">,</span><span class="token property">"mode"</span><span class="token operator">:</span><span class="token string">"single"</span><span class="token punctuation">,</span><span class="token property">"variable"</span><span class="token operator">:</span><span class="token string">"Robot_Position"</span><span class="token punctuation">,</span><span class="token property">"program"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Read Robot_Position"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">200</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">360</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"832807bfdc4b76f0"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"c0f712b9e355f1f8"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"eth-ip in"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"ad7b17411c8e83aa"</span><span class="token punctuation">,</span><span class="token property">"endpoint"</span><span class="token operator">:</span><span class="token string">"4ab2910b66e16220"</span><span class="token punctuation">,</span><span class="token property">"mode"</span><span class="token operator">:</span><span class="token string">"single"</span><span class="token punctuation">,</span><span class="token property">"variable"</span><span class="token operator">:</span><span class="token string">"Conveyor_Running"</span><span class="token punctuation">,</span><span class="token property">"program"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Read Conveyor_Running"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">210</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">440</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"fbf1b3e38897a9c7"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"db77621e418f1222"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"eth-ip in"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"ad7b17411c8e83aa"</span><span class="token punctuation">,</span><span class="token property">"endpoint"</span><span class="token operator">:</span><span class="token string">"4ab2910b66e16220"</span><span class="token punctuation">,</span><span class="token property">"mode"</span><span class="token operator">:</span><span class="token string">"single"</span><span class="token punctuation">,</span><span class="token property">"variable"</span><span class="token operator">:</span><span class="token string">"Line4_State"</span><span class="token punctuation">,</span><span class="token property">"program"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Read Line4_State"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">190</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">520</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"cdeffd9e52cc4384"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"848af9b76f969dd2"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"eth-ip in"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"ad7b17411c8e83aa"</span><span class="token punctuation">,</span><span class="token property">"endpoint"</span><span class="token operator">:</span><span class="token string">"4ab2910b66e16220"</span><span class="token punctuation">,</span><span class="token property">"mode"</span><span class="token operator">:</span><span class="token string">"single"</span><span class="token punctuation">,</span><span class="token property">"variable"</span><span class="token operator">:</span><span class="token string">"Line4_Fault"</span><span class="token punctuation">,</span><span class="token property">"program"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Read Line4_Fault"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">190</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">600</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"0c595b0ac2550593"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"7774d6ce188c288c"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"s7 out"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"ad7b17411c8e83aa"</span><span class="token punctuation">,</span><span class="token property">"endpoint"</span><span class="token operator">:</span><span class="token string">"a1bec25858c6f3ef"</span><span class="token punctuation">,</span><span class="token property">"variable"</span><span class="token operator">:</span><span class="token string">"Robot_RTS"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Write Robot_RTS"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">610</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">280</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"f1572463c50bb4cb"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"s7 out"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"ad7b17411c8e83aa"</span><span class="token punctuation">,</span><span class="token property">"endpoint"</span><span class="token operator">:</span><span class="token string">"a1bec25858c6f3ef"</span><span class="token punctuation">,</span><span class="token property">"variable"</span><span class="token operator">:</span><span class="token string">"Robot_Position"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Write Robot_Position"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">620</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">360</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"fbf1b3e38897a9c7"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"s7 out"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"ad7b17411c8e83aa"</span><span class="token punctuation">,</span><span class="token property">"endpoint"</span><span class="token operator">:</span><span class="token string">"a1bec25858c6f3ef"</span><span class="token punctuation">,</span><span class="token property">"variable"</span><span class="token operator">:</span><span class="token string">"Conveyor_Running"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Write Conveyor_Running"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">630</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">440</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"cdeffd9e52cc4384"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"s7 out"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"ad7b17411c8e83aa"</span><span class="token punctuation">,</span><span class="token property">"endpoint"</span><span class="token operator">:</span><span class="token string">"a1bec25858c6f3ef"</span><span class="token punctuation">,</span><span class="token property">"variable"</span><span class="token operator">:</span><span class="token string">"Line4_State"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Write Line4_State"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">610</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">520</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"0c595b0ac2550593"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"s7 out"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"ad7b17411c8e83aa"</span><span class="token punctuation">,</span><span class="token property">"endpoint"</span><span class="token operator">:</span><span class="token string">"a1bec25858c6f3ef"</span><span class="token punctuation">,</span><span class="token property">"variable"</span><span class="token operator">:</span><span class="token string">"Line4_Fault"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Write Line4_Fault"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">610</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">600</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"832807bfdc4b76f0"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"rbe"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"ad7b17411c8e83aa"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"func"</span><span class="token operator">:</span><span class="token string">"deadbandEq"</span><span class="token punctuation">,</span><span class="token property">"gap"</span><span class="token operator">:</span><span class="token string">"3%"</span><span class="token punctuation">,</span><span class="token property">"start"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"inout"</span><span class="token operator">:</span><span class="token string">"in"</span><span class="token punctuation">,</span><span class="token property">"septopics"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"property"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"topi"</span><span class="token operator">:</span><span class="token string">"topic"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">420</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">360</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"f1572463c50bb4cb"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"4ab2910b66e16220"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"eth-ip endpoint"</span><span class="token punctuation">,</span><span class="token property">"address"</span><span class="token operator">:</span><span class="token string">"192.168.0.5"</span><span class="token punctuation">,</span><span class="token property">"slot"</span><span class="token operator">:</span><span class="token string">"0"</span><span class="token punctuation">,</span><span class="token property">"cycletime"</span><span class="token operator">:</span><span class="token string">"1000"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Line4"</span><span class="token punctuation">,</span><span class="token property">"vartable"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token property">""</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token property">"Conveyor_RTS"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"BOOL"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token property">"Robot_RTS"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"BOOL"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token property">"Robot_Position"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"REAL"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token property">"Conveyor_Running"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"BOOL"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token property">"Line4_State"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"DINT"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token property">"Line4_Fault"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"BOOL"</span><span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"a1bec25858c6f3ef"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"s7 endpoint"</span><span class="token punctuation">,</span><span class="token property">"transport"</span><span class="token operator">:</span><span class="token string">"iso-on-tcp"</span><span class="token punctuation">,</span><span class="token property">"address"</span><span class="token operator">:</span><span class="token string">"192.168.0.10"</span><span class="token punctuation">,</span><span class="token property">"port"</span><span class="token operator">:</span><span class="token string">"102"</span><span class="token punctuation">,</span><span class="token property">"rack"</span><span class="token operator">:</span><span class="token string">"0"</span><span class="token punctuation">,</span><span class="token property">"slot"</span><span class="token operator">:</span><span class="token string">"1"</span><span class="token punctuation">,</span><span class="token property">"localtsaphi"</span><span class="token operator">:</span><span class="token string">"01"</span><span class="token punctuation">,</span><span class="token property">"localtsaplo"</span><span class="token operator">:</span><span class="token string">"00"</span><span class="token punctuation">,</span><span class="token property">"remotetsaphi"</span><span class="token operator">:</span><span class="token string">"01"</span><span class="token punctuation">,</span><span class="token property">"remotetsaplo"</span><span class="token operator">:</span><span class="token string">"00"</span><span class="token punctuation">,</span><span class="token property">"connmode"</span><span class="token operator">:</span><span class="token string">"rack-slot"</span><span class="token punctuation">,</span><span class="token property">"adapter"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"busaddr"</span><span class="token operator">:</span><span class="token string">"2"</span><span class="token punctuation">,</span><span class="token property">"cycletime"</span><span class="token operator">:</span><span class="token string">"1000"</span><span class="token punctuation">,</span><span class="token property">"timeout"</span><span class="token operator">:</span><span class="token string">"3000"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Stacklight PLC"</span><span class="token punctuation">,</span><span class="token property">"vartable"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"addr"</span><span class="token operator">:</span><span class="token string">"DB1,X0.0"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Conveyor_RTS"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"addr"</span><span class="token operator">:</span><span class="token string">"DB1,X0.1"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Robot_RTS"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"addr"</span><span class="token operator">:</span><span class="token string">"DB1,R2"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Robot_Position"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"addr"</span><span class="token operator">:</span><span class="token string">"DB1,X6.0"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Conveyor_Running"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"addr"</span><span class="token operator">:</span><span class="token string">"DB1,DI8"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Line4_State"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"addr"</span><span class="token operator">:</span><span class="token string">"DB1,X12.0"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Line4_Fault"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">]</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-385" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
https://flowfuse.com/blog/2023/06/connect-to-hivemq-in-flowforge/Connect Node-RED to HiveMQ Cloud an MQTT BrokerA Guide to Connecting HiveMQ with Node-RED2023-06-13T00:00:00ZZJ van de Weg<p>In the world of IIoT (Industrial Internet of Things), effective and efficient communication between devices is crucial. One protocol that has gained significant popularity for its lightweight and scalable nature is MQTT (Message Queuing Telemetry Transport). This post explains what MQTT is, highlight its relevance in IIoT, and walk you through the process of connecting a broker (HiveMQ) with Node-RED in FlowFuse.</p>
<!--more-->
<h2 id="understanding-mqtt" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/connect-to-hivemq-in-flowforge/#understanding-mqtt"># </a> Understanding MQTT</h2>
<p><a href="https://en.wikipedia.org/wiki/MQTT">MQTT</a>, of which development started in 1999, is a publish-subscribe-based messaging protocol designed to enable efficient communication between IoT devices. It operates on top of TCP/IP like for example HTTP, and provids a lightweight approach to messaging. MQTT follows a client-server model, where devices, known as clients, publish messages to a central server called the broker. Other clients, interested in receiving those messages, subscribe to specific topics on the broker.</p>
<h2 id="the-advantages-of-mqtt-in-iiot" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/connect-to-hivemq-in-flowforge/#the-advantages-of-mqtt-in-iiot"># </a> The Advantages of MQTT in IIoT</h2>
<p>There are several reasons why MQTT has become a preferred choice for IoT and industrial IoT applications:</p>
<ol>
<li><strong>Low Overhead</strong>: MQTT uses a small packet size, minimizing bandwidth consumption and reducing network traffic, making it suitable for low-power devices and networks.</li>
<li><strong>Reliability</strong>: MQTT incorporates a Quality of Service (QoS) mechanism that ensures message delivery, making it ideal for applications that require reliable data transmission.</li>
<li><strong>Asynchronous Communication</strong>: MQTT enables asynchronous communication, allowing devices to operate independently, reducing latency and increasing system responsiveness.</li>
</ol>
<h2 id="sending-messages-to-a-mqtt-broker-with-node-red" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/connect-to-hivemq-in-flowforge/#sending-messages-to-a-mqtt-broker-with-node-red"># </a> Sending messages to a MQTT broker with Node-RED</h2>
<p>As broker we'll use a <a href="https://www.hivemq.com/mqtt-cloud-broker/">Cloud MQTT broker</a>
provided by HiveMQ. We'll use FlowFuse to host and manage the Node-RED instance for us. After opening the editor
the MQTT nodes are pre-installed as these are "Core Nodes" in Node-RED.</p>
<p>Drag in the "Inject" node, as well as the "MQTT out" node and connect the Injects output to the MQTT
out node. Now it's time to configure the MQTT node to connect to the broker. On HiveMQ you should generate both a username and password, afterwards copy and paste those to the Node-RED MQTT Server
config pane, along with the server details:</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/node-red-config-mqtt-server-ieXcyJyRvJ-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/node-red-config-mqtt-server-ieXcyJyRvJ-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Configuring a MQTT broker in Node-RED" alt="Configure the MQTT broker in Node-RED" loading="lazy" decoding="async" src="https://flowfuse.com/img/node-red-config-mqtt-server-ieXcyJyRvJ-650.jpeg" width="650" height="433" /></picture></p>
<p>After saving the config, and deploying the changes, the flow should tell display a green
status bubble under the MQTT node which tells you it's connected and configured properly.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/connected-mqtt-node-tbDJJcp5yO-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/connected-mqtt-node-tbDJJcp5yO-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Connected MQTT node in Node-RED" alt="Connected MQTT node in Node-RED"" loading="lazy" decoding="async" src="https://flowfuse.com/img/connected-mqtt-node-tbDJJcp5yO-650.jpeg" width="650" height="110" /></picture></p>
<p>If we than set the Inject node to send a message every say 1 second, the timestamp will be
sent to the broker through MQTT!</p>
<h2 id="receiving-message-from-a-mqtt-broker-with-node-red" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/connect-to-hivemq-in-flowforge/#receiving-message-from-a-mqtt-broker-with-node-red"># </a> Receiving message from a MQTT broker with Node-RED</h2>
<p>Drag in the "mqtt in" node, and connect it to the "Debug" node.
Open the MQTT in node, and select the server configured. Do note that the topic
this node is listening on must match what was previously selected.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/mqtt-in-config-node-red-ts4Syw4xQk-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/mqtt-in-config-node-red-ts4Syw4xQk-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Receiving MQTT messages in Node-RED" alt="Receiving MQTT messages in Node-RED" loading="lazy" decoding="async" src="https://flowfuse.com/img/mqtt-in-config-node-red-ts4Syw4xQk-650.jpeg" width="650" height="442" /></picture></p>
<p>When deployed you should again see the status bubble turn green, and have a
timestamp appear in the sidebar every second!</p>
<h2 id="conclusion" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/connect-to-hivemq-in-flowforge/#conclusion"># </a> Conclusion</h2>
<p>MQTT has emerged as a lightweight and efficient messaging protocol for IIoT applications. Its low overhead, reliability, and asynchronous communication make it an good choice. By following the steps outlined above, you can easily connect MQTT using HiveMQ with Node-RED and leverage the power of MQTT in your applications.</p>
<p>For the sake of simplicity we've sent messages from one Node-RED to another Node-RED.
Sending data from and to a Node-RED is much easier achieved with the FlowFuse
<a href="https://flowfuse.com/docs/user/projectnodes/">Project Nodes</a>.</p>
https://flowfuse.com/blog/2023/06/introducing-the-flowforge-community-forum/Introducing the FlowFuse Community ForumA Community Forum for support, inspiration, and knowledge sharing2023-06-12T12:00:00ZZJ van de Weg<p>We are thrilled to announce the launch of the <a href="https://discourse.nodered.org/c/vendors/flowfuse/24">Community Forum for FlowFuse</a>.
A forum dedicated to empowering developers and enthusiasts to create innovative
applications using FlowFuse, Node-RED and related technologies.</p>
<!--more-->
<p>Our community faces a new set of challenges, for example how to configure FlowFuse templates as administrator, or integration of the FlowFuse platform into another existing environment. These questions do not fit on the Node-RED discourse which is why FlowFuse now sports our own Community Forum. Furthermore, it’s the intent to keep the Node-RED forums vendor agnostic by the OpenJS foundation. Given FlowFuse is a vendor, it’s a fine balance to find. We hope and intend to be additive to the Node-RED community at large.</p>
<p>At FlowFuse, our vision is to create a thriving community of Node-RED and MQTT enthusiasts who are passionate about building real-world solutions. We believe in the power of collaboration, knowledge sharing, and problem-solving. With this in mind, FlowFuse aims to foster a positive and inclusive environment where members can engage in discussions, exchange ideas, and support one another.</p>
<p>Initially the forum is used to allow for discussions under each blog post on the FlowFuse blog, as well as a venue to provide community support. We also welcome discussions on the roadmap and backlog of FlowFuse. We have hopes that this community thrives and provides guidance, inspiration and opportunity to learn.</p>
https://flowfuse.com/blog/2023/06/community-news-06/Community News June 2023Your monthly update for the FlowFuse and Node-RED communities2023-06-09T00:00:00Z<p>Welcome to the FlowFuse newsletter for June 2023, a monthly roundup of what’s been happening with both FlowFuse and the wider Node-RED community.</p>
<!--more-->
<h2 id="new-release" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/community-news-06/#new-release"># </a> New Release</h2>
<p>This week we released FlowFuse 1.8, featuring high availability for Node-RED and DevOps software delivery pipelines. Both these features were in high demand from our community and will make it easier to reliably deliver Node-RED for business critical applications.</p>
<p>Read about the details of FlowFuse 1.8 in our <a href="https://flowfuse.com/blog/2023/06/flowforge-1-8-released/">release announcement</a>.</p>
<h2 id="upcoming-events" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/community-news-06/#upcoming-events"># </a> Upcoming events</h2>
<h3 id="building-node-red-applications-for-scalability-and-high-availability" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/community-news-06/#building-node-red-applications-for-scalability-and-high-availability"># </a> Building Node-RED Applications for Scalability and High Availability</h3>
<p>Our June webinar will focus on the new FlowFuse 1.8 feature of running high availability Node-RED applications. Marian Demme, FlowFuse Product Manager, will lead this session and share practical insights and best practices to show how FlowFuse can unlock the true potential of Node-RED in large-scale deployments.</p>
<p><a href="https://flowfuse.com/webinars/2023/building-scalable-ha-node-red/">Sign-up today</a> to join us on June 22.</p>
<h3 id="build-an-edge-to-cloud-solution-with-the-ming-stack" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/community-news-06/#build-an-edge-to-cloud-solution-with-the-ming-stack"># </a> Build an Edge-to-Cloud Solution with the MING Stack</h3>
<p>On June 27, FlowFuse is doing a webinar with our friends at InfluxDB. A great opportunity to see how easy it is to use Node-RED and InfluxDB to send data from the edge to the cloud. <a href="https://www.influxdata.com/resources/build-an-edge-to-cloud-solution-with-the-ming-stack/?utm_source=partner&utm_medium=referral&utm_campaign=2023-06-27_Webinar_FlowFuse-NodeRED&utm_term=speaker">Sign-up today</a>.</p>
<h2 id="from-our-blog" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/community-news-06/#from-our-blog"># </a> From our Blog</h2>
<ul>
<li>
<p><a href="https://flowfuse.com/blog/2023/05/bringing-high-availability-to-node-red/">Bringing High Availability to Node-RED</a> - FlowFuse CTO discusses the strategy for delivering high availability in the FlowFuse platform.</p>
</li>
<li>
<p>Two articles featuring how to connect Modbus data with Node-RED:</p>
<ul>
<li><a href="https://flowfuse.com/blog/2023/05/visualize-production-data-via-modbus-in-node-red/">Using Node-RED to Visualize Industrial Production Data via Modbus</a></li>
<li>[Best Practices Integrating a Modbus Device With Node-RED](/blog/2023/05/integrating modbus with node-red/)</li>
</ul>
</li>
<li>
<p><a href="https://flowfuse.com/blog/2023/06/3-quick-node-red-tips-7/">Node-RED Tips - Dashboard Edition</a> - A new set of Node-RED quick tips that are focused on using Node-RED Dashboard.</p>
</li>
<li>
<p><a href="https://flowfuse.com/blog/2023/05/persisting-chart-data-in-node-red/">Persisting chart data in Node-RED Dashboards</a> - How to store data from the Node-RED Dasbhaord chart node.</p>
</li>
<li>
<p><a href="https://flowfuse.com/blog/2023/05/node-red-community-survey-results/">Node-RED Community Survey Results</a> - A quick summary of the Node-RED Community Survey results.</p>
</li>
<li>
<p><a href="https://flowfuse.com/blog/2023/05/flowforge-1-7-released/">FlowFuse 1.7 Now Available with Remote Node-RED Editor Access</a></p>
</li>
</ul>
<h2 id="from-the-community" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/community-news-06/#from-the-community"># </a> From the Community</h2>
<p>Gerrit Riessen has published a list of <a href="https://gorenje.medium.com/fourteen-for-fourteen-against-why-i-love-hate-and-connect-with-node-23797f9466ec">Pros and Cons for using Node-RED</a>. It is a pretty comprehensive list so check it out. FlowFuse is working to address some of the cons in Gerrit's list, specifically software delivery pipelines and the ability to deploy out to many end points.</p>
<h2 id="join-our-team" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/community-news-06/#join-our-team"># </a> Join Our Team</h2>
<p>FlowFuse is expanding our team. Check out the current openings:</p>
<ul>
<li>
<p><a href="https://boards.greenhouse.io/flowfuse/jobs/4796271004">DevOps Engineer</a></p>
</li>
<li>
<p><a href="https://boards.greenhouse.io/flowfuse/jobs/4843566004">Sales Representative</a></p>
</li>
</ul>
https://flowfuse.com/blog/2023/06/flowforge-1-8-released/FlowFuse now offers High Availability Node-REDFlowFuse 1.8 makes Node-RED applications more reliable and scalable, plus more streamline deployment pipelines.2023-06-08T00:00:00ZMarian Demme<p>FlowFuse 1.8 introduces two key features that allow organizations to reliably deploy Node-RED applications into production. In 1.8, it is now possible to run Node-RED applications with high availability so the application is more scalable and more fault tolerant. FlowFuse 1.8 also introduces software deliver pipelines, so development teams can now set up dev/test/production environments for their Node-RED applications.</p>
<!--more-->
<h2 id="more-reliable-and-scalable-node-red-applications" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/flowforge-1-8-released/#more-reliable-and-scalable-node-red-applications"># </a> More reliable and scalable Node-RED applications</h2>
<p>FlowFuse now makes it possible to deploy business critical applications built in Node-RED that are reliable and scalable. The new 1.8 features allows a Node-RED instance to be deployed in high availability mode, meaning two instances of the same Node-RED flows are available behind a load balancer. This allows for increased traffic to be automatically distributed across the two Node-RED instances. This means your Node-RED applications can handle more traffic and experience less downtime. For more details, please see our <a href="https://flowfuse.com/docs/user/high-availability">documentation</a>.</p>
<p>Additionally, we're pleased to offer a 30-day premium trial license for self-managed installs on Kubernetes. To avail of this offer, book a demo at <a href="https://flowfuse.com/book-demo">flowforge.com/book-demo</a>.</p>
<p>High Availability is our first <a href="https://flowfuse.com/handbook/product/versioning/#preview-features">preview feature</a>, and your feedback is crucial. We encourage you to try out HA in your Node-RED instances and share your experiences with us. Your feedback will help us refine this feature and make it even better.</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/mbDkjKhVwIw" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
<h2 id="devops-pipelines" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/flowforge-1-8-released/#devops-pipelines"># </a> DevOps Pipelines</h2>
<p>FlowFuse 1.8 introduces the concept of Pipelines to better organize your Node-RED development. Development team can now set up different staging environments for different steps in the development cycle, ex. test, development and production. Node-RED instances can be pushed along a pipeline as they move along the development process. This allows for a better organized and predictable development process for your team.</p>
<p>The new Pipelines feature builds upon the Staged Development support that we introduced in<a href="https://flowfuse.com/blog/2023/02/flowforge-1-4-0-released">FlowFuse Version 1.4</a>. We highly recommend that development teams avoid developing their flows directly in production instances. This approach fosters a more reliable and robust development process, reducing the risks associated with production environment modifications. Instead, start your development in a dedicated development or test instance and then deploy your Node-RED instance to production once they have been thoroughly tested and reviewed.</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/Pbql22f3vqY" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
<h2 id="user-interface-for-device-agent" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/flowforge-1-8-released/#user-interface-for-device-agent"># </a> User interface for Device Agent</h2>
<p>In our previous release, we introduced <a href="https://flowfuse.com/blog/2023/05/flowforge-1-7-released">Editor Access for Devices</a>. Now, the FlowFuse Device Agent now comes with its very own User Interface (UI) for configuration.</p>
<p>Imagine this: Your industrial equipment arrives with the Device Agent preinstalled. In the past, you might have faced challenges in configuring and connecting your device with FlowFuse, particularly if you had no direct shell access. But not any more.</p>
<p>With the newly introduced UI, you can easily set up and connect your device with FlowFuse without needing to access the command line interface directly. This simplifies the process significantly and saves you time. For more details, see our <a href="https://flowfuse.com/docs/user/devices/">documentation</a>.</p>
<h2 id="node-red-3.1-beta-3-available" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/flowforge-1-8-released/#node-red-3.1-beta-3-available"># </a> Node-RED 3.1 Beta 3 Available</h2>
<p>FlowFuse Cloud is a great place to try out the new Node-RED features, with FlowFuse Cloud now including the <a href="https://discourse.nodered.org/t/node-red-3-1-0-beta-3-released/78716">Node-RED 3.1.0-beta.3</a>. If you want to try this version you can <a href="https://flowfuse.com/docs/user/instance-settings/">duplicate your instance</a> and <a href="https://flowfuse.com/docs/user/changestack/">upgrade your stack</a>.</p>
<h2 id="ongoing-topics" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/flowforge-1-8-released/#ongoing-topics"># </a> Ongoing Topics</h2>
<h3 id="soc2-certification" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/flowforge-1-8-released/#soc2-certification"># </a> SOC2 Certification</h3>
<p>We're making great strides on our journey towards SOC2 certification, striving to meet the highest industry standards for security and privacy. While we're not quite ready to disclose specific milestones, be assured that everything is progressing smoothly. As we continue working diligently towards our target, we promise to keep you informed every step of the way. Our unwavering commitment to deliver secure and private services to our customers and partners remains our foremost priority. Stay tuned for more updates!</p>
<h2 id="what's-next%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/flowforge-1-8-released/#what's-next%3F"># </a> What's next?</h2>
<p>We're always working to enhance your experience with FlowFuse. Here's how you can stay informed and contribute:</p>
<ul>
<li><strong>Roadmap Overview</strong>: Check out our <a href="https://flowfuse.com/product/roadmap/">Product Roadmap Page</a> to see what we're planning for future updates.</li>
<li><strong>Entire Roadmap</strong>: Visit our <a href="https://github.com/orgs/FlowFuse/projects/5">Roadmap on GitHub</a> to follow our progress and contribute your ideas.</li>
<li><strong>Feedback</strong>: We're interested in your thoughts about FlowFuse. Your feedback is crucial to us, and we'd love to hear about your experiences with the new features and improvements. Please share your thoughts, suggestions, or report any <a href="https://github.com/FlowFuse/flowfuse/issues/new/choose">issues on GitHub</a>.</li>
</ul>
<p>Together, we can make FlowFuse better with each release!</p>
<h2 id="bug-fixes" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/flowforge-1-8-released/#bug-fixes"># </a> Bug Fixes</h2>
<p>When editing a device in developer mode via the tunnel/proxy connection, a list of team projects are not presented in the "Target" field of the project-link nodes. <a href="https://github.com/FlowFuse/flowfuse/issues/2228">#2228</a></p>
<p>If a user invites an external user to their team with an sso-enable email domain, when that user registers and logs in, they are not added to the team they were invited to and must be re-invited. <a href="https://github.com/FlowFuse/flowfuse/issues/2232">#2232</a></p>
<p>No warning given if tying to start device editor when NR is not running <a href="https://github.com/FlowFuse/flowfuse/issues/2233">#2233</a></p>
<p>Stuck on the form Create a new Application & Instance after using an already known instance name <a href="https://github.com/FlowFuse/flowfuse/issues/2221">#2221</a></p>
<p>If the device agent finds itself in Developer mode, it stops pulling snapshots from the platform <a href="https://github.com/FlowFuse/device-agent/issues/97">#97</a></p>
<p>Accessing the Admin Settings General page resets the Platform Statstics token <a href="https://github.com/FlowFuse/flowfuse/issues/2140">#2140</a></p>
<p>Selection of Team and Instance in nr-tools-plugin not possible <a href="https://github.com/FlowFuse/nr-tools-plugin/issues/15">#15</a></p>
<p>HOME env var not set within Node-RED process <a href="https://github.com/FlowFuse/flowforge-nr-launcher/issues/117">#117</a></p>
<h2 id="try-it-out" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/flowforge-1-8-released/#try-it-out"># </a> Try it out</h2>
<p>We're confident you can have self managed FlowFuse running locally in under 30 minutes.
You can install our <a href="https://flowfuse.com/docs/install/local/">local build</a>, use <a href="https://flowfuse.com/docs/install/docker/">Docker</a>, or <a href="https://flowfuse.com/docs/install/kubernetes/">Kubernetes</a>.</p>
<p>If you'd rather use our hosted offering: <a href="https://app.flowfuse.com/account/create">Get started for free</a> on FlowFuse Cloud.</p>
<h2 id="upgrading-flowfuse" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/flowforge-1-8-released/#upgrading-flowfuse"># </a> Upgrading FlowFuse</h2>
<p><a href="https://app.flowfuse.com/">FlowFuse Cloud</a> is already running 1.8.</p>
<p>If you installed a previous version of FlowFuse and want to upgrade, our documentation provides a
guide for <a href="https://flowfuse.com/docs/upgrade/">upgrading your FlowFuse instance</a>.</p>
<h2 id="getting-help" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/flowforge-1-8-released/#getting-help"># </a> Getting help</h2>
<p>Please check FlowFuse's <a href="https://flowfuse.com/docs/">documentation</a> as the answers to many questions are covered there. Additionally you can go the the <a href="https://discourse.nodered.org/c/vendors/flowfuse/24">community forum</a> if you have
any feedback or feature requests.</p>
https://flowfuse.com/blog/2023/06/import-modules/Use any npm module in Node-REDSee how you can easily import any npm module, for use in a Node-RED function node.2023-06-05T00:00:00ZJoe PavittSteve McLaughlin<p>Node-RED has <a href="https://flows.nodered.org/search?type=node" target="_blank">an incredibly rich resource of integrations available</a>, but sometimes you need that little bit of extra functionality, or access to a Node.js module that doesn't have it's own custom nodes in Node-RED. <strong>We can easily import any npm module within the built-in Node-RED function nodes.</strong></p>
<!--more-->
<p>Historically in Node-RED, you would have needed to manually <code>npm install</code> modules from the command line, but now that it's so easy to run Node-RED in the Cloud, where you don't have easy access to those tools, what are the other options available?</p>
<h2 id="function-node---setup" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/import-modules/#function-node---setup"># </a> Function Node - Setup</h2>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/npmimport-add--dD1VwKW6h-650.avif 650w, https://flowfuse.com/img/npmimport-add--dD1VwKW6h-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/npmimport-add--dD1VwKW6h-650.webp 650w, https://flowfuse.com/img/npmimport-add--dD1VwKW6h-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/npmimport-add--dD1VwKW6h-650.jpeg 650w, https://flowfuse.com/img/npmimport-add--dD1VwKW6h-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Location of the 'add' button in order to import an npm module intoa function node" alt="Location of the "add" button in order to import an npm module intoa function node" loading="lazy" decoding="async" src="https://flowfuse.com/img/npmimport-add--dD1VwKW6h-650.jpeg" width="1300" height="753" /></picture></p>
<p>All you need is the name of the module you want to import, then:</p>
<ol>
<li>Drop in a new "function" node & double-click it</li>
<li>Switch to the "Setup" tab</li>
<li>Underneath the "modules" tab, click "+ add" in the bottom-left of the window.</li>
<li>Enter the name of the module you want to use in the newly created row, and (optionally) modify the <code>variable</code> that this module will be imported in as.</li>
<li>Switch back to the "On Message" tab and write your function. Your new module will be available via the <code>variable</code> you defined in the "Setup" tab.</li>
</ol>
<h2 id="example%3A-moment.js" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/import-modules/#example%3A-moment.js"># </a> Example: Moment.js</h2>
<video width="560" height="315" controls="">
<source src="https://website-data.s3.eu-west-1.amazonaws.com/MomentJS+Demo.mp4" type="video/mp4" />
</video>
<p>Recently we wanted to use <a href="https://www.npmjs.com/package/moment">moment</a> for some custom date calculations. Whilst there was set of <a href="https://flows.nodered.org/node/node-red-contrib-moment">Moment Node-RED nodes</a> already available, it didn't have all of the functionality we needed.</p>
<p>So, all we needed to do was import the module into a function node, and define our comparison there instead, here's a working example:</p>
<h2 id="example%3A-easy-crc" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/import-modules/#example%3A-easy-crc"># </a> Example: Easy CRC</h2>
<video width="560" height="315" controls="">
<source src="https://website-data.s3.eu-west-1.amazonaws.com/Easy+CRC+Demo.mp4" type="video/mp4" />
</video>
<p>Something we see <a href="https://discourse.nodered.org/search?q=crc%20order%3Alatest">a lot on the Node-RED Forums</a> are questions on how to conduct CRC calculations. There is a popular node module <code>easy-crc</code> that can be imported and used in the function nodes, e.g:</p>
<h2 id="example%3A-posthog" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/import-modules/#example%3A-posthog"># </a> Example: PostHog</h2>
<video width="560" height="315" controls="">
<source src="https://website-data.s3.eu-west-1.amazonaws.com/PostHog+Node+Demo.mp4" type="video/mp4" />
</video>
<p>Node-RED is great for <a href="https://flowfuse.com/solutions/data-integration/">data integration</a>. We use <a href="https://posthog.com/" target="_blank">PostHog</a> for our internal Product Analysis. We record live events as they occur on FlowFuse Cloud to better understand features that are (and are not) used.</p>
<p>We wanted to investigate whether or not we could add backdated data, which in theory was possible via their <a href="https://posthog.com/docs/libraries/node" target="_blank">posthog-node</a> module. We wanted to populate it with data driven from our own database and API.</p>
<p>Within two minutes, we could wire up a node to retrieve data from our API, and then ingest it into <code>posthog-node</code> via the import of a function node.</p>
https://flowfuse.com/blog/2023/05/bringing-high-availability-to-node-red/Bringing High Availability to Node-REDHow we are tackling the hard problems of HA in FlowFuse2023-06-02T12:00:00ZNick O'Leary<p>Many companies look to deploy Node-RED into use cases that require the application
to have a high degree of availability, reliability, and scalability. Following up
our <a href="https://flowfuse.com/blog/2023/02/highly-available-node-red/">previous post on the subject</a>, in this
post I’m going to look at some of the technical details of achieving HA, the
approaches available and what that means for the work we’re doing at FlowFuse
and upstream in Node-RED.</p>
<!--more-->
<p>Everyone we speak to has a different set of requirements for this topic. To help
with the discussion, I’m going to look at two ways of approaching it:</p>
<ul>
<li>The <strong>hot-spare approach</strong> where you have a second instance of the application
ready to take over when the primary fails. This achieves availability but
doesn’t contribute to scalability.</li>
<li>The <strong>load-balanced approach</strong> where you have a second active instance of the
application and work is shared between them. If either fails, the other
continues running. A side-effect of this approach is a higher potential
through-put and scalability; although in practice you need to ensure capacity
to tolerate an instance failing.</li>
</ul>
<p>To consider which approach is most appropriate in the context of Node-RED, we
need to look at the benefits and complications of each approach. It comes down
to two factors; statefulness and how work is routed.</p>
<h3 id="statefulness" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/bringing-high-availability-to-node-red/#statefulness"># </a> Statefulness</h3>
<p>There are two types of state to consider when thinking about a Node-RED flow:
<strong>explicit</strong> and <strong>implicit</strong> state.</p>
<p>Explicit state is what is programmed into the flow. For example, a flow may store
state in Context or use an external database service. Within FlowFuse we provide
two types of context - the default in-memory context store and a database-backed
persistent store. Currently the database-backed store includes a memory-caching
layer to provide better performance and interoperability. That gets tricky when
you want to have multiple instances sharing the same store. The context API
doesn’t provide a way to atomically update values - so you can get into classic
concurrency issues around two applications trying to update the same value.</p>
<p>The other type of state is that which is implicitly maintained in a flow - even
if the user hasn’t explicitly configured it. For example, the Smooth node can be
used to calculate a running average value of messages passing through it. The
node does that by keeping in memory the recent values so it can recalculate the
average with each update. If you have multiple instances, then the node will be
calculating the average for just the message its instances sees.</p>
<p>Another example of implicit state is the Batch node that can be used to group
messages into batches. Again - it will only be able to do that for the selection
of messages the instance receives.</p>
<p>It very much depends on the requirements of a flow and what nodes it uses, as to
how the state can be handled.</p>
<p>In the hot-spare approach, as only one instance is active at any time, a lot of
the explicit state handling will work as expected. However the implicit state
remains bound to the individual Node-RED instances.</p>
<p>In the load-balanced approach, care has to be taken to ensure any state generated
by the flow is done in a way that copes with multiple instances accessing it at
the same time.</p>
<p>A key take-away from this being that a flow has to be created with HA and/or scaling
in mind.</p>
<h3 id="routing-work" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/bringing-high-availability-to-node-red/#routing-work"># </a> Routing work</h3>
<p>Node-RED makes it easy to integrate with lots of different sources of events.
A couple of the most common being HTTP and MQTT. When considering how to handle
multiple instances of an application we need to think about how work is routed
to those instances.</p>
<p>HTTP is the most well understood; you put a load-balancing proxy in front of the
Node-RED instances and it takes care of sharing out the incoming requests. In
the hot-spare scenario, the proxy needs to know which instance is active - that
requires some coordination within the platform to track that properly.</p>
<p>MQTT is commonly used with Node-RED, but unlike HTTP which is in-bound, MQTT
works by having Node-RED create an out-bound connection to a broker and then
subscribing to the topics of interest. In the early days of MQTT that would mean
each instance would subscribe to the same set of topics and receive every message.
That doesn’t really fit any HA model.</p>
<p>With the publication of MQTTv5, the concept of Shared Subscriptions was added;
the ability for a group of clients to connect, subscribe to the same topic and
have the broker distribute messages between them. At this point you do get load
balancing across your Node-RED instances - as long as the MQTT nodes are suitably
configured.</p>
<p>There are lots of other nodes that can be used to trigger flows, whether by
listening for events on an API, connecting to locally attached hardware and many
things in between. Typically, those that are more cloud-aligned, such as messaging
systems like Kafka and AMQP will have very well established ways of doing load
balancing.</p>
<p>Managing out-bound connections gets more complicated in the hot-spare scenario.</p>
<p>If we only had to deal with in-bound connections, the hot-spare instance can just
sit there waiting for work to be passed its way. But once you have out-bound
connections, then you have a problem. The hot-spare instance should only create
its out-bound connections when it becomes the active instance. In real terms,
that means the Node-RED flows should only be started when the instance becomes
active.</p>
<p>With our goal to minimize the Mean Time To Recovery (MTTR), we need to find a
way to get that spare instance running as quickly as possible; if it takes just
as long to start the spare instance as it does to restart the failed primary
instance, then it isn’t much of an improvement.</p>
<p>The key here is that Node-RED allows you to start the runtime without the flows
running. That gets everything loaded and the runtime ready ahead of time. It can
then start the flows at a moment's notice with a simple call to the runtime admin
API.</p>
<h3 id="detecting-failure" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/bringing-high-availability-to-node-red/#detecting-failure"># </a> Detecting failure</h3>
<p>A key requirement of the hot-spare approach to HA is knowing when to failover to
the spare.</p>
<p>This requires close monitoring of the active instance to know whether it's still
working. How quickly you can detect failure is key to reducing the time to recovery.
This is where you have to think about the different ways an instance could fail -
has it crashed, has it hung, has it got ‘stuck’?</p>
<p>Detecting failure usually involves some combination of heartbeat ‘pings’ between
the instances to check each is able to respond to requests. The spare instance
then needs to be able to decide for itself whether it should become the active
instance - and do so safely. You do not want to accidentally have two instances
active at the same time. This can get quite complicated to achieve safely, but
there are a number of approaches that can be used. We’ll be exploring them as we
continue our journey towards HA.</p>
<h3 id="editing-flows" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/bringing-high-availability-to-node-red/#editing-flows"># </a> Editing Flows</h3>
<p>Within the Node-RED architecture, each instance also serves up its own editor.
This is what you get when you point your web browser at it.</p>
<p>In a HA world, once you have multiple instances running behind an HTTP load
balancer, there is a tricky question of how you edit the flows. If each request
hits a different instance, just loading the editor will result in different bits
coming from different instances. That can typically be solved at the load balancer
level by creating sticky-sessions; ensuring for a given client, each request is
routed to a consistent instance. That solves part of the issue, but the next
challenge is what to do when the Deploy button is pressed. That is how new flows
are passed from the editor to the runtime. When you have multiple instances, we
need to make sure that they all get updated. That is quite a tricky problem to
solve with the current Node-RED APIs - and something we’ll be working on both in
FlowFuse and in the upstream Node-RED project to resolve.</p>
<p>That said, a more immediate solution could well be to take advantage of separate
development/production instances. You develop in a single instance and, when happy
with what you’ve got, roll it out to your HA-ready production instance. This
bypasses the need to edit the flows in the HA environment at all.</p>
<p>Whichever method is used, there is a question of how you minimize downtime whilst
deploying an update. In a purely in-bound environment, solutions can be built
where the new application is deployed alongside the old version and, when everything
is ready, the in-bound events are redirected to the new version. But that isn’t
feasible when you have out-bound connections to deal with as well. For some users,
having a scheduled maintenance window for doing updates will be completely acceptable.</p>
<p>As with the hot-spare approach to failover, a similar method could be used that
starts new instances of Node-RED alongside the old, but with the flows all stopped.
Then, once everything is ready, the old instances are stopped and the new instances
started - minimizing the downtime, although not completely removing it.</p>
<h3 id="continuing-the-ha-journey-at-flowfuse" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/bringing-high-availability-to-node-red/#continuing-the-ha-journey-at-flowfuse"># </a> Continuing the HA journey at FlowFuse</h3>
<p>So the question is how are we going to apply all of this to what we’re building
at FlowFuse. We cannot do everything at once, so we have to prioritize which
scenarios we’re going to address first. Consequently, drawing from customer
feedback, we have chosen to start with the scaling side of high availability -
allowing multiple copies of an instance to be run with appropriate load
balancing put in front of it.</p>
<p>We are building FlowFuse as an open platform with the ability to run on top of
Docker Compose and Kubernetes. As we get into some of these HA features, we will
need to look carefully at where we can lean on these underlying technologies -
we don’t want to reinvent the wheel here.</p>
<p>Our initial focus is going to be when running in a Kubernetes environment - just
as we do with our hosted FlowFuse Cloud platform. Kubernetes provides lots of
the building blocks for creating a scalable and highly available solution, but
it certainly doesn’t do all of the work for you.</p>
<p>We've identified our initial set of tasks and changes to how we'll run Node-RED
instance with the k8s environment. You can follow our progress with this
<a href="https://github.com/FlowFuse/flowfuse/issues/2156">issue</a> on our backlog.</p>
<p>I hope this post has given some useful insight into the problems we’re looking
to solve at FlowFuse. As it's such an important requirement for many users we’ll
keep you updated as we make progress.</p>
https://flowfuse.com/blog/2023/06/3-quick-node-red-tips-7/Node-RED Tips - Dashboard EditionSave yourself time when working with Node-RED Dashboards with these three tips.2023-06-01T12:00:00ZRob Marcer<p>There is usually more than one way to complete a given task in software, and Node-RED is no exception. In each of this series of blog posts, we are going to share three useful tips to save yourself time when working on your flows.</p>
<!--more-->
<p>In this Node-RED Tips article, we are going to focus on <a href="https://flows.nodered.org/node/node-red-dashboard">Node-RED Dashboard</a>. Dashboard is a great tool for creating HMI (Human Machine Interfaces), it's also the most popular custom node for Node-RED with thousands of downloads per week.</p>
<h3 id="1.-responsive-layouts-(almost)" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/3-quick-node-red-tips-7/#1.-responsive-layouts-(almost)"># </a> 1. Responsive layouts (almost)</h3>
<p>Responsive design is the ability for a webpage to change its content to best fit the features of a device used to view the page. For example, when viewing a graph on a mobile phone or a laptop the available screen space differs significantly in size as well as aspect-ratio.</p>
<p>Dashboard doesn't offer the feature to change graph sizes based on the screen of a viewing device. That being said, there is one trick you can use to make your dashboards a lot more useful on small and large screens alike.</p>
<p>Place your content into Dashboard 'groups', those groups can make use of wider screens by sitting side by side where the screen is big enough while stacking vertically on smaller devices.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/dashboard-groups-S_kHXTg-Ii-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/dashboard-groups-S_kHXTg-Ii-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="4 dashboard groups which can sit side by side or above each other" alt="4 dashboard groups which can sit side by side or above each other" loading="lazy" decoding="async" src="https://flowfuse.com/img/dashboard-groups-S_kHXTg-Ii-650.jpeg" width="650" height="579" /></picture></p>
<p>The image below shows what happens when you change the screen size for this dashboard.</p>
<p><picture><source type="image/gif" srcset="https://flowfuse.com/img/responsive-E0mhVCUWw3-600.gif 600w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Changing the aspect ratio of the screen" alt="Changing the aspect ratio of the screen" loading="lazy" decoding="async" src="https://flowfuse.com/img/responsive-E0mhVCUWw3-600.webp" width="600" height="437" /></picture></p>
<p>If you'd like to try this out on your own Node-RED, you can import the flow below.</p>
<div style="position: relative">
<pre class="language-json"><code id="code-31" class="language-json"><br /><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"e351b1251dfbc2f7"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"tab"</span><span class="token punctuation">,</span><span class="token property">"label"</span><span class="token operator">:</span><span class="token string">"Flow 1"</span><span class="token punctuation">,</span><span class="token property">"disabled"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"info"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"env"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"d388b48fcbed93a1"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_gauge"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"e351b1251dfbc2f7"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"group"</span><span class="token operator">:</span><span class="token string">"ba1ff527abfa5261"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"gtype"</span><span class="token operator">:</span><span class="token string">"gage"</span><span class="token punctuation">,</span><span class="token property">"title"</span><span class="token operator">:</span><span class="token string">"gauge"</span><span class="token punctuation">,</span><span class="token property">"label"</span><span class="token operator">:</span><span class="token string">"units"</span><span class="token punctuation">,</span><span class="token property">"format"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"min"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"max"</span><span class="token operator">:</span><span class="token string">"100"</span><span class="token punctuation">,</span><span class="token property">"colors"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"#00b500"</span><span class="token punctuation">,</span><span class="token string">"#e6e600"</span><span class="token punctuation">,</span><span class="token string">"#ca3838"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"seg1"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"seg2"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"diff"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">350</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">80</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"80780894450cfb6d"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_button"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"e351b1251dfbc2f7"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"group"</span><span class="token operator">:</span><span class="token string">"ba1ff527abfa5261"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"passthru"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"label"</span><span class="token operator">:</span><span class="token string">"Update"</span><span class="token punctuation">,</span><span class="token property">"tooltip"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"color"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"bgcolor"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"icon"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"payload"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"payloadType"</span><span class="token operator">:</span><span class="token string">"str"</span><span class="token punctuation">,</span><span class="token property">"topic"</span><span class="token operator">:</span><span class="token string">"topic"</span><span class="token punctuation">,</span><span class="token property">"topicType"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">80</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">80</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"49e78ff51c3a1ea3"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"07b44990e5d5b5f6"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_chart"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"e351b1251dfbc2f7"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"group"</span><span class="token operator">:</span><span class="token string">"ba1ff527abfa5261"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"label"</span><span class="token operator">:</span><span class="token string">"chart"</span><span class="token punctuation">,</span><span class="token property">"chartType"</span><span class="token operator">:</span><span class="token string">"line"</span><span class="token punctuation">,</span><span class="token property">"legend"</span><span class="token operator">:</span><span class="token string">"false"</span><span class="token punctuation">,</span><span class="token property">"xformat"</span><span class="token operator">:</span><span class="token string">"HH:mm:ss"</span><span class="token punctuation">,</span><span class="token property">"interpolate"</span><span class="token operator">:</span><span class="token string">"linear"</span><span class="token punctuation">,</span><span class="token property">"nodata"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"dot"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"ymin"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"ymax"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"removeOlder"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"removeOlderPoints"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"removeOlderUnit"</span><span class="token operator">:</span><span class="token string">"60"</span><span class="token punctuation">,</span><span class="token property">"cutout"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"useOneColor"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"useUTC"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"colors"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"#1f77b4"</span><span class="token punctuation">,</span><span class="token string">"#aec7e8"</span><span class="token punctuation">,</span><span class="token string">"#ff7f0e"</span><span class="token punctuation">,</span><span class="token string">"#2ca02c"</span><span class="token punctuation">,</span><span class="token string">"#98df8a"</span><span class="token punctuation">,</span><span class="token string">"#d62728"</span><span class="token punctuation">,</span><span class="token string">"#ff9896"</span><span class="token punctuation">,</span><span class="token string">"#9467bd"</span><span class="token punctuation">,</span><span class="token string">"#c5b0d5"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"outputs"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"useDifferentColor"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">350</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">120</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"1482bcf69325aa92"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"e351b1251dfbc2f7"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"repeat"</span><span class="token operator">:</span><span class="token string">"1"</span><span class="token punctuation">,</span><span class="token property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"once"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"onceDelay"</span><span class="token operator">:</span><span class="token number">0.1</span><span class="token punctuation">,</span><span class="token property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">90</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">120</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"49e78ff51c3a1ea3"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"49e78ff51c3a1ea3"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"random"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"e351b1251dfbc2f7"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"low"</span><span class="token operator">:</span><span class="token string">"0"</span><span class="token punctuation">,</span><span class="token property">"high"</span><span class="token operator">:</span><span class="token string">"100"</span><span class="token punctuation">,</span><span class="token property">"inte"</span><span class="token operator">:</span><span class="token string">"true"</span><span class="token punctuation">,</span><span class="token property">"property"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">220</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">100</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"d388b48fcbed93a1"</span><span class="token punctuation">,</span><span class="token string">"07b44990e5d5b5f6"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"38996d8eb9f6535d"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_gauge"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"e351b1251dfbc2f7"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"group"</span><span class="token operator">:</span><span class="token string">"f6052a3dccc77ea3"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"gtype"</span><span class="token operator">:</span><span class="token string">"gage"</span><span class="token punctuation">,</span><span class="token property">"title"</span><span class="token operator">:</span><span class="token string">"gauge"</span><span class="token punctuation">,</span><span class="token property">"label"</span><span class="token operator">:</span><span class="token string">"units"</span><span class="token punctuation">,</span><span class="token property">"format"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"min"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"max"</span><span class="token operator">:</span><span class="token string">"100"</span><span class="token punctuation">,</span><span class="token property">"colors"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"#00b500"</span><span class="token punctuation">,</span><span class="token string">"#e6e600"</span><span class="token punctuation">,</span><span class="token string">"#ca3838"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"seg1"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"seg2"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"diff"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">350</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">240</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"cf5599fbda28e614"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_button"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"e351b1251dfbc2f7"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"group"</span><span class="token operator">:</span><span class="token string">"f6052a3dccc77ea3"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"passthru"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"label"</span><span class="token operator">:</span><span class="token string">"Update"</span><span class="token punctuation">,</span><span class="token property">"tooltip"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"color"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"bgcolor"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"icon"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"payload"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"payloadType"</span><span class="token operator">:</span><span class="token string">"str"</span><span class="token punctuation">,</span><span class="token property">"topic"</span><span class="token operator">:</span><span class="token string">"topic"</span><span class="token punctuation">,</span><span class="token property">"topicType"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">80</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">240</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"f093c63e17a620ba"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"936438ebf9eef986"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_chart"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"e351b1251dfbc2f7"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"group"</span><span class="token operator">:</span><span class="token string">"f6052a3dccc77ea3"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"label"</span><span class="token operator">:</span><span class="token string">"chart"</span><span class="token punctuation">,</span><span class="token property">"chartType"</span><span class="token operator">:</span><span class="token string">"line"</span><span class="token punctuation">,</span><span class="token property">"legend"</span><span class="token operator">:</span><span class="token string">"false"</span><span class="token punctuation">,</span><span class="token property">"xformat"</span><span class="token operator">:</span><span class="token string">"HH:mm:ss"</span><span class="token punctuation">,</span><span class="token property">"interpolate"</span><span class="token operator">:</span><span class="token string">"linear"</span><span class="token punctuation">,</span><span class="token property">"nodata"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"dot"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"ymin"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"ymax"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"removeOlder"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"removeOlderPoints"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"removeOlderUnit"</span><span class="token operator">:</span><span class="token string">"60"</span><span class="token punctuation">,</span><span class="token property">"cutout"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"useOneColor"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"useUTC"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"colors"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"#1f77b4"</span><span class="token punctuation">,</span><span class="token string">"#aec7e8"</span><span class="token punctuation">,</span><span class="token string">"#ff7f0e"</span><span class="token punctuation">,</span><span class="token string">"#2ca02c"</span><span class="token punctuation">,</span><span class="token string">"#98df8a"</span><span class="token punctuation">,</span><span class="token string">"#d62728"</span><span class="token punctuation">,</span><span class="token string">"#ff9896"</span><span class="token punctuation">,</span><span class="token string">"#9467bd"</span><span class="token punctuation">,</span><span class="token string">"#c5b0d5"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"outputs"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"useDifferentColor"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">350</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">280</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"60a40faa335f943e"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"e351b1251dfbc2f7"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"repeat"</span><span class="token operator">:</span><span class="token string">"1"</span><span class="token punctuation">,</span><span class="token property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"once"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"onceDelay"</span><span class="token operator">:</span><span class="token number">0.1</span><span class="token punctuation">,</span><span class="token property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">90</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">280</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"f093c63e17a620ba"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"f093c63e17a620ba"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"random"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"e351b1251dfbc2f7"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"low"</span><span class="token operator">:</span><span class="token string">"0"</span><span class="token punctuation">,</span><span class="token property">"high"</span><span class="token operator">:</span><span class="token string">"100"</span><span class="token punctuation">,</span><span class="token property">"inte"</span><span class="token operator">:</span><span class="token string">"true"</span><span class="token punctuation">,</span><span class="token property">"property"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">220</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">260</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"38996d8eb9f6535d"</span><span class="token punctuation">,</span><span class="token string">"936438ebf9eef986"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"e284b90164e648e6"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_gauge"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"e351b1251dfbc2f7"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"group"</span><span class="token operator">:</span><span class="token string">"1e4a72d62ed7564c"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"gtype"</span><span class="token operator">:</span><span class="token string">"gage"</span><span class="token punctuation">,</span><span class="token property">"title"</span><span class="token operator">:</span><span class="token string">"gauge"</span><span class="token punctuation">,</span><span class="token property">"label"</span><span class="token operator">:</span><span class="token string">"units"</span><span class="token punctuation">,</span><span class="token property">"format"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"min"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"max"</span><span class="token operator">:</span><span class="token string">"100"</span><span class="token punctuation">,</span><span class="token property">"colors"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"#00b500"</span><span class="token punctuation">,</span><span class="token string">"#e6e600"</span><span class="token punctuation">,</span><span class="token string">"#ca3838"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"seg1"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"seg2"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"diff"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">350</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">380</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"cabe7a8150dbfaf6"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_button"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"e351b1251dfbc2f7"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"group"</span><span class="token operator">:</span><span class="token string">"1e4a72d62ed7564c"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"passthru"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"label"</span><span class="token operator">:</span><span class="token string">"Update"</span><span class="token punctuation">,</span><span class="token property">"tooltip"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"color"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"bgcolor"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"icon"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"payload"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"payloadType"</span><span class="token operator">:</span><span class="token string">"str"</span><span class="token punctuation">,</span><span class="token property">"topic"</span><span class="token operator">:</span><span class="token string">"topic"</span><span class="token punctuation">,</span><span class="token property">"topicType"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">80</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">380</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"7b9862186954c4b3"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"ac116116c56e6c3c"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_chart"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"e351b1251dfbc2f7"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"group"</span><span class="token operator">:</span><span class="token string">"1e4a72d62ed7564c"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"label"</span><span class="token operator">:</span><span class="token string">"chart"</span><span class="token punctuation">,</span><span class="token property">"chartType"</span><span class="token operator">:</span><span class="token string">"line"</span><span class="token punctuation">,</span><span class="token property">"legend"</span><span class="token operator">:</span><span class="token string">"false"</span><span class="token punctuation">,</span><span class="token property">"xformat"</span><span class="token operator">:</span><span class="token string">"HH:mm:ss"</span><span class="token punctuation">,</span><span class="token property">"interpolate"</span><span class="token operator">:</span><span class="token string">"linear"</span><span class="token punctuation">,</span><span class="token property">"nodata"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"dot"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"ymin"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"ymax"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"removeOlder"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"removeOlderPoints"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"removeOlderUnit"</span><span class="token operator">:</span><span class="token string">"60"</span><span class="token punctuation">,</span><span class="token property">"cutout"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"useOneColor"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"useUTC"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"colors"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"#1f77b4"</span><span class="token punctuation">,</span><span class="token string">"#aec7e8"</span><span class="token punctuation">,</span><span class="token string">"#ff7f0e"</span><span class="token punctuation">,</span><span class="token string">"#2ca02c"</span><span class="token punctuation">,</span><span class="token string">"#98df8a"</span><span class="token punctuation">,</span><span class="token string">"#d62728"</span><span class="token punctuation">,</span><span class="token string">"#ff9896"</span><span class="token punctuation">,</span><span class="token string">"#9467bd"</span><span class="token punctuation">,</span><span class="token string">"#c5b0d5"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"outputs"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"useDifferentColor"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">350</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">420</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"bb27ef41380ec1d2"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"e351b1251dfbc2f7"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"repeat"</span><span class="token operator">:</span><span class="token string">"1"</span><span class="token punctuation">,</span><span class="token property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"once"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"onceDelay"</span><span class="token operator">:</span><span class="token number">0.1</span><span class="token punctuation">,</span><span class="token property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">90</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">420</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"7b9862186954c4b3"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"7b9862186954c4b3"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"random"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"e351b1251dfbc2f7"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"low"</span><span class="token operator">:</span><span class="token string">"0"</span><span class="token punctuation">,</span><span class="token property">"high"</span><span class="token operator">:</span><span class="token string">"100"</span><span class="token punctuation">,</span><span class="token property">"inte"</span><span class="token operator">:</span><span class="token string">"true"</span><span class="token punctuation">,</span><span class="token property">"property"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">220</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">400</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"e284b90164e648e6"</span><span class="token punctuation">,</span><span class="token string">"ac116116c56e6c3c"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"e891f555bad51f01"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_gauge"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"e351b1251dfbc2f7"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"group"</span><span class="token operator">:</span><span class="token string">"fcc4481a9e329266"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"gtype"</span><span class="token operator">:</span><span class="token string">"gage"</span><span class="token punctuation">,</span><span class="token property">"title"</span><span class="token operator">:</span><span class="token string">"gauge"</span><span class="token punctuation">,</span><span class="token property">"label"</span><span class="token operator">:</span><span class="token string">"units"</span><span class="token punctuation">,</span><span class="token property">"format"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"min"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"max"</span><span class="token operator">:</span><span class="token string">"100"</span><span class="token punctuation">,</span><span class="token property">"colors"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"#00b500"</span><span class="token punctuation">,</span><span class="token string">"#e6e600"</span><span class="token punctuation">,</span><span class="token string">"#ca3838"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"seg1"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"seg2"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"diff"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">350</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">500</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"fa090cd1a0e97885"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_button"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"e351b1251dfbc2f7"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"group"</span><span class="token operator">:</span><span class="token string">"fcc4481a9e329266"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"passthru"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"label"</span><span class="token operator">:</span><span class="token string">"Update"</span><span class="token punctuation">,</span><span class="token property">"tooltip"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"color"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"bgcolor"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"icon"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"payload"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"payloadType"</span><span class="token operator">:</span><span class="token string">"str"</span><span class="token punctuation">,</span><span class="token property">"topic"</span><span class="token operator">:</span><span class="token string">"topic"</span><span class="token punctuation">,</span><span class="token property">"topicType"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">80</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">500</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"bb4e945a2a8e681c"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"1c3a8aa84dfc85fe"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_chart"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"e351b1251dfbc2f7"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"group"</span><span class="token operator">:</span><span class="token string">"fcc4481a9e329266"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"label"</span><span class="token operator">:</span><span class="token string">"chart"</span><span class="token punctuation">,</span><span class="token property">"chartType"</span><span class="token operator">:</span><span class="token string">"line"</span><span class="token punctuation">,</span><span class="token property">"legend"</span><span class="token operator">:</span><span class="token string">"false"</span><span class="token punctuation">,</span><span class="token property">"xformat"</span><span class="token operator">:</span><span class="token string">"HH:mm:ss"</span><span class="token punctuation">,</span><span class="token property">"interpolate"</span><span class="token operator">:</span><span class="token string">"linear"</span><span class="token punctuation">,</span><span class="token property">"nodata"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"dot"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"ymin"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"ymax"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"removeOlder"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"removeOlderPoints"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"removeOlderUnit"</span><span class="token operator">:</span><span class="token string">"60"</span><span class="token punctuation">,</span><span class="token property">"cutout"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"useOneColor"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"useUTC"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"colors"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"#1f77b4"</span><span class="token punctuation">,</span><span class="token string">"#aec7e8"</span><span class="token punctuation">,</span><span class="token string">"#ff7f0e"</span><span class="token punctuation">,</span><span class="token string">"#2ca02c"</span><span class="token punctuation">,</span><span class="token string">"#98df8a"</span><span class="token punctuation">,</span><span class="token string">"#d62728"</span><span class="token punctuation">,</span><span class="token string">"#ff9896"</span><span class="token punctuation">,</span><span class="token string">"#9467bd"</span><span class="token punctuation">,</span><span class="token string">"#c5b0d5"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"outputs"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"useDifferentColor"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">350</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">540</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"796f79538c15dd66"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"e351b1251dfbc2f7"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"repeat"</span><span class="token operator">:</span><span class="token string">"1"</span><span class="token punctuation">,</span><span class="token property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"once"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"onceDelay"</span><span class="token operator">:</span><span class="token number">0.1</span><span class="token punctuation">,</span><span class="token property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">90</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">540</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"bb4e945a2a8e681c"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"bb4e945a2a8e681c"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"random"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"e351b1251dfbc2f7"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"low"</span><span class="token operator">:</span><span class="token string">"0"</span><span class="token punctuation">,</span><span class="token property">"high"</span><span class="token operator">:</span><span class="token string">"100"</span><span class="token punctuation">,</span><span class="token property">"inte"</span><span class="token operator">:</span><span class="token string">"true"</span><span class="token punctuation">,</span><span class="token property">"property"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">220</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">520</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"e891f555bad51f01"</span><span class="token punctuation">,</span><span class="token string">"1c3a8aa84dfc85fe"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"ba1ff527abfa5261"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_group"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Machine 1"</span><span class="token punctuation">,</span><span class="token property">"tab"</span><span class="token operator">:</span><span class="token string">"39383a7a648193dd"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"disp"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token string">"6"</span><span class="token punctuation">,</span><span class="token property">"collapse"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"f6052a3dccc77ea3"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_group"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Machine 2"</span><span class="token punctuation">,</span><span class="token property">"tab"</span><span class="token operator">:</span><span class="token string">"39383a7a648193dd"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token property">"disp"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token string">"6"</span><span class="token punctuation">,</span><span class="token property">"collapse"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"1e4a72d62ed7564c"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_group"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Machine 3"</span><span class="token punctuation">,</span><span class="token property">"tab"</span><span class="token operator">:</span><span class="token string">"39383a7a648193dd"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token property">"disp"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token string">"6"</span><span class="token punctuation">,</span><span class="token property">"collapse"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"fcc4481a9e329266"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_group"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Machine 4"</span><span class="token punctuation">,</span><span class="token property">"tab"</span><span class="token operator">:</span><span class="token string">"39383a7a648193dd"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token number">4</span><span class="token punctuation">,</span><span class="token property">"disp"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token string">"6"</span><span class="token punctuation">,</span><span class="token property">"collapse"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"39383a7a648193dd"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_tab"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Node-RED Tips"</span><span class="token punctuation">,</span><span class="token property">"icon"</span><span class="token operator">:</span><span class="token string">"dashboard"</span><span class="token punctuation">,</span><span class="token property">"disabled"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"hidden"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">}</span><span class="token punctuation">]</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-31" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<h3 id="2.-add-more-than-one-series-of-data-to-a-line-chart" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/3-quick-node-red-tips-7/#2.-add-more-than-one-series-of-data-to-a-line-chart"># </a> 2. Add more than one series of data to a line chart</h3>
<p>Being able to add more than one series of data to a single chart can make the data far more useful. One great way to use this is to compare the same data from different sensors. In this example I'm going to show the external and internal temperature at a location on the same chart.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/temp-graph-Snc3Eb9LW2-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/temp-graph-Snc3Eb9LW2-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Graphing two series on the same line chart" alt="Graphing two series on the same line chart" loading="lazy" decoding="async" src="https://flowfuse.com/img/temp-graph-Snc3Eb9LW2-650.jpeg" width="650" height="262" /></picture></p>
<p>To do this you need to give a different msg.topic to each series, you can add that using a change node before passing the data to the chart.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/chart-topics-2Ded7EgcZC-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/chart-topics-2Ded7EgcZC-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Defining the name for each series" alt="Defining the name for each series" loading="lazy" decoding="async" src="https://flowfuse.com/img/chart-topics-2Ded7EgcZC-650.jpeg" width="650" height="107" /></picture></p>
<p>If you'd like to view this chart on your own Node-RED, you can import the flow below.</p>
<div style="position: relative">
<pre class="language-json"><code id="code-50" class="language-json"><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"3eb08d4843164efc"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_chart"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"58569b35dacd54f3"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"group"</span><span class="token operator">:</span><span class="token string">"41e847ff22249c0e"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token string">"12"</span><span class="token punctuation">,</span><span class="token property">"height"</span><span class="token operator">:</span><span class="token string">"5"</span><span class="token punctuation">,</span><span class="token property">"label"</span><span class="token operator">:</span><span class="token string">"Celsius"</span><span class="token punctuation">,</span><span class="token property">"chartType"</span><span class="token operator">:</span><span class="token string">"line"</span><span class="token punctuation">,</span><span class="token property">"legend"</span><span class="token operator">:</span><span class="token string">"true"</span><span class="token punctuation">,</span><span class="token property">"xformat"</span><span class="token operator">:</span><span class="token string">"dd HH:mm"</span><span class="token punctuation">,</span><span class="token property">"interpolate"</span><span class="token operator">:</span><span class="token string">"linear"</span><span class="token punctuation">,</span><span class="token property">"nodata"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"dot"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"ymin"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"ymax"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"removeOlder"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"removeOlderPoints"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"removeOlderUnit"</span><span class="token operator">:</span><span class="token string">"604800"</span><span class="token punctuation">,</span><span class="token property">"cutout"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"useOneColor"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"useUTC"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"colors"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"#1f77b4"</span><span class="token punctuation">,</span><span class="token string">"#aec7e8"</span><span class="token punctuation">,</span><span class="token string">"#ff7f0e"</span><span class="token punctuation">,</span><span class="token string">"#2ca02c"</span><span class="token punctuation">,</span><span class="token string">"#98df8a"</span><span class="token punctuation">,</span><span class="token string">"#d62728"</span><span class="token punctuation">,</span><span class="token string">"#ff9896"</span><span class="token punctuation">,</span><span class="token string">"#9467bd"</span><span class="token punctuation">,</span><span class="token string">"#c5b0d5"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"outputs"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"useDifferentColor"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">280</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">180</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"c4a13220356f76d3"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"58569b35dacd54f3"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"repeat"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"once"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"onceDelay"</span><span class="token operator">:</span><span class="token number">0.1</span><span class="token punctuation">,</span><span class="token property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"payload"</span><span class="token operator">:</span><span class="token string">"[{\"series\":[\"inside\",\"outside\"],\"data\":[[{\"x\":1685015544647,\"y\":20.8},{\"x\":1685015844687,\"y\":20.8},{\"x\":1685016144791,\"y\":20.8},{\"x\":1685016444933,\"y\":20.8},{\"x\":1685016745032,\"y\":20.8},{\"x\":1685017045123,\"y\":20.8},{\"x\":1685017345223,\"y\":20.8},{\"x\":1685017645339,\"y\":20.8},{\"x\":1685017945424,\"y\":20.8},{\"x\":1685018245500,\"y\":20.8},{\"x\":1685018545670,\"y\":20.8},{\"x\":1685018860580,\"y\":20.8},{\"x\":1685019160814,\"y\":20.8},{\"x\":1685019460832,\"y\":20.8},{\"x\":1685019760943,\"y\":20.8},{\"x\":1685020061037,\"y\":20.8},{\"x\":1685020361249,\"y\":20.8},{\"x\":1685020661264,\"y\":20.8},{\"x\":1685020961381,\"y\":20.8},{\"x\":1685021261473,\"y\":20.8},{\"x\":1685021561721,\"y\":20.8},{\"x\":1685021876580,\"y\":20.6},{\"x\":1685022176696,\"y\":20.7},{\"x\":1685022476852,\"y\":20.8},{\"x\":1685022776957,\"y\":20.8},{\"x\":1685023077032,\"y\":20.8},{\"x\":1685023377120,\"y\":20.8},{\"x\":1685023677234,\"y\":20.8},{\"x\":1685023977339,\"y\":20.8},{\"x\":1685024277455,\"y\":20.8},{\"x\":1685024577576,\"y\":20.8},{\"x\":1685024892578,\"y\":20.8},{\"x\":1685025192616,\"y\":20.8},{\"x\":1685025492757,\"y\":20.8},{\"x\":1685025792847,\"y\":20.7},{\"x\":1685026092949,\"y\":20.8},{\"x\":1685026393052,\"y\":20.8},{\"x\":1685026693174,\"y\":20.8},{\"x\":1685026993234,\"y\":20.8},{\"x\":1685027293387,\"y\":20.8},{\"x\":1685027593514,\"y\":20.8},{\"x\":1685027908550,\"y\":20.8},{\"x\":1685028208624,\"y\":20.8},{\"x\":1685028508708,\"y\":20.8},{\"x\":1685028808828,\"y\":20.8},{\"x\":1685029108909,\"y\":20.8},{\"x\":1685029409026,\"y\":20.8},{\"x\":1685029709096,\"y\":20.8},{\"x\":1685030009262,\"y\":20.8},{\"x\":1685030309361,\"y\":20.8},{\"x\":1685030609541,\"y\":20.8},{\"x\":1685030924565,\"y\":20.8},{\"x\":1685031239588,\"y\":20.8},{\"x\":1685031539702,\"y\":20.8},{\"x\":1685031839784,\"y\":20.8},{\"x\":1685032139922,\"y\":20.8},{\"x\":1685032440027,\"y\":20.8},{\"x\":1685032740134,\"y\":20.6},{\"x\":1685033040252,\"y\":20.7},{\"x\":1685033340317,\"y\":20.5},{\"x\":1685033640450,\"y\":20.5},{\"x\":1685033940507,\"y\":20.6},{\"x\":1685034240592,\"y\":20.5},{\"x\":1685034540633,\"y\":20.4},{\"x\":1685034840784,\"y\":20.4},{\"x\":1685035140888,\"y\":20.5},{\"x\":1685035441026,\"y\":20.4},{\"x\":1685035741107,\"y\":20.5},{\"x\":1685036041205,\"y\":20.5},{\"x\":1685036341328,\"y\":20.5},{\"x\":1685036641457,\"y\":20.5},{\"x\":1685036941583,\"y\":20.4},{\"x\":1685037256578,\"y\":20.5},{\"x\":1685037556715,\"y\":20.5},{\"x\":1685037856773,\"y\":20.5},{\"x\":1685038156902,\"y\":20.5},{\"x\":1685038457023,\"y\":20.5},{\"x\":1685038757090,\"y\":20.5},{\"x\":1685039057219,\"y\":20.5},{\"x\":1685039357278,\"y\":20.5},{\"x\":1685039657449,\"y\":20.5},{\"x\":1685039957553,\"y\":20.5},{\"x\":1685040257570,\"y\":20.5},{\"x\":1685040557615,\"y\":20.5},{\"x\":1685040857735,\"y\":20.4},{\"x\":1685041157843,\"y\":20.4},{\"x\":1685041457971,\"y\":20.5},{\"x\":1685041758072,\"y\":20.5},{\"x\":1685042058154,\"y\":20.5},{\"x\":1685042358273,\"y\":20.5},{\"x\":1685042658392,\"y\":20.5},{\"x\":1685042958486,\"y\":20.6},{\"x\":1685043258518,\"y\":20.6},{\"x\":1685043558568,\"y\":20.6},{\"x\":1685043858688,\"y\":20.5},{\"x\":1685044158769,\"y\":20.5},{\"x\":1685044458908,\"y\":20.5},{\"x\":1685044758984,\"y\":20.5},{\"x\":1685045059095,\"y\":20.5},{\"x\":1685045359169,\"y\":20.5},{\"x\":1685045659320,\"y\":20.5},{\"x\":1685045959367,\"y\":20.5},{\"x\":1685046259469,\"y\":20.7},{\"x\":1685046559497,\"y\":20.6},{\"x\":1685046859589,\"y\":20.5},{\"x\":1685047159647,\"y\":20.6},{\"x\":1685047459714,\"y\":20.6},{\"x\":1685047759793,\"y\":20.7},{\"x\":1685048059921,\"y\":20.7},{\"x\":1685048359994,\"y\":20.6},{\"x\":1685048659997,\"y\":20.7},{\"x\":1685048960056,\"y\":20.7},{\"x\":1685049260070,\"y\":20.8},{\"x\":1685049560116,\"y\":20.8},{\"x\":1685049860167,\"y\":20.8},{\"x\":1685050160212,\"y\":20.8},{\"x\":1685050460281,\"y\":20.8},{\"x\":1685050760368,\"y\":20.8},{\"x\":1685051060400,\"y\":20.7},{\"x\":1685051360435,\"y\":20.8},{\"x\":1685051660553,\"y\":20.8},{\"x\":1685051960585,\"y\":20.8},{\"x\":1685052260665,\"y\":20.8},{\"x\":1685052560675,\"y\":20.8},{\"x\":1685052860700,\"y\":20.7},{\"x\":1685053160749,\"y\":20.8},{\"x\":1685053460790,\"y\":20.8},{\"x\":1685053760855,\"y\":20.7},{\"x\":1685054060931,\"y\":20.7},{\"x\":1685054361019,\"y\":20.7},{\"x\":1685054661030,\"y\":20.7},{\"x\":1685054961121,\"y\":20.7},{\"x\":1685055261227,\"y\":20.7},{\"x\":1685055576250,\"y\":20.7},{\"x\":1685055891289,\"y\":20.5},{\"x\":1685056191290,\"y\":20.6},{\"x\":1685056491397,\"y\":20.7},{\"x\":1685056791444,\"y\":20.7},{\"x\":1685057091489,\"y\":20.7},{\"x\":1685057391516,\"y\":20.7},{\"x\":1685057691607,\"y\":20.7},{\"x\":1685057991660,\"y\":20.7},{\"x\":1685058291741,\"y\":20.6},{\"x\":1685058606760,\"y\":20.5},{\"x\":1685058906775,\"y\":20.5},{\"x\":1685059206866,\"y\":20.5},{\"x\":1685059506900,\"y\":20.5},{\"x\":1685059806979,\"y\":20.4},{\"x\":1685060107035,\"y\":20.5},{\"x\":1685060407099,\"y\":20.5},{\"x\":1685060707132,\"y\":20.4},{\"x\":1685061007199,\"y\":20.5},{\"x\":1685061307220,\"y\":20.4},{\"x\":1685061607228,\"y\":20.5},{\"x\":1685061907286,\"y\":20.6},{\"x\":1685062207289,\"y\":20.7},{\"x\":1685062507315,\"y\":20.6},{\"x\":1685062807355,\"y\":20.7},{\"x\":1685063107395,\"y\":20.7},{\"x\":1685063407413,\"y\":20.7},{\"x\":1685063707465,\"y\":20.7},{\"x\":1685064007492,\"y\":20.7},{\"x\":1685064307565,\"y\":20.7},{\"x\":1685064607587,\"y\":20.7},{\"x\":1685064907609,\"y\":20.7},{\"x\":1685065207618,\"y\":20.5},{\"x\":1685065507642,\"y\":20.4},{\"x\":1685065807670,\"y\":20.4},{\"x\":1685066107679,\"y\":20.4},{\"x\":1685066407758,\"y\":20.5},{\"x\":1685066707760,\"y\":20.3},{\"x\":1685067007798,\"y\":20.4},{\"x\":1685067307865,\"y\":20.4},{\"x\":1685067622903,\"y\":20.4},{\"x\":1685067937922,\"y\":20.4},{\"x\":1685068237945,\"y\":20.4},{\"x\":1685068537971,\"y\":20.3},{\"x\":1685068838009,\"y\":20.3},{\"x\":1685069138060,\"y\":20.2},{\"x\":1685069453065,\"y\":20.3},{\"x\":1685069753104,\"y\":20.3},{\"x\":1685070053108,\"y\":20.2},{\"x\":1685070353140,\"y\":20.3},{\"x\":1685070653170,\"y\":20.2},{\"x\":1685070953219,\"y\":20.2},{\"x\":1685071253232,\"y\":20.2},{\"x\":1685071553258,\"y\":20},{\"x\":1685071853260,\"y\":20},{\"x\":1685072153324,\"y\":20.2},{\"x\":1685072453329,\"y\":20.2},{\"x\":1685072753343,\"y\":19.9},{\"x\":1685073053359,\"y\":20},{\"x\":1685073353402,\"y\":19.9},{\"x\":1685073653411,\"y\":19.9},{\"x\":1685073953453,\"y\":20},{\"x\":1685074253462,\"y\":20},{\"x\":1685074553509,\"y\":20},{\"x\":1685074853529,\"y\":20},{\"x\":1685075153554,\"y\":20},{\"x\":1685075453556,\"y\":20},{\"x\":1685075753590,\"y\":20},{\"x\":1685076053642,\"y\":20.2},{\"x\":1685076368644,\"y\":20},{\"x\":1685076668676,\"y\":20.2},{\"x\":1685076968685,\"y\":20.3},{\"x\":1685077268752,\"y\":20.3},{\"x\":1685077583729,\"y\":20.3},{\"x\":1685077883800,\"y\":20.2},{\"x\":1685078198760,\"y\":20.2},{\"x\":1685078498762,\"y\":20.4},{\"x\":1685078798782,\"y\":20.4},{\"x\":1685079098837,\"y\":20.5},{\"x\":1685079398903,\"y\":20.5},{\"x\":1685079698965,\"y\":20.6},{\"x\":1685079999013,\"y\":20.7},{\"x\":1685080299091,\"y\":20.8},{\"x\":1685080599234,\"y\":20.8},{\"x\":1685080899276,\"y\":20.8},{\"x\":1685081199340,\"y\":20.8},{\"x\":1685081499403,\"y\":20.8},{\"x\":1685081799441,\"y\":20.8},{\"x\":1685082099467,\"y\":20.9},{\"x\":1685082399584,\"y\":20.8},{\"x\":1685082699624,\"y\":21},{\"x\":1685082999670,\"y\":21},{\"x\":1685083299724,\"y\":21.2},{\"x\":1685083599810,\"y\":21.2},{\"x\":1685083899884,\"y\":21.2},{\"x\":1685084199935,\"y\":21.2},{\"x\":1685084500001,\"y\":21.3},{\"x\":1685084800063,\"y\":21.4},{\"x\":1685085115072,\"y\":21.5},{\"x\":1685085415170,\"y\":21.5},{\"x\":1685085715226,\"y\":21.5},{\"x\":1685086015289,\"y\":21.5},{\"x\":1685086315365,\"y\":21.5},{\"x\":1685086615447,\"y\":21.5},{\"x\":1685086915501,\"y\":21.7},{\"x\":1685087215603,\"y\":21.7},{\"x\":1685087515642,\"y\":21.6},{\"x\":1685087815732,\"y\":21.6},{\"x\":1685088115759,\"y\":21.7},{\"x\":1685088415793,\"y\":21.9},{\"x\":1685088715840,\"y\":21.9},{\"x\":1685089015891,\"y\":21.9},{\"x\":1685089315950,\"y\":21.9},{\"x\":1685089616045,\"y\":21.9},{\"x\":1685089916094,\"y\":21.9},{\"x\":1685090216153,\"y\":21.9},{\"x\":1685090516202,\"y\":21.9},{\"x\":1685090816299,\"y\":21.9},{\"x\":1685091116304,\"y\":22},{\"x\":1685091416326,\"y\":22},{\"x\":1685091716409,\"y\":22},{\"x\":1685092016500,\"y\":22},{\"x\":1685092316555,\"y\":21.9},{\"x\":1685092616597,\"y\":21.9},{\"x\":1685092916687,\"y\":21.9},{\"x\":1685093216749,\"y\":21.9},{\"x\":1685093516770,\"y\":21.9},{\"x\":1685093816833,\"y\":21.8},{\"x\":1685094116862,\"y\":21.8},{\"x\":1685094416941,\"y\":21.9},{\"x\":1685094717014,\"y\":21.8},{\"x\":1685095017079,\"y\":21.8},{\"x\":1685095317146,\"y\":21.9},{\"x\":1685095617198,\"y\":21.9},{\"x\":1685095917267,\"y\":22},{\"x\":1685096217380,\"y\":22},{\"x\":1685096517436,\"y\":22.2},{\"x\":1685096817481,\"y\":22.1},{\"x\":1685097117519,\"y\":21.9},{\"x\":1685097417582,\"y\":21.9},{\"x\":1685097717607,\"y\":21.9},{\"x\":1685098017734,\"y\":21.9},{\"x\":1685098317791,\"y\":21.9},{\"x\":1685098617850,\"y\":21.9},{\"x\":1685098917939,\"y\":21.9},{\"x\":1685099218020,\"y\":21.9},{\"x\":1685099518088,\"y\":21.9},{\"x\":1685099818190,\"y\":21.9},{\"x\":1685100118269,\"y\":21.9},{\"x\":1685100418304,\"y\":21.9},{\"x\":1685100718355,\"y\":21.9},{\"x\":1685101018437,\"y\":22},{\"x\":1685101318544,\"y\":22.1},{\"x\":1685101618646,\"y\":22},{\"x\":1685101918720,\"y\":22},{\"x\":1685102218803,\"y\":22},{\"x\":1685102518914,\"y\":21.9},{\"x\":1685102818997,\"y\":21.9},{\"x\":1685103119093,\"y\":21.9},{\"x\":1685103419119,\"y\":21.9},{\"x\":1685103719183,\"y\":21.9},{\"x\":1685104019263,\"y\":21.9},{\"x\":1685104319361,\"y\":21.9},{\"x\":1685104619467,\"y\":21.9},{\"x\":1685104919565,\"y\":21.9},{\"x\":1685105219692,\"y\":21.9},{\"x\":1685105261657,\"y\":21.9},{\"x\":1685105275726,\"y\":21.9},{\"x\":1685105316848,\"y\":21.9},{\"x\":1685105388676,\"y\":21.9},{\"x\":1685105475001,\"y\":21.9},{\"x\":1685105501466,\"y\":21.9},{\"x\":1685105576628,\"y\":21.9},{\"x\":1685105627162,\"y\":21.9},{\"x\":1685105653330,\"y\":21.9},{\"x\":1685105684112,\"y\":21.9},{\"x\":1685105722222,\"y\":21.9},{\"x\":1685105769629,\"y\":21.9},{\"x\":1685105825666,\"y\":21.9},{\"x\":1685105889137,\"y\":21.9},{\"x\":1685105910507,\"y\":21.9},{\"x\":1685105970749,\"y\":21.9},{\"x\":1685106270828,\"y\":21.9},{\"x\":1685106570844,\"y\":21.9},{\"x\":1685106870845,\"y\":21.9},{\"x\":1685107170872,\"y\":21.9},{\"x\":1685107485846,\"y\":21.9},{\"x\":1685107785884,\"y\":21.9},{\"x\":1685108100859,\"y\":21.9},{\"x\":1685108400859,\"y\":21.9},{\"x\":1685108700881,\"y\":21.9},{\"x\":1685109000885,\"y\":21.9},{\"x\":1685109300898,\"y\":21.9},{\"x\":1685109615915,\"y\":21.8},{\"x\":1685109930873,\"y\":21.9},{\"x\":1685110230928,\"y\":21.9},{\"x\":1685110545931,\"y\":21.7},{\"x\":1685110845948,\"y\":21.7},{\"x\":1685111145989,\"y\":21.7},{\"x\":1685111460988,\"y\":21.7},{\"x\":1685111761062,\"y\":21.8},{\"x\":1685112061067,\"y\":21.6},{\"x\":1685112361107,\"y\":21.7},{\"x\":1685112661141,\"y\":21.7},{\"x\":1685112961145,\"y\":21.8},{\"x\":1685113261191,\"y\":21.8},{\"x\":1685113561195,\"y\":21.8},{\"x\":1685113861234,\"y\":21.8},{\"x\":1685114161272,\"y\":21.8},{\"x\":1685114461288,\"y\":21.7},{\"x\":1685114761326,\"y\":21.7},{\"x\":1685115061359,\"y\":21.7},{\"x\":1685115361389,\"y\":21.7},{\"x\":1685115661413,\"y\":21.6},{\"x\":1685115961522,\"y\":21.7},{\"x\":1685116276440,\"y\":21.7},{\"x\":1685116576471,\"y\":21.5},{\"x\":1685116876500,\"y\":21.5},{\"x\":1685117176511,\"y\":21.5},{\"x\":1685117476538,\"y\":21.6},{\"x\":1685117776599,\"y\":21.6},{\"x\":1685118091580,\"y\":21.8},{\"x\":1685118391620,\"y\":21.6},{\"x\":1685118691646,\"y\":21.7},{\"x\":1685118991656,\"y\":21.7},{\"x\":1685119291661,\"y\":21.5},{\"x\":1685119591684,\"y\":21.5},{\"x\":1685119891711,\"y\":21.5},{\"x\":1685120191732,\"y\":21.5},{\"x\":1685120491763,\"y\":21.5},{\"x\":1685120791797,\"y\":21.4},{\"x\":1685121091832,\"y\":21.2},{\"x\":1685121406802,\"y\":21.2},{\"x\":1685121706853,\"y\":21.1},{\"x\":1685122021885,\"y\":21.1},{\"x\":1685122336872,\"y\":21.2},{\"x\":1685122636878,\"y\":21.2},{\"x\":1685122936903,\"y\":21.1},{\"x\":1685123236933,\"y\":21},{\"x\":1685123536988,\"y\":21},{\"x\":1685123837007,\"y\":21.1},{\"x\":1685124137007,\"y\":21},{\"x\":1685124437098,\"y\":21},{\"x\":1685124737193,\"y\":21},{\"x\":1685125037270,\"y\":21},{\"x\":1685125337370,\"y\":20.9},{\"x\":1685125637493,\"y\":20.9},{\"x\":1685125937530,\"y\":21},{\"x\":1685126237627,\"y\":20.9},{\"x\":1685126537712,\"y\":20.8},{\"x\":1685126837733,\"y\":20.8},{\"x\":1685127137746,\"y\":20.8},{\"x\":1685127437870,\"y\":20.8},{\"x\":1685127737940,\"y\":20.8},{\"x\":1685128038026,\"y\":20.8},{\"x\":1685128338109,\"y\":20.8},{\"x\":1685128638215,\"y\":20.8},{\"x\":1685128938321,\"y\":20.8},{\"x\":1685129238409,\"y\":20.8},{\"x\":1685129538484,\"y\":20.8},{\"x\":1685129838514,\"y\":20.8},{\"x\":1685130138614,\"y\":20.8},{\"x\":1685130438644,\"y\":20.8},{\"x\":1685130738716,\"y\":20.8},{\"x\":1685131038856,\"y\":20.8},{\"x\":1685131338912,\"y\":20.8},{\"x\":1685131639028,\"y\":20.8},{\"x\":1685131939140,\"y\":20.8},{\"x\":1685132239222,\"y\":20.8},{\"x\":1685132539344,\"y\":20.8},{\"x\":1685132839390,\"y\":20.8},{\"x\":1685133154381,\"y\":20.8},{\"x\":1685133454402,\"y\":20.8},{\"x\":1685133754494,\"y\":20.8},{\"x\":1685134054557,\"y\":20.8},{\"x\":1685134354644,\"y\":20.8},{\"x\":1685134654753,\"y\":20.8},{\"x\":1685134954810,\"y\":20.8},{\"x\":1685135254894,\"y\":20.7},{\"x\":1685135554961,\"y\":20.8},{\"x\":1685135854990,\"y\":20.8},{\"x\":1685136155013,\"y\":20.8},{\"x\":1685136455070,\"y\":20.8},{\"x\":1685136755172,\"y\":20.8},{\"x\":1685137055242,\"y\":20.8},{\"x\":1685137355339,\"y\":20.8},{\"x\":1685137655440,\"y\":20.7},{\"x\":1685137955504,\"y\":20.7},{\"x\":1685138255592,\"y\":20.6},{\"x\":1685138555675,\"y\":20.6},{\"x\":1685138855742,\"y\":20.6},{\"x\":1685139155750,\"y\":20.6},{\"x\":1685139455841,\"y\":20.5},{\"x\":1685139755904,\"y\":20.6},{\"x\":1685140055961,\"y\":20.5},{\"x\":1685140356100,\"y\":20.6},{\"x\":1685140656187,\"y\":20.5},{\"x\":1685140956268,\"y\":20.4},{\"x\":1685141256384,\"y\":20.4},{\"x\":1685141556467,\"y\":20.4},{\"x\":1685141856547,\"y\":20.4},{\"x\":1685142156630,\"y\":20.3},{\"x\":1685142456678,\"y\":20.2},{\"x\":1685142756713,\"y\":20.3},{\"x\":1685143056833,\"y\":20.3},{\"x\":1685143356922,\"y\":20.3},{\"x\":1685143657019,\"y\":20.3},{\"x\":1685143957116,\"y\":20.2},{\"x\":1685144257203,\"y\":20.2},{\"x\":1685144557262,\"y\":20.1},{\"x\":1685144857393,\"y\":20.2},{\"x\":1685145157511,\"y\":20.2},{\"x\":1685145457515,\"y\":20.2},{\"x\":1685145757583,\"y\":20},{\"x\":1685146057687,\"y\":20},{\"x\":1685146357780,\"y\":20.1},{\"x\":1685146657878,\"y\":19.9},{\"x\":1685146957969,\"y\":19.9},{\"x\":1685147258066,\"y\":20},{\"x\":1685147558163,\"y\":20},{\"x\":1685147858255,\"y\":19.9},{\"x\":1685148158303,\"y\":19.9},{\"x\":1685148458377,\"y\":19.9},{\"x\":1685148758392,\"y\":19.9},{\"x\":1685149058441,\"y\":19.9},{\"x\":1685149358550,\"y\":19.9},{\"x\":1685149658652,\"y\":19.5},{\"x\":1685149958735,\"y\":19.5},{\"x\":1685150258816,\"y\":19.5},{\"x\":1685150558892,\"y\":19.5},{\"x\":1685150858996,\"y\":19.5},{\"x\":1685151159109,\"y\":19.5},{\"x\":1685151459166,\"y\":19.5},{\"x\":1685151759230,\"y\":19.5},{\"x\":1685152059291,\"y\":19.5},{\"x\":1685152359350,\"y\":19.5},{\"x\":1685152659430,\"y\":19.5},{\"x\":1685152959526,\"y\":19.5},{\"x\":1685153259622,\"y\":19.5},{\"x\":1685153559728,\"y\":19.5},{\"x\":1685153859883,\"y\":19.5},{\"x\":1685154159899,\"y\":19.5},{\"x\":1685154459974,\"y\":19.5},{\"x\":1685154760016,\"y\":19.5},{\"x\":1685155060096,\"y\":19.5},{\"x\":1685155360142,\"y\":19.5},{\"x\":1685155660284,\"y\":19.5},{\"x\":1685155960372,\"y\":19.5},{\"x\":1685156260469,\"y\":19.5},{\"x\":1685156560559,\"y\":19.5},{\"x\":1685156860664,\"y\":19.5},{\"x\":1685157160732,\"y\":19.5},{\"x\":1685157460827,\"y\":19.5},{\"x\":1685157760925,\"y\":19.5},{\"x\":1685158061041,\"y\":19.4},{\"x\":1685158361093,\"y\":19.4},{\"x\":1685158661174,\"y\":19.4},{\"x\":1685158961238,\"y\":19.4},{\"x\":1685159261356,\"y\":19.4},{\"x\":1685159561460,\"y\":19.4},{\"x\":1685159861591,\"y\":19.4},{\"x\":1685160161622,\"y\":19.5},{\"x\":1685160461727,\"y\":19.4},{\"x\":1685160761798,\"y\":19.3},{\"x\":1685161061899,\"y\":19.3},{\"x\":1685161361960,\"y\":19.3},{\"x\":1685161662030,\"y\":19.3},{\"x\":1685161962083,\"y\":19.2},{\"x\":1685162262205,\"y\":19.2},{\"x\":1685162562329,\"y\":19.2},{\"x\":1685162862420,\"y\":19.2},{\"x\":1685163162514,\"y\":19.3},{\"x\":1685163462630,\"y\":19.4},{\"x\":1685163762689,\"y\":19.5},{\"x\":1685164062785,\"y\":19.5},{\"x\":1685164362862,\"y\":19.5},{\"x\":1685164662929,\"y\":19.5},{\"x\":1685164962989,\"y\":19.5},{\"x\":1685165263080,\"y\":19.5},{\"x\":1685165563213,\"y\":19.5},{\"x\":1685165863284,\"y\":19.5},{\"x\":1685166163398,\"y\":19.7},{\"x\":1685166463432,\"y\":20},{\"x\":1685166763562,\"y\":20},{\"x\":1685167063657,\"y\":20.3},{\"x\":1685167363752,\"y\":20.3},{\"x\":1685167663818,\"y\":20.2},{\"x\":1685167963868,\"y\":20.4},{\"x\":1685168263959,\"y\":20.5},{\"x\":1685168564052,\"y\":20.7},{\"x\":1685168864152,\"y\":20.8},{\"x\":1685169164297,\"y\":20.8},{\"x\":1685169464371,\"y\":20.8},{\"x\":1685169764428,\"y\":20.9},{\"x\":1685170064553,\"y\":21},{\"x\":1685170364630,\"y\":20.8},{\"x\":1685170664689,\"y\":20.8},{\"x\":1685170964744,\"y\":20.9},{\"x\":1685171264839,\"y\":21},{\"x\":1685171564944,\"y\":21},{\"x\":1685171865046,\"y\":21.1},{\"x\":1685172165136,\"y\":21.1},{\"x\":1685172465216,\"y\":21.2},{\"x\":1685172765270,\"y\":21.5},{\"x\":1685173065378,\"y\":21.5},{\"x\":1685173365491,\"y\":21.5},{\"x\":1685173665574,\"y\":21.5},{\"x\":1685173965634,\"y\":21.5},{\"x\":1685174265651,\"y\":21.5},{\"x\":1685174565770,\"y\":21.5},{\"x\":1685174865842,\"y\":21.5},{\"x\":1685175165962,\"y\":21.5},{\"x\":1685175466056,\"y\":21.5},{\"x\":1685175766151,\"y\":21.6},{\"x\":1685176066247,\"y\":21.7},{\"x\":1685176366347,\"y\":21.6},{\"x\":1685176666421,\"y\":21.6},{\"x\":1685176966481,\"y\":21.7},{\"x\":1685177266535,\"y\":21.7},{\"x\":1685177566618,\"y\":21.7},{\"x\":1685177866715,\"y\":21.8},{\"x\":1685178166786,\"y\":21.7},{\"x\":1685178466868,\"y\":21.7},{\"x\":1685178766964,\"y\":21.8},{\"x\":1685179067013,\"y\":21.9},{\"x\":1685179367161,\"y\":21.9},{\"x\":1685179667226,\"y\":21.9},{\"x\":1685179967298,\"y\":21.9},{\"x\":1685180267304,\"y\":21.9},{\"x\":1685180567400,\"y\":21.9},{\"x\":1685180867474,\"y\":21.9},{\"x\":1685181167605,\"y\":21.9},{\"x\":1685181467661,\"y\":21.9},{\"x\":1685181767781,\"y\":21.9},{\"x\":1685182067847,\"y\":21.9},{\"x\":1685182367916,\"y\":21.9},{\"x\":1685182668010,\"y\":21.9},{\"x\":1685182968067,\"y\":21.9},{\"x\":1685183268142,\"y\":21.9},{\"x\":1685183568218,\"y\":21.9},{\"x\":1685183868264,\"y\":21.9},{\"x\":1685184168356,\"y\":22},{\"x\":1685184468449,\"y\":22},{\"x\":1685184768557,\"y\":22},{\"x\":1685185068624,\"y\":22.2},{\"x\":1685185368711,\"y\":22.1},{\"x\":1685185668784,\"y\":22.1},{\"x\":1685185968847,\"y\":22},{\"x\":1685186268953,\"y\":21.9},{\"x\":1685186568982,\"y\":21.9},{\"x\":1685186868996,\"y\":21.9},{\"x\":1685187169094,\"y\":21.9},{\"x\":1685187469146,\"y\":21.9},{\"x\":1685187769224,\"y\":21.9},{\"x\":1685188069250,\"y\":21.9},{\"x\":1685188369327,\"y\":21.9},{\"x\":1685188669411,\"y\":21.7},{\"x\":1685188969475,\"y\":21.7},{\"x\":1685189269500,\"y\":21.5},{\"x\":1685189569548,\"y\":21.5},{\"x\":1685189869583,\"y\":21.6},{\"x\":1685190169645,\"y\":21.7},{\"x\":1685190469717,\"y\":21.7},{\"x\":1685190769801,\"y\":21.7},{\"x\":1685191069848,\"y\":21.7},{\"x\":1685191369885,\"y\":21.7},{\"x\":1685191669980,\"y\":21.7},{\"x\":1685191970014,\"y\":21.7},{\"x\":1685192270055,\"y\":21.6},{\"x\":1685192570106,\"y\":21.7},{\"x\":1685192870150,\"y\":21.7},{\"x\":1685193170235,\"y\":21.6},{\"x\":1685193470249,\"y\":21.5},{\"x\":1685193770302,\"y\":21.5},{\"x\":1685194070311,\"y\":21.6},{\"x\":1685194370328,\"y\":21.7},{\"x\":1685194670393,\"y\":21.7},{\"x\":1685194985377,\"y\":21.7},{\"x\":1685195285440,\"y\":21.7},{\"x\":1685195585471,\"y\":21.7},{\"x\":1685195885473,\"y\":21.7},{\"x\":1685196185514,\"y\":21.6},{\"x\":1685196485562,\"y\":21.7},{\"x\":1685196800615,\"y\":21.7},{\"x\":1685197115572,\"y\":21.7},{\"x\":1685197415601,\"y\":21.7},{\"x\":1685197715640,\"y\":21.7},{\"x\":1685198015652,\"y\":21.7},{\"x\":1685198315706,\"y\":21.7},{\"x\":1685198615725,\"y\":21.7},{\"x\":1685198915775,\"y\":21.8},{\"x\":1685199215786,\"y\":21.8},{\"x\":1685199515831,\"y\":21.9},{\"x\":1685199815856,\"y\":21.8},{\"x\":1685200115858,\"y\":21.9},{\"x\":1685200415875,\"y\":21.8},{\"x\":1685200715913,\"y\":21.8},{\"x\":1685201015918,\"y\":21.8},{\"x\":1685201315964,\"y\":21.9},{\"x\":1685201616032,\"y\":21.9},{\"x\":1685201916044,\"y\":21.9},{\"x\":1685202231051,\"y\":21.9},{\"x\":1685202531062,\"y\":21.9},{\"x\":1685202831089,\"y\":21.8},{\"x\":1685203131095,\"y\":21.8},{\"x\":1685203431195,\"y\":21.8},{\"x\":1685203746138,\"y\":21.8},{\"x\":1685204046168,\"y\":21.8},{\"x\":1685204346182,\"y\":21.7},{\"x\":1685204646203,\"y\":21.8},{\"x\":1685204946241,\"y\":21.9},{\"x\":1685205246243,\"y\":21.9},{\"x\":1685205546262,\"y\":21.9},{\"x\":1685205846296,\"y\":21.9},{\"x\":1685206146312,\"y\":21.9},{\"x\":1685206446335,\"y\":21.9},{\"x\":1685206746375,\"y\":21.9},{\"x\":1685207046395,\"y\":21.9},{\"x\":1685207346549,\"y\":21.9},{\"x\":1685207661544,\"y\":21.9},{\"x\":1685207961647,\"y\":21.9},{\"x\":1685208261700,\"y\":21.9},{\"x\":1685208561766,\"y\":21.9},{\"x\":1685208861855,\"y\":21.9},{\"x\":1685209161943,\"y\":21.9},{\"x\":1685209462007,\"y\":21.9},{\"x\":1685209762097,\"y\":21.9},{\"x\":1685210077101,\"y\":21.9},{\"x\":1685210377152,\"y\":21.9},{\"x\":1685210677231,\"y\":21.9},{\"x\":1685210977296,\"y\":21.9},{\"x\":1685211277406,\"y\":21.9},{\"x\":1685211577537,\"y\":21.9},{\"x\":1685211877620,\"y\":21.9},{\"x\":1685212177660,\"y\":21.9},{\"x\":1685212477797,\"y\":21.9},{\"x\":1685212777837,\"y\":21.9},{\"x\":1685213077881,\"y\":21.9},{\"x\":1685213377932,\"y\":21.9},{\"x\":1685213677997,\"y\":21.9},{\"x\":1685213978205,\"y\":21.9},{\"x\":1685214293200,\"y\":21.9},{\"x\":1685214593270,\"y\":21.9},{\"x\":1685214893375,\"y\":21.9},{\"x\":1685215193482,\"y\":21.9},{\"x\":1685215493529,\"y\":21.8},{\"x\":1685215793531,\"y\":21.9},{\"x\":1685216093643,\"y\":21.9},{\"x\":1685216393738,\"y\":22},{\"x\":1685216693784,\"y\":21.9},{\"x\":1685216993880,\"y\":21.9},{\"x\":1685217293962,\"y\":21.7},{\"x\":1685217594100,\"y\":21.7},{\"x\":1685217894151,\"y\":21.7},{\"x\":1685218194256,\"y\":21.6},{\"x\":1685218494376,\"y\":21.5},{\"x\":1685218794467,\"y\":21.5},{\"x\":1685219094477,\"y\":21.5},{\"x\":1685219394675,\"y\":21.5},{\"x\":1685219709688,\"y\":21.5},{\"x\":1685220009789,\"y\":21.5},{\"x\":1685220309889,\"y\":21.5},{\"x\":1685220609986,\"y\":21.4},{\"x\":1685220910080,\"y\":21.5},{\"x\":1685221210236,\"y\":21.5},{\"x\":1685221510267,\"y\":21.5},{\"x\":1685221810331,\"y\":21.5},{\"x\":1685222110381,\"y\":21.4},{\"x\":1685222410481,\"y\":21.4},{\"x\":1685222710598,\"y\":21.3},{\"x\":1685223010661,\"y\":21.5},{\"x\":1685223310759,\"y\":21.5},{\"x\":1685223610881,\"y\":21.5},{\"x\":1685223911009,\"y\":21.5},{\"x\":1685224211106,\"y\":21.5},{\"x\":1685224511191,\"y\":21.5},{\"x\":1685224811272,\"y\":21.4},{\"x\":1685225111309,\"y\":21.4},{\"x\":1685225411398,\"y\":21.3},{\"x\":1685225711438,\"y\":21.2},{\"x\":1685226011552,\"y\":21.2},{\"x\":1685226311659,\"y\":21.2},{\"x\":1685226611773,\"y\":21.2},{\"x\":1685226911876,\"y\":21.2},{\"x\":1685227211995,\"y\":21.2},{\"x\":1685227512070,\"y\":21.2},{\"x\":1685227812175,\"y\":21.2},{\"x\":1685228112250,\"y\":21.2},{\"x\":1685228412314,\"y\":21},{\"x\":1685228712352,\"y\":21},{\"x\":1685229012470,\"y\":21},{\"x\":1685229312587,\"y\":21},{\"x\":1685229612662,\"y\":21.1},{\"x\":1685229912736,\"y\":21},{\"x\":1685230212847,\"y\":20.9},{\"x\":1685230512904,\"y\":21},{\"x\":1685230813034,\"y\":21},{\"x\":1685231113081,\"y\":21},{\"x\":1685231413122,\"y\":20.8},{\"x\":1685231713183,\"y\":20.8},{\"x\":1685232013342,\"y\":20.8},{\"x\":1685232328321,\"y\":20.8},{\"x\":1685232628419,\"y\":20.8},{\"x\":1685232928528,\"y\":20.8},{\"x\":1685233228604,\"y\":20.8},{\"x\":1685233528687,\"y\":20.8},{\"x\":1685233828743,\"y\":20.8},{\"x\":1685234128809,\"y\":20.8},{\"x\":1685234428883,\"y\":20.8},{\"x\":1685234728963,\"y\":20.8},{\"x\":1685235028977,\"y\":20.8},{\"x\":1685235329064,\"y\":20.8},{\"x\":1685235629163,\"y\":20.8},{\"x\":1685235929251,\"y\":20.8},{\"x\":1685236229341,\"y\":20.8},{\"x\":1685236529423,\"y\":20.7},{\"x\":1685236829513,\"y\":20.7},{\"x\":1685237129612,\"y\":20.8},{\"x\":1685237429697,\"y\":20.7},{\"x\":1685237729771,\"y\":20.7},{\"x\":1685238029832,\"y\":20.5},{\"x\":1685238329902,\"y\":20.5},{\"x\":1685238629974,\"y\":20.5},{\"x\":1685238930096,\"y\":20.5},{\"x\":1685239230144,\"y\":20.6},{\"x\":1685239530225,\"y\":20.6},{\"x\":1685239830331,\"y\":20.6},{\"x\":1685240130366,\"y\":20.6},{\"x\":1685240430509,\"y\":20.5},{\"x\":1685240730597,\"y\":20.5},{\"x\":1685241030697,\"y\":20.4},{\"x\":1685241330716,\"y\":20.4},{\"x\":1685241630792,\"y\":20.4},{\"x\":1685241930839,\"y\":20.4},{\"x\":1685242230957,\"y\":20.4},{\"x\":1685242531061,\"y\":20.4},{\"x\":1685242831116,\"y\":20.4},{\"x\":1685243131245,\"y\":20.4},{\"x\":1685243431358,\"y\":20.4},{\"x\":1685243731422,\"y\":20.3},{\"x\":1685244031484,\"y\":20.3},{\"x\":1685244331554,\"y\":20.2},{\"x\":1685244631614,\"y\":20.3},{\"x\":1685244931700,\"y\":20.3},{\"x\":1685245231790,\"y\":20.3},{\"x\":1685245531908,\"y\":20.3},{\"x\":1685245832059,\"y\":20.3},{\"x\":1685246132107,\"y\":20.3},{\"x\":1685246432206,\"y\":20.3},{\"x\":1685246732334,\"y\":20.3},{\"x\":1685247032445,\"y\":20.3},{\"x\":1685247332472,\"y\":20.2},{\"x\":1685247632538,\"y\":20.2},{\"x\":1685247932668,\"y\":20.2},{\"x\":1685248232731,\"y\":20.2},{\"x\":1685248532806,\"y\":20.2},{\"x\":1685248832930,\"y\":20.2},{\"x\":1685249133015,\"y\":20.2},{\"x\":1685249433093,\"y\":20.2},{\"x\":1685249733189,\"y\":20.2},{\"x\":1685250033291,\"y\":20.1},{\"x\":1685250333378,\"y\":20},{\"x\":1685250633446,\"y\":20},{\"x\":1685250933493,\"y\":20},{\"x\":1685251233569,\"y\":20},{\"x\":1685251533627,\"y\":20},{\"x\":1685251833774,\"y\":20.1},{\"x\":1685252133852,\"y\":20.2},{\"x\":1685252433955,\"y\":20.2},{\"x\":1685252734091,\"y\":20.2},{\"x\":1685253034179,\"y\":20},{\"x\":1685253334257,\"y\":19.9},{\"x\":1685253634325,\"y\":20},{\"x\":1685253934367,\"y\":20.2},{\"x\":1685254234489,\"y\":20.2},{\"x\":1685254534587,\"y\":20.2},{\"x\":1685254834680,\"y\":20.2},{\"x\":1685255134805,\"y\":20.3},{\"x\":1685255434885,\"y\":20.3},{\"x\":1685255735002,\"y\":20.3},{\"x\":1685256035085,\"y\":20.5},{\"x\":1685256335179,\"y\":20.5},{\"x\":1685256635254,\"y\":20.3},{\"x\":1685256935309,\"y\":20.3},{\"x\":1685257235338,\"y\":20.3},{\"x\":1685257535440,\"y\":20.3},{\"x\":1685257835520,\"y\":20.4},{\"x\":1685258135635,\"y\":20.5},{\"x\":1685258435709,\"y\":20.5},{\"x\":1685258735790,\"y\":20.5},{\"x\":1685259035904,\"y\":20.5},{\"x\":1685259335965,\"y\":20.4},{\"x\":1685259636005,\"y\":20.4},{\"x\":1685259936052,\"y\":20.4},{\"x\":1685260236148,\"y\":20.5},{\"x\":1685260536249,\"y\":20.4},{\"x\":1685260836320,\"y\":20.5},{\"x\":1685261136489,\"y\":20.5},{\"x\":1685261436489,\"y\":20.6},{\"x\":1685261736607,\"y\":20.5},{\"x\":1685262036710,\"y\":20.5},{\"x\":1685262336806,\"y\":20.4},{\"x\":1685262636943,\"y\":20.4},{\"x\":1685262936991,\"y\":20.3},{\"x\":1685263237019,\"y\":20.3},{\"x\":1685263537113,\"y\":20.3},{\"x\":1685263837223,\"y\":20.3},{\"x\":1685264137303,\"y\":20.3},{\"x\":1685264437449,\"y\":20.4},{\"x\":1685264737520,\"y\":20.3},{\"x\":1685265037596,\"y\":20.4},{\"x\":1685265337653,\"y\":20.3},{\"x\":1685265637725,\"y\":20.3},{\"x\":1685265937773,\"y\":20.3},{\"x\":1685266237884,\"y\":20.3},{\"x\":1685266537917,\"y\":20.3},{\"x\":1685266837940,\"y\":20.3},{\"x\":1685267138006,\"y\":20.3},{\"x\":1685267438089,\"y\":20.3},{\"x\":1685267738177,\"y\":20.3},{\"x\":1685268038239,\"y\":20.4},{\"x\":1685268338288,\"y\":20.3},{\"x\":1685268638340,\"y\":20.4},{\"x\":1685268938413,\"y\":20.3},{\"x\":1685269238479,\"y\":20.4},{\"x\":1685269538567,\"y\":20.4},{\"x\":1685269838641,\"y\":20.4},{\"x\":1685270138681,\"y\":20.3},{\"x\":1685270438761,\"y\":20.3},{\"x\":1685270738813,\"y\":20.3},{\"x\":1685271038911,\"y\":20.3},{\"x\":1685271338993,\"y\":20},{\"x\":1685271638994,\"y\":20},{\"x\":1685271939107,\"y\":20.2},{\"x\":1685272239155,\"y\":20.3},{\"x\":1685272539230,\"y\":20.3},{\"x\":1685272839299,\"y\":20.3},{\"x\":1685273139339,\"y\":20.3},{\"x\":1685273439382,\"y\":20.2},{\"x\":1685273739450,\"y\":19.9},{\"x\":1685274039516,\"y\":19.9},{\"x\":1685274339570,\"y\":20.2},{\"x\":1685274639651,\"y\":20.3},{\"x\":1685274939715,\"y\":20.5},{\"x\":1685275239718,\"y\":20.5},{\"x\":1685275539821,\"y\":20.6},{\"x\":1685275839883,\"y\":20.5},{\"x\":1685276139936,\"y\":20.3},{\"x\":1685276439971,\"y\":20.3},{\"x\":1685276740019,\"y\":20.3},{\"x\":1685277040061,\"y\":20.2},{\"x\":1685277340154,\"y\":20},{\"x\":1685277640177,\"y\":19.9},{\"x\":1685277940231,\"y\":20},{\"x\":1685278240249,\"y\":20},{\"x\":1685278540299,\"y\":19.9},{\"x\":1685278840376,\"y\":19.9},{\"x\":1685279140399,\"y\":19.5},{\"x\":1685279440422,\"y\":19.7},{\"x\":1685279740489,\"y\":19.8},{\"x\":1685280040542,\"y\":19.8},{\"x\":1685280340547,\"y\":19.5},{\"x\":1685280640612,\"y\":19.5},{\"x\":1685280940692,\"y\":19.5},{\"x\":1685280995978,\"y\":19.5},{\"x\":1685281186232,\"y\":19.5},{\"x\":1685281372604,\"y\":19.5},{\"x\":1685281687601,\"y\":19.5},{\"x\":1685281710226,\"y\":19.5},{\"x\":1685281749591,\"y\":19.5},{\"x\":1685281762017,\"y\":19.5},{\"x\":1685281799605,\"y\":19.5},{\"x\":1685282023556,\"y\":19.5},{\"x\":1685282044430,\"y\":19.5},{\"x\":1685282166915,\"y\":19.5},{\"x\":1685282208131,\"y\":19.5},{\"x\":1685282217923,\"y\":19.5},{\"x\":1685282260379,\"y\":19.5},{\"x\":1685282339652,\"y\":19.5},{\"x\":1685282364558,\"y\":19.5},{\"x\":1685282412077,\"y\":19.5},{\"x\":1685282588188,\"y\":19.5},{\"x\":1685282614967,\"y\":19.5},{\"x\":1685282852605,\"y\":19.5},{\"x\":1685282960718,\"y\":19.5},{\"x\":1685282980565,\"y\":19.5},{\"x\":1685283037810,\"y\":19.5},{\"x\":1685283067001,\"y\":19.5},{\"x\":1685283122144,\"y\":19.5},{\"x\":1685283272482,\"y\":19.5},{\"x\":1685283343031,\"y\":19.5},{\"x\":1685283445211,\"y\":19.5},{\"x\":1685283473050,\"y\":19.5},{\"x\":1685283503945,\"y\":19.4},{\"x\":1685283559122,\"y\":19.5},{\"x\":1685283661335,\"y\":19.5},{\"x\":1685283679196,\"y\":19.5},{\"x\":1685283753141,\"y\":19.5},{\"x\":1685283789923,\"y\":19.4},{\"x\":1685283796674,\"y\":19.4},{\"x\":1685284111596,\"y\":19.5},{\"x\":1685284411624,\"y\":19.5},{\"x\":1685284726634,\"y\":20},{\"x\":1685285041633,\"y\":19.9},{\"x\":1685285341650,\"y\":19.6},{\"x\":1685285641691,\"y\":19.8},{\"x\":1685285941711,\"y\":20},{\"x\":1685286241759,\"y\":20},{\"x\":1685286541841,\"y\":19.7},{\"x\":1685286856821,\"y\":20},{\"x\":1685287156833,\"y\":20.3},{\"x\":1685287456865,\"y\":20.4},{\"x\":1685287756902,\"y\":20.3},{\"x\":1685288056933,\"y\":20.3},{\"x\":1685288357007,\"y\":20.3},{\"x\":1685288671988,\"y\":20.1},{\"x\":1685288972004,\"y\":20.2},{\"x\":1685289272052,\"y\":20},{\"x\":1685289572077,\"y\":20},{\"x\":1685289872089,\"y\":20},{\"x\":1685290172161,\"y\":19.9},{\"x\":1685290487147,\"y\":20},{\"x\":1685290787163,\"y\":20},{\"x\":1685291087218,\"y\":19.9},{\"x\":1685291387247,\"y\":19.9},{\"x\":1685291687274,\"y\":20},{\"x\":1685291987283,\"y\":20.2},{\"x\":1685292287334,\"y\":20},{\"x\":1685292587380,\"y\":19.9},{\"x\":1685292887389,\"y\":19.9},{\"x\":1685293187427,\"y\":19.8},{\"x\":1685293502456,\"y\":19.7},{\"x\":1685293817480,\"y\":19.5},{\"x\":1685294117492,\"y\":19.6},{\"x\":1685294417507,\"y\":19.9},{\"x\":1685294717548,\"y\":20},{\"x\":1685295017585,\"y\":19.9},{\"x\":1685295317622,\"y\":19.6},{\"x\":1685295617633,\"y\":20},{\"x\":1685295917642,\"y\":19.7},{\"x\":1685296217701,\"y\":19.9},{\"x\":1685296532704,\"y\":19.5},{\"x\":1685296832750,\"y\":19.5},{\"x\":1685297132754,\"y\":19.5},{\"x\":1685297432771,\"y\":19.5},{\"x\":1685297732796,\"y\":19.5},{\"x\":1685298032828,\"y\":19.5},{\"x\":1685298332882,\"y\":19.5},{\"x\":1685298647889,\"y\":19.5},{\"x\":1685298947921,\"y\":19.5},{\"x\":1685299247969,\"y\":19.5},{\"x\":1685299547997,\"y\":19.5},{\"x\":1685299848026,\"y\":19.5},{\"x\":1685300163050,\"y\":19.5},{\"x\":1685300463065,\"y\":19.5},{\"x\":1685300763075,\"y\":19.5},{\"x\":1685301063109,\"y\":19.5},{\"x\":1685301363164,\"y\":19.5},{\"x\":1685301678208,\"y\":19.5},{\"x\":1685301993216,\"y\":19.5},{\"x\":1685302293269,\"y\":19.5},{\"x\":1685302593314,\"y\":19.5},{\"x\":1685302908310,\"y\":19.5},{\"x\":1685303208329,\"y\":19.5},{\"x\":1685303508359,\"y\":19.5},{\"x\":1685303808369,\"y\":19.5},{\"x\":1685304108395,\"y\":19.5},{\"x\":1685304408424,\"y\":19.3},{\"x\":1685304708455,\"y\":19.4},{\"x\":1685305008461,\"y\":19.4},{\"x\":1685305308490,\"y\":19.4},{\"x\":1685305608530,\"y\":19.5},{\"x\":1685305908539,\"y\":19.5},{\"x\":1685306208562,\"y\":19.4},{\"x\":1685306508616,\"y\":19.5},{\"x\":1685306823616,\"y\":19.5},{\"x\":1685307123649,\"y\":19.5},{\"x\":1685307423661,\"y\":19.5},{\"x\":1685307723699,\"y\":19.5},{\"x\":1685308023733,\"y\":19.5},{\"x\":1685308323779,\"y\":19.5},{\"x\":1685308638772,\"y\":19.5},{\"x\":1685308938793,\"y\":19.5},{\"x\":1685309238818,\"y\":19.5},{\"x\":1685309538833,\"y\":19.5},{\"x\":1685309838872,\"y\":19.5},{\"x\":1685310138910,\"y\":19.5},{\"x\":1685310453907,\"y\":19.5},{\"x\":1685310768906,\"y\":19.5},{\"x\":1685311068915,\"y\":19.5},{\"x\":1685311368965,\"y\":19.5},{\"x\":1685311668966,\"y\":19.5},{\"x\":1685311968998,\"y\":19.5},{\"x\":1685312269016,\"y\":19.5},{\"x\":1685312569034,\"y\":19.5},{\"x\":1685312869061,\"y\":19.5},{\"x\":1685313169072,\"y\":19.5},{\"x\":1685313484093,\"y\":19.5},{\"x\":1685313784097,\"y\":19.6},{\"x\":1685314084113,\"y\":19.5},{\"x\":1685314384134,\"y\":19.7},{\"x\":1685314684165,\"y\":19.9},{\"x\":1685314984191,\"y\":19.9},{\"x\":1685315299157,\"y\":19.9},{\"x\":1685315599168,\"y\":20},{\"x\":1685315899192,\"y\":19.9},{\"x\":1685316199221,\"y\":20.1},{\"x\":1685316514243,\"y\":20},{\"x\":1685316814264,\"y\":20.2},{\"x\":1685317129218,\"y\":20.2},{\"x\":1685317444217,\"y\":20.2},{\"x\":1685317744298,\"y\":20.3},{\"x\":1685318059259,\"y\":20.3},{\"x\":1685318359275,\"y\":20.3},{\"x\":1685318659355,\"y\":20.3},{\"x\":1685318959404,\"y\":20.3},{\"x\":1685319259419,\"y\":20.2},{\"x\":1685319559443,\"y\":20.3},{\"x\":1685319859535,\"y\":20.3},{\"x\":1685320159597,\"y\":20.3},{\"x\":1685320459678,\"y\":20.3},{\"x\":1685320759851,\"y\":20.3},{\"x\":1685321074857,\"y\":20.2},{\"x\":1685321374890,\"y\":20.3},{\"x\":1685321674930,\"y\":20.3},{\"x\":1685321974980,\"y\":20.3},{\"x\":1685322274993,\"y\":20.3},{\"x\":1685322575024,\"y\":20.3},{\"x\":1685322875122,\"y\":20.3},{\"x\":1685323175196,\"y\":20.3},{\"x\":1685323475244,\"y\":20.3},{\"x\":1685323775309,\"y\":20.4},{\"x\":1685324075375,\"y\":20.3},{\"x\":1685324375402,\"y\":20.4},{\"x\":1685324675425,\"y\":20.5},{\"x\":1685324975485,\"y\":20.5},{\"x\":1685325275523,\"y\":20.5},{\"x\":1685325575582,\"y\":20.5},{\"x\":1685325875647,\"y\":20.5},{\"x\":1685326175713,\"y\":20.5},{\"x\":1685326475768,\"y\":20.4},{\"x\":1685326775825,\"y\":20.4},{\"x\":1685327075908,\"y\":20.4},{\"x\":1685327376002,\"y\":20.4},{\"x\":1685327676015,\"y\":20.4},{\"x\":1685327976059,\"y\":20.4},{\"x\":1685328276184,\"y\":20.4},{\"x\":1685328591156,\"y\":20.4},{\"x\":1685328891332,\"y\":20.4},{\"x\":1685329206306,\"y\":20.4},{\"x\":1685329506397,\"y\":20.4},{\"x\":1685329806440,\"y\":20.3},{\"x\":1685330106549,\"y\":20.3},{\"x\":1685330406587,\"y\":20.3},{\"x\":1685330706687,\"y\":20.2},{\"x\":1685331006741,\"y\":20.3},{\"x\":1685331306759,\"y\":20.3},{\"x\":1685331606822,\"y\":20.2},{\"x\":1685331906872,\"y\":20.2},{\"x\":1685332206974,\"y\":20.2},{\"x\":1685332507043,\"y\":20.3},{\"x\":1685332807216,\"y\":20.2},{\"x\":1685333122210,\"y\":20.2},{\"x\":1685333422298,\"y\":20.2},{\"x\":1685333722396,\"y\":20.2},{\"x\":1685334022464,\"y\":20.2},{\"x\":1685334322536,\"y\":20.2},{\"x\":1685334622591,\"y\":20.2},{\"x\":1685334922644,\"y\":20.2},{\"x\":1685335222714,\"y\":20.1},{\"x\":1685335522841,\"y\":20},{\"x\":1685335822919,\"y\":20},{\"x\":1685336122954,\"y\":20},{\"x\":1685336423087,\"y\":19.9},{\"x\":1685336723138,\"y\":20},{\"x\":1685337023185,\"y\":19.9},{\"x\":1685337323274,\"y\":19.9},{\"x\":1685337623330,\"y\":19.9},{\"x\":1685337923414,\"y\":20},{\"x\":1685338223520,\"y\":19.9},{\"x\":1685338523616,\"y\":20},{\"x\":1685338823724,\"y\":19.9},{\"x\":1685339123797,\"y\":20},{\"x\":1685339423870,\"y\":19.9},{\"x\":1685339723950,\"y\":19.9},{\"x\":1685340024030,\"y\":19.9},{\"x\":1685340324090,\"y\":20},{\"x\":1685340624115,\"y\":20},{\"x\":1685340924164,\"y\":20},{\"x\":1685341224265,\"y\":20},{\"x\":1685341524353,\"y\":20},{\"x\":1685341824453,\"y\":20},{\"x\":1685342124531,\"y\":20.2},{\"x\":1685342424622,\"y\":19.9},{\"x\":1685342724753,\"y\":20},{\"x\":1685343024799,\"y\":20.2},{\"x\":1685343324830,\"y\":20},{\"x\":1685343624890,\"y\":19.9},{\"x\":1685343924971,\"y\":20.2},{\"x\":1685344225070,\"y\":20.2},{\"x\":1685344525149,\"y\":20.3},{\"x\":1685344825216,\"y\":20.2},{\"x\":1685345125344,\"y\":20.2},{\"x\":1685345425362,\"y\":20.3},{\"x\":1685345725441,\"y\":20.3},{\"x\":1685346025536,\"y\":20.3},{\"x\":1685346325591,\"y\":20},{\"x\":1685346625679,\"y\":20.2},{\"x\":1685346925731,\"y\":20.2},{\"x\":1685347225748,\"y\":20.3},{\"x\":1685347525839,\"y\":20.3},{\"x\":1685347825931,\"y\":20.3},{\"x\":1685348126031,\"y\":20.3},{\"x\":1685348426089,\"y\":20.3},{\"x\":1685348726163,\"y\":20.3},{\"x\":1685349026225,\"y\":20.3},{\"x\":1685349326308,\"y\":20.3},{\"x\":1685349626392,\"y\":20},{\"x\":1685349926466,\"y\":20},{\"x\":1685350226553,\"y\":20.2},{\"x\":1685350526651,\"y\":19.9},{\"x\":1685350826811,\"y\":20},{\"x\":1685351141763,\"y\":19.9},{\"x\":1685351441827,\"y\":20.2},{\"x\":1685351741927,\"y\":20.2},{\"x\":1685352042064,\"y\":20.1},{\"x\":1685352342100,\"y\":20.3},{\"x\":1685352642170,\"y\":20},{\"x\":1685352942245,\"y\":19.9},{\"x\":1685353242314,\"y\":19.9},{\"x\":1685353542387,\"y\":20},{\"x\":1685353842461,\"y\":20},{\"x\":1685354142491,\"y\":20},{\"x\":1685354442557,\"y\":19.9},{\"x\":1685354742628,\"y\":20},{\"x\":1685355042729,\"y\":20.3},{\"x\":1685355342838,\"y\":20.2},{\"x\":1685355642921,\"y\":20.3},{\"x\":1685355942977,\"y\":20},{\"x\":1685356243149,\"y\":19.9},{\"x\":1685356558148,\"y\":19.5},{\"x\":1685356858211,\"y\":19.9},{\"x\":1685357158249,\"y\":20},{\"x\":1685357458282,\"y\":19.6},{\"x\":1685357758424,\"y\":20},{\"x\":1685358058471,\"y\":19.5},{\"x\":1685358358569,\"y\":19.5},{\"x\":1685358658635,\"y\":20},{\"x\":1685358958716,\"y\":20.1},{\"x\":1685359258767,\"y\":20},{\"x\":1685359558873,\"y\":19.9},{\"x\":1685359858954,\"y\":20.2},{\"x\":1685360159014,\"y\":20.2},{\"x\":1685360459077,\"y\":20},{\"x\":1685360759117,\"y\":19.9},{\"x\":1685361059194,\"y\":19.8},{\"x\":1685361359285,\"y\":20},{\"x\":1685361659377,\"y\":20},{\"x\":1685361959454,\"y\":20.1},{\"x\":1685362259508,\"y\":20.2},{\"x\":1685362559586,\"y\":19.9},{\"x\":1685362859674,\"y\":20},{\"x\":1685363159756,\"y\":20},{\"x\":1685363459810,\"y\":19.5},{\"x\":1685363759869,\"y\":19.6},{\"x\":1685364059953,\"y\":19.5},{\"x\":1685364360040,\"y\":19.9},{\"x\":1685364660157,\"y\":19.9},{\"x\":1685364960261,\"y\":19.9},{\"x\":1685365260272,\"y\":19.9},{\"x\":1685365560367,\"y\":20},{\"x\":1685365860483,\"y\":19.9},{\"x\":1685366160569,\"y\":19.9},{\"x\":1685366460633,\"y\":19.5},{\"x\":1685366760670,\"y\":19.5},{\"x\":1685367060781,\"y\":19.5},{\"x\":1685367360928,\"y\":19.5},{\"x\":1685367660996,\"y\":19.5},{\"x\":1685367961125,\"y\":19.5},{\"x\":1685368261267,\"y\":19.5},{\"x\":1685368561326,\"y\":19.5},{\"x\":1685368861443,\"y\":19.5},{\"x\":1685369161528,\"y\":19.5},{\"x\":1685369461571,\"y\":19.5},{\"x\":1685369761618,\"y\":19.5},{\"x\":1685370061811,\"y\":19.5},{\"x\":1685370361876,\"y\":19.5},{\"x\":1685370661975,\"y\":19.5},{\"x\":1685370962096,\"y\":19.5},{\"x\":1685371262161,\"y\":19.5},{\"x\":1685371562287,\"y\":19.5},{\"x\":1685371862386,\"y\":19.5},{\"x\":1685372162471,\"y\":19.5},{\"x\":1685372462563,\"y\":19.4},{\"x\":1685372762583,\"y\":19.2},{\"x\":1685373062692,\"y\":19.2},{\"x\":1685373362813,\"y\":19.1},{\"x\":1685373662925,\"y\":19.3},{\"x\":1685373963012,\"y\":19.2},{\"x\":1685374263073,\"y\":19.2},{\"x\":1685374563193,\"y\":19},{\"x\":1685374863306,\"y\":19.2},{\"x\":1685375163412,\"y\":19.3},{\"x\":1685375463446,\"y\":19.4},{\"x\":1685375763533,\"y\":19.4},{\"x\":1685376063611,\"y\":19.2},{\"x\":1685376363690,\"y\":19.1},{\"x\":1685376663795,\"y\":19},{\"x\":1685376963909,\"y\":19.2},{\"x\":1685377263998,\"y\":19.3},{\"x\":1685377564112,\"y\":19.1},{\"x\":1685377864184,\"y\":19.2},{\"x\":1685378164260,\"y\":19.1},{\"x\":1685378464309,\"y\":19},{\"x\":1685378764426,\"y\":19},{\"x\":1685379064528,\"y\":19},{\"x\":1685379364568,\"y\":19.2},{\"x\":1685379664627,\"y\":19.1},{\"x\":1685379964711,\"y\":19},{\"x\":1685380264778,\"y\":19.1},{\"x\":1685380564838,\"y\":19.2},{\"x\":1685380864899,\"y\":19},{\"x\":1685381164922,\"y\":19},{\"x\":1685381464995,\"y\":18.9},{\"x\":1685381765085,\"y\":18.9},{\"x\":1685382065145,\"y\":18.9},{\"x\":1685382365238,\"y\":18.9},{\"x\":1685382665304,\"y\":18.9},{\"x\":1685382965394,\"y\":19},{\"x\":1685383265458,\"y\":19},{\"x\":1685383565523,\"y\":18.9},{\"x\":1685383865573,\"y\":18.9},{\"x\":1685384165635,\"y\":18.7},{\"x\":1685384465670,\"y\":18.7},{\"x\":1685384765740,\"y\":18.7},{\"x\":1685385065812,\"y\":18.9},{\"x\":1685385365909,\"y\":18.8},{\"x\":1685385665940,\"y\":18.7},{\"x\":1685385966015,\"y\":18.9},{\"x\":1685386266095,\"y\":18.9},{\"x\":1685386566159,\"y\":18.8},{\"x\":1685386866204,\"y\":18.5},{\"x\":1685387166270,\"y\":18.5},{\"x\":1685387466325,\"y\":18.7},{\"x\":1685387766371,\"y\":18.5},{\"x\":1685388066417,\"y\":18.7},{\"x\":1685388366441,\"y\":18.7},{\"x\":1685388666495,\"y\":18.7},{\"x\":1685388966561,\"y\":18.4},{\"x\":1685389266600,\"y\":18.4},{\"x\":1685389566607,\"y\":18.4},{\"x\":1685389866660,\"y\":18.4},{\"x\":1685390166677,\"y\":18.5},{\"x\":1685390466746,\"y\":18.5},{\"x\":1685390781720,\"y\":18.6},{\"x\":1685391081770,\"y\":18.6},{\"x\":1685391381808,\"y\":18.4},{\"x\":1685391681836,\"y\":18.4},{\"x\":1685391981922,\"y\":18.4},{\"x\":1685392281964,\"y\":18.4},{\"x\":1685392582032,\"y\":18.4},{\"x\":1685392897029,\"y\":18.4},{\"x\":1685393197037,\"y\":18.4},{\"x\":1685393497068,\"y\":18.4},{\"x\":1685393797107,\"y\":18.4},{\"x\":1685394097146,\"y\":18.4},{\"x\":1685394397195,\"y\":18.4},{\"x\":1685394697240,\"y\":18.4},{\"x\":1685394997269,\"y\":18.4},{\"x\":1685395297315,\"y\":18.4},{\"x\":1685395597344,\"y\":18.4},{\"x\":1685395897378,\"y\":18.4},{\"x\":1685396197391,\"y\":18.4},{\"x\":1685396497411,\"y\":18.4},{\"x\":1685396797418,\"y\":18.3},{\"x\":1685397097514,\"y\":18.4},{\"x\":1685397397526,\"y\":18.2},{\"x\":1685397697553,\"y\":18.1},{\"x\":1685397997603,\"y\":18.1},{\"x\":1685398297622,\"y\":18.1},{\"x\":1685398597700,\"y\":18.1},{\"x\":1685398897737,\"y\":18.2},{\"x\":1685399212765,\"y\":18.2},{\"x\":1685399527768,\"y\":18},{\"x\":1685399827776,\"y\":18.1},{\"x\":1685400127841,\"y\":17.9},{\"x\":1685400442841,\"y\":18},{\"x\":1685400742935,\"y\":17.9},{\"x\":1685401057950,\"y\":18},{\"x\":1685401357960,\"y\":18},{\"x\":1685401657984,\"y\":18.1},{\"x\":1685401957995,\"y\":18},{\"x\":1685402258067,\"y\":18.1},{\"x\":1685402573081,\"y\":18},{\"x\":1685402873096,\"y\":17.9},{\"x\":1685403173117,\"y\":17.9},{\"x\":1685403473129,\"y\":17.9},{\"x\":1685403773148,\"y\":17.9},{\"x\":1685404073175,\"y\":18},{\"x\":1685404373229,\"y\":17.9},{\"x\":1685404688249,\"y\":17.9},{\"x\":1685404988317,\"y\":17.9},{\"x\":1685405288409,\"y\":17.9},{\"x\":1685405588488,\"y\":17.9},{\"x\":1685405888522,\"y\":17.9},{\"x\":1685406188569,\"y\":17.9},{\"x\":1685406488623,\"y\":17.9},{\"x\":1685406788688,\"y\":17.9},{\"x\":1685407088721,\"y\":17.9},{\"x\":1685407388765,\"y\":17.9},{\"x\":1685407688838,\"y\":17.9},{\"x\":1685407988885,\"y\":17.9},{\"x\":1685408288915,\"y\":17.9},{\"x\":1685408588993,\"y\":17.9},{\"x\":1685408889074,\"y\":17.9},{\"x\":1685409189147,\"y\":17.9},{\"x\":1685409489206,\"y\":17.9},{\"x\":1685409789249,\"y\":17.9},{\"x\":1685410089310,\"y\":17.9},{\"x\":1685410389345,\"y\":17.9},{\"x\":1685410704354,\"y\":17.9},{\"x\":1685411004452,\"y\":17.9},{\"x\":1685411304516,\"y\":17.9},{\"x\":1685411604552,\"y\":17.9},{\"x\":1685411904625,\"y\":17.8},{\"x\":1685412204887,\"y\":17.8},{\"x\":1685412519762,\"y\":17.7},{\"x\":1685412819867,\"y\":17.7},{\"x\":1685413119886,\"y\":17.8},{\"x\":1685413419976,\"y\":17.7},{\"x\":1685413719986,\"y\":17.7},{\"x\":1685414020028,\"y\":17.7},{\"x\":1685414320085,\"y\":17.7},{\"x\":1685414620140,\"y\":17.7},{\"x\":1685414920229,\"y\":17.7},{\"x\":1685415220270,\"y\":17.7},{\"x\":1685415520407,\"y\":17.7},{\"x\":1685415820425,\"y\":17.7},{\"x\":1685416120509,\"y\":17.7},{\"x\":1685416420519,\"y\":17.7},{\"x\":1685416720605,\"y\":17.7},{\"x\":1685417020626,\"y\":17.7},{\"x\":1685417320672,\"y\":17.7},{\"x\":1685417620774,\"y\":17.7},{\"x\":1685417920843,\"y\":17.7},{\"x\":1685418220900,\"y\":17.8},{\"x\":1685418520971,\"y\":17.7},{\"x\":1685418821022,\"y\":17.7},{\"x\":1685419121073,\"y\":17.8},{\"x\":1685419421171,\"y\":17.9},{\"x\":1685419721181,\"y\":17.7},{\"x\":1685420021225,\"y\":17.7},{\"x\":1685420321304,\"y\":17.6},{\"x\":1685420621355,\"y\":17.7},{\"x\":1685420921447,\"y\":17.7},{\"x\":1685421221522,\"y\":17.7},{\"x\":1685421521582,\"y\":17.7},{\"x\":1685421821663,\"y\":17.7},{\"x\":1685422121736,\"y\":17.6},{\"x\":1685422421818,\"y\":17.7},{\"x\":1685422721865,\"y\":17.7},{\"x\":1685423021869,\"y\":17.6},{\"x\":1685423321956,\"y\":17.4},{\"x\":1685423622015,\"y\":17.5},{\"x\":1685423922080,\"y\":17.4},{\"x\":1685424222162,\"y\":17.5},{\"x\":1685424522203,\"y\":17.5},{\"x\":1685424822288,\"y\":17.5},{\"x\":1685425122362,\"y\":17.4},{\"x\":1685425422438,\"y\":17.4},{\"x\":1685425722513,\"y\":17.4},{\"x\":1685426022547,\"y\":17.4},{\"x\":1685426322620,\"y\":17.5},{\"x\":1685426622723,\"y\":17.5},{\"x\":1685426922744,\"y\":17.4},{\"x\":1685427222854,\"y\":17.4},{\"x\":1685427522913,\"y\":17.4},{\"x\":1685427823002,\"y\":17.4},{\"x\":1685428123104,\"y\":17.5},{\"x\":1685428423173,\"y\":17.5},{\"x\":1685428723329,\"y\":17.4},{\"x\":1685429038338,\"y\":17.4},{\"x\":1685429338390,\"y\":17.4},{\"x\":1685429638534,\"y\":17.4},{\"x\":1685429938550,\"y\":17.4},{\"x\":1685430238655,\"y\":17.4},{\"x\":1685430538750,\"y\":17.4},{\"x\":1685430838822,\"y\":17.3},{\"x\":1685431139008,\"y\":17.5},{\"x\":1685431439050,\"y\":17.5},{\"x\":1685431739109,\"y\":17.4},{\"x\":1685432039156,\"y\":17.5},{\"x\":1685432339204,\"y\":17.7},{\"x\":1685432639299,\"y\":17.3},{\"x\":1685432939394,\"y\":17.2},{\"x\":1685433239499,\"y\":17.2},{\"x\":1685433539575,\"y\":17.2},{\"x\":1685433839700,\"y\":17.2},{\"x\":1685434139771,\"y\":16.9},{\"x\":1685434439873,\"y\":16.7},{\"x\":1685434739965,\"y\":16.5},{\"x\":1685435040038,\"y\":16.5},{\"x\":1685435340054,\"y\":16.5},{\"x\":1685435640133,\"y\":16.5},{\"x\":1685435940205,\"y\":16.5},{\"x\":1685436240311,\"y\":16.8},{\"x\":1685436540423,\"y\":16.9},{\"x\":1685436840548,\"y\":17.1},{\"x\":1685437140665,\"y\":17},{\"x\":1685437440701,\"y\":16.8},{\"x\":1685437740799,\"y\":16.5},{\"x\":1685438040887,\"y\":16.5},{\"x\":1685438340964,\"y\":16.5},{\"x\":1685438641030,\"y\":17.2},{\"x\":1685438941063,\"y\":17.2},{\"x\":1685439241150,\"y\":17.2},{\"x\":1685439541265,\"y\":17},{\"x\":1685439841366,\"y\":17.2},{\"x\":1685440141451,\"y\":16.5},{\"x\":1685440441506,\"y\":16.5},{\"x\":1685440741607,\"y\":16.5},{\"x\":1685441041684,\"y\":16.5},{\"x\":1685441341786,\"y\":16.5},{\"x\":1685441641830,\"y\":16.5},{\"x\":1685441941863,\"y\":16.5},{\"x\":1685442241939,\"y\":17},{\"x\":1685442542010,\"y\":17.3},{\"x\":1685442842108,\"y\":17.2},{\"x\":1685443142199,\"y\":16.6},{\"x\":1685443442319,\"y\":17.2},{\"x\":1685443742376,\"y\":16.5},{\"x\":1685444042480,\"y\":16.8},{\"x\":1685444342574,\"y\":16.8},{\"x\":1685444642649,\"y\":16.5},{\"x\":1685444942748,\"y\":17.2},{\"x\":1685445242792,\"y\":17.1},{\"x\":1685445542799,\"y\":17.2},{\"x\":1685445842907,\"y\":17.3},{\"x\":1685446143003,\"y\":17.4},{\"x\":1685446443122,\"y\":17.4},{\"x\":1685446743194,\"y\":17.3},{\"x\":1685447043298,\"y\":17.2},{\"x\":1685447343341,\"y\":17.4},{\"x\":1685447643442,\"y\":17.2},{\"x\":1685447943557,\"y\":17.2},{\"x\":1685448243632,\"y\":17.3},{\"x\":1685448543708,\"y\":17.2},{\"x\":1685448843747,\"y\":17.1},{\"x\":1685449143768,\"y\":16.6},{\"x\":1685449443878,\"y\":16.5},{\"x\":1685449743965,\"y\":16.5},{\"x\":1685450044053,\"y\":16.5},{\"x\":1685450344178,\"y\":17.2},{\"x\":1685450644263,\"y\":17.3},{\"x\":1685450944279,\"y\":17.4},{\"x\":1685451244382,\"y\":17.2},{\"x\":1685451544448,\"y\":17.3},{\"x\":1685451844600,\"y\":17.3},{\"x\":1685452144626,\"y\":17.4},{\"x\":1685452444701,\"y\":17.4},{\"x\":1685452744749,\"y\":17.2},{\"x\":1685453044818,\"y\":17.4},{\"x\":1685453344909,\"y\":17.7},{\"x\":1685453645071,\"y\":17.6},{\"x\":1685453945113,\"y\":17.5},{\"x\":1685454245205,\"y\":17.6},{\"x\":1685454545276,\"y\":17.6},{\"x\":1685454845390,\"y\":17.7},{\"x\":1685455145455,\"y\":17.8},{\"x\":1685455445552,\"y\":17.7},{\"x\":1685455745631,\"y\":17.7},{\"x\":1685456045706,\"y\":17.7},{\"x\":1685456345813,\"y\":17.6},{\"x\":1685456645826,\"y\":17.7},{\"x\":1685456945928,\"y\":17.7},{\"x\":1685457246034,\"y\":17.4},{\"x\":1685457546104,\"y\":17.4},{\"x\":1685457846188,\"y\":17.6},{\"x\":1685458146263,\"y\":17.9},{\"x\":1685458446341,\"y\":17.9},{\"x\":1685458746470,\"y\":17.9},{\"x\":1685459046554,\"y\":17.8},{\"x\":1685459346643,\"y\":17.7},{\"x\":1685459646708,\"y\":17.9},{\"x\":1685459946734,\"y\":18},{\"x\":1685460246833,\"y\":17.9},{\"x\":1685460546913,\"y\":17.9},{\"x\":1685460847002,\"y\":17.9},{\"x\":1685461147079,\"y\":17.9},{\"x\":1685461447115,\"y\":17.9},{\"x\":1685461747181,\"y\":17.9},{\"x\":1685462047303,\"y\":17.9},{\"x\":1685462347360,\"y\":17.9},{\"x\":1685462647457,\"y\":17.9},{\"x\":1685462947533,\"y\":17.9},{\"x\":1685463247622,\"y\":17.9},{\"x\":1685463437946,\"y\":17.9},{\"x\":1685463752894,\"y\":17.9},{\"x\":1685464067891,\"y\":17.9},{\"x\":1685464367932,\"y\":17.9},{\"x\":1685464668016,\"y\":18.2},{\"x\":1685464968034,\"y\":18.2},{\"x\":1685465268109,\"y\":17.9},{\"x\":1685465568127,\"y\":17.9},{\"x\":1685465868179,\"y\":18},{\"x\":1685466168200,\"y\":18},{\"x\":1685466468292,\"y\":17.9},{\"x\":1685466783247,\"y\":17.9},{\"x\":1685467083281,\"y\":18},{\"x\":1685467383324,\"y\":18},{\"x\":1685467683356,\"y\":17.9},{\"x\":1685467983393,\"y\":17.9},{\"x\":1685468283508,\"y\":18},{\"x\":1685468598507,\"y\":17.9},{\"x\":1685468898532,\"y\":17.9},{\"x\":1685469198568,\"y\":17.9},{\"x\":1685469498602,\"y\":17.9},{\"x\":1685469798635,\"y\":17.9},{\"x\":1685470098653,\"y\":17.8},{\"x\":1685470398701,\"y\":17.8},{\"x\":1685470698741,\"y\":17.8},{\"x\":1685470998770,\"y\":17.7},{\"x\":1685471298800,\"y\":17.8},{\"x\":1685471598821,\"y\":17.9},{\"x\":1685471898877,\"y\":17.7},{\"x\":1685472198886,\"y\":17.7},{\"x\":1685472498957,\"y\":17.7},{\"x\":1685472798992,\"y\":17.7},{\"x\":1685473099049,\"y\":17.9},{\"x\":1685473414059,\"y\":17.9},{\"x\":1685473714086,\"y\":17.7},{\"x\":1685474014164,\"y\":17.6},{\"x\":1685474314238,\"y\":17.4},{\"x\":1685474629191,\"y\":17.5},{\"x\":1685474929212,\"y\":17.6},{\"x\":1685475229261,\"y\":17.7},{\"x\":1685475529275,\"y\":17.4},{\"x\":1685475829340,\"y\":17.4},{\"x\":1685476129417,\"y\":17.4},{\"x\":1685476429433,\"y\":17.4},{\"x\":1685476729449,\"y\":17.3},{\"x\":1685477029470,\"y\":17.2},{\"x\":1685477329512,\"y\":17.2},{\"x\":1685477629544,\"y\":17.3},{\"x\":1685477929562,\"y\":17.4},{\"x\":1685478229615,\"y\":17.3},{\"x\":1685478529641,\"y\":17},{\"x\":1685478829667,\"y\":16.5},{\"x\":1685479129749,\"y\":16.5},{\"x\":1685479429791,\"y\":16.5},{\"x\":1685479729807,\"y\":16.5},{\"x\":1685480029843,\"y\":16.5},{\"x\":1685480329850,\"y\":16.5},{\"x\":1685480629899,\"y\":16.7},{\"x\":1685480929954,\"y\":16.5},{\"x\":1685481244998,\"y\":16.5},{\"x\":1685481545012,\"y\":16.5},{\"x\":1685481845043,\"y\":16.5},{\"x\":1685482145093,\"y\":16.5},{\"x\":1685482445120,\"y\":16.5},{\"x\":1685482745153,\"y\":16.5},{\"x\":1685483045222,\"y\":16.5},{\"x\":1685483345235,\"y\":16.5},{\"x\":1685483645258,\"y\":16.5},{\"x\":1685483945299,\"y\":16.5},{\"x\":1685484245340,\"y\":16.5},{\"x\":1685484545382,\"y\":16.5},{\"x\":1685484845385,\"y\":16.5},{\"x\":1685485145425,\"y\":16.5},{\"x\":1685485445459,\"y\":16.5},{\"x\":1685485745479,\"y\":16.5},{\"x\":1685486045546,\"y\":16.5},{\"x\":1685486345575,\"y\":16.5},{\"x\":1685486645633,\"y\":16.5},{\"x\":1685486945725,\"y\":16.5},{\"x\":1685487260693,\"y\":16.5},{\"x\":1685487560707,\"y\":16.5},{\"x\":1685487860814,\"y\":16.5},{\"x\":1685488175808,\"y\":16.5},{\"x\":1685488475825,\"y\":16.5},{\"x\":1685488775853,\"y\":16.5},{\"x\":1685489075914,\"y\":16.5},{\"x\":1685489375930,\"y\":16.5},{\"x\":1685489675982,\"y\":16.5},{\"x\":1685489976039,\"y\":16.5},{\"x\":1685490276048,\"y\":16.5},{\"x\":1685490576126,\"y\":16.5},{\"x\":1685490876150,\"y\":16.5},{\"x\":1685491176154,\"y\":16.5},{\"x\":1685491476262,\"y\":16.5},{\"x\":1685491791218,\"y\":16.5},{\"x\":1685492091237,\"y\":16.5},{\"x\":1685492391276,\"y\":16.5},{\"x\":1685492691341,\"y\":16.5},{\"x\":1685492991352,\"y\":16.5},{\"x\":1685493291416,\"y\":16.5},{\"x\":1685493591464,\"y\":16.5},{\"x\":1685493891476,\"y\":16.2},{\"x\":1685494191553,\"y\":16.5},{\"x\":1685494491555,\"y\":16.5},{\"x\":1685494806655,\"y\":16.5},{\"x\":1685495121636,\"y\":16.5},{\"x\":1685495436647,\"y\":16.5},{\"x\":1685495736703,\"y\":16.5},{\"x\":1685496036726,\"y\":16.4},{\"x\":1685496336779,\"y\":16.5},{\"x\":1685496636854,\"y\":16.4},{\"x\":1685496951873,\"y\":16.4},{\"x\":1685497251911,\"y\":16.5},{\"x\":1685497566911,\"y\":16.5},{\"x\":1685497866915,\"y\":16.5},{\"x\":1685498166972,\"y\":16.2},{\"x\":1685498466989,\"y\":16.2},{\"x\":1685498767043,\"y\":16.4},{\"x\":1685499067095,\"y\":16.2},{\"x\":1685499367129,\"y\":16.5},{\"x\":1685499667180,\"y\":16.4},{\"x\":1685499967184,\"y\":16.5},{\"x\":1685500282215,\"y\":16.5},{\"x\":1685500582236,\"y\":16.5},{\"x\":1685500882309,\"y\":16.5},{\"x\":1685501197336,\"y\":16.4},{\"x\":1685501497371,\"y\":16.2},{\"x\":1685501797405,\"y\":16.3},{\"x\":1685502097446,\"y\":16.1},{\"x\":1685502397471,\"y\":16},{\"x\":1685502697518,\"y\":15.7},{\"x\":1685502997526,\"y\":16},{\"x\":1685503297549,\"y\":16},{\"x\":1685503597589,\"y\":16.2},{\"x\":1685503897624,\"y\":16.2},{\"x\":1685504197687,\"y\":16},{\"x\":1685504497728,\"y\":15.9},{\"x\":1685504797753,\"y\":16},{\"x\":1685505097809,\"y\":16},{\"x\":1685505397837,\"y\":16.2},{\"x\":1685505697885,\"y\":16.4},{\"x\":1685505997899,\"y\":16.3},{\"x\":1685506297916,\"y\":16.1},{\"x\":1685506597958,\"y\":16},{\"x\":1685506897987,\"y\":16},{\"x\":1685507198004,\"y\":15.8},{\"x\":1685507498078,\"y\":15.9},{\"x\":1685507798110,\"y\":16},{\"x\":1685508098131,\"y\":15.8},{\"x\":1685508398152,\"y\":16},{\"x\":1685508698194,\"y\":15.9},{\"x\":1685508998213,\"y\":15.8},{\"x\":1685509298220,\"y\":15.8},{\"x\":1685509598290,\"y\":15.9},{\"x\":1685509898323,\"y\":15.7},{\"x\":1685510198331,\"y\":15.7},{\"x\":1685510498370,\"y\":15.7},{\"x\":1685510798393,\"y\":15.5},{\"x\":1685511098454,\"y\":15.8},{\"x\":1685511398491,\"y\":15.7},{\"x\":1685511698520,\"y\":15.9},{\"x\":1685512013528,\"y\":15.9},{\"x\":1685512313605,\"y\":15.8},{\"x\":1685512628564,\"y\":15.7},{\"x\":1685512928630,\"y\":15.5},{\"x\":1685513228650,\"y\":15.5},{\"x\":1685513528663,\"y\":15.5},{\"x\":1685513828703,\"y\":15.6},{\"x\":1685514143711,\"y\":15.7},{\"x\":1685514443729,\"y\":15.7},{\"x\":1685514743749,\"y\":15.8},{\"x\":1685515043937,\"y\":15.7},{\"x\":1685515358896,\"y\":15.5},{\"x\":1685515658956,\"y\":15.6},{\"x\":1685515959007,\"y\":15.7},{\"x\":1685516259087,\"y\":15.6},{\"x\":1685516559112,\"y\":15.9},{\"x\":1685516859194,\"y\":16},{\"x\":1685517174175,\"y\":15.9},{\"x\":1685517474229,\"y\":15.8},{\"x\":1685517774323,\"y\":15.7},{\"x\":1685518074366,\"y\":15.7},{\"x\":1685518374438,\"y\":15.7},{\"x\":1685518674561,\"y\":15.9},{\"x\":1685518974586,\"y\":15.7},{\"x\":1685519274602,\"y\":16},{\"x\":1685519574700,\"y\":15.7},{\"x\":1685519889719,\"y\":15.8},{\"x\":1685520189753,\"y\":15.9},{\"x\":1685520489831,\"y\":15.8},{\"x\":1685520789861,\"y\":15.9},{\"x\":1685521089913,\"y\":16},{\"x\":1685521390016,\"y\":15.7},{\"x\":1685521690069,\"y\":15.5},{\"x\":1685521990135,\"y\":15.5},{\"x\":1685522290216,\"y\":15.5},{\"x\":1685522590301,\"y\":15.5},{\"x\":1685522905260,\"y\":15.7},{\"x\":1685523205311,\"y\":15.7},{\"x\":1685523505402,\"y\":15.7},{\"x\":1685523805456,\"y\":15.6},{\"x\":1685524105543,\"y\":15.9},{\"x\":1685524405592,\"y\":15.7},{\"x\":1685524705754,\"y\":15.5},{\"x\":1685525005757,\"y\":15.5},{\"x\":1685525305830,\"y\":15.7},{\"x\":1685525605894,\"y\":15.5},{\"x\":1685525905934,\"y\":15.7},{\"x\":1685526205944,\"y\":15.7},{\"x\":1685526505986,\"y\":15.5},{\"x\":1685526806078,\"y\":15.6},{\"x\":1685527106180,\"y\":15.8},{\"x\":1685527406287,\"y\":15.5},{\"x\":1685527706314,\"y\":15.6},{\"x\":1685528006417,\"y\":15.7},{\"x\":1685528306469,\"y\":15.8},{\"x\":1685528606541,\"y\":15.9},{\"x\":1685528906576,\"y\":15.7},{\"x\":1685529206598,\"y\":15.7},{\"x\":1685529506705,\"y\":15.7},{\"x\":1685529806799,\"y\":15.5},{\"x\":1685530106900,\"y\":15.7},{\"x\":1685530406997,\"y\":15.9},{\"x\":1685530707031,\"y\":15.9},{\"x\":1685531007135,\"y\":15.7},{\"x\":1685531307217,\"y\":15.9},{\"x\":1685531607277,\"y\":15.7},{\"x\":1685531907312,\"y\":15.9},{\"x\":1685532207333,\"y\":16},{\"x\":1685532507449,\"y\":15.9},{\"x\":1685532807538,\"y\":16},{\"x\":1685533107607,\"y\":15.9},{\"x\":1685533407716,\"y\":16.1},{\"x\":1685533707801,\"y\":16.4},{\"x\":1685534007891,\"y\":16.5},{\"x\":1685534307936,\"y\":17.9},{\"x\":1685534607976,\"y\":18.5},{\"x\":1685534908043,\"y\":19},{\"x\":1685535208090,\"y\":19.4},{\"x\":1685535508186,\"y\":19.5},{\"x\":1685535808331,\"y\":19.5},{\"x\":1685536108352,\"y\":19.5},{\"x\":1685536408438,\"y\":19.9},{\"x\":1685536708630,\"y\":20.2},{\"x\":1685537023666,\"y\":20.3},{\"x\":1685537323705,\"y\":20.5},{\"x\":1685537623753,\"y\":20.4},{\"x\":1685537923799,\"y\":20.4},{\"x\":1685538223965,\"y\":20.5},{\"x\":1685538538965,\"y\":20.4},{\"x\":1685538839060,\"y\":20.5},{\"x\":1685539139180,\"y\":20.5},{\"x\":1685539439233,\"y\":20.5},{\"x\":1685539739375,\"y\":20.4},{\"x\":1685540039424,\"y\":20.6},{\"x\":1685540339520,\"y\":20.4},{\"x\":1685540639601,\"y\":20.6},{\"x\":1685540939668,\"y\":20.5},{\"x\":1685541239749,\"y\":20.5},{\"x\":1685541539840,\"y\":20.8},{\"x\":1685541839913,\"y\":20.5},{\"x\":1685542139995,\"y\":20.4},{\"x\":1685542440177,\"y\":20.8},{\"x\":1685542740192,\"y\":20.4},{\"x\":1685543040283,\"y\":20.8},{\"x\":1685543340389,\"y\":20.5},{\"x\":1685543640471,\"y\":20.8},{\"x\":1685543940473,\"y\":20.5},{\"x\":1685544240621,\"y\":20.8},{\"x\":1685544540685,\"y\":20.5},{\"x\":1685544840799,\"y\":20.7},{\"x\":1685545140901,\"y\":20.5},{\"x\":1685545441001,\"y\":20.8},{\"x\":1685545741065,\"y\":20.6},{\"x\":1685546041186,\"y\":20.5},{\"x\":1685546341243,\"y\":20.7},{\"x\":1685546641292,\"y\":20.4},{\"x\":1685546941376,\"y\":20.8},{\"x\":1685547241438,\"y\":20.5},{\"x\":1685547541565,\"y\":20.8},{\"x\":1685547841634,\"y\":20.5},{\"x\":1685548141711,\"y\":20.8},{\"x\":1685548441854,\"y\":20.6},{\"x\":1685548741902,\"y\":20.5},{\"x\":1685549042002,\"y\":20.8},{\"x\":1685549342099,\"y\":20.5},{\"x\":1685549642156,\"y\":20.8},{\"x\":1685549942238,\"y\":20.7},{\"x\":1685550242287,\"y\":20.5},{\"x\":1685550542321,\"y\":20.8},{\"x\":1685550842435,\"y\":20.7},{\"x\":1685551142532,\"y\":20.5},{\"x\":1685551442679,\"y\":20.8},{\"x\":1685551742742,\"y\":20.8},{\"x\":1685552042824,\"y\":20.7},{\"x\":1685552342904,\"y\":20.6},{\"x\":1685552643024,\"y\":20.7},{\"x\":1685552943102,\"y\":20.7},{\"x\":1685553243197,\"y\":20.7},{\"x\":1685553543262,\"y\":20.7},{\"x\":1685553843353,\"y\":20.8},{\"x\":1685554143366,\"y\":20.8},{\"x\":1685554443531,\"y\":20.8},{\"x\":1685554743589,\"y\":20.8},{\"x\":1685555043690,\"y\":20.8},{\"x\":1685555343799,\"y\":20.8},{\"x\":1685555643872,\"y\":20.8},{\"x\":1685555943930,\"y\":20.8},{\"x\":1685556244056,\"y\":20.8},{\"x\":1685556544148,\"y\":20.8},{\"x\":1685556844209,\"y\":20.8},{\"x\":1685557144344,\"y\":20.7},{\"x\":1685557444363,\"y\":20.8},{\"x\":1685557744405,\"y\":20.7},{\"x\":1685558044539,\"y\":20.7},{\"x\":1685558344605,\"y\":20.7},{\"x\":1685558644713,\"y\":20.7},{\"x\":1685558944785,\"y\":20.7},{\"x\":1685559244901,\"y\":20.6},{\"x\":1685559544945,\"y\":20.6},{\"x\":1685559845042,\"y\":20.5},{\"x\":1685560145143,\"y\":20.5},{\"x\":1685560445241,\"y\":20.6},{\"x\":1685560745257,\"y\":20.5},{\"x\":1685561045328,\"y\":20.5},{\"x\":1685561345445,\"y\":20.5},{\"x\":1685561645525,\"y\":20.6},{\"x\":1685561945646,\"y\":20.8},{\"x\":1685562245696,\"y\":20.7},{\"x\":1685562545795,\"y\":20.6},{\"x\":1685562845871,\"y\":20.7},{\"x\":1685563145971,\"y\":20.8},{\"x\":1685563446094,\"y\":20.7},{\"x\":1685563746173,\"y\":20.5},{\"x\":1685564046283,\"y\":20.8},{\"x\":1685564346314,\"y\":20.8},{\"x\":1685564646386,\"y\":20.7},{\"x\":1685564946460,\"y\":20.6},{\"x\":1685565246561,\"y\":20.5},{\"x\":1685565546656,\"y\":20.7},{\"x\":1685565846745,\"y\":20.8},{\"x\":1685566146812,\"y\":20.6},{\"x\":1685566446933,\"y\":20.7},{\"x\":1685566746982,\"y\":20.7},{\"x\":1685567047084,\"y\":20.5},{\"x\":1685567347176,\"y\":20.8},{\"x\":1685567647243,\"y\":20.5},{\"x\":1685567947275,\"y\":20.8},{\"x\":1685568247414,\"y\":20.8},{\"x\":1685568547487,\"y\":20.8},{\"x\":1685568847582,\"y\":20.6},{\"x\":1685569147698,\"y\":20.6},{\"x\":1685569447750,\"y\":20.5},{\"x\":1685569747835,\"y\":20.8},{\"x\":1685570047948,\"y\":20.7},{\"x\":1685570348041,\"y\":20.5},{\"x\":1685570648135,\"y\":20.7},{\"x\":1685570948186,\"y\":20.7},{\"x\":1685571248285,\"y\":20.5},{\"x\":1685571548397,\"y\":20.7},{\"x\":1685571848461,\"y\":20.6},{\"x\":1685572148552,\"y\":20.7},{\"x\":1685572448646,\"y\":20.8},{\"x\":1685572748724,\"y\":20.7},{\"x\":1685573048812,\"y\":20.4},{\"x\":1685573348924,\"y\":20.8},{\"x\":1685573648998,\"y\":20.7},{\"x\":1685573949035,\"y\":20.5},{\"x\":1685574249162,\"y\":20.7},{\"x\":1685574564170,\"y\":20.5},{\"x\":1685574864211,\"y\":20.3},{\"x\":1685575164295,\"y\":20.3},{\"x\":1685575464392,\"y\":20.3},{\"x\":1685575764473,\"y\":20.2},{\"x\":1685576064520,\"y\":20},{\"x\":1685576364561,\"y\":19.9},{\"x\":1685576664649,\"y\":19.6},{\"x\":1685576964764,\"y\":19.5},{\"x\":1685577264783,\"y\":19.5},{\"x\":1685577564825,\"y\":19.5},{\"x\":1685577864898,\"y\":19.5},{\"x\":1685578165022,\"y\":19.5},{\"x\":1685578465041,\"y\":19.5},{\"x\":1685578765123,\"y\":19.5},{\"x\":1685579065190,\"y\":19.5},{\"x\":1685579365242,\"y\":19.5},{\"x\":1685579665270,\"y\":19.5},{\"x\":1685579965342,\"y\":19.5},{\"x\":1685580265419,\"y\":19.5},{\"x\":1685580565474,\"y\":19.5},{\"x\":1685580865528,\"y\":19.5},{\"x\":1685581165617,\"y\":19.5},{\"x\":1685581465707,\"y\":19.5},{\"x\":1685581765780,\"y\":19.5},{\"x\":1685582065871,\"y\":19.5},{\"x\":1685582365914,\"y\":19.5},{\"x\":1685582665994,\"y\":19.5},{\"x\":1685582966029,\"y\":19.5},{\"x\":1685583266054,\"y\":19.5},{\"x\":1685583566137,\"y\":19.5},{\"x\":1685583866167,\"y\":19.5},{\"x\":1685584166249,\"y\":19.5},{\"x\":1685584466332,\"y\":19.5},{\"x\":1685584766387,\"y\":19.5},{\"x\":1685585066444,\"y\":19.5},{\"x\":1685585366558,\"y\":19.5},{\"x\":1685585666591,\"y\":19.5},{\"x\":1685585966705,\"y\":19.5},{\"x\":1685586281700,\"y\":19.5},{\"x\":1685586581763,\"y\":19.5},{\"x\":1685586881831,\"y\":19.5},{\"x\":1685587181935,\"y\":19.5},{\"x\":1685587481999,\"y\":19.4},{\"x\":1685587782043,\"y\":19.4},{\"x\":1685588082116,\"y\":19.4},{\"x\":1685588382188,\"y\":19.4},{\"x\":1685588682255,\"y\":19.4},{\"x\":1685588982296,\"y\":19.4},{\"x\":1685589282341,\"y\":19.3},{\"x\":1685589582405,\"y\":19.4},{\"x\":1685589882472,\"y\":19.4},{\"x\":1685590182540,\"y\":19.3},{\"x\":1685590482618,\"y\":19.3},{\"x\":1685590782722,\"y\":19.3},{\"x\":1685591082771,\"y\":19.3},{\"x\":1685591382819,\"y\":19.2},{\"x\":1685591682931,\"y\":19.2},{\"x\":1685591982967,\"y\":19.2},{\"x\":1685592282986,\"y\":19.2},{\"x\":1685592583082,\"y\":19.2},{\"x\":1685592883165,\"y\":19.2},{\"x\":1685593183195,\"y\":19.2},{\"x\":1685593483277,\"y\":19.1},{\"x\":1685593783380,\"y\":19.2},{\"x\":1685594083450,\"y\":19.2},{\"x\":1685594383491,\"y\":19.2},{\"x\":1685594683592,\"y\":19.1},{\"x\":1685594983618,\"y\":19.1},{\"x\":1685595283711,\"y\":19.1},{\"x\":1685595583730,\"y\":19.1},{\"x\":1685595883817,\"y\":19},{\"x\":1685596183896,\"y\":19},{\"x\":1685596483953,\"y\":19},{\"x\":1685596784061,\"y\":19},{\"x\":1685597084124,\"y\":19},{\"x\":1685597384139,\"y\":19.1},{\"x\":1685597684213,\"y\":19},{\"x\":1685597984240,\"y\":19},{\"x\":1685598284312,\"y\":19},{\"x\":1685598584338,\"y\":19},{\"x\":1685598884381,\"y\":19},{\"x\":1685599184436,\"y\":19},{\"x\":1685599499407,\"y\":19},{\"x\":1685599799490,\"y\":18.9},{\"x\":1685600099528,\"y\":19},{\"x\":1685600399539,\"y\":19},{\"x\":1685600699637,\"y\":19},{\"x\":1685600999644,\"y\":19},{\"x\":1685601299689,\"y\":19},{\"x\":1685601599758,\"y\":19},{\"x\":1685601899826,\"y\":19},{\"x\":1685602199848,\"y\":18.9},{\"x\":1685602499869,\"y\":18.9},{\"x\":1685602799939,\"y\":19},{\"x\":1685603099979,\"y\":18.9},{\"x\":1685603414978,\"y\":18.9},{\"x\":1685603715053,\"y\":19},{\"x\":1685604030039,\"y\":19},{\"x\":1685604330117,\"y\":19},{\"x\":1685604630167,\"y\":19},{\"x\":1685604930199,\"y\":19},{\"x\":1685605230238,\"y\":18.9},{\"x\":1685605530260,\"y\":19},{\"x\":1685605830318,\"y\":19},{\"x\":1685606130319,\"y\":19},{\"x\":1685606430335,\"y\":19},{\"x\":1685606730393,\"y\":19},{\"x\":1685607030458,\"y\":19},{\"x\":1685607330485,\"y\":19.5},{\"x\":1685607630516,\"y\":20.3},{\"x\":1685607930568,\"y\":20.6},{\"x\":1685608230576,\"y\":20.4},{\"x\":1685608530643,\"y\":20.5},{\"x\":1685608830684,\"y\":20.5},{\"x\":1685609130723,\"y\":20.5},{\"x\":1685609430778,\"y\":20.5},{\"x\":1685609745753,\"y\":20.7},{\"x\":1685610045798,\"y\":20.4},{\"x\":1685610345834,\"y\":20.7},{\"x\":1685610645876,\"y\":20.4},{\"x\":1685610945921,\"y\":20.8},{\"x\":1685611245935,\"y\":20.5},{\"x\":1685611545963,\"y\":20.8},{\"x\":1685611845989,\"y\":20.6},{\"x\":1685612146117,\"y\":20.5},{\"x\":1685612446189,\"y\":20.8},{\"x\":1685612746312,\"y\":20.6},{\"x\":1685613046346,\"y\":20.5},{\"x\":1685613346425,\"y\":20.8},{\"x\":1685613646580,\"y\":20.6},{\"x\":1685613961556,\"y\":20.6},{\"x\":1685614261648,\"y\":20.7},{\"x\":1685614576669,\"y\":20.7},{\"x\":1685614876695,\"y\":20.5},{\"x\":1685615176733,\"y\":20.4},{\"x\":1685615476808,\"y\":20.7},{\"x\":1685615776863,\"y\":20.7},{\"x\":1685616076917,\"y\":20.5},{\"x\":1685616376987,\"y\":20.4},{\"x\":1685616677033,\"y\":20.3},{\"x\":1685616977113,\"y\":20.3},{\"x\":1685617277203,\"y\":20.3},{\"x\":1685617577236,\"y\":20.3},{\"x\":1685617877275,\"y\":20.2},{\"x\":1685618177324,\"y\":20.3},{\"x\":1685618477408,\"y\":20.2},{\"x\":1685618777447,\"y\":20.3},{\"x\":1685619077601,\"y\":20.2},{\"x\":1685619377646,\"y\":20.2},{\"x\":1685619677730,\"y\":20.1},{\"x\":1685619977761,\"y\":20.2},{\"x\":1685620017473,\"y\":20.1},{\"x\":1685620080667,\"y\":20.1}],[{\"x\":1685015251039,\"y\":19.18},{\"x\":1685015551015,\"y\":19.18},{\"x\":1685015851010,\"y\":19.18},{\"x\":1685016151028,\"y\":19.09},{\"x\":1685016451042,\"y\":18.75},{\"x\":1685016751019,\"y\":18.66},{\"x\":1685017051028,\"y\":18.75},{\"x\":1685017351047,\"y\":18.89},{\"x\":1685017651031,\"y\":18.8},{\"x\":1685017951098,\"y\":18.83},{\"x\":1685018251018,\"y\":18.3},{\"x\":1685018551020,\"y\":18.3},{\"x\":1685018851032,\"y\":18.36},{\"x\":1685019151038,\"y\":18.36},{\"x\":1685019451035,\"y\":19.14},{\"x\":1685019751031,\"y\":19.04},{\"x\":1685020051038,\"y\":19.64},{\"x\":1685020351040,\"y\":19.42},{\"x\":1685020651063,\"y\":19.88},{\"x\":1685020951079,\"y\":19.73},{\"x\":1685021251036,\"y\":19.73},{\"x\":1685021551137,\"y\":19.54},{\"x\":1685021851047,\"y\":19.21},{\"x\":1685022151057,\"y\":19.13},{\"x\":1685022451042,\"y\":19.21},{\"x\":1685022751080,\"y\":19.1},{\"x\":1685023051043,\"y\":18.46},{\"x\":1685023351058,\"y\":18.46},{\"x\":1685023651118,\"y\":18.47},{\"x\":1685023951188,\"y\":18.48},{\"x\":1685024251055,\"y\":18.48},{\"x\":1685024551051,\"y\":18.44},{\"x\":1685024851052,\"y\":18.44},{\"x\":1685025151135,\"y\":18.73},{\"x\":1685025451076,\"y\":18.73},{\"x\":1685025751061,\"y\":18.73},{\"x\":1685026051071,\"y\":19.02},{\"x\":1685026351158,\"y\":19.05},{\"x\":1685026651115,\"y\":19.03},{\"x\":1685026951071,\"y\":19.03},{\"x\":1685027251066,\"y\":19.03},{\"x\":1685027551148,\"y\":18.62},{\"x\":1685027851058,\"y\":18.62},{\"x\":1685028151059,\"y\":18.62},{\"x\":1685028451112,\"y\":19},{\"x\":1685028751146,\"y\":18.91},{\"x\":1685029051091,\"y\":18.1},{\"x\":1685029351104,\"y\":18.12},{\"x\":1685029651134,\"y\":18.51},{\"x\":1685029951350,\"y\":18.12},{\"x\":1685030251085,\"y\":18.51},{\"x\":1685030551087,\"y\":18.42},{\"x\":1685030851113,\"y\":18.46},{\"x\":1685031151160,\"y\":18.37},{\"x\":1685031451109,\"y\":18.33},{\"x\":1685031751080,\"y\":18.21},{\"x\":1685032051082,\"y\":18.3},{\"x\":1685032351518,\"y\":18.3},{\"x\":1685032651206,\"y\":17.89},{\"x\":1685032951081,\"y\":17.8},{\"x\":1685033251086,\"y\":17.8},{\"x\":1685033551096,\"y\":17.8},{\"x\":1685033851075,\"y\":17.8},{\"x\":1685034151086,\"y\":17.78},{\"x\":1685034451139,\"y\":17.63},{\"x\":1685034751066,\"y\":17.63},{\"x\":1685035051075,\"y\":17.63},{\"x\":1685035351084,\"y\":17.54},{\"x\":1685035651091,\"y\":17.54},{\"x\":1685035951102,\"y\":17.55},{\"x\":1685036251109,\"y\":17.28},{\"x\":1685036551080,\"y\":17.54},{\"x\":1685036851085,\"y\":17.25},{\"x\":1685037151113,\"y\":17.2},{\"x\":1685037451085,\"y\":16.99},{\"x\":1685037751124,\"y\":16.99},{\"x\":1685038051100,\"y\":16.99},{\"x\":1685038351547,\"y\":17.1},{\"x\":1685038651116,\"y\":17.02},{\"x\":1685038951187,\"y\":16.94},{\"x\":1685039251190,\"y\":16.88},{\"x\":1685039551190,\"y\":16.85},{\"x\":1685039851181,\"y\":16.85},{\"x\":1685040151138,\"y\":16.82},{\"x\":1685040451132,\"y\":16.79},{\"x\":1685040751183,\"y\":16.79},{\"x\":1685041051160,\"y\":16.79},{\"x\":1685041351171,\"y\":16.7},{\"x\":1685041651173,\"y\":16.44},{\"x\":1685041951215,\"y\":16.44},{\"x\":1685042251220,\"y\":16.48},{\"x\":1685042551262,\"y\":16.52},{\"x\":1685042851204,\"y\":16.48},{\"x\":1685043151252,\"y\":16.52},{\"x\":1685043451209,\"y\":16.4},{\"x\":1685043751246,\"y\":16.26},{\"x\":1685044051210,\"y\":16.26},{\"x\":1685044351522,\"y\":16.26},{\"x\":1685044651215,\"y\":16.17},{\"x\":1685044951218,\"y\":16.17},{\"x\":1685045251281,\"y\":15.98},{\"x\":1685045551345,\"y\":15.98},{\"x\":1685045851232,\"y\":16.01},{\"x\":1685046151240,\"y\":15.98},{\"x\":1685046451276,\"y\":15.75},{\"x\":1685046751262,\"y\":15.75},{\"x\":1685047051266,\"y\":15.75},{\"x\":1685047351285,\"y\":15.68},{\"x\":1685047651267,\"y\":15.68},{\"x\":1685047951728,\"y\":15.49},{\"x\":1685048251321,\"y\":15.5},{\"x\":1685048551265,\"y\":15.49},{\"x\":1685048851352,\"y\":15.35},{\"x\":1685049151302,\"y\":15.35},{\"x\":1685049451264,\"y\":14.98},{\"x\":1685049751268,\"y\":14.98},{\"x\":1685050051322,\"y\":14.97},{\"x\":1685050351309,\"y\":14.97},{\"x\":1685050651266,\"y\":14.75},{\"x\":1685050951264,\"y\":14.75},{\"x\":1685051251276,\"y\":14.82},{\"x\":1685051551291,\"y\":14.73},{\"x\":1685051851384,\"y\":14.57},{\"x\":1685052151274,\"y\":14.41},{\"x\":1685052451281,\"y\":14.41},{\"x\":1685052751280,\"y\":14.35},{\"x\":1685053051279,\"y\":14.49},{\"x\":1685053351326,\"y\":14.29},{\"x\":1685053651310,\"y\":14.3},{\"x\":1685053951323,\"y\":14.29},{\"x\":1685054251377,\"y\":13.95},{\"x\":1685054551303,\"y\":13.95},{\"x\":1685054851307,\"y\":13.95},{\"x\":1685055151655,\"y\":13.71},{\"x\":1685055451302,\"y\":13.71},{\"x\":1685055751335,\"y\":13.58},{\"x\":1685056051330,\"y\":13.55},{\"x\":1685056351435,\"y\":13.58},{\"x\":1685056651370,\"y\":13.33},{\"x\":1685056951348,\"y\":13.58},{\"x\":1685057251335,\"y\":13.23},{\"x\":1685057551642,\"y\":13.23},{\"x\":1685057851342,\"y\":13.23},{\"x\":1685058151360,\"y\":12.98},{\"x\":1685058451395,\"y\":13},{\"x\":1685058751511,\"y\":13.01},{\"x\":1685059051391,\"y\":13.01},{\"x\":1685059351339,\"y\":12.9},{\"x\":1685059651359,\"y\":12.9},{\"x\":1685059951438,\"y\":12.48},{\"x\":1685060251356,\"y\":12.48},{\"x\":1685060551372,\"y\":12.48},{\"x\":1685060851371,\"y\":12.32},{\"x\":1685061151374,\"y\":12.32},{\"x\":1685061451412,\"y\":11.72},{\"x\":1685061751394,\"y\":11.63},{\"x\":1685062051381,\"y\":11.72},{\"x\":1685062352047,\"y\":11.55},{\"x\":1685062651444,\"y\":11.36},{\"x\":1685062951373,\"y\":11.46},{\"x\":1685063251410,\"y\":11.36},{\"x\":1685063551479,\"y\":11.37},{\"x\":1685063851380,\"y\":11.36},{\"x\":1685064151391,\"y\":11.44},{\"x\":1685064451471,\"y\":11.34},{\"x\":1685064751589,\"y\":11.32},{\"x\":1685065051396,\"y\":11.26},{\"x\":1685065351399,\"y\":11.22},{\"x\":1685065651409,\"y\":11.39},{\"x\":1685065952272,\"y\":11.33},{\"x\":1685066251396,\"y\":11.21},{\"x\":1685066551403,\"y\":11.21},{\"x\":1685066851417,\"y\":11.34},{\"x\":1685067151442,\"y\":11.28},{\"x\":1685067451399,\"y\":11.27},{\"x\":1685067751460,\"y\":11.06},{\"x\":1685068051420,\"y\":11.27},{\"x\":1685068351485,\"y\":11.02},{\"x\":1685068651412,\"y\":11.02},{\"x\":1685068951402,\"y\":10.91},{\"x\":1685069251450,\"y\":11},{\"x\":1685069551482,\"y\":11},{\"x\":1685069851414,\"y\":10.88},{\"x\":1685070151414,\"y\":10.66},{\"x\":1685070451408,\"y\":10.66},{\"x\":1685070752331,\"y\":10.76},{\"x\":1685071051424,\"y\":10.76},{\"x\":1685071351428,\"y\":10.76},{\"x\":1685071651498,\"y\":10.55},{\"x\":1685071951451,\"y\":10.55},{\"x\":1685072251483,\"y\":10.55},{\"x\":1685072551428,\"y\":10.55},{\"x\":1685072851477,\"y\":10.34},{\"x\":1685073151490,\"y\":10.34},{\"x\":1685073451401,\"y\":10.34},{\"x\":1685073751433,\"y\":10.08},{\"x\":1685074051433,\"y\":10.08},{\"x\":1685074351659,\"y\":9.98},{\"x\":1685074651481,\"y\":9.98},{\"x\":1685074951442,\"y\":9.98},{\"x\":1685075251486,\"y\":9.76},{\"x\":1685075553145,\"y\":9.76},{\"x\":1685075851454,\"y\":9.76},{\"x\":1685076151559,\"y\":9.76},{\"x\":1685076451455,\"y\":9.76},{\"x\":1685076751637,\"y\":9.76},{\"x\":1685077051562,\"y\":10.23},{\"x\":1685077351466,\"y\":10.23},{\"x\":1685077651495,\"y\":10.23},{\"x\":1685077951596,\"y\":10.15},{\"x\":1685078251465,\"y\":10.36},{\"x\":1685078551490,\"y\":10.36},{\"x\":1685078851486,\"y\":10.82},{\"x\":1685079152413,\"y\":10.82},{\"x\":1685079451481,\"y\":11.06},{\"x\":1685079751484,\"y\":11.06},{\"x\":1685080051515,\"y\":11.26},{\"x\":1685080353153,\"y\":11.08},{\"x\":1685080651466,\"y\":11.37},{\"x\":1685080951559,\"y\":11.85},{\"x\":1685081251496,\"y\":12.07},{\"x\":1685081552662,\"y\":11.54},{\"x\":1685081851505,\"y\":11.54},{\"x\":1685082151498,\"y\":12.9},{\"x\":1685082451574,\"y\":11.98},{\"x\":1685082752768,\"y\":12.05},{\"x\":1685083051516,\"y\":12.05},{\"x\":1685083351518,\"y\":12.54},{\"x\":1685083651522,\"y\":12.54},{\"x\":1685083951825,\"y\":13.01},{\"x\":1685084251526,\"y\":13.01},{\"x\":1685084551531,\"y\":13.84},{\"x\":1685084851537,\"y\":14.15},{\"x\":1685085154315,\"y\":14.2},{\"x\":1685085451540,\"y\":14.2},{\"x\":1685085751599,\"y\":14.74},{\"x\":1685086051532,\"y\":14.65},{\"x\":1685086352440,\"y\":14.65},{\"x\":1685086651538,\"y\":15.31},{\"x\":1685086951544,\"y\":15.31},{\"x\":1685087251583,\"y\":15.43},{\"x\":1685087552469,\"y\":15.61},{\"x\":1685087851550,\"y\":15.43},{\"x\":1685088151549,\"y\":15.75},{\"x\":1685088451547,\"y\":15.75},{\"x\":1685088752994,\"y\":16.44},{\"x\":1685089051545,\"y\":16.44},{\"x\":1685089351589,\"y\":16.84},{\"x\":1685089651598,\"y\":16.44},{\"x\":1685089952825,\"y\":16.84},{\"x\":1685090251561,\"y\":17.35},{\"x\":1685090551636,\"y\":17.66},{\"x\":1685090851564,\"y\":17.56},{\"x\":1685091152016,\"y\":17.66},{\"x\":1685091451594,\"y\":17.93},{\"x\":1685091751567,\"y\":18.04},{\"x\":1685092051581,\"y\":17.93},{\"x\":1685092352469,\"y\":18.08},{\"x\":1685092651613,\"y\":18.17},{\"x\":1685092951598,\"y\":18.25},{\"x\":1685093251572,\"y\":18.23},{\"x\":1685093551684,\"y\":18.43},{\"x\":1685093851596,\"y\":18.5},{\"x\":1685094151578,\"y\":18.5},{\"x\":1685094451581,\"y\":18.85},{\"x\":1685094753849,\"y\":18.85},{\"x\":1685095051634,\"y\":19.17},{\"x\":1685095351592,\"y\":19.09},{\"x\":1685095651582,\"y\":19.37},{\"x\":1685095952262,\"y\":19.37},{\"x\":1685096251665,\"y\":19.46},{\"x\":1685096551653,\"y\":19.46},{\"x\":1685096851597,\"y\":19.46},{\"x\":1685097151894,\"y\":19.32},{\"x\":1685097451605,\"y\":19.59},{\"x\":1685097751603,\"y\":19.85},{\"x\":1685098051603,\"y\":19.75},{\"x\":1685098351825,\"y\":19.65},{\"x\":1685098651611,\"y\":19.82},{\"x\":1685098951612,\"y\":19.65},{\"x\":1685099251620,\"y\":19.57},{\"x\":1685099554557,\"y\":19.84},{\"x\":1685099851611,\"y\":19.98},{\"x\":1685100151610,\"y\":19.98},{\"x\":1685100451674,\"y\":19.9},{\"x\":1685100751631,\"y\":19.9},{\"x\":1685101051671,\"y\":20.45},{\"x\":1685101351650,\"y\":20.45},{\"x\":1685101651625,\"y\":20.45},{\"x\":1685101952592,\"y\":19.74},{\"x\":1685102251628,\"y\":19.74},{\"x\":1685102551620,\"y\":19.74},{\"x\":1685102851630,\"y\":19.84},{\"x\":1685103152663,\"y\":20.53},{\"x\":1685103451625,\"y\":20.53},{\"x\":1685103751638,\"y\":20.37},{\"x\":1685104051653,\"y\":20.37},{\"x\":1685104351690,\"y\":20.42},{\"x\":1685104651625,\"y\":20.92},{\"x\":1685104951669,\"y\":21.05},{\"x\":1685105251635,\"y\":20.92},{\"x\":1685106270209,\"y\":21.51},{\"x\":1685106570210,\"y\":21.28},{\"x\":1685106870262,\"y\":21.31},{\"x\":1685107170259,\"y\":20.87},{\"x\":1685107470202,\"y\":20.87},{\"x\":1685107770205,\"y\":20.87},{\"x\":1685108070201,\"y\":20.24},{\"x\":1685108370268,\"y\":20.24},{\"x\":1685108670211,\"y\":20.81},{\"x\":1685108970215,\"y\":20.61},{\"x\":1685109270264,\"y\":21.02},{\"x\":1685109570225,\"y\":21.02},{\"x\":1685109870210,\"y\":21.35},{\"x\":1685110170276,\"y\":21.42},{\"x\":1685110470215,\"y\":21.08},{\"x\":1685110770218,\"y\":21.08},{\"x\":1685111070267,\"y\":21.3},{\"x\":1685111370237,\"y\":21.32},{\"x\":1685111670242,\"y\":21.21},{\"x\":1685111970278,\"y\":21.56},{\"x\":1685112270243,\"y\":21.43},{\"x\":1685112570286,\"y\":20.62},{\"x\":1685112870312,\"y\":20.61},{\"x\":1685113170279,\"y\":20.61},{\"x\":1685113470259,\"y\":20.52},{\"x\":1685113770274,\"y\":21.03},{\"x\":1685114070330,\"y\":20.96},{\"x\":1685114370346,\"y\":20.62},{\"x\":1685114670290,\"y\":20.62},{\"x\":1685114970303,\"y\":20.62},{\"x\":1685115270293,\"y\":20.57},{\"x\":1685115570345,\"y\":20.81},{\"x\":1685115870301,\"y\":20.81},{\"x\":1685116170341,\"y\":20.85},{\"x\":1685116470425,\"y\":20.35},{\"x\":1685116770319,\"y\":20.73},{\"x\":1685117070306,\"y\":20.35},{\"x\":1685117370344,\"y\":20.75},{\"x\":1685117670330,\"y\":20.75},{\"x\":1685117970336,\"y\":20.75},{\"x\":1685118270330,\"y\":20.45},{\"x\":1685118570325,\"y\":20.45},{\"x\":1685118870362,\"y\":19.95},{\"x\":1685119170359,\"y\":19.95},{\"x\":1685119470369,\"y\":19.95},{\"x\":1685119770365,\"y\":19.92},{\"x\":1685120070363,\"y\":20.06},{\"x\":1685120370385,\"y\":20.17},{\"x\":1685120670359,\"y\":20.17},{\"x\":1685120970383,\"y\":20.08},{\"x\":1685121270373,\"y\":19.95},{\"x\":1685121570376,\"y\":19.85},{\"x\":1685121870394,\"y\":19.88},{\"x\":1685122170385,\"y\":19.88},{\"x\":1685122470467,\"y\":19},{\"x\":1685122770415,\"y\":19},{\"x\":1685123070412,\"y\":19},{\"x\":1685123370409,\"y\":18.86},{\"x\":1685123670402,\"y\":18.86},{\"x\":1685123970418,\"y\":18.86},{\"x\":1685124270399,\"y\":18.86},{\"x\":1685124570415,\"y\":18.79},{\"x\":1685124870446,\"y\":18.79},{\"x\":1685125170457,\"y\":18.85},{\"x\":1685125470494,\"y\":18.85},{\"x\":1685125770424,\"y\":18.85},{\"x\":1685126070436,\"y\":18.71},{\"x\":1685126370464,\"y\":18.71},{\"x\":1685126670446,\"y\":18.67},{\"x\":1685126970458,\"y\":18.67},{\"x\":1685127270730,\"y\":17.76},{\"x\":1685127570540,\"y\":17.84},{\"x\":1685127870479,\"y\":17.42},{\"x\":1685128170488,\"y\":17.42},{\"x\":1685128470446,\"y\":17.32},{\"x\":1685128770711,\"y\":17.38},{\"x\":1685129070493,\"y\":17.55},{\"x\":1685129370460,\"y\":17.46},{\"x\":1685129670456,\"y\":17.51},{\"x\":1685129970444,\"y\":16.98},{\"x\":1685130270452,\"y\":16.94},{\"x\":1685130570463,\"y\":16.94},{\"x\":1685130870454,\"y\":16.63},{\"x\":1685131170558,\"y\":16.63},{\"x\":1685131470459,\"y\":16.63},{\"x\":1685131770480,\"y\":15.83},{\"x\":1685132070539,\"y\":15.61},{\"x\":1685132370654,\"y\":15.61},{\"x\":1685132670510,\"y\":15.17},{\"x\":1685132970470,\"y\":15.17},{\"x\":1685133270483,\"y\":15.17},{\"x\":1685133570534,\"y\":15.33},{\"x\":1685133870537,\"y\":15.17},{\"x\":1685134170481,\"y\":15.33},{\"x\":1685134470522,\"y\":15.17},{\"x\":1685134770619,\"y\":15.17},{\"x\":1685135070468,\"y\":15.17},{\"x\":1685135370539,\"y\":14.12},{\"x\":1685135670470,\"y\":14.12},{\"x\":1685135970588,\"y\":14.12},{\"x\":1685136270506,\"y\":13.94},{\"x\":1685136570482,\"y\":13.94},{\"x\":1685136870483,\"y\":13.88},{\"x\":1685137170591,\"y\":13.53},{\"x\":1685137470482,\"y\":13.29},{\"x\":1685137770513,\"y\":13.29},{\"x\":1685138070565,\"y\":13.24},{\"x\":1685138370612,\"y\":13.3},{\"x\":1685138670513,\"y\":12.65},{\"x\":1685138970488,\"y\":13.03},{\"x\":1685139270567,\"y\":12.44},{\"x\":1685139570520,\"y\":12.44},{\"x\":1685139870495,\"y\":12.47},{\"x\":1685140170514,\"y\":12.41},{\"x\":1685140470469,\"y\":12.41},{\"x\":1685140770566,\"y\":12.32},{\"x\":1685141070532,\"y\":11.91},{\"x\":1685141370505,\"y\":11.91},{\"x\":1685141670535,\"y\":11.91},{\"x\":1685141970572,\"y\":11.87},{\"x\":1685142270528,\"y\":11.87},{\"x\":1685142570539,\"y\":11.49},{\"x\":1685142870540,\"y\":11.49},{\"x\":1685143170721,\"y\":11.69},{\"x\":1685143470532,\"y\":11.69},{\"x\":1685143770537,\"y\":11.69},{\"x\":1685144070587,\"y\":11.38},{\"x\":1685144370585,\"y\":11.29},{\"x\":1685144670544,\"y\":11.38},{\"x\":1685144970592,\"y\":11.66},{\"x\":1685145270578,\"y\":11.66},{\"x\":1685145570616,\"y\":11.66},{\"x\":1685145870578,\"y\":11.54},{\"x\":1685146170575,\"y\":11.3},{\"x\":1685146470586,\"y\":11.26},{\"x\":1685146770618,\"y\":10.97},{\"x\":1685147070575,\"y\":10.97},{\"x\":1685147370627,\"y\":11.06},{\"x\":1685147670593,\"y\":10.78},{\"x\":1685147970600,\"y\":11.06},{\"x\":1685148270605,\"y\":10.65},{\"x\":1685148570644,\"y\":10.63},{\"x\":1685148870584,\"y\":10.63},{\"x\":1685149170590,\"y\":10.63},{\"x\":1685149470587,\"y\":10.44},{\"x\":1685149770583,\"y\":10.44},{\"x\":1685150070580,\"y\":10.1},{\"x\":1685150370584,\"y\":10.1},{\"x\":1685150670582,\"y\":10.03},{\"x\":1685150970594,\"y\":10.03},{\"x\":1685151270632,\"y\":10.08},{\"x\":1685151570591,\"y\":10.08},{\"x\":1685151870605,\"y\":9.61},{\"x\":1685152170611,\"y\":9.61},{\"x\":1685152470611,\"y\":9.42},{\"x\":1685152770613,\"y\":9.42},{\"x\":1685153070628,\"y\":9.48},{\"x\":1685153370683,\"y\":9.39},{\"x\":1685153670664,\"y\":9.33},{\"x\":1685153970636,\"y\":9.33},{\"x\":1685154270611,\"y\":9.33},{\"x\":1685154570650,\"y\":9.14},{\"x\":1685154870623,\"y\":9.14},{\"x\":1685155170939,\"y\":9.05},{\"x\":1685155470674,\"y\":8.95},{\"x\":1685155770628,\"y\":8.95},{\"x\":1685156070642,\"y\":8.86},{\"x\":1685156370678,\"y\":8.95},{\"x\":1685156670691,\"y\":8.95},{\"x\":1685156970647,\"y\":8.95},{\"x\":1685157270649,\"y\":8.48},{\"x\":1685157570728,\"y\":8.51},{\"x\":1685157870653,\"y\":8.67},{\"x\":1685158170653,\"y\":8.67},{\"x\":1685158470652,\"y\":8.47},{\"x\":1685158770755,\"y\":8.29},{\"x\":1685159070671,\"y\":8.29},{\"x\":1685159370691,\"y\":8.19},{\"x\":1685159670661,\"y\":8.19},{\"x\":1685159971379,\"y\":8.08},{\"x\":1685160270711,\"y\":8.04},{\"x\":1685160570739,\"y\":8.22},{\"x\":1685160870655,\"y\":8.22},{\"x\":1685161170787,\"y\":8.04},{\"x\":1685161470703,\"y\":8.24},{\"x\":1685161770668,\"y\":8.04},{\"x\":1685162070717,\"y\":8.02},{\"x\":1685162371170,\"y\":7.93},{\"x\":1685162670708,\"y\":8.02},{\"x\":1685162970719,\"y\":8.55},{\"x\":1685163270676,\"y\":8.55},{\"x\":1685163571126,\"y\":8.55},{\"x\":1685163870678,\"y\":8.77},{\"x\":1685164170681,\"y\":8.69},{\"x\":1685164470773,\"y\":9.46},{\"x\":1685164771057,\"y\":9.68},{\"x\":1685165070675,\"y\":9.97},{\"x\":1685165370677,\"y\":9.83},{\"x\":1685165670713,\"y\":10.29},{\"x\":1685165970916,\"y\":10.29},{\"x\":1685166270681,\"y\":10.47},{\"x\":1685166570684,\"y\":10.47},{\"x\":1685166870680,\"y\":11},{\"x\":1685167171095,\"y\":10.85},{\"x\":1685167470678,\"y\":11.53},{\"x\":1685167770689,\"y\":12.14},{\"x\":1685168070683,\"y\":12.14},{\"x\":1685168370787,\"y\":11.68},{\"x\":1685168670739,\"y\":11.68},{\"x\":1685168970743,\"y\":11.98},{\"x\":1685169270696,\"y\":11.98},{\"x\":1685169570699,\"y\":11.98},{\"x\":1685169870784,\"y\":13.66},{\"x\":1685170170701,\"y\":13.66},{\"x\":1685170470695,\"y\":13.66},{\"x\":1685170770757,\"y\":13.66},{\"x\":1685171070684,\"y\":13.98},{\"x\":1685171370697,\"y\":13.98},{\"x\":1685171670698,\"y\":14.38},{\"x\":1685171971138,\"y\":14.38},{\"x\":1685172270759,\"y\":13.85},{\"x\":1685172570699,\"y\":13.85},{\"x\":1685172870711,\"y\":13.85},{\"x\":1685173170778,\"y\":15.4},{\"x\":1685173470740,\"y\":15.5},{\"x\":1685173770702,\"y\":15.18},{\"x\":1685174070719,\"y\":15.49},{\"x\":1685174371094,\"y\":15.8},{\"x\":1685174670695,\"y\":15.49},{\"x\":1685174970800,\"y\":16.03},{\"x\":1685175270722,\"y\":15.86},{\"x\":1685175570763,\"y\":15.86},{\"x\":1685175870697,\"y\":16.35},{\"x\":1685176170707,\"y\":16.48},{\"x\":1685176470754,\"y\":16.94},{\"x\":1685176770748,\"y\":16.94},{\"x\":1685177070739,\"y\":17.05},{\"x\":1685177370721,\"y\":17.05},{\"x\":1685177670735,\"y\":17.05},{\"x\":1685177971115,\"y\":17.66},{\"x\":1685178270740,\"y\":17.66},{\"x\":1685178570747,\"y\":17.64},{\"x\":1685178870774,\"y\":18.01},{\"x\":1685179171072,\"y\":17.92},{\"x\":1685179470822,\"y\":18.19},{\"x\":1685179770758,\"y\":18.1},{\"x\":1685180070762,\"y\":18.19},{\"x\":1685180370805,\"y\":18.1},{\"x\":1685180670780,\"y\":18.51},{\"x\":1685180970809,\"y\":18.65},{\"x\":1685181270793,\"y\":18.72},{\"x\":1685181570900,\"y\":19.19},{\"x\":1685181870801,\"y\":19.1},{\"x\":1685182170811,\"y\":19.19},{\"x\":1685182470860,\"y\":19.44},{\"x\":1685182771048,\"y\":19.67},{\"x\":1685183070826,\"y\":19.44},{\"x\":1685183370877,\"y\":19.67},{\"x\":1685183670882,\"y\":19.85},{\"x\":1685183970939,\"y\":19.85},{\"x\":1685184270841,\"y\":19.85},{\"x\":1685184570853,\"y\":19.96},{\"x\":1685184870900,\"y\":20.18},{\"x\":1685185170967,\"y\":20.47},{\"x\":1685185470866,\"y\":20.18},{\"x\":1685185770871,\"y\":20.65},{\"x\":1685186070870,\"y\":20.65},{\"x\":1685186370892,\"y\":20.6},{\"x\":1685186670893,\"y\":20.57},{\"x\":1685186970904,\"y\":20.71},{\"x\":1685187270868,\"y\":20.71},{\"x\":1685187572989,\"y\":20.99},{\"x\":1685187870872,\"y\":20.99},{\"x\":1685188170877,\"y\":20.99},{\"x\":1685188470913,\"y\":21.13},{\"x\":1685188771470,\"y\":21.2},{\"x\":1685189070899,\"y\":21.12},{\"x\":1685189370894,\"y\":21.2},{\"x\":1685189670921,\"y\":21.41},{\"x\":1685189971610,\"y\":21.41},{\"x\":1685190270898,\"y\":21.41},{\"x\":1685190570940,\"y\":21.32},{\"x\":1685190870918,\"y\":21.32},{\"x\":1685191171751,\"y\":21.78},{\"x\":1685191470923,\"y\":21.68},{\"x\":1685191770922,\"y\":21.68},{\"x\":1685192070981,\"y\":22.17},{\"x\":1685192371026,\"y\":22.17},{\"x\":1685192670934,\"y\":22.17},{\"x\":1685192970954,\"y\":22.46},{\"x\":1685193270953,\"y\":22.46},{\"x\":1685193571076,\"y\":21.99},{\"x\":1685193870942,\"y\":21.91},{\"x\":1685194171071,\"y\":21.99},{\"x\":1685194470972,\"y\":21.91},{\"x\":1685194770981,\"y\":21.91},{\"x\":1685195070960,\"y\":23.06},{\"x\":1685195370975,\"y\":22.73},{\"x\":1685195670969,\"y\":23.06},{\"x\":1685195971032,\"y\":22.82},{\"x\":1685196270973,\"y\":22.82},{\"x\":1685196570982,\"y\":22.82},{\"x\":1685196870986,\"y\":21.82},{\"x\":1685197171084,\"y\":21.93},{\"x\":1685197470984,\"y\":22.31},{\"x\":1685197770988,\"y\":22.31},{\"x\":1685198070990,\"y\":22.31},{\"x\":1685198371020,\"y\":22.31},{\"x\":1685198671053,\"y\":22.37},{\"x\":1685198970993,\"y\":22.23},{\"x\":1685199271011,\"y\":22.37},{\"x\":1685199571046,\"y\":22.48},{\"x\":1685199871115,\"y\":21.98},{\"x\":1685200171006,\"y\":21.98},{\"x\":1685200471008,\"y\":21.98},{\"x\":1685200771192,\"y\":22.9},{\"x\":1685201071014,\"y\":22.9},{\"x\":1685201371067,\"y\":22.11},{\"x\":1685201671018,\"y\":22.11},{\"x\":1685201971372,\"y\":22.11},{\"x\":1685202271010,\"y\":21.91},{\"x\":1685202571020,\"y\":21.91},{\"x\":1685202871094,\"y\":22.37},{\"x\":1685203171957,\"y\":22.04},{\"x\":1685203471024,\"y\":21.92},{\"x\":1685203771087,\"y\":22.72},{\"x\":1685204071079,\"y\":22.72},{\"x\":1685204372043,\"y\":22.63},{\"x\":1685204671023,\"y\":22.63},{\"x\":1685204971067,\"y\":22.65},{\"x\":1685205271028,\"y\":22.65},{\"x\":1685205571490,\"y\":22.29},{\"x\":1685205871024,\"y\":21.93},{\"x\":1685206171037,\"y\":21.93},{\"x\":1685206471023,\"y\":21.53},{\"x\":1685206771057,\"y\":21.53},{\"x\":1685207071049,\"y\":20.84},{\"x\":1685207371039,\"y\":20.84},{\"x\":1685207671107,\"y\":20.92},{\"x\":1685207971068,\"y\":20.84},{\"x\":1685208271098,\"y\":22.62},{\"x\":1685208571110,\"y\":22.62},{\"x\":1685208871086,\"y\":22.62},{\"x\":1685209171774,\"y\":20.91},{\"x\":1685209471092,\"y\":20.82},{\"x\":1685209771092,\"y\":19.71},{\"x\":1685210071129,\"y\":19.73},{\"x\":1685210371211,\"y\":19.73},{\"x\":1685210671121,\"y\":19.24},{\"x\":1685210971142,\"y\":21.59},{\"x\":1685211271109,\"y\":21.59},{\"x\":1685211573673,\"y\":21.59},{\"x\":1685211871103,\"y\":21.59},{\"x\":1685212171150,\"y\":21.56},{\"x\":1685212471136,\"y\":21.47},{\"x\":1685212771652,\"y\":20.46},{\"x\":1685213071195,\"y\":20.46},{\"x\":1685213371188,\"y\":19.23},{\"x\":1685213671169,\"y\":19.15},{\"x\":1685213971280,\"y\":19.23},{\"x\":1685214271228,\"y\":19.41},{\"x\":1685214571150,\"y\":19.41},{\"x\":1685214871151,\"y\":19.24},{\"x\":1685215171157,\"y\":19.21},{\"x\":1685215471219,\"y\":19.21},{\"x\":1685215771223,\"y\":18.87},{\"x\":1685216071239,\"y\":18.72},{\"x\":1685216371187,\"y\":18.87},{\"x\":1685216671220,\"y\":16.48},{\"x\":1685216971167,\"y\":16.48},{\"x\":1685217271190,\"y\":16.48},{\"x\":1685217571385,\"y\":16.48},{\"x\":1685217871202,\"y\":16.48},{\"x\":1685218171176,\"y\":16.48},{\"x\":1685218471193,\"y\":17.13},{\"x\":1685218772083,\"y\":17.04},{\"x\":1685219071242,\"y\":16.94},{\"x\":1685219371182,\"y\":16.94},{\"x\":1685219671182,\"y\":16.94},{\"x\":1685219971327,\"y\":17.29},{\"x\":1685220271195,\"y\":17.28},{\"x\":1685220571204,\"y\":17.28},{\"x\":1685220871265,\"y\":16.43},{\"x\":1685221171213,\"y\":16.43},{\"x\":1685221471206,\"y\":16.43},{\"x\":1685221771244,\"y\":16.32},{\"x\":1685222071214,\"y\":16.32},{\"x\":1685222371240,\"y\":16.22},{\"x\":1685222671231,\"y\":15.63},{\"x\":1685222971227,\"y\":15.63},{\"x\":1685223271215,\"y\":15.63},{\"x\":1685223571642,\"y\":15.63},{\"x\":1685223871216,\"y\":14.69},{\"x\":1685224171238,\"y\":14.69},{\"x\":1685224471255,\"y\":15.05},{\"x\":1685224771718,\"y\":15.05},{\"x\":1685225071254,\"y\":15},{\"x\":1685225371225,\"y\":14.91},{\"x\":1685225671230,\"y\":14.91},{\"x\":1685225971278,\"y\":15.03},{\"x\":1685226271229,\"y\":14.76},{\"x\":1685226571268,\"y\":14.62},{\"x\":1685226871228,\"y\":14.62},{\"x\":1685227171310,\"y\":14.58},{\"x\":1685227471236,\"y\":14.47},{\"x\":1685227771233,\"y\":14.47},{\"x\":1685228071264,\"y\":14.56},{\"x\":1685228371438,\"y\":14.56},{\"x\":1685228671307,\"y\":14.37},{\"x\":1685228971287,\"y\":14.26},{\"x\":1685229271247,\"y\":14.17},{\"x\":1685229571283,\"y\":14.26},{\"x\":1685229871252,\"y\":14.08},{\"x\":1685230171240,\"y\":14.08},{\"x\":1685230471249,\"y\":13.81},{\"x\":1685230771547,\"y\":13.9},{\"x\":1685231071282,\"y\":13.88},{\"x\":1685231371247,\"y\":13.88},{\"x\":1685231671245,\"y\":13.57},{\"x\":1685231971299,\"y\":13.8},{\"x\":1685232271267,\"y\":13.8},{\"x\":1685232571258,\"y\":13.67},{\"x\":1685232871256,\"y\":13.67},{\"x\":1685233172128,\"y\":13.34},{\"x\":1685233471266,\"y\":13.26},{\"x\":1685233771304,\"y\":13.55},{\"x\":1685234071280,\"y\":13.5},{\"x\":1685234371267,\"y\":13.55},{\"x\":1685234671308,\"y\":13.47},{\"x\":1685234971294,\"y\":13.47},{\"x\":1685235271259,\"y\":13.47},{\"x\":1685235573201,\"y\":13.47},{\"x\":1685235871295,\"y\":13.51},{\"x\":1685236171262,\"y\":13.65},{\"x\":1685236471308,\"y\":13.36},{\"x\":1685236772640,\"y\":13.36},{\"x\":1685237071263,\"y\":13.55},{\"x\":1685237371273,\"y\":13.46},{\"x\":1685237671265,\"y\":13.46},{\"x\":1685237972838,\"y\":13.08},{\"x\":1685238271265,\"y\":13.08},{\"x\":1685238571268,\"y\":13.08},{\"x\":1685238871275,\"y\":13.28},{\"x\":1685239172611,\"y\":13.41},{\"x\":1685239471288,\"y\":13.33},{\"x\":1685239771274,\"y\":13.31},{\"x\":1685240071325,\"y\":13.15},{\"x\":1685240372227,\"y\":13.07},{\"x\":1685240671318,\"y\":13.07},{\"x\":1685240971329,\"y\":13.07},{\"x\":1685241271288,\"y\":13.07},{\"x\":1685241571466,\"y\":13.07},{\"x\":1685241871279,\"y\":12.98},{\"x\":1685242171369,\"y\":13.28},{\"x\":1685242471346,\"y\":13.28},{\"x\":1685242771307,\"y\":13.28},{\"x\":1685243071278,\"y\":13.28},{\"x\":1685243371329,\"y\":13.28},{\"x\":1685243671340,\"y\":13.34},{\"x\":1685243971443,\"y\":13.34},{\"x\":1685244271334,\"y\":13.34},{\"x\":1685244571292,\"y\":13.34},{\"x\":1685244871333,\"y\":13.47},{\"x\":1685245171537,\"y\":13.69},{\"x\":1685245471361,\"y\":13.69},{\"x\":1685245771298,\"y\":13.69},{\"x\":1685246071304,\"y\":13.6},{\"x\":1685246371537,\"y\":13.65},{\"x\":1685246671321,\"y\":13.56},{\"x\":1685246971335,\"y\":13.65},{\"x\":1685247271382,\"y\":13.48},{\"x\":1685247571470,\"y\":13.48},{\"x\":1685247871384,\"y\":13.28},{\"x\":1685248171411,\"y\":13.28},{\"x\":1685248471353,\"y\":13.24},{\"x\":1685248771403,\"y\":13.24},{\"x\":1685249071402,\"y\":13.23},{\"x\":1685249371376,\"y\":13.23},{\"x\":1685249671393,\"y\":13.23},{\"x\":1685249971493,\"y\":13.17},{\"x\":1685250271426,\"y\":13.08},{\"x\":1685250571467,\"y\":13.11},{\"x\":1685250871415,\"y\":13.14},{\"x\":1685251171439,\"y\":13.14},{\"x\":1685251471413,\"y\":13.14},{\"x\":1685251771409,\"y\":13.14},{\"x\":1685252071420,\"y\":13.19},{\"x\":1685252371615,\"y\":13.25},{\"x\":1685252671425,\"y\":13.17},{\"x\":1685252971434,\"y\":13.18},{\"x\":1685253271482,\"y\":13.38},{\"x\":1685253571596,\"y\":13.3},{\"x\":1685253871453,\"y\":13.38},{\"x\":1685254171462,\"y\":13.45},{\"x\":1685254471470,\"y\":13.51},{\"x\":1685254771721,\"y\":13.58},{\"x\":1685255071473,\"y\":13.58},{\"x\":1685255371478,\"y\":13.58},{\"x\":1685255671578,\"y\":13.78},{\"x\":1685255971776,\"y\":13.54},{\"x\":1685256271512,\"y\":13.78},{\"x\":1685256571498,\"y\":13.76},{\"x\":1685256871502,\"y\":13.87},{\"x\":1685257171620,\"y\":13.87},{\"x\":1685257471509,\"y\":14.11},{\"x\":1685257771511,\"y\":14.36},{\"x\":1685258071508,\"y\":14.36},{\"x\":1685258371764,\"y\":14.39},{\"x\":1685258671517,\"y\":14.56},{\"x\":1685258971516,\"y\":14.56},{\"x\":1685259271515,\"y\":14.92},{\"x\":1685259571742,\"y\":14.92},{\"x\":1685259871562,\"y\":15.01},{\"x\":1685260171531,\"y\":15.01},{\"x\":1685260471534,\"y\":15.01},{\"x\":1685260771696,\"y\":14.85},{\"x\":1685261071539,\"y\":15.04},{\"x\":1685261371589,\"y\":15.04},{\"x\":1685261671538,\"y\":15.4},{\"x\":1685261971867,\"y\":15.59},{\"x\":1685262271550,\"y\":15.59},{\"x\":1685262571548,\"y\":15.59},{\"x\":1685262871567,\"y\":15.46},{\"x\":1685263171794,\"y\":15.73},{\"x\":1685263471562,\"y\":15.69},{\"x\":1685263771602,\"y\":15.85},{\"x\":1685264071565,\"y\":15.71},{\"x\":1685264371846,\"y\":15.71},{\"x\":1685264671596,\"y\":15.72},{\"x\":1685264971615,\"y\":15.73},{\"x\":1685265271570,\"y\":15.73},{\"x\":1685265571596,\"y\":15.65},{\"x\":1685265871585,\"y\":15.47},{\"x\":1685266171591,\"y\":15.47},{\"x\":1685266471584,\"y\":15.48},{\"x\":1685266771720,\"y\":15.72},{\"x\":1685267071581,\"y\":15.72},{\"x\":1685267371587,\"y\":15.9},{\"x\":1685267671638,\"y\":16.17},{\"x\":1685267971896,\"y\":16.17},{\"x\":1685268271589,\"y\":15.98},{\"x\":1685268571603,\"y\":16.37},{\"x\":1685268871604,\"y\":16.37},{\"x\":1685269171897,\"y\":16.65},{\"x\":1685269471607,\"y\":16.58},{\"x\":1685269771613,\"y\":16.58},{\"x\":1685270071662,\"y\":16.41},{\"x\":1685270371882,\"y\":16.41},{\"x\":1685270671617,\"y\":16.41},{\"x\":1685270971621,\"y\":16.28},{\"x\":1685271271686,\"y\":16.19},{\"x\":1685271571713,\"y\":16.22},{\"x\":1685271871621,\"y\":16.15},{\"x\":1685272171630,\"y\":16.22},{\"x\":1685272471630,\"y\":15.92},{\"x\":1685272771817,\"y\":15.96},{\"x\":1685273071635,\"y\":15.96},{\"x\":1685273371650,\"y\":16.12},{\"x\":1685273671673,\"y\":15.95},{\"x\":1685273971701,\"y\":16.31},{\"x\":1685274271656,\"y\":16.31},{\"x\":1685274571692,\"y\":16.32},{\"x\":1685274871686,\"y\":16.32},{\"x\":1685275171921,\"y\":16.73},{\"x\":1685275471665,\"y\":16.65},{\"x\":1685275771698,\"y\":16.73},{\"x\":1685276071659,\"y\":16.22},{\"x\":1685276371756,\"y\":16.22},{\"x\":1685276671662,\"y\":16.48},{\"x\":1685276971675,\"y\":15.89},{\"x\":1685277271661,\"y\":15.89},{\"x\":1685277571970,\"y\":15.63},{\"x\":1685277871714,\"y\":15.68},{\"x\":1685278171675,\"y\":15.63},{\"x\":1685278471667,\"y\":15.56},{\"x\":1685278771920,\"y\":15.65},{\"x\":1685279071689,\"y\":15.87},{\"x\":1685279371671,\"y\":15.87},{\"x\":1685279671675,\"y\":15.87},{\"x\":1685279972052,\"y\":15.71},{\"x\":1685280271668,\"y\":15.71},{\"x\":1685280571670,\"y\":16.04},{\"x\":1685280871676,\"y\":16.04},{\"x\":1685281671888,\"y\":15.97},{\"x\":1685284096032,\"y\":15.5},{\"x\":1685284395921,\"y\":15.5},{\"x\":1685284695933,\"y\":15.5},{\"x\":1685284995930,\"y\":15.47},{\"x\":1685285295935,\"y\":15.47},{\"x\":1685285595944,\"y\":15.8},{\"x\":1685285895939,\"y\":15.8},{\"x\":1685286195949,\"y\":15.51},{\"x\":1685286495951,\"y\":15.51},{\"x\":1685286796009,\"y\":15.36},{\"x\":1685287095965,\"y\":15.27},{\"x\":1685287395953,\"y\":15.27},{\"x\":1685287695970,\"y\":15.36},{\"x\":1685287995955,\"y\":15.36},{\"x\":1685288295961,\"y\":15.34},{\"x\":1685288595996,\"y\":14.97},{\"x\":1685288895968,\"y\":14.97},{\"x\":1685289196133,\"y\":14.79},{\"x\":1685289495999,\"y\":14.79},{\"x\":1685289795972,\"y\":14.69},{\"x\":1685290095973,\"y\":14.69},{\"x\":1685290395973,\"y\":14.69},{\"x\":1685290695981,\"y\":14.79},{\"x\":1685290996003,\"y\":14.79},{\"x\":1685291295989,\"y\":14.79},{\"x\":1685291595985,\"y\":14.77},{\"x\":1685291896008,\"y\":14.5},{\"x\":1685292196008,\"y\":14.5},{\"x\":1685292496041,\"y\":14.55},{\"x\":1685292796005,\"y\":14.47},{\"x\":1685293096013,\"y\":14.55},{\"x\":1685293396082,\"y\":14.49},{\"x\":1685293696011,\"y\":14.45},{\"x\":1685293996026,\"y\":14.65},{\"x\":1685294296016,\"y\":14.65},{\"x\":1685294596031,\"y\":14.43},{\"x\":1685294896026,\"y\":14.43},{\"x\":1685295196031,\"y\":14.42},{\"x\":1685295496032,\"y\":14.4},{\"x\":1685295796073,\"y\":14.53},{\"x\":1685296096031,\"y\":14.53},{\"x\":1685296396105,\"y\":14.32},{\"x\":1685296696030,\"y\":14.24},{\"x\":1685296996047,\"y\":14.24},{\"x\":1685297296080,\"y\":14.48},{\"x\":1685297596038,\"y\":14.4},{\"x\":1685297896041,\"y\":14.48},{\"x\":1685298196059,\"y\":14.08},{\"x\":1685298496041,\"y\":14.08},{\"x\":1685298796049,\"y\":14.33},{\"x\":1685299096058,\"y\":14},{\"x\":1685299396061,\"y\":13.59},{\"x\":1685299696048,\"y\":13.56},{\"x\":1685299996049,\"y\":13.56},{\"x\":1685300296111,\"y\":13.8},{\"x\":1685300596061,\"y\":13.71},{\"x\":1685300896068,\"y\":13.71},{\"x\":1685301196056,\"y\":13.49},{\"x\":1685301496064,\"y\":13.49},{\"x\":1685301796076,\"y\":13.49},{\"x\":1685302096103,\"y\":13.4},{\"x\":1685302396063,\"y\":13.46},{\"x\":1685302696077,\"y\":13.34},{\"x\":1685302996145,\"y\":13.04},{\"x\":1685303296067,\"y\":12.95},{\"x\":1685303596073,\"y\":13.04},{\"x\":1685303896072,\"y\":12.69},{\"x\":1685304196079,\"y\":12.67},{\"x\":1685304496103,\"y\":12.49},{\"x\":1685304796082,\"y\":12.49},{\"x\":1685305096071,\"y\":12.49},{\"x\":1685305396094,\"y\":12.49},{\"x\":1685305696124,\"y\":12.2},{\"x\":1685305996075,\"y\":12.14},{\"x\":1685306296121,\"y\":11.8},{\"x\":1685306596072,\"y\":11.8},{\"x\":1685306896081,\"y\":11.8},{\"x\":1685307196124,\"y\":11.34},{\"x\":1685307496091,\"y\":11.34},{\"x\":1685307797175,\"y\":11.28},{\"x\":1685308096131,\"y\":11.3},{\"x\":1685308396095,\"y\":11.28},{\"x\":1685308696095,\"y\":11.3},{\"x\":1685308996098,\"y\":11.22},{\"x\":1685309296119,\"y\":11},{\"x\":1685309596104,\"y\":11},{\"x\":1685309896135,\"y\":10.5},{\"x\":1685310196123,\"y\":10.5},{\"x\":1685310496134,\"y\":10.5},{\"x\":1685310796104,\"y\":10.45},{\"x\":1685311096115,\"y\":10.45},{\"x\":1685311396137,\"y\":10.24},{\"x\":1685311696121,\"y\":10.24},{\"x\":1685311996202,\"y\":10.21},{\"x\":1685312296125,\"y\":10.21},{\"x\":1685312596146,\"y\":10.21},{\"x\":1685312896148,\"y\":9.93},{\"x\":1685313196132,\"y\":10.07},{\"x\":1685313496203,\"y\":9.89},{\"x\":1685313796150,\"y\":9.83},{\"x\":1685314096147,\"y\":9.75},{\"x\":1685314396195,\"y\":9.81},{\"x\":1685314696202,\"y\":9.81},{\"x\":1685314996169,\"y\":9.68},{\"x\":1685315296183,\"y\":9.65},{\"x\":1685315596155,\"y\":9.37},{\"x\":1685315896207,\"y\":9.43},{\"x\":1685316196167,\"y\":9.43},{\"x\":1685316496181,\"y\":9.32},{\"x\":1685316796216,\"y\":9.22},{\"x\":1685317096164,\"y\":9.22},{\"x\":1685317396213,\"y\":8.84},{\"x\":1685317696170,\"y\":8.76},{\"x\":1685317996185,\"y\":8.81},{\"x\":1685318296172,\"y\":8.72},{\"x\":1685318596191,\"y\":8.81},{\"x\":1685318896205,\"y\":8.99},{\"x\":1685319196165,\"y\":8.99},{\"x\":1685319496187,\"y\":8.9},{\"x\":1685319796169,\"y\":8.9},{\"x\":1685320096204,\"y\":8.99},{\"x\":1685320396170,\"y\":8.7},{\"x\":1685320696174,\"y\":8.65},{\"x\":1685320996175,\"y\":8.65},{\"x\":1685321296205,\"y\":8.41},{\"x\":1685321596177,\"y\":8.41},{\"x\":1685321896203,\"y\":8.41},{\"x\":1685322196246,\"y\":8.09},{\"x\":1685322496225,\"y\":7.88},{\"x\":1685322796181,\"y\":7.88},{\"x\":1685323096176,\"y\":7.73},{\"x\":1685323396175,\"y\":7.73},{\"x\":1685323696184,\"y\":7.67},{\"x\":1685323996186,\"y\":7.67},{\"x\":1685324296221,\"y\":7.83},{\"x\":1685324596190,\"y\":7.74},{\"x\":1685324896222,\"y\":7.83},{\"x\":1685325196203,\"y\":7.74},{\"x\":1685325496188,\"y\":7.32},{\"x\":1685325796536,\"y\":7.32},{\"x\":1685326096185,\"y\":7.32},{\"x\":1685326396231,\"y\":7.41},{\"x\":1685326696191,\"y\":7.41},{\"x\":1685326996194,\"y\":7.41},{\"x\":1685327296195,\"y\":7.29},{\"x\":1685327596190,\"y\":7.3},{\"x\":1685327896227,\"y\":7.33},{\"x\":1685328196279,\"y\":7.33},{\"x\":1685328496276,\"y\":7.33},{\"x\":1685328796240,\"y\":7.2},{\"x\":1685329096191,\"y\":7.2},{\"x\":1685329396192,\"y\":7.11},{\"x\":1685329696248,\"y\":7.2},{\"x\":1685329996247,\"y\":7.2},{\"x\":1685330296206,\"y\":7.2},{\"x\":1685330596222,\"y\":7.11},{\"x\":1685330896241,\"y\":7.37},{\"x\":1685331196223,\"y\":7.37},{\"x\":1685331496227,\"y\":7.37},{\"x\":1685331796287,\"y\":7.54},{\"x\":1685332096241,\"y\":7.54},{\"x\":1685332396262,\"y\":7.25},{\"x\":1685332696288,\"y\":7.34},{\"x\":1685332996282,\"y\":7.25},{\"x\":1685333296250,\"y\":7.34},{\"x\":1685333596314,\"y\":7.3},{\"x\":1685333896248,\"y\":7.3},{\"x\":1685334196250,\"y\":7.22},{\"x\":1685334496287,\"y\":7.3},{\"x\":1685334796262,\"y\":7.3},{\"x\":1685335096310,\"y\":7.34},{\"x\":1685335396322,\"y\":7.34},{\"x\":1685335696328,\"y\":7.35},{\"x\":1685335996277,\"y\":7.35},{\"x\":1685336296341,\"y\":7.46},{\"x\":1685336596305,\"y\":7.46},{\"x\":1685336896288,\"y\":7.46},{\"x\":1685337196337,\"y\":7.77},{\"x\":1685337496307,\"y\":7.68},{\"x\":1685337796344,\"y\":7.77},{\"x\":1685338096310,\"y\":7.7},{\"x\":1685338396309,\"y\":7.7},{\"x\":1685338696313,\"y\":7.87},{\"x\":1685338996338,\"y\":7.91},{\"x\":1685339296305,\"y\":8.24},{\"x\":1685339596306,\"y\":8.24},{\"x\":1685339896363,\"y\":8.87},{\"x\":1685340196325,\"y\":8.81},{\"x\":1685340496328,\"y\":8.87},{\"x\":1685340796324,\"y\":8.93},{\"x\":1685341096323,\"y\":8.93},{\"x\":1685341396403,\"y\":9.54},{\"x\":1685341696331,\"y\":9.46},{\"x\":1685341996329,\"y\":9.48},{\"x\":1685342296334,\"y\":9.53},{\"x\":1685342596385,\"y\":9.94},{\"x\":1685342896330,\"y\":9.94},{\"x\":1685343196338,\"y\":10.15},{\"x\":1685343496342,\"y\":10.74},{\"x\":1685343796354,\"y\":10.74},{\"x\":1685344096339,\"y\":11.17},{\"x\":1685344396346,\"y\":11.17},{\"x\":1685344697407,\"y\":11.29},{\"x\":1685344996353,\"y\":11.26},{\"x\":1685345296424,\"y\":11.74},{\"x\":1685345596406,\"y\":11.65},{\"x\":1685345896351,\"y\":11.65},{\"x\":1685346196416,\"y\":12.07},{\"x\":1685346496410,\"y\":12.16},{\"x\":1685346796378,\"y\":12.07},{\"x\":1685347096406,\"y\":12.03},{\"x\":1685347396359,\"y\":12.03},{\"x\":1685347696378,\"y\":12.03},{\"x\":1685347996394,\"y\":12.1},{\"x\":1685348296366,\"y\":12.1},{\"x\":1685348596360,\"y\":12.02},{\"x\":1685348896369,\"y\":12.44},{\"x\":1685349196480,\"y\":12.49},{\"x\":1685349496365,\"y\":12.49},{\"x\":1685349796376,\"y\":12.49},{\"x\":1685350096394,\"y\":12.97},{\"x\":1685350396369,\"y\":12.97},{\"x\":1685350696451,\"y\":13.05},{\"x\":1685350996421,\"y\":13.19},{\"x\":1685351296370,\"y\":13.05},{\"x\":1685351596436,\"y\":13.25},{\"x\":1685351896375,\"y\":13.25},{\"x\":1685352196381,\"y\":13.25},{\"x\":1685352496379,\"y\":13.28},{\"x\":1685352796390,\"y\":13.28},{\"x\":1685353096503,\"y\":13.97},{\"x\":1685353396412,\"y\":13.97},{\"x\":1685353696392,\"y\":13.97},{\"x\":1685353996429,\"y\":14.15},{\"x\":1685354296437,\"y\":14.15},{\"x\":1685354596450,\"y\":14.15},{\"x\":1685354896393,\"y\":14.3},{\"x\":1685355196401,\"y\":14.3},{\"x\":1685355496440,\"y\":14.36},{\"x\":1685355796402,\"y\":14.36},{\"x\":1685356096449,\"y\":14.32},{\"x\":1685356396391,\"y\":14.24},{\"x\":1685356696401,\"y\":14.32},{\"x\":1685356996401,\"y\":14.61},{\"x\":1685357296408,\"y\":14.61},{\"x\":1685357596403,\"y\":15.01},{\"x\":1685357896429,\"y\":15.59},{\"x\":1685358196393,\"y\":15.59},{\"x\":1685358496468,\"y\":15.59},{\"x\":1685358796424,\"y\":16},{\"x\":1685359096400,\"y\":16},{\"x\":1685359396448,\"y\":16.11},{\"x\":1685359696410,\"y\":16.08},{\"x\":1685359996404,\"y\":16.08},{\"x\":1685360296411,\"y\":16.35},{\"x\":1685360596442,\"y\":16.35},{\"x\":1685360896460,\"y\":16.44},{\"x\":1685361196442,\"y\":16.44},{\"x\":1685361496409,\"y\":16.44},{\"x\":1685361796427,\"y\":16.52},{\"x\":1685362096416,\"y\":16.62},{\"x\":1685362396413,\"y\":16.67},{\"x\":1685362696411,\"y\":16.68},{\"x\":1685362996461,\"y\":16.79},{\"x\":1685363296411,\"y\":16.85},{\"x\":1685363596420,\"y\":16.79},{\"x\":1685363896467,\"y\":16.76},{\"x\":1685364196435,\"y\":16.76},{\"x\":1685364496434,\"y\":16.76},{\"x\":1685364796430,\"y\":16.68},{\"x\":1685365096423,\"y\":17.1},{\"x\":1685365396432,\"y\":17.1},{\"x\":1685365696497,\"y\":17.46},{\"x\":1685365996459,\"y\":17.44},{\"x\":1685366296423,\"y\":17.46},{\"x\":1685366596445,\"y\":17.44},{\"x\":1685366896437,\"y\":17.38},{\"x\":1685367196433,\"y\":17.38},{\"x\":1685367496432,\"y\":17.38},{\"x\":1685367796435,\"y\":17.27},{\"x\":1685368096426,\"y\":17.27},{\"x\":1685368396429,\"y\":17.26},{\"x\":1685368696436,\"y\":17.26},{\"x\":1685368996438,\"y\":17.44},{\"x\":1685369296428,\"y\":17.32},{\"x\":1685369596501,\"y\":17.5},{\"x\":1685369896441,\"y\":17.42},{\"x\":1685370196509,\"y\":17.5},{\"x\":1685370496485,\"y\":17.7},{\"x\":1685370796502,\"y\":17.7},{\"x\":1685371096455,\"y\":17.7},{\"x\":1685371396510,\"y\":17.39},{\"x\":1685371696485,\"y\":17.39},{\"x\":1685371996502,\"y\":17.64},{\"x\":1685372296476,\"y\":17.31},{\"x\":1685372596474,\"y\":17.78},{\"x\":1685372896482,\"y\":17.78},{\"x\":1685373196484,\"y\":17.78},{\"x\":1685373496572,\"y\":17.86},{\"x\":1685373796514,\"y\":17.78},{\"x\":1685374096510,\"y\":17.81},{\"x\":1685374396544,\"y\":17.86},{\"x\":1685374696519,\"y\":17.78},{\"x\":1685374996566,\"y\":17.78},{\"x\":1685375296542,\"y\":17.89},{\"x\":1685375596519,\"y\":17.89},{\"x\":1685375896531,\"y\":17.89},{\"x\":1685376196570,\"y\":17.89},{\"x\":1685376496581,\"y\":18.04},{\"x\":1685376796589,\"y\":18.04},{\"x\":1685377096547,\"y\":17.74},{\"x\":1685377396613,\"y\":17.74},{\"x\":1685377696596,\"y\":17.6},{\"x\":1685377996542,\"y\":17.51},{\"x\":1685378296565,\"y\":17.51},{\"x\":1685378596624,\"y\":17.51},{\"x\":1685378896627,\"y\":17.42},{\"x\":1685379196643,\"y\":17.2},{\"x\":1685379496586,\"y\":17.42},{\"x\":1685379796637,\"y\":17.09},{\"x\":1685380096596,\"y\":17.09},{\"x\":1685380396635,\"y\":17.11},{\"x\":1685380696607,\"y\":17.04},{\"x\":1685380996713,\"y\":17.08},{\"x\":1685381296598,\"y\":16.99},{\"x\":1685381596615,\"y\":17.08},{\"x\":1685381896608,\"y\":17.03},{\"x\":1685382196647,\"y\":17.03},{\"x\":1685382496621,\"y\":16.09},{\"x\":1685382796622,\"y\":16.25},{\"x\":1685383096636,\"y\":16.25},{\"x\":1685383396656,\"y\":16.25},{\"x\":1685383696677,\"y\":16.1},{\"x\":1685383996640,\"y\":16.09},{\"x\":1685384296634,\"y\":16.09},{\"x\":1685384596702,\"y\":16.09},{\"x\":1685384896755,\"y\":15.72},{\"x\":1685385196657,\"y\":15.7},{\"x\":1685385496648,\"y\":15.72},{\"x\":1685385796721,\"y\":14.94},{\"x\":1685386096661,\"y\":14.89},{\"x\":1685386396764,\"y\":14.48},{\"x\":1685386696644,\"y\":14.48},{\"x\":1685386996711,\"y\":14.39},{\"x\":1685387296665,\"y\":14.47},{\"x\":1685387596687,\"y\":14.47},{\"x\":1685387896719,\"y\":14.45},{\"x\":1685388196746,\"y\":14.37},{\"x\":1685388496677,\"y\":14.36},{\"x\":1685388796728,\"y\":14.16},{\"x\":1685389096728,\"y\":14.95},{\"x\":1685389396772,\"y\":15.89},{\"x\":1685389696700,\"y\":15.8},{\"x\":1685389996694,\"y\":15.8},{\"x\":1685390296741,\"y\":13.52},{\"x\":1685390596769,\"y\":13.52},{\"x\":1685390896706,\"y\":13.52},{\"x\":1685391196708,\"y\":12.38},{\"x\":1685391496778,\"y\":12.52},{\"x\":1685391796848,\"y\":12.52},{\"x\":1685392096805,\"y\":12.37},{\"x\":1685392396723,\"y\":12.01},{\"x\":1685392696723,\"y\":12.01},{\"x\":1685392996799,\"y\":11.33},{\"x\":1685393296731,\"y\":11.58},{\"x\":1685393596725,\"y\":11.33},{\"x\":1685393896759,\"y\":11.64},{\"x\":1685394196778,\"y\":11.64},{\"x\":1685394496727,\"y\":11.63},{\"x\":1685394796838,\"y\":11},{\"x\":1685395096733,\"y\":10.92},{\"x\":1685395396756,\"y\":10.84},{\"x\":1685395696744,\"y\":10.81},{\"x\":1685395996738,\"y\":10.81},{\"x\":1685396296745,\"y\":10.81},{\"x\":1685396596863,\"y\":9.92},{\"x\":1685396896748,\"y\":9.92},{\"x\":1685397196744,\"y\":9.92},{\"x\":1685397496752,\"y\":9.84},{\"x\":1685397797031,\"y\":9.29},{\"x\":1685398096745,\"y\":9.59},{\"x\":1685398396778,\"y\":9.29},{\"x\":1685398696753,\"y\":9.67},{\"x\":1685398996882,\"y\":9.8},{\"x\":1685399296749,\"y\":9.67},{\"x\":1685399596872,\"y\":9.64},{\"x\":1685399896856,\"y\":9.29},{\"x\":1685400196853,\"y\":9.29},{\"x\":1685400496758,\"y\":9.29},{\"x\":1685400796806,\"y\":8.88},{\"x\":1685401096749,\"y\":8.88},{\"x\":1685401396853,\"y\":8.88},{\"x\":1685401696823,\"y\":8.87},{\"x\":1685401996749,\"y\":8.93},{\"x\":1685402296834,\"y\":8.83},{\"x\":1685402596862,\"y\":8.83},{\"x\":1685402896766,\"y\":8.83},{\"x\":1685403196764,\"y\":8.69},{\"x\":1685403496778,\"y\":8.79},{\"x\":1685403796902,\"y\":8.76},{\"x\":1685404096775,\"y\":8.76},{\"x\":1685404396829,\"y\":8.45},{\"x\":1685404696790,\"y\":8.45},{\"x\":1685404996816,\"y\":8.36},{\"x\":1685405296883,\"y\":8.71},{\"x\":1685405596870,\"y\":8.7},{\"x\":1685405896793,\"y\":8.63},{\"x\":1685406196983,\"y\":8.7},{\"x\":1685406496794,\"y\":8.47},{\"x\":1685406796799,\"y\":8.47},{\"x\":1685407096806,\"y\":8.41},{\"x\":1685407396889,\"y\":8.27},{\"x\":1685407696814,\"y\":8.19},{\"x\":1685407996818,\"y\":8.27},{\"x\":1685408296823,\"y\":8.19},{\"x\":1685408596913,\"y\":8.19},{\"x\":1685408896867,\"y\":7.82},{\"x\":1685409196827,\"y\":7.82},{\"x\":1685409496885,\"y\":7.78},{\"x\":1685409796923,\"y\":7.69},{\"x\":1685410096833,\"y\":7.69},{\"x\":1685410396863,\"y\":7.68},{\"x\":1685410696853,\"y\":7.69},{\"x\":1685410996931,\"y\":7.59},{\"x\":1685411296850,\"y\":7.59},{\"x\":1685411596860,\"y\":7.59},{\"x\":1685411896863,\"y\":7.34},{\"x\":1685412197065,\"y\":7.41},{\"x\":1685412496865,\"y\":7.34},{\"x\":1685412796871,\"y\":7.34},{\"x\":1685413096914,\"y\":7.41},{\"x\":1685413396986,\"y\":7.41},{\"x\":1685413696881,\"y\":7.41},{\"x\":1685413996886,\"y\":7.35},{\"x\":1685414296923,\"y\":7.82},{\"x\":1685414597013,\"y\":7.95},{\"x\":1685414896976,\"y\":7.95},{\"x\":1685415196895,\"y\":7.95},{\"x\":1685415496889,\"y\":7.95},{\"x\":1685415796967,\"y\":8.17},{\"x\":1685416096899,\"y\":8.17},{\"x\":1685416396952,\"y\":8.17},{\"x\":1685416696900,\"y\":8.09},{\"x\":1685416997056,\"y\":8.23},{\"x\":1685417296914,\"y\":8.21},{\"x\":1685417596918,\"y\":8.23},{\"x\":1685417896941,\"y\":8.11},{\"x\":1685418197072,\"y\":8.11},{\"x\":1685418496972,\"y\":7.78},{\"x\":1685418796976,\"y\":7.78},{\"x\":1685419096917,\"y\":7.78},{\"x\":1685419397122,\"y\":7.76},{\"x\":1685419696925,\"y\":7.7},{\"x\":1685419996981,\"y\":7.76},{\"x\":1685420296927,\"y\":7.98},{\"x\":1685420597159,\"y\":7.68},{\"x\":1685420896981,\"y\":8.25},{\"x\":1685421196938,\"y\":8.25},{\"x\":1685421496968,\"y\":9.25},{\"x\":1685421797058,\"y\":8.95},{\"x\":1685422096935,\"y\":8.95},{\"x\":1685422397004,\"y\":9.27},{\"x\":1685422696956,\"y\":9.27},{\"x\":1685422997188,\"y\":9.29},{\"x\":1685423296955,\"y\":9.29},{\"x\":1685423597001,\"y\":9.11},{\"x\":1685423896956,\"y\":9.02},{\"x\":1685424197012,\"y\":9.02},{\"x\":1685424497000,\"y\":9.11},{\"x\":1685424796971,\"y\":9.02},{\"x\":1685425096964,\"y\":10.04},{\"x\":1685425397109,\"y\":10.04},{\"x\":1685425696964,\"y\":10.02},{\"x\":1685425996974,\"y\":9.99},{\"x\":1685426296965,\"y\":10.2},{\"x\":1685426597100,\"y\":10.28},{\"x\":1685426896989,\"y\":10.33},{\"x\":1685427196988,\"y\":10.33},{\"x\":1685427497031,\"y\":10.45},{\"x\":1685427797156,\"y\":10.38},{\"x\":1685428097083,\"y\":10.94},{\"x\":1685428396991,\"y\":10.94},{\"x\":1685428696996,\"y\":10.82},{\"x\":1685428997105,\"y\":11.01},{\"x\":1685429296992,\"y\":11.01},{\"x\":1685429597030,\"y\":11.01},{\"x\":1685429896994,\"y\":11.04},{\"x\":1685430197076,\"y\":11.04},{\"x\":1685430497010,\"y\":11.39},{\"x\":1685430796999,\"y\":11.6},{\"x\":1685431097007,\"y\":11.55},{\"x\":1685431397249,\"y\":11.81},{\"x\":1685431697002,\"y\":11.81},{\"x\":1685431997013,\"y\":11.81},{\"x\":1685432297009,\"y\":11.82},{\"x\":1685432597030,\"y\":11.82},{\"x\":1685432897132,\"y\":12.15},{\"x\":1685433197016,\"y\":12.07},{\"x\":1685433497009,\"y\":12.15},{\"x\":1685433797139,\"y\":12.16},{\"x\":1685434097016,\"y\":12.19},{\"x\":1685434397064,\"y\":12.22},{\"x\":1685434697027,\"y\":12.14},{\"x\":1685434997238,\"y\":12.14},{\"x\":1685435297077,\"y\":12.32},{\"x\":1685435597014,\"y\":12.33},{\"x\":1685435897071,\"y\":12.41},{\"x\":1685436197195,\"y\":12.35},{\"x\":1685436497013,\"y\":12.35},{\"x\":1685436797015,\"y\":12.32},{\"x\":1685437097050,\"y\":12.32},{\"x\":1685437397237,\"y\":12.33},{\"x\":1685437697030,\"y\":12.33},{\"x\":1685437997069,\"y\":12.27},{\"x\":1685438297034,\"y\":12.19},{\"x\":1685438597203,\"y\":12.17},{\"x\":1685438897033,\"y\":12.34},{\"x\":1685439197064,\"y\":12.31},{\"x\":1685439497033,\"y\":12.32},{\"x\":1685439797107,\"y\":12.31},{\"x\":1685440097051,\"y\":13.11},{\"x\":1685440397038,\"y\":13.21},{\"x\":1685440697073,\"y\":13.37},{\"x\":1685440997179,\"y\":13.19},{\"x\":1685441297048,\"y\":13.28},{\"x\":1685441597041,\"y\":13.19},{\"x\":1685441897039,\"y\":13.29},{\"x\":1685442197094,\"y\":13.29},{\"x\":1685442497030,\"y\":13.33},{\"x\":1685442797045,\"y\":13.33},{\"x\":1685443097030,\"y\":13.2},{\"x\":1685443397349,\"y\":13.31},{\"x\":1685443697027,\"y\":13.31},{\"x\":1685443997092,\"y\":13.23},{\"x\":1685444297033,\"y\":13.77},{\"x\":1685444597073,\"y\":13.68},{\"x\":1685444897078,\"y\":16.19},{\"x\":1685445197034,\"y\":16.19},{\"x\":1685445497068,\"y\":16.19},{\"x\":1685445797209,\"y\":16.19},{\"x\":1685446097058,\"y\":16.19},{\"x\":1685446397051,\"y\":17.22},{\"x\":1685446697059,\"y\":17.22},{\"x\":1685446997166,\"y\":18.41},{\"x\":1685447297115,\"y\":18.41},{\"x\":1685447597112,\"y\":18.41},{\"x\":1685447897089,\"y\":18.41},{\"x\":1685448197159,\"y\":12.74},{\"x\":1685448497098,\"y\":12.72},{\"x\":1685448797127,\"y\":12.89},{\"x\":1685449097105,\"y\":12.97},{\"x\":1685449397373,\"y\":13.15},{\"x\":1685449697109,\"y\":13.03},{\"x\":1685449997136,\"y\":13.06},{\"x\":1685450297128,\"y\":13.06},{\"x\":1685450597387,\"y\":13.06},{\"x\":1685450897183,\"y\":13.21},{\"x\":1685451197144,\"y\":13.21},{\"x\":1685451497142,\"y\":13.33},{\"x\":1685451797185,\"y\":13.33},{\"x\":1685452097148,\"y\":13.57},{\"x\":1685452397249,\"y\":13.64},{\"x\":1685452697161,\"y\":13.64},{\"x\":1685452997474,\"y\":13.64},{\"x\":1685453297206,\"y\":13.97},{\"x\":1685453597173,\"y\":13.69},{\"x\":1685453897183,\"y\":13.94},{\"x\":1685454197215,\"y\":13.94},{\"x\":1685454497192,\"y\":14.16},{\"x\":1685454797260,\"y\":14.48},{\"x\":1685455097202,\"y\":14.67},{\"x\":1685455397476,\"y\":14.67},{\"x\":1685455697209,\"y\":14.86},{\"x\":1685455997240,\"y\":15.03},{\"x\":1685456297262,\"y\":15.18},{\"x\":1685456597249,\"y\":15.18},{\"x\":1685456897228,\"y\":15.09},{\"x\":1685457197269,\"y\":15.55},{\"x\":1685457497236,\"y\":15.55},{\"x\":1685457797465,\"y\":15.55},{\"x\":1685458097286,\"y\":16.03},{\"x\":1685458397242,\"y\":16.03},{\"x\":1685458697267,\"y\":16.03},{\"x\":1685458997286,\"y\":15.84},{\"x\":1685459297248,\"y\":15.84},{\"x\":1685459597268,\"y\":16.22},{\"x\":1685459897263,\"y\":16.22},{\"x\":1685460197357,\"y\":16.94},{\"x\":1685460497301,\"y\":16.94},{\"x\":1685460797266,\"y\":16.94},{\"x\":1685461097305,\"y\":16.95},{\"x\":1685461397544,\"y\":17.05},{\"x\":1685461697280,\"y\":16.95},{\"x\":1685461997291,\"y\":16.97},{\"x\":1685462297287,\"y\":16.97},{\"x\":1685462597465,\"y\":17.35},{\"x\":1685462897303,\"y\":17.35},{\"x\":1685463197366,\"y\":17.2},{\"x\":1685463737229,\"y\":17.2},{\"x\":1685464037277,\"y\":17.14},{\"x\":1685464337245,\"y\":17.14},{\"x\":1685464637256,\"y\":17.03},{\"x\":1685464937262,\"y\":17.14},{\"x\":1685465237316,\"y\":17.08},{\"x\":1685465537294,\"y\":17.08},{\"x\":1685465837334,\"y\":17.31},{\"x\":1685466137337,\"y\":17.31},{\"x\":1685466437310,\"y\":17.03},{\"x\":1685466737354,\"y\":17.04},{\"x\":1685467037407,\"y\":16.96},{\"x\":1685467337326,\"y\":17.16},{\"x\":1685467637328,\"y\":17.13},{\"x\":1685467937333,\"y\":16.81},{\"x\":1685468237339,\"y\":16.48},{\"x\":1685468537360,\"y\":16.48},{\"x\":1685468837368,\"y\":16.47},{\"x\":1685469137413,\"y\":15.9},{\"x\":1685469437370,\"y\":16.04},{\"x\":1685469737372,\"y\":15.9},{\"x\":1685470037427,\"y\":15.82},{\"x\":1685470337392,\"y\":15.82},{\"x\":1685470637406,\"y\":15.82},{\"x\":1685470937407,\"y\":15.69},{\"x\":1685471237416,\"y\":15.83},{\"x\":1685471537421,\"y\":15.83},{\"x\":1685471837423,\"y\":15.95},{\"x\":1685472137555,\"y\":15.16},{\"x\":1685472437434,\"y\":15.08},{\"x\":1685472737439,\"y\":14.87},{\"x\":1685473037727,\"y\":14.79},{\"x\":1685473337523,\"y\":15.1},{\"x\":1685473637452,\"y\":14.79},{\"x\":1685473937500,\"y\":14.51},{\"x\":1685474237504,\"y\":14.29},{\"x\":1685474537449,\"y\":14.29},{\"x\":1685474837471,\"y\":14.21},{\"x\":1685475137479,\"y\":14.06},{\"x\":1685475437511,\"y\":13.27},{\"x\":1685475737497,\"y\":13.27},{\"x\":1685476037496,\"y\":13.19},{\"x\":1685476337572,\"y\":13.61},{\"x\":1685476637511,\"y\":13.49},{\"x\":1685476937513,\"y\":13.47},{\"x\":1685477237528,\"y\":13.42},{\"x\":1685477537526,\"y\":13.44},{\"x\":1685477837530,\"y\":13.44},{\"x\":1685478137582,\"y\":13.03},{\"x\":1685478437532,\"y\":13.14},{\"x\":1685478737565,\"y\":12.83},{\"x\":1685479037545,\"y\":12.91},{\"x\":1685479337555,\"y\":12.59},{\"x\":1685479637566,\"y\":12.56},{\"x\":1685479937595,\"y\":12.5},{\"x\":1685480237565,\"y\":12.61},{\"x\":1685480537635,\"y\":12.43},{\"x\":1685480837564,\"y\":12.43},{\"x\":1685481137578,\"y\":12.27},{\"x\":1685481437654,\"y\":12.32},{\"x\":1685481737583,\"y\":12.24},{\"x\":1685482037634,\"y\":12.13},{\"x\":1685482337596,\"y\":12.13},{\"x\":1685482637588,\"y\":12.04},{\"x\":1685482937605,\"y\":11.88},{\"x\":1685483237606,\"y\":11.88},{\"x\":1685483537617,\"y\":11.87},{\"x\":1685483837694,\"y\":11.87},{\"x\":1685484137652,\"y\":11.83},{\"x\":1685484437620,\"y\":11.55},{\"x\":1685484737629,\"y\":11.83},{\"x\":1685485037682,\"y\":11.43},{\"x\":1685485337673,\"y\":11.43},{\"x\":1685485637637,\"y\":11.43},{\"x\":1685485937698,\"y\":11.4},{\"x\":1685486237666,\"y\":11.4},{\"x\":1685486537695,\"y\":11.4},{\"x\":1685486837701,\"y\":11.34},{\"x\":1685487137670,\"y\":11.34},{\"x\":1685487437690,\"y\":11.34},{\"x\":1685487737711,\"y\":11.08},{\"x\":1685488037671,\"y\":11.08},{\"x\":1685488337728,\"y\":11.08},{\"x\":1685488637752,\"y\":11.06},{\"x\":1685488937679,\"y\":11.06},{\"x\":1685489237735,\"y\":11.04},{\"x\":1685489537691,\"y\":10.96},{\"x\":1685489837848,\"y\":11.05},{\"x\":1685490137701,\"y\":11.05},{\"x\":1685490437705,\"y\":10.95},{\"x\":1685490737730,\"y\":10.86},{\"x\":1685491037756,\"y\":10.8},{\"x\":1685491337708,\"y\":10.8},{\"x\":1685491637705,\"y\":10.8},{\"x\":1685491937711,\"y\":10.71},{\"x\":1685492237764,\"y\":10.8},{\"x\":1685492537769,\"y\":10.8},{\"x\":1685492837718,\"y\":10.8},{\"x\":1685493137753,\"y\":10.8},{\"x\":1685493437930,\"y\":10.87},{\"x\":1685493737724,\"y\":10.87},{\"x\":1685494037777,\"y\":10.61},{\"x\":1685494337747,\"y\":10.52},{\"x\":1685494637852,\"y\":10.61},{\"x\":1685494937737,\"y\":10.61},{\"x\":1685495237777,\"y\":10.63},{\"x\":1685495537775,\"y\":10.62},{\"x\":1685495837812,\"y\":10.51},{\"x\":1685496137755,\"y\":10.43},{\"x\":1685496437796,\"y\":10.49},{\"x\":1685496737809,\"y\":10.49},{\"x\":1685497037761,\"y\":10.49},{\"x\":1685497337761,\"y\":10.23},{\"x\":1685497637765,\"y\":10.23},{\"x\":1685497937814,\"y\":10.31},{\"x\":1685498237807,\"y\":10.31},{\"x\":1685498537788,\"y\":10.31},{\"x\":1685498837775,\"y\":10.23},{\"x\":1685499137789,\"y\":10.23},{\"x\":1685499437805,\"y\":10.23},{\"x\":1685499737817,\"y\":10.31},{\"x\":1685500037780,\"y\":10.31},{\"x\":1685500337844,\"y\":10.14},{\"x\":1685500637891,\"y\":10.14},{\"x\":1685500937793,\"y\":10.14},{\"x\":1685501237793,\"y\":10.14},{\"x\":1685501537807,\"y\":10.05},{\"x\":1685501837925,\"y\":10.05},{\"x\":1685502137801,\"y\":10.05},{\"x\":1685502437811,\"y\":9.97},{\"x\":1685502737895,\"y\":10.14},{\"x\":1685503037900,\"y\":10.16},{\"x\":1685503337808,\"y\":10.16},{\"x\":1685503637807,\"y\":10.08},{\"x\":1685503937812,\"y\":9.94},{\"x\":1685504237850,\"y\":9.94},{\"x\":1685504537822,\"y\":9.99},{\"x\":1685504837872,\"y\":9.96},{\"x\":1685505137866,\"y\":9.98},{\"x\":1685505438032,\"y\":9.98},{\"x\":1685505737834,\"y\":9.98},{\"x\":1685506037879,\"y\":9.81},{\"x\":1685506337861,\"y\":9.81},{\"x\":1685506637914,\"y\":9.81},{\"x\":1685506937872,\"y\":9.81},{\"x\":1685507237889,\"y\":9.81},{\"x\":1685507537838,\"y\":9.81},{\"x\":1685507837888,\"y\":9.81},{\"x\":1685508137887,\"y\":9.82},{\"x\":1685508437832,\"y\":9.73},{\"x\":1685508737867,\"y\":9.82},{\"x\":1685509037974,\"y\":9.62},{\"x\":1685509337857,\"y\":9.82},{\"x\":1685509637848,\"y\":9.62},{\"x\":1685509937889,\"y\":9.62},{\"x\":1685510237947,\"y\":9.62},{\"x\":1685510537889,\"y\":9.65},{\"x\":1685510837852,\"y\":9.65},{\"x\":1685511137855,\"y\":9.65},{\"x\":1685511437965,\"y\":9.57},{\"x\":1685511737859,\"y\":9.57},{\"x\":1685512037848,\"y\":9.54},{\"x\":1685512337852,\"y\":9.55},{\"x\":1685512638025,\"y\":9.58},{\"x\":1685512937857,\"y\":9.57},{\"x\":1685513237850,\"y\":9.58},{\"x\":1685513537848,\"y\":9.57},{\"x\":1685513837893,\"y\":9.57},{\"x\":1685514137857,\"y\":9.75},{\"x\":1685514437855,\"y\":9.75},{\"x\":1685514737977,\"y\":9.84},{\"x\":1685515037889,\"y\":9.84},{\"x\":1685515337874,\"y\":9.84},{\"x\":1685515637865,\"y\":9.84},{\"x\":1685515937961,\"y\":9.84},{\"x\":1685516238059,\"y\":9.84},{\"x\":1685516537872,\"y\":9.75},{\"x\":1685516837969,\"y\":10.01},{\"x\":1685517137902,\"y\":10.01},{\"x\":1685517437997,\"y\":10.01},{\"x\":1685517737887,\"y\":10.03},{\"x\":1685518037974,\"y\":10.03},{\"x\":1685518337895,\"y\":9.92},{\"x\":1685518637932,\"y\":9.92},{\"x\":1685518937904,\"y\":9.96},{\"x\":1685519238002,\"y\":10.1},{\"x\":1685519537959,\"y\":10.1},{\"x\":1685519837988,\"y\":10.1},{\"x\":1685520137912,\"y\":10.1},{\"x\":1685520437906,\"y\":10.37},{\"x\":1685520737913,\"y\":10.33},{\"x\":1685521038006,\"y\":10.33},{\"x\":1685521337908,\"y\":10.33},{\"x\":1685521637915,\"y\":10.33},{\"x\":1685521937963,\"y\":10.25},{\"x\":1685522238080,\"y\":10.54},{\"x\":1685522537924,\"y\":10.54},{\"x\":1685522837919,\"y\":10.54},{\"x\":1685523137944,\"y\":10.5},{\"x\":1685523438045,\"y\":10.6},{\"x\":1685523737930,\"y\":10.58},{\"x\":1685524037929,\"y\":10.52},{\"x\":1685524337974,\"y\":10.82},{\"x\":1685524638007,\"y\":10.82},{\"x\":1685524937934,\"y\":10.82},{\"x\":1685525237935,\"y\":10.95},{\"x\":1685525537943,\"y\":10.99},{\"x\":1685525838078,\"y\":11.08},{\"x\":1685526137951,\"y\":11.08},{\"x\":1685526437950,\"y\":10.99},{\"x\":1685526737944,\"y\":11.07},{\"x\":1685527038721,\"y\":11.07},{\"x\":1685527338012,\"y\":11.11},{\"x\":1685527637961,\"y\":11.11},{\"x\":1685527937952,\"y\":11.07},{\"x\":1685528238080,\"y\":11.16},{\"x\":1685528537978,\"y\":11.03},{\"x\":1685528837960,\"y\":11.12},{\"x\":1685529137967,\"y\":11.08},{\"x\":1685529438131,\"y\":11.61},{\"x\":1685529738016,\"y\":11.61},{\"x\":1685530037967,\"y\":11.61},{\"x\":1685530337963,\"y\":11.61},{\"x\":1685530638067,\"y\":11.61},{\"x\":1685530937995,\"y\":11.61},{\"x\":1685531237967,\"y\":11.61},{\"x\":1685531537979,\"y\":12.07},{\"x\":1685531838029,\"y\":11.73},{\"x\":1685532137972,\"y\":11.72},{\"x\":1685532437974,\"y\":11.73},{\"x\":1685532738070,\"y\":11.43},{\"x\":1685533038022,\"y\":11.92},{\"x\":1685533338038,\"y\":16.07},{\"x\":1685533637982,\"y\":16.07},{\"x\":1685533938045,\"y\":16.07},{\"x\":1685534238057,\"y\":16.07},{\"x\":1685534537980,\"y\":16.07},{\"x\":1685534838036,\"y\":12.17},{\"x\":1685535137993,\"y\":12.17},{\"x\":1685535438136,\"y\":12.17},{\"x\":1685535737984,\"y\":12.17},{\"x\":1685536037986,\"y\":12.17},{\"x\":1685536337985,\"y\":12.17},{\"x\":1685536638024,\"y\":11.9},{\"x\":1685536938025,\"y\":15.91},{\"x\":1685537237999,\"y\":15.91},{\"x\":1685537538002,\"y\":15.91},{\"x\":1685537838106,\"y\":15.91},{\"x\":1685538138007,\"y\":15.82},{\"x\":1685538438058,\"y\":13.28},{\"x\":1685538738048,\"y\":13.28},{\"x\":1685539038104,\"y\":13.28},{\"x\":1685539338007,\"y\":13.2},{\"x\":1685539638019,\"y\":13.2},{\"x\":1685539938003,\"y\":13.33},{\"x\":1685540238052,\"y\":13.2},{\"x\":1685540538039,\"y\":16.75},{\"x\":1685540838017,\"y\":16.67},{\"x\":1685541138064,\"y\":16.75},{\"x\":1685541438054,\"y\":16.67},{\"x\":1685541738229,\"y\":17.3},{\"x\":1685542038012,\"y\":17.22},{\"x\":1685542338042,\"y\":17.3},{\"x\":1685542638126,\"y\":18.38},{\"x\":1685542938012,\"y\":18.38},{\"x\":1685543238056,\"y\":18.97},{\"x\":1685543538110,\"y\":17.86},{\"x\":1685543838052,\"y\":17.86},{\"x\":1685544138125,\"y\":17.78},{\"x\":1685544438027,\"y\":17.78},{\"x\":1685544738110,\"y\":14.96},{\"x\":1685545038075,\"y\":14.94},{\"x\":1685545338027,\"y\":14.94},{\"x\":1685545638075,\"y\":15.63},{\"x\":1685545938022,\"y\":15.63},{\"x\":1685546238174,\"y\":16},{\"x\":1685546538079,\"y\":15.83},{\"x\":1685546838020,\"y\":15.81},{\"x\":1685547138129,\"y\":14.9},{\"x\":1685547438095,\"y\":14.83},{\"x\":1685547738125,\"y\":14.9},{\"x\":1685548038046,\"y\":14.83},{\"x\":1685548338056,\"y\":14.9},{\"x\":1685548638087,\"y\":14.85},{\"x\":1685548938038,\"y\":14.85},{\"x\":1685549238040,\"y\":14.85},{\"x\":1685549538033,\"y\":14.97},{\"x\":1685549838168,\"y\":14.97},{\"x\":1685550138087,\"y\":15.03},{\"x\":1685550438030,\"y\":14.97},{\"x\":1685550738120,\"y\":14.3},{\"x\":1685551038139,\"y\":14.3},{\"x\":1685551338037,\"y\":13.6},{\"x\":1685551638033,\"y\":13.49},{\"x\":1685551938041,\"y\":13.47},{\"x\":1685552238174,\"y\":13.61},{\"x\":1685552538043,\"y\":13.61},{\"x\":1685552838043,\"y\":13.52},{\"x\":1685553138067,\"y\":13.52},{\"x\":1685553438546,\"y\":13.6},{\"x\":1685553738055,\"y\":13.52},{\"x\":1685554038140,\"y\":13.59},{\"x\":1685554338045,\"y\":13.51},{\"x\":1685554638134,\"y\":13.16},{\"x\":1685554938070,\"y\":13.16},{\"x\":1685555238057,\"y\":13.18},{\"x\":1685555538064,\"y\":13.07},{\"x\":1685555838093,\"y\":13.07},{\"x\":1685556138085,\"y\":13.14},{\"x\":1685556438188,\"y\":13.11},{\"x\":1685556738092,\"y\":13.12},{\"x\":1685557038192,\"y\":13.01},{\"x\":1685557338095,\"y\":13.01},{\"x\":1685557638182,\"y\":12.89},{\"x\":1685557938150,\"y\":12.8},{\"x\":1685558238172,\"y\":12.61},{\"x\":1685558538110,\"y\":12.8},{\"x\":1685558838201,\"y\":12.58},{\"x\":1685559138123,\"y\":12.58},{\"x\":1685559438206,\"y\":12.59},{\"x\":1685559738189,\"y\":12.57},{\"x\":1685560038129,\"y\":12.57},{\"x\":1685560338155,\"y\":12.57},{\"x\":1685560638404,\"y\":12.29},{\"x\":1685560938173,\"y\":12.29},{\"x\":1685561238169,\"y\":12.29},{\"x\":1685561538183,\"y\":12.17},{\"x\":1685561838237,\"y\":12.17},{\"x\":1685562138233,\"y\":12.21},{\"x\":1685562438249,\"y\":12.18},{\"x\":1685562738211,\"y\":12.18},{\"x\":1685563038228,\"y\":12.09},{\"x\":1685563338214,\"y\":12.07},{\"x\":1685563638217,\"y\":12.07},{\"x\":1685563938231,\"y\":11.8},{\"x\":1685564238362,\"y\":11.86},{\"x\":1685564538381,\"y\":11.83},{\"x\":1685564838277,\"y\":11.83},{\"x\":1685565138242,\"y\":11.79},{\"x\":1685565438280,\"y\":11.7},{\"x\":1685565738251,\"y\":11.53},{\"x\":1685566038259,\"y\":11.53},{\"x\":1685566338265,\"y\":11.53},{\"x\":1685566638303,\"y\":11.43},{\"x\":1685566938268,\"y\":11.43},{\"x\":1685567238323,\"y\":11.33},{\"x\":1685567538343,\"y\":11.39},{\"x\":1685567838304,\"y\":11.31},{\"x\":1685568138281,\"y\":11.39},{\"x\":1685568438336,\"y\":11.31},{\"x\":1685568738284,\"y\":11.31},{\"x\":1685569038329,\"y\":11.31},{\"x\":1685569338310,\"y\":11.25},{\"x\":1685569638302,\"y\":11.25},{\"x\":1685569938300,\"y\":11.25},{\"x\":1685570238298,\"y\":10.97},{\"x\":1685570538297,\"y\":10.97},{\"x\":1685570838294,\"y\":10.97},{\"x\":1685571138323,\"y\":10.78},{\"x\":1685571438384,\"y\":10.78},{\"x\":1685571738313,\"y\":10.78},{\"x\":1685572038419,\"y\":10.8},{\"x\":1685572338315,\"y\":10.8},{\"x\":1685572638324,\"y\":10.8},{\"x\":1685572938327,\"y\":10.44},{\"x\":1685573238329,\"y\":10.44},{\"x\":1685573538333,\"y\":10.44},{\"x\":1685573838369,\"y\":10.44},{\"x\":1685574138332,\"y\":10.44},{\"x\":1685574438328,\"y\":10.43},{\"x\":1685574738335,\"y\":10.43},{\"x\":1685575038372,\"y\":10.42},{\"x\":1685575338334,\"y\":10.43},{\"x\":1685575638376,\"y\":10.44},{\"x\":1685575938389,\"y\":10.48},{\"x\":1685576238419,\"y\":10.39},{\"x\":1685576538344,\"y\":10.11},{\"x\":1685576838359,\"y\":10.2},{\"x\":1685577138380,\"y\":10.29},{\"x\":1685577438375,\"y\":10.29},{\"x\":1685577738413,\"y\":10.3},{\"x\":1685578038361,\"y\":10.29},{\"x\":1685578338371,\"y\":10.3},{\"x\":1685578638503,\"y\":10.18},{\"x\":1685578938376,\"y\":10.18},{\"x\":1685579238383,\"y\":10.09},{\"x\":1685579538380,\"y\":10.17},{\"x\":1685579838438,\"y\":10.13},{\"x\":1685580138376,\"y\":9.88},{\"x\":1685580438398,\"y\":9.88},{\"x\":1685580738405,\"y\":9.94},{\"x\":1685581038616,\"y\":9.94},{\"x\":1685581338395,\"y\":9.94},{\"x\":1685581638435,\"y\":9.94},{\"x\":1685581938409,\"y\":9.88},{\"x\":1685582238480,\"y\":9.86},{\"x\":1685582538402,\"y\":9.86},{\"x\":1685582838405,\"y\":9.86},{\"x\":1685583138415,\"y\":9.86},{\"x\":1685583438613,\"y\":9.86},{\"x\":1685583738415,\"y\":9.88},{\"x\":1685584038410,\"y\":9.88},{\"x\":1685584338448,\"y\":9.79},{\"x\":1685584638454,\"y\":9.88},{\"x\":1685584938414,\"y\":9.88},{\"x\":1685585238420,\"y\":9.98},{\"x\":1685585538423,\"y\":9.89},{\"x\":1685585838440,\"y\":9.89},{\"x\":1685586138428,\"y\":9.84},{\"x\":1685586438423,\"y\":9.84},{\"x\":1685586738424,\"y\":9.79},{\"x\":1685587038648,\"y\":9.93},{\"x\":1685587338431,\"y\":9.79},{\"x\":1685587638450,\"y\":9.79},{\"x\":1685587938475,\"y\":9.88},{\"x\":1685588238559,\"y\":9.88},{\"x\":1685588538441,\"y\":9.88},{\"x\":1685588838584,\"y\":9.67},{\"x\":1685589138428,\"y\":9.58},{\"x\":1685589438536,\"y\":9.67},{\"x\":1685589738473,\"y\":9.67},{\"x\":1685590038433,\"y\":9.67},{\"x\":1685590338478,\"y\":9.67},{\"x\":1685590638761,\"y\":9.42},{\"x\":1685590938425,\"y\":9.42},{\"x\":1685591238442,\"y\":9.42},{\"x\":1685591538439,\"y\":9.31},{\"x\":1685591838504,\"y\":9.31},{\"x\":1685592138436,\"y\":9.34},{\"x\":1685592438435,\"y\":9.34},{\"x\":1685592738487,\"y\":9.38},{\"x\":1685593038723,\"y\":9.38},{\"x\":1685593338444,\"y\":9.38},{\"x\":1685593638424,\"y\":9.34},{\"x\":1685593938457,\"y\":9.34},{\"x\":1685594238655,\"y\":9.86},{\"x\":1685594538452,\"y\":9.86},{\"x\":1685594838449,\"y\":9.86},{\"x\":1685595138489,\"y\":9.84},{\"x\":1685595438547,\"y\":9.84},{\"x\":1685595738460,\"y\":9.78},{\"x\":1685596038492,\"y\":9.85},{\"x\":1685596338571,\"y\":9.85},{\"x\":1685596638545,\"y\":9.85},{\"x\":1685596938457,\"y\":9.76},{\"x\":1685597238477,\"y\":9.85},{\"x\":1685597538472,\"y\":9.8},{\"x\":1685597838494,\"y\":9.83},{\"x\":1685598138501,\"y\":9.86},{\"x\":1685598438509,\"y\":10.14},{\"x\":1685598738535,\"y\":10.14},{\"x\":1685599038819,\"y\":10.14},{\"x\":1685599338484,\"y\":10.07},{\"x\":1685599638529,\"y\":10.07},{\"x\":1685599938480,\"y\":10.14},{\"x\":1685600238698,\"y\":10.23},{\"x\":1685600538482,\"y\":10.1},{\"x\":1685600838527,\"y\":10.43},{\"x\":1685601138487,\"y\":10.43},{\"x\":1685601438740,\"y\":10.43},{\"x\":1685601738547,\"y\":10.45},{\"x\":1685602038498,\"y\":10.36},{\"x\":1685602338488,\"y\":10.43},{\"x\":1685602638682,\"y\":10.46},{\"x\":1685602938581,\"y\":10.46},{\"x\":1685603238508,\"y\":10.47},{\"x\":1685603538503,\"y\":10.47},{\"x\":1685603838572,\"y\":10.47},{\"x\":1685604138511,\"y\":10.47},{\"x\":1685604438579,\"y\":10.6},{\"x\":1685604738515,\"y\":10.51},{\"x\":1685605038560,\"y\":10.55},{\"x\":1685605338556,\"y\":11.07},{\"x\":1685605638563,\"y\":11.07},{\"x\":1685605938519,\"y\":11.07},{\"x\":1685606238594,\"y\":11.05},{\"x\":1685606538513,\"y\":11.12},{\"x\":1685606838518,\"y\":11.15},{\"x\":1685607138518,\"y\":11.15},{\"x\":1685607438879,\"y\":11.19},{\"x\":1685607738543,\"y\":11.19},{\"x\":1685608038530,\"y\":11.42},{\"x\":1685608338527,\"y\":11.33},{\"x\":1685608638628,\"y\":11.33},{\"x\":1685608938572,\"y\":11.54},{\"x\":1685609238526,\"y\":11.54},{\"x\":1685609538568,\"y\":11.54},{\"x\":1685609838674,\"y\":11.73},{\"x\":1685610138530,\"y\":11.54},{\"x\":1685610438525,\"y\":11.73},{\"x\":1685610738604,\"y\":11.81},{\"x\":1685611038666,\"y\":11.81},{\"x\":1685611338564,\"y\":11.72},{\"x\":1685611638584,\"y\":12.09},{\"x\":1685611938537,\"y\":12.09},{\"x\":1685612238596,\"y\":12.09},{\"x\":1685612538547,\"y\":12.11},{\"x\":1685612838540,\"y\":12.11},{\"x\":1685613138539,\"y\":12.07},{\"x\":1685613438767,\"y\":12.53},{\"x\":1685613738611,\"y\":12.64},{\"x\":1685614038551,\"y\":12.51},{\"x\":1685614338551,\"y\":12.64},{\"x\":1685614638741,\"y\":12.64},{\"x\":1685614938559,\"y\":12.64},{\"x\":1685615238587,\"y\":13.05},{\"x\":1685615538593,\"y\":13.15},{\"x\":1685615838836,\"y\":13.07},{\"x\":1685616138551,\"y\":13.07},{\"x\":1685616438549,\"y\":13.17},{\"x\":1685616738558,\"y\":13.26},{\"x\":1685617038760,\"y\":13.26},{\"x\":1685617338558,\"y\":13.36},{\"x\":1685617638534,\"y\":13.36},{\"x\":1685617938635,\"y\":13.73},{\"x\":1685618238566,\"y\":13.71},{\"x\":1685618538558,\"y\":13.71},{\"x\":1685618838593,\"y\":13.75},{\"x\":1685619138565,\"y\":13.75},{\"x\":1685619438673,\"y\":13.93},{\"x\":1685619738585,\"y\":13.93}]],\"labels\":[\"\"]}]"</span><span class="token punctuation">,</span><span class="token property">"payloadType"</span><span class="token operator">:</span><span class="token string">"json"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">150</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">180</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"3eb08d4843164efc"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"41e847ff22249c0e"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_group"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Temperature"</span><span class="token punctuation">,</span><span class="token property">"tab"</span><span class="token operator">:</span><span class="token string">"1d985094b1a81b0c"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token number">5</span><span class="token punctuation">,</span><span class="token property">"disp"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token string">"24"</span><span class="token punctuation">,</span><span class="token property">"collapse"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"1d985094b1a81b0c"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_tab"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Wide View"</span><span class="token punctuation">,</span><span class="token property">"icon"</span><span class="token operator">:</span><span class="token string">"dashboard"</span><span class="token punctuation">,</span><span class="token property">"disabled"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"hidden"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">}</span><span class="token punctuation">]</span><br /></code></pre>
<button class="code-copy " data-clipboard-target="#code-50" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<h3 id="3.-using-sliders-and-persisting-the-current-value" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/06/3-quick-node-red-tips-7/#3.-using-sliders-and-persisting-the-current-value"># </a> 3. Using sliders and persisting the current value</h3>
<p>Sliders are a really useful user-interface element. Where you need to control the speed of a piece of machinery, having the ability to use a slider rather than manually typing in a value is a much better fit for shop-floor HMIs.</p>
<p>When using sliders in your dashboards, it's important to consider how you will persist the state of the slider. If you don't persist the state, you will find that a redeploy of your dashboard will set the slider back to the default value. That would also change the speed of your machine.</p>
<p><picture><source type="image/gif" srcset="https://flowfuse.com/img/slider-ui-g-ru3pSeKO-540.gif 540w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="An example of a slider in a HMI" alt="An example of a slider in a HMI" loading="lazy" decoding="async" src="https://flowfuse.com/img/slider-ui-g-ru3pSeKO-540.webp" width="540" height="164" /></picture></p>
<p>To retain the current value of the slider we can use Node-RED's context. Each time the slider value is updated, we store the value in context. Each time we deploy the flow, we can now load the value back from context.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/slider-flow-O7FNKYG1-X-565.avif 565w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/slider-flow-O7FNKYG1-X-565.webp 565w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Flow to retain the slider value after a deploy" alt="Flow to retain the slider value after a deploy" loading="lazy" decoding="async" src="https://flowfuse.com/img/slider-flow-O7FNKYG1-X-565.jpeg" width="565" height="164" /></picture></p>
<p>If you'd like to view this slider and the flow which makes it work on your own Node-RED, you can import the flow below.</p>
<div style="position: relative">
<pre class="language-json"><code id="code-72" class="language-json"><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"05340e7a133098a6"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_slider"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"0e6be5088cecccc1"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"label"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"tooltip"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"group"</span><span class="token operator">:</span><span class="token string">"41e847ff22249c0e"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"passthru"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"outs"</span><span class="token operator">:</span><span class="token string">"all"</span><span class="token punctuation">,</span><span class="token property">"topic"</span><span class="token operator">:</span><span class="token string">"topic"</span><span class="token punctuation">,</span><span class="token property">"topicType"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"min"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"max"</span><span class="token operator">:</span><span class="token string">"20"</span><span class="token punctuation">,</span><span class="token property">"step"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">230</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">300</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"945db61c94fc0704"</span><span class="token punctuation">,</span><span class="token string">"ad7819da2cfbcd4e"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"849d76d146ff8c12"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"0e6be5088cecccc1"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Inject on deploy"</span><span class="token punctuation">,</span><span class="token property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"repeat"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"once"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"onceDelay"</span><span class="token operator">:</span><span class="token number">0.1</span><span class="token punctuation">,</span><span class="token property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">160</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">240</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"aeedb3c60965c1af"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"945db61c94fc0704"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"0e6be5088cecccc1"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Set global-slider-value = msg.payload"</span><span class="token punctuation">,</span><span class="token property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"slider-value"</span><span class="token punctuation">,</span><span class="token property">"pt"</span><span class="token operator">:</span><span class="token string">"global"</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">450</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">300</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"aeedb3c60965c1af"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"0e6be5088cecccc1"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Set msg.payload = global.slider-value"</span><span class="token punctuation">,</span><span class="token property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">"slider-value"</span><span class="token punctuation">,</span><span class="token property">"tot"</span><span class="token operator">:</span><span class="token string">"global"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">410</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">240</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"05340e7a133098a6"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"ad7819da2cfbcd4e"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_text"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"0e6be5088cecccc1"</span><span class="token punctuation">,</span><span class="token property">"group"</span><span class="token operator">:</span><span class="token string">"41e847ff22249c0e"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"label"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"format"</span><span class="token operator">:</span><span class="token string">"The current value is meters per minute"</span><span class="token punctuation">,</span><span class="token property">"layout"</span><span class="token operator">:</span><span class="token string">"row-spread"</span><span class="token punctuation">,</span><span class="token property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"style"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"font"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"fontSize"</span><span class="token operator">:</span><span class="token number">16</span><span class="token punctuation">,</span><span class="token property">"color"</span><span class="token operator">:</span><span class="token string">"#000000"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">350</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">340</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"41e847ff22249c0e"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_group"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Meters per Minute"</span><span class="token punctuation">,</span><span class="token property">"tab"</span><span class="token operator">:</span><span class="token string">"466e33abb95e4dd4"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token number">5</span><span class="token punctuation">,</span><span class="token property">"disp"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token string">"10"</span><span class="token punctuation">,</span><span class="token property">"collapse"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"466e33abb95e4dd4"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_tab"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Sliders"</span><span class="token punctuation">,</span><span class="token property">"icon"</span><span class="token operator">:</span><span class="token string">"dashboard"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token property">"disabled"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"hidden"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">}</span><span class="token punctuation">]</span><br /></code></pre>
<button class="code-copy " data-clipboard-target="#code-72" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>We hope you found these tips useful, if you'd like to suggest some of your own tips which you think we should share in our future blog posts please <a href="mailto:contact@flowfuse.com">get in touch</a>. You can also read some of our previous Node-RED tips using the links below.</p>
<p><a href="https://flowfuse.com/blog/2023/04/3-quick-node-red-tips-6/">Node-RED Tips - Subflows, Link Nodes, and the Range Node</a><br />
<a href="https://flowfuse.com/blog/2023/03/3-quick-node-red-tips-5/">Node-RED Tips - Importing, Exporting, and Grouping Flows</a><br />
<a href="https://flowfuse.com/blog/2023/03/3-quick-node-red-tips-4/">Node-RED Tips - Smooth, Catch, and Maths</a><br />
<a href="https://flowfuse.com/blog/2023/03/3-quick-node-red-tips-3/">Node-RED Tips - Exec, Filter, and Debug</a><br />
<a href="https://flowfuse.com/blog/2023/02/3-quick-node-red-tips-2/">Node-RED Tips - Deploying, Debugging, and Delaying</a><br />
<a href="https://flowfuse.com/blog/2023/02/3-quick-node-red-tips-1/">Node-RED Tips - Wiring Shortcuts</a></p>
https://flowfuse.com/blog/2023/05/node-red-community-survey-results/Node-RED Community Survey ResultsDiscover the trends and insights into the Node-RED community2023-05-31T00:00:00Z<p>The Node-RED community recently published the results of their <a href="https://nodered.org/about/community/survey/2023/">2023 Community Survey</a>, building upon their <a href="https://nodered.org/about/community/survey/2019/">2019 survey</a>. The findings reveal some interesting trends within the Node-RED community that are worth highlighting.</p>
<!--more-->
<ol>
<li>
<p><strong>Passionate and Experienced Community</strong>. The Node-RED community has shown a remarkable increase in experience. In 2019, only 28.3% of users had been utilizing Node-RED for over two years. However, in 2023, this number has grown to an impressive 65.2%. This indicates that Node-RED has become a go-to tool for many individuals, demonstrating their continued loyalty to the platform. Moreover, the community highly regards Node-RED, with 94% of respondents rating it as a 4 or 5 on a scale of 1 to 5.</p>
<p>Developer tools can fall out of fashion but it is clear Node-RED is providing value and is being used by developers.</p>
</li>
<li>
<p><strong>Increasing Adoption in Industrial and Manufacturing Automation</strong>. The survey also revealed a significant increase in Node-RED usage within the manufacturing and industrial automation industries. Several data points support this finding, including a rise from 31.5% to 40.3% in respondents identifying themselves as working in the manufacturing industry. Additionally, there has been an increase in the use of Node-RED applications for Industrial IoT/PLC devices, which grew from 24% to 35.8% in 2023. Furthermore, the adoption of popular manufacturing industry protocols like <a href="https://opcfoundation.org/">OPC-UA</a> and <a href="https://modbus.org/">Modbus</a> has also increased, with OPC-UA usage rising from 9.3% to 16.7% and Modbus usage increasing from 15.8% to 27.6%.</p>
</li>
<li>
<p><strong>InfluxDB dominance in the Node-RED community</strong>.<a href="https://www.influxdata.com/"> InfluxDB</a> has emerged as the leading database within the Node-RED community. Its usage has grown significantly, from 24.2% in 2019 to 43.9% in 2023. On the other hand, MySQL, the next most popular database, experienced a slight decrease in usage, dropping from 32.4% to 31.4%.</p>
<p>It is evident that the MING stack (MQTT/Mosquitto, InfluxDB, Node-RED, and Grafana) is gaining momentum and becoming a preferred choice for developers.</p>
</li>
<li>
<p><strong>Limitations to Node-RED Adoption</strong>. This year's survey also explored factors that might limit the adoption of Node-RED. Approximately 27.9% of respondents stated that they perceived no additional need for Node-RED. However, the next most common responses were related to the perception that Node-RED is only suitable for proof-of-concept (POC) projects (19.9%), the lack of specific Node-RED features (13.3%), and the absence of professional support (10.1%).</p>
<p>It is important for the Node-RED community to demonstrate the platform's usage in production environments. Although changing the perception of Node-RED as solely a POC tool may take time, FlowFuse is committed to helping shift this perspective. Moreover, FlowFuse aims to address other identified issues by developing the FlowFuse platform, which will provide the necessary features to create reliable, secure, and dependable Node-RED applications. FlowFuse will also offer professional support to all its customers, ensuring that users have the assistance they need.</p>
</li>
</ol>
<p>Thank you to everyone that completed the Node-RED Survey. The insights from the survey will help the community to build a better Node-RED. Check out the detailed results on the <a href="https://nodered.org/about/community/survey/2023/">nodered.org website</a>.</p>
https://flowfuse.com/blog/2023/05/persisting-chart-data-in-node-red/Persisting chart data in Node-RED DashboardsKeep your historic chart data safe and available2023-05-25T00:00:00ZRob Marcer<p>Node-RED makes it easy to create HMI (Human Machine Interfaces) using the <a href="https://flows.nodered.org/node/node-red-dashboard">Dashboard set of custom nodes</a>.</p>
<!--more-->
<p>One of the most useful features of Dashboard is the ability to store historic data passed to a chart within the chart node itself. This makes your flows far simpler than would be the case if you needed to send the entire data set to the chart for each update.</p>
<h3 id="the-importance-of-persisting-chart-data" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/persisting-chart-data-in-node-red/#the-importance-of-persisting-chart-data"># </a> The Importance of Persisting Chart Data</h3>
<p>Storing the data in the chart node is fine to show prototypes of HMIs, but where it's vital the correct data is always shown we are going to need a backup. Data can easily be lost when you move your flow to a new device, restart your instance, or simply when upgrading Node-RED.</p>
<p>How can we store our chart data so we can be confident it will be there each time a user views your HMI?</p>
<h3 id="example-dashboard" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/persisting-chart-data-in-node-red/#example-dashboard"># </a> Example Dashboard</h3>
<p>In this example, we are passing in a random number between one and 10 each second. With each new value received the chart updates and as mentioned about, the values are also stored in the chart node.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/chart-8saZ4hVldf-605.avif 605w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/chart-8saZ4hVldf-605.webp 605w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Charting the random numbers" alt="Charting the random numbers" loading="lazy" decoding="async" src="https://flowfuse.com/img/chart-8saZ4hVldf-605.jpeg" width="605" height="107" /></picture></p>
<p>If you'd like to see and edit the flows I've created, you can copy and paste the JSON below into your Node-RED import feature.</p>
<div style="position: relative">
<pre class="language-json"><code id="code-28" class="language-json"><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"c6825b1001216b89"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"668c56888fd0f960"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"repeat"</span><span class="token operator">:</span><span class="token string">"1"</span><span class="token punctuation">,</span><span class="token property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"once"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"onceDelay"</span><span class="token operator">:</span><span class="token number">0.1</span><span class="token punctuation">,</span><span class="token property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">110</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">220</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"6b609d978540fb2a"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"6b609d978540fb2a"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"Number"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"668c56888fd0f960"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Random Number"</span><span class="token punctuation">,</span><span class="token property">"minimum"</span><span class="token operator">:</span><span class="token string">"1"</span><span class="token punctuation">,</span><span class="token property">"maximum"</span><span class="token operator">:</span><span class="token string">"10"</span><span class="token punctuation">,</span><span class="token property">"roundTo"</span><span class="token operator">:</span><span class="token string">"0"</span><span class="token punctuation">,</span><span class="token property">"Floor"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">270</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">220</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"794846db6dc8cef8"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"794846db6dc8cef8"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_chart"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"668c56888fd0f960"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"group"</span><span class="token operator">:</span><span class="token string">"af1535b39b74f94a"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"label"</span><span class="token operator">:</span><span class="token string">"chart"</span><span class="token punctuation">,</span><span class="token property">"chartType"</span><span class="token operator">:</span><span class="token string">"line"</span><span class="token punctuation">,</span><span class="token property">"legend"</span><span class="token operator">:</span><span class="token string">"false"</span><span class="token punctuation">,</span><span class="token property">"xformat"</span><span class="token operator">:</span><span class="token string">"HH:mm:ss"</span><span class="token punctuation">,</span><span class="token property">"interpolate"</span><span class="token operator">:</span><span class="token string">"linear"</span><span class="token punctuation">,</span><span class="token property">"nodata"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"dot"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"ymin"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"ymax"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"removeOlder"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"removeOlderPoints"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"removeOlderUnit"</span><span class="token operator">:</span><span class="token string">"3600"</span><span class="token punctuation">,</span><span class="token property">"cutout"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"useOneColor"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"useUTC"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"colors"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"#1f77b4"</span><span class="token punctuation">,</span><span class="token string">"#aec7e8"</span><span class="token punctuation">,</span><span class="token string">"#ff7f0e"</span><span class="token punctuation">,</span><span class="token string">"#2ca02c"</span><span class="token punctuation">,</span><span class="token string">"#98df8a"</span><span class="token punctuation">,</span><span class="token string">"#d62728"</span><span class="token punctuation">,</span><span class="token string">"#ff9896"</span><span class="token punctuation">,</span><span class="token string">"#9467bd"</span><span class="token punctuation">,</span><span class="token string">"#c5b0d5"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"outputs"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"useDifferentColor"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">430</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">220</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"ad53848ee4b0d91e"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"ad53848ee4b0d91e"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"debug"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"668c56888fd0f960"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"debug"</span><span class="token punctuation">,</span><span class="token property">"active"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"tosidebar"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"console"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"tostatus"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"complete"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"targetType"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"statusVal"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"statusType"</span><span class="token operator">:</span><span class="token string">"auto"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">550</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">220</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"af1535b39b74f94a"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_group"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Example"</span><span class="token punctuation">,</span><span class="token property">"tab"</span><span class="token operator">:</span><span class="token string">"14f1442eb7525190"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"disp"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token string">"6"</span><span class="token punctuation">,</span><span class="token property">"collapse"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"14f1442eb7525190"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_tab"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Home"</span><span class="token punctuation">,</span><span class="token property">"icon"</span><span class="token operator">:</span><span class="token string">"dashboard"</span><span class="token punctuation">,</span><span class="token property">"disabled"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"hidden"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">}</span><span class="token punctuation">]</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-28" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<h3 id="how-can-we-store-and-recall-the-chart-data%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/persisting-chart-data-in-node-red/#how-can-we-store-and-recall-the-chart-data%3F"># </a> How can we store and recall the chart data?</h3>
<p>The chart node has a really useful feature which allows us to access all the data currently shown in the chart. Each time the chart receives new data, it's added to the existing values then the whole data set is sent out the outbound port of the chart node.</p>
<p>Now that we have a way to easily access the chart data in a single payload, we next need to store that data somewhere safer. I'm going to explain 3 potential solutions, which I use on a regular basis.</p>
<h4 id="1.-node-red-file-out-and-file-in-nodes" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/persisting-chart-data-in-node-red/#1.-node-red-file-out-and-file-in-nodes"># </a> 1. Node-RED file-out and file-in nodes</h4>
<p>Node-RED can read and write data to a local filesystem. Being that we already have the chart data in a single payload, we just need to write that payload to a file for later use, which we can do using the file-out node.</p>
<p>This example flow shows how to use the file-out node to write the chart data to your local filesystem.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/send-data-to-file-eMfpaNe38K-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/send-data-to-file-eMfpaNe38K-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Sending the chart data to a file" alt="Sending the chart data to a file" loading="lazy" decoding="async" src="https://flowfuse.com/img/send-data-to-file-eMfpaNe38K-650.jpeg" width="650" height="75" /></picture></p>
<div style="position: relative">
<pre class="language-json"><code id="code-50" class="language-json"><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"ead9df683d29fb8a"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"668c56888fd0f960"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"repeat"</span><span class="token operator">:</span><span class="token string">"1"</span><span class="token punctuation">,</span><span class="token property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"once"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"onceDelay"</span><span class="token operator">:</span><span class="token number">0.1</span><span class="token punctuation">,</span><span class="token property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">110</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">560</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"ef5359b8bd3f78b3"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"ef5359b8bd3f78b3"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"Number"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"668c56888fd0f960"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Random Number"</span><span class="token punctuation">,</span><span class="token property">"minimum"</span><span class="token operator">:</span><span class="token string">"1"</span><span class="token punctuation">,</span><span class="token property">"maximum"</span><span class="token operator">:</span><span class="token string">"10"</span><span class="token punctuation">,</span><span class="token property">"roundTo"</span><span class="token operator">:</span><span class="token string">"0"</span><span class="token punctuation">,</span><span class="token property">"Floor"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">270</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">560</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"69ad440cd8d1ce30"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"69ad440cd8d1ce30"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_chart"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"668c56888fd0f960"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"group"</span><span class="token operator">:</span><span class="token string">"af1535b39b74f94a"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"label"</span><span class="token operator">:</span><span class="token string">"chart"</span><span class="token punctuation">,</span><span class="token property">"chartType"</span><span class="token operator">:</span><span class="token string">"line"</span><span class="token punctuation">,</span><span class="token property">"legend"</span><span class="token operator">:</span><span class="token string">"false"</span><span class="token punctuation">,</span><span class="token property">"xformat"</span><span class="token operator">:</span><span class="token string">"HH:mm:ss"</span><span class="token punctuation">,</span><span class="token property">"interpolate"</span><span class="token operator">:</span><span class="token string">"linear"</span><span class="token punctuation">,</span><span class="token property">"nodata"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"dot"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"ymin"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"ymax"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"removeOlder"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"removeOlderPoints"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"removeOlderUnit"</span><span class="token operator">:</span><span class="token string">"3600"</span><span class="token punctuation">,</span><span class="token property">"cutout"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"useOneColor"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"useUTC"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"colors"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"#1f77b4"</span><span class="token punctuation">,</span><span class="token string">"#aec7e8"</span><span class="token punctuation">,</span><span class="token string">"#ff7f0e"</span><span class="token punctuation">,</span><span class="token string">"#2ca02c"</span><span class="token punctuation">,</span><span class="token string">"#98df8a"</span><span class="token punctuation">,</span><span class="token string">"#d62728"</span><span class="token punctuation">,</span><span class="token string">"#ff9896"</span><span class="token punctuation">,</span><span class="token string">"#9467bd"</span><span class="token punctuation">,</span><span class="token string">"#c5b0d5"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"outputs"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"useDifferentColor"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">430</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">560</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"e4e7758028477505"</span><span class="token punctuation">,</span><span class="token string">"d9d6a2e34767f568"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"e4e7758028477505"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"debug"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"668c56888fd0f960"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"debug"</span><span class="token punctuation">,</span><span class="token property">"active"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"tosidebar"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"console"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"tostatus"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"complete"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"targetType"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"statusVal"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"statusType"</span><span class="token operator">:</span><span class="token string">"auto"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">550</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">560</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"d9d6a2e34767f568"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"json"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"668c56888fd0f960"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"property"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"pretty"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">550</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">600</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"b5b020fb17f615df"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"b5b020fb17f615df"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"file"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"668c56888fd0f960"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"filename"</span><span class="token operator">:</span><span class="token string">"example.json"</span><span class="token punctuation">,</span><span class="token property">"filenameType"</span><span class="token operator">:</span><span class="token string">"str"</span><span class="token punctuation">,</span><span class="token property">"appendNewline"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"createDir"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"overwriteFile"</span><span class="token operator">:</span><span class="token string">"true"</span><span class="token punctuation">,</span><span class="token property">"encoding"</span><span class="token operator">:</span><span class="token string">"none"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">690</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">600</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"a6d9eab41d4dcf97"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"a6d9eab41d4dcf97"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"debug"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"668c56888fd0f960"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"debug 92"</span><span class="token punctuation">,</span><span class="token property">"active"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"tosidebar"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"console"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"tostatus"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"complete"</span><span class="token operator">:</span><span class="token string">"false"</span><span class="token punctuation">,</span><span class="token property">"statusVal"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"statusType"</span><span class="token operator">:</span><span class="token string">"auto"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">840</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">600</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"af1535b39b74f94a"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_group"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Example"</span><span class="token punctuation">,</span><span class="token property">"tab"</span><span class="token operator">:</span><span class="token string">"14f1442eb7525190"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"disp"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token string">"6"</span><span class="token punctuation">,</span><span class="token property">"collapse"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"14f1442eb7525190"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_tab"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Home"</span><span class="token punctuation">,</span><span class="token property">"icon"</span><span class="token operator">:</span><span class="token string">"dashboard"</span><span class="token punctuation">,</span><span class="token property">"disabled"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"hidden"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">}</span><span class="token punctuation">]</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-50" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>As the chart node sends the full data set each time new data is added, we overwrite the content of the file rather than append the new values.</p>
<p>The next step is to pull the data back from the filesystem to your Node-RED instance. Node-RED makes this very easy using the file-in node.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/import-data-from-the-file-MOysjJds0f-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/import-data-from-the-file-MOysjJds0f-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Import the chart data from the file" alt="Import the chart data from the file" loading="lazy" decoding="async" src="https://flowfuse.com/img/import-data-from-the-file-MOysjJds0f-650.jpeg" width="650" height="102" /></picture></p>
<div style="position: relative">
<pre class="language-json"><code id="code-60" class="language-json"><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"ead9df683d29fb8a"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"668c56888fd0f960"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"repeat"</span><span class="token operator">:</span><span class="token string">"1"</span><span class="token punctuation">,</span><span class="token property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"once"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"onceDelay"</span><span class="token operator">:</span><span class="token number">0.1</span><span class="token punctuation">,</span><span class="token property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">110</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">560</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"ef5359b8bd3f78b3"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"ef5359b8bd3f78b3"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"Number"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"668c56888fd0f960"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Random Number"</span><span class="token punctuation">,</span><span class="token property">"minimum"</span><span class="token operator">:</span><span class="token string">"1"</span><span class="token punctuation">,</span><span class="token property">"maximum"</span><span class="token operator">:</span><span class="token string">"10"</span><span class="token punctuation">,</span><span class="token property">"roundTo"</span><span class="token operator">:</span><span class="token string">"0"</span><span class="token punctuation">,</span><span class="token property">"Floor"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">270</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">560</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"69ad440cd8d1ce30"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"69ad440cd8d1ce30"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_chart"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"668c56888fd0f960"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"group"</span><span class="token operator">:</span><span class="token string">"af1535b39b74f94a"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"label"</span><span class="token operator">:</span><span class="token string">"chart"</span><span class="token punctuation">,</span><span class="token property">"chartType"</span><span class="token operator">:</span><span class="token string">"line"</span><span class="token punctuation">,</span><span class="token property">"legend"</span><span class="token operator">:</span><span class="token string">"false"</span><span class="token punctuation">,</span><span class="token property">"xformat"</span><span class="token operator">:</span><span class="token string">"HH:mm:ss"</span><span class="token punctuation">,</span><span class="token property">"interpolate"</span><span class="token operator">:</span><span class="token string">"linear"</span><span class="token punctuation">,</span><span class="token property">"nodata"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"dot"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"ymin"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"ymax"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"removeOlder"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"removeOlderPoints"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"removeOlderUnit"</span><span class="token operator">:</span><span class="token string">"3600"</span><span class="token punctuation">,</span><span class="token property">"cutout"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"useOneColor"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"useUTC"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"colors"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"#1f77b4"</span><span class="token punctuation">,</span><span class="token string">"#aec7e8"</span><span class="token punctuation">,</span><span class="token string">"#ff7f0e"</span><span class="token punctuation">,</span><span class="token string">"#2ca02c"</span><span class="token punctuation">,</span><span class="token string">"#98df8a"</span><span class="token punctuation">,</span><span class="token string">"#d62728"</span><span class="token punctuation">,</span><span class="token string">"#ff9896"</span><span class="token punctuation">,</span><span class="token string">"#9467bd"</span><span class="token punctuation">,</span><span class="token string">"#c5b0d5"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"outputs"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"useDifferentColor"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">430</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">560</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"e4e7758028477505"</span><span class="token punctuation">,</span><span class="token string">"d9d6a2e34767f568"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"e4e7758028477505"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"debug"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"668c56888fd0f960"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"debug"</span><span class="token punctuation">,</span><span class="token property">"active"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"tosidebar"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"console"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"tostatus"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"complete"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"targetType"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"statusVal"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"statusType"</span><span class="token operator">:</span><span class="token string">"auto"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">550</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">560</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"d9d6a2e34767f568"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"json"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"668c56888fd0f960"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"property"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"pretty"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">550</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">600</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"b5b020fb17f615df"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"b5b020fb17f615df"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"file"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"668c56888fd0f960"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"filename"</span><span class="token operator">:</span><span class="token string">"example.json"</span><span class="token punctuation">,</span><span class="token property">"filenameType"</span><span class="token operator">:</span><span class="token string">"str"</span><span class="token punctuation">,</span><span class="token property">"appendNewline"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"createDir"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"overwriteFile"</span><span class="token operator">:</span><span class="token string">"true"</span><span class="token punctuation">,</span><span class="token property">"encoding"</span><span class="token operator">:</span><span class="token string">"none"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">690</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">600</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"a6d9eab41d4dcf97"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"a6d9eab41d4dcf97"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"debug"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"668c56888fd0f960"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"debug 92"</span><span class="token punctuation">,</span><span class="token property">"active"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"tosidebar"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"console"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"tostatus"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"complete"</span><span class="token operator">:</span><span class="token string">"false"</span><span class="token punctuation">,</span><span class="token property">"statusVal"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"statusType"</span><span class="token operator">:</span><span class="token string">"auto"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">840</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">600</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"e9cb9350f1aaeb38"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"668c56888fd0f960"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"import data"</span><span class="token punctuation">,</span><span class="token property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"repeat"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"once"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"onceDelay"</span><span class="token operator">:</span><span class="token number">0.1</span><span class="token punctuation">,</span><span class="token property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">110</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">660</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"600f014947f73d8f"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"600f014947f73d8f"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"file in"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"668c56888fd0f960"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"filename"</span><span class="token operator">:</span><span class="token string">"example.json"</span><span class="token punctuation">,</span><span class="token property">"filenameType"</span><span class="token operator">:</span><span class="token string">"str"</span><span class="token punctuation">,</span><span class="token property">"format"</span><span class="token operator">:</span><span class="token string">"utf8"</span><span class="token punctuation">,</span><span class="token property">"chunk"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"sendError"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"encoding"</span><span class="token operator">:</span><span class="token string">"none"</span><span class="token punctuation">,</span><span class="token property">"allProps"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">270</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">660</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"972118c0e114f47b"</span><span class="token punctuation">,</span><span class="token string">"69ad440cd8d1ce30"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"972118c0e114f47b"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"debug"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"668c56888fd0f960"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"debug 93"</span><span class="token punctuation">,</span><span class="token property">"active"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"tosidebar"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"console"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"tostatus"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"complete"</span><span class="token operator">:</span><span class="token string">"false"</span><span class="token punctuation">,</span><span class="token property">"statusVal"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"statusType"</span><span class="token operator">:</span><span class="token string">"auto"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">420</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">660</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"af1535b39b74f94a"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_group"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Example"</span><span class="token punctuation">,</span><span class="token property">"tab"</span><span class="token operator">:</span><span class="token string">"14f1442eb7525190"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"disp"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token string">"6"</span><span class="token punctuation">,</span><span class="token property">"collapse"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"14f1442eb7525190"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_tab"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Home"</span><span class="token punctuation">,</span><span class="token property">"icon"</span><span class="token operator">:</span><span class="token string">"dashboard"</span><span class="token punctuation">,</span><span class="token property">"disabled"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"hidden"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">}</span><span class="token punctuation">]</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-60" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>When you press the 'import data' trigger node, the data is loaded in from the filesystem and shown in the chart. You may want to automate that task to run each you deploy your Node-RED instance.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/inject-on-deploy-8POKAssRX9-510.avif 510w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/inject-on-deploy-8POKAssRX9-510.webp 510w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Import data on deploy" alt="Import data on deploy" loading="lazy" decoding="async" src="https://flowfuse.com/img/inject-on-deploy-8POKAssRX9-510.jpeg" width="510" height="518" /></picture></p>
<p>Bear in mind that your data is stored in your filesystem, if your storage drive fails you will lose your data, you might want to consider taking backups and storing elsewhere for emergencies.</p>
<h4 id="2.-flowfuse's-persistent-context" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/persisting-chart-data-in-node-red/#2.-flowfuse's-persistent-context"># </a> 2. FlowFuse's persistent context</h4>
<p>FlowFuse Cloud and premium self hosted version provides persistent context storage as part of its Node-RED instances. This allows you to create, read, update, and delete data as needed, even if you have restarted a Node-RED instance.</p>
<p>This flow shows chart data being sent to persistent context so we can access it later. The process is very similar to using the file-out and file-in nodes.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/store-in-context-qicqXo41Bu-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/store-in-context-qicqXo41Bu-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Storing the chart data in context" alt="Storing the chart data in context" loading="lazy" decoding="async" src="https://flowfuse.com/img/store-in-context-qicqXo41Bu-650.jpeg" width="650" height="80" /></picture></p>
<div style="position: relative">
<pre class="language-json"><code id="code-82" class="language-json"><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"c6825b1001216b89"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"4767c2f7095bee53"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"repeat"</span><span class="token operator">:</span><span class="token string">"1"</span><span class="token punctuation">,</span><span class="token property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"once"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"onceDelay"</span><span class="token operator">:</span><span class="token number">0.1</span><span class="token punctuation">,</span><span class="token property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">170</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">100</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"6b609d978540fb2a"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"794846db6dc8cef8"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_chart"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"4767c2f7095bee53"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"group"</span><span class="token operator">:</span><span class="token string">"af1535b39b74f94a"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"label"</span><span class="token operator">:</span><span class="token string">"chart"</span><span class="token punctuation">,</span><span class="token property">"chartType"</span><span class="token operator">:</span><span class="token string">"line"</span><span class="token punctuation">,</span><span class="token property">"legend"</span><span class="token operator">:</span><span class="token string">"false"</span><span class="token punctuation">,</span><span class="token property">"xformat"</span><span class="token operator">:</span><span class="token string">"HH:mm:ss"</span><span class="token punctuation">,</span><span class="token property">"interpolate"</span><span class="token operator">:</span><span class="token string">"linear"</span><span class="token punctuation">,</span><span class="token property">"nodata"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"dot"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"ymin"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"ymax"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"removeOlder"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"removeOlderPoints"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"removeOlderUnit"</span><span class="token operator">:</span><span class="token string">"3600"</span><span class="token punctuation">,</span><span class="token property">"cutout"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"useOneColor"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"useUTC"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"colors"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"#1f77b4"</span><span class="token punctuation">,</span><span class="token string">"#aec7e8"</span><span class="token punctuation">,</span><span class="token string">"#ff7f0e"</span><span class="token punctuation">,</span><span class="token string">"#2ca02c"</span><span class="token punctuation">,</span><span class="token string">"#98df8a"</span><span class="token punctuation">,</span><span class="token string">"#d62728"</span><span class="token punctuation">,</span><span class="token string">"#ff9896"</span><span class="token punctuation">,</span><span class="token string">"#9467bd"</span><span class="token punctuation">,</span><span class="token string">"#c5b0d5"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"outputs"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"useDifferentColor"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">490</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">100</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"ad53848ee4b0d91e"</span><span class="token punctuation">,</span><span class="token string">"938c7d878545e623"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"ad53848ee4b0d91e"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"debug"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"4767c2f7095bee53"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"debug"</span><span class="token punctuation">,</span><span class="token property">"active"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"tosidebar"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"console"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"tostatus"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"complete"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"targetType"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"statusVal"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"statusType"</span><span class="token operator">:</span><span class="token string">"auto"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">610</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">100</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"6b609d978540fb2a"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"Number"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"4767c2f7095bee53"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Random Number"</span><span class="token punctuation">,</span><span class="token property">"minimum"</span><span class="token operator">:</span><span class="token string">"1"</span><span class="token punctuation">,</span><span class="token property">"maximum"</span><span class="token operator">:</span><span class="token string">"10"</span><span class="token punctuation">,</span><span class="token property">"roundTo"</span><span class="token operator">:</span><span class="token string">"0"</span><span class="token punctuation">,</span><span class="token property">"Floor"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">330</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">100</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"794846db6dc8cef8"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"938c7d878545e623"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"4767c2f7095bee53"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"#:(persistent)::chart-data"</span><span class="token punctuation">,</span><span class="token property">"pt"</span><span class="token operator">:</span><span class="token string">"global"</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">660</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">140</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"3792cc96a748e75a"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"3792cc96a748e75a"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"debug"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"4767c2f7095bee53"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"debug 1"</span><span class="token punctuation">,</span><span class="token property">"active"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"tosidebar"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"console"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"tostatus"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"complete"</span><span class="token operator">:</span><span class="token string">"false"</span><span class="token punctuation">,</span><span class="token property">"statusVal"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"statusType"</span><span class="token operator">:</span><span class="token string">"auto"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">840</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">140</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"af1535b39b74f94a"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_group"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Example"</span><span class="token punctuation">,</span><span class="token property">"tab"</span><span class="token operator">:</span><span class="token string">"14f1442eb7525190"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"disp"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token string">"6"</span><span class="token punctuation">,</span><span class="token property">"collapse"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"14f1442eb7525190"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_tab"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Home"</span><span class="token punctuation">,</span><span class="token property">"icon"</span><span class="token operator">:</span><span class="token string">"dashboard"</span><span class="token punctuation">,</span><span class="token property">"disabled"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"hidden"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">}</span><span class="token punctuation">]</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-82" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>We now need to have a method to load the data back into our chart. We will again use a manual 'import data' trigger to load the full set of data from the persistent context, and then push it back into the chart.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/context-with-import-J5KlfFGxJL-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/context-with-import-J5KlfFGxJL-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Importing the chart data from context" alt="Importing the chart data from context" loading="lazy" decoding="async" src="https://flowfuse.com/img/context-with-import-J5KlfFGxJL-650.jpeg" width="650" height="102" /></picture></p>
<div style="position: relative">
<pre class="language-json"><code id="code-89" class="language-json"><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"c6825b1001216b89"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"4767c2f7095bee53"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"repeat"</span><span class="token operator">:</span><span class="token string">"1"</span><span class="token punctuation">,</span><span class="token property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"once"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"onceDelay"</span><span class="token operator">:</span><span class="token number">0.1</span><span class="token punctuation">,</span><span class="token property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">170</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">100</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"6b609d978540fb2a"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"794846db6dc8cef8"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_chart"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"4767c2f7095bee53"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"group"</span><span class="token operator">:</span><span class="token string">"af1535b39b74f94a"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"label"</span><span class="token operator">:</span><span class="token string">"chart"</span><span class="token punctuation">,</span><span class="token property">"chartType"</span><span class="token operator">:</span><span class="token string">"line"</span><span class="token punctuation">,</span><span class="token property">"legend"</span><span class="token operator">:</span><span class="token string">"false"</span><span class="token punctuation">,</span><span class="token property">"xformat"</span><span class="token operator">:</span><span class="token string">"HH:mm:ss"</span><span class="token punctuation">,</span><span class="token property">"interpolate"</span><span class="token operator">:</span><span class="token string">"linear"</span><span class="token punctuation">,</span><span class="token property">"nodata"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"dot"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"ymin"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"ymax"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"removeOlder"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"removeOlderPoints"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"removeOlderUnit"</span><span class="token operator">:</span><span class="token string">"3600"</span><span class="token punctuation">,</span><span class="token property">"cutout"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"useOneColor"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"useUTC"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"colors"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"#1f77b4"</span><span class="token punctuation">,</span><span class="token string">"#aec7e8"</span><span class="token punctuation">,</span><span class="token string">"#ff7f0e"</span><span class="token punctuation">,</span><span class="token string">"#2ca02c"</span><span class="token punctuation">,</span><span class="token string">"#98df8a"</span><span class="token punctuation">,</span><span class="token string">"#d62728"</span><span class="token punctuation">,</span><span class="token string">"#ff9896"</span><span class="token punctuation">,</span><span class="token string">"#9467bd"</span><span class="token punctuation">,</span><span class="token string">"#c5b0d5"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"outputs"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"useDifferentColor"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">490</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">100</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"ad53848ee4b0d91e"</span><span class="token punctuation">,</span><span class="token string">"938c7d878545e623"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"ad53848ee4b0d91e"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"debug"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"4767c2f7095bee53"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"debug"</span><span class="token punctuation">,</span><span class="token property">"active"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"tosidebar"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"console"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"tostatus"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"complete"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"targetType"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"statusVal"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"statusType"</span><span class="token operator">:</span><span class="token string">"auto"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">610</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">100</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"6b609d978540fb2a"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"Number"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"4767c2f7095bee53"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Random Number"</span><span class="token punctuation">,</span><span class="token property">"minimum"</span><span class="token operator">:</span><span class="token string">"1"</span><span class="token punctuation">,</span><span class="token property">"maximum"</span><span class="token operator">:</span><span class="token string">"10"</span><span class="token punctuation">,</span><span class="token property">"roundTo"</span><span class="token operator">:</span><span class="token string">"0"</span><span class="token punctuation">,</span><span class="token property">"Floor"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">330</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">100</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"794846db6dc8cef8"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"938c7d878545e623"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"4767c2f7095bee53"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"#:(persistent)::chart-data"</span><span class="token punctuation">,</span><span class="token property">"pt"</span><span class="token operator">:</span><span class="token string">"global"</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">660</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">140</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"3792cc96a748e75a"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"3792cc96a748e75a"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"debug"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"4767c2f7095bee53"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"debug 1"</span><span class="token punctuation">,</span><span class="token property">"active"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"tosidebar"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"console"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"tostatus"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"complete"</span><span class="token operator">:</span><span class="token string">"false"</span><span class="token punctuation">,</span><span class="token property">"statusVal"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"statusType"</span><span class="token operator">:</span><span class="token string">"auto"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">840</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">140</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"3379276c77b4691c"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"4767c2f7095bee53"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"import data"</span><span class="token punctuation">,</span><span class="token property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"repeat"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"once"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"onceDelay"</span><span class="token operator">:</span><span class="token number">0.1</span><span class="token punctuation">,</span><span class="token property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">150</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">180</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"ddd1ef41321fb4a6"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"ddd1ef41321fb4a6"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"4767c2f7095bee53"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">"#:(persistent)::chart-data"</span><span class="token punctuation">,</span><span class="token property">"tot"</span><span class="token operator">:</span><span class="token string">"global"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">320</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">180</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"794846db6dc8cef8"</span><span class="token punctuation">,</span><span class="token string">"fa65b958e34bc971"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"fa65b958e34bc971"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"debug"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"4767c2f7095bee53"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"debug 2"</span><span class="token punctuation">,</span><span class="token property">"active"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"tosidebar"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"console"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"tostatus"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"complete"</span><span class="token operator">:</span><span class="token string">"false"</span><span class="token punctuation">,</span><span class="token property">"statusVal"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"statusType"</span><span class="token operator">:</span><span class="token string">"auto"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">480</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">180</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"af1535b39b74f94a"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_group"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Example"</span><span class="token punctuation">,</span><span class="token property">"tab"</span><span class="token operator">:</span><span class="token string">"14f1442eb7525190"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"disp"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token string">"6"</span><span class="token punctuation">,</span><span class="token property">"collapse"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"14f1442eb7525190"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_tab"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Home"</span><span class="token punctuation">,</span><span class="token property">"icon"</span><span class="token operator">:</span><span class="token string">"dashboard"</span><span class="token punctuation">,</span><span class="token property">"disabled"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"hidden"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">}</span><span class="token punctuation">]</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-89" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>You may have noticed that when we are pushing duplicate data into the chart it automatically checks to see if the data is already stored. If the data points are already in the chart the new data is disregard. This saves us writing an extra section of the flow to delete the data before we load it in.</p>
<h4 id="3.-expose-the-data-via-an-api-then-manually-import-it" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/persisting-chart-data-in-node-red/#3.-expose-the-data-via-an-api-then-manually-import-it"># </a> 3. Expose the data via an API then manually import it</h4>
<p>In some cases you may want to copy your chart data to somewhere outside of your Node-RED instances. You can do this by creating a simple API which allows an outside system to request the chart data. You can also manually go to the URL of the API in a web browser to get your data. This example flow allows a user or system to access the chart data via a URL.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/send-chart-data-to-api-RSQzaiNjYY-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/send-chart-data-to-api-RSQzaiNjYY-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Share the chart data via the API" alt="Share the chart data via the API" loading="lazy" decoding="async" src="https://flowfuse.com/img/send-chart-data-to-api-RSQzaiNjYY-650.jpeg" width="650" height="163" /></picture></p>
<div style="position: relative">
<pre class="language-json"><code id="code-102" class="language-json"><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"6523e86042252710"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"4767c2f7095bee53"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"repeat"</span><span class="token operator">:</span><span class="token string">"1"</span><span class="token punctuation">,</span><span class="token property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"once"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"onceDelay"</span><span class="token operator">:</span><span class="token number">0.1</span><span class="token punctuation">,</span><span class="token property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">150</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">540</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"d51aba5f9a808592"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"427c60f2c4f523b7"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_chart"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"4767c2f7095bee53"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"group"</span><span class="token operator">:</span><span class="token string">"af1535b39b74f94a"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"label"</span><span class="token operator">:</span><span class="token string">"chart"</span><span class="token punctuation">,</span><span class="token property">"chartType"</span><span class="token operator">:</span><span class="token string">"line"</span><span class="token punctuation">,</span><span class="token property">"legend"</span><span class="token operator">:</span><span class="token string">"false"</span><span class="token punctuation">,</span><span class="token property">"xformat"</span><span class="token operator">:</span><span class="token string">"HH:mm:ss"</span><span class="token punctuation">,</span><span class="token property">"interpolate"</span><span class="token operator">:</span><span class="token string">"linear"</span><span class="token punctuation">,</span><span class="token property">"nodata"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"dot"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"ymin"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"ymax"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"removeOlder"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"removeOlderPoints"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"removeOlderUnit"</span><span class="token operator">:</span><span class="token string">"3600"</span><span class="token punctuation">,</span><span class="token property">"cutout"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"useOneColor"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"useUTC"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"colors"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"#1f77b4"</span><span class="token punctuation">,</span><span class="token string">"#aec7e8"</span><span class="token punctuation">,</span><span class="token string">"#ff7f0e"</span><span class="token punctuation">,</span><span class="token string">"#2ca02c"</span><span class="token punctuation">,</span><span class="token string">"#98df8a"</span><span class="token punctuation">,</span><span class="token string">"#d62728"</span><span class="token punctuation">,</span><span class="token string">"#ff9896"</span><span class="token punctuation">,</span><span class="token string">"#9467bd"</span><span class="token punctuation">,</span><span class="token string">"#c5b0d5"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"outputs"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"useDifferentColor"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">470</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">540</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"ba84cd1820120139"</span><span class="token punctuation">,</span><span class="token string">"d9087436f4769691"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"ba84cd1820120139"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"debug"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"4767c2f7095bee53"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"debug"</span><span class="token punctuation">,</span><span class="token property">"active"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"tosidebar"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"console"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"tostatus"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"complete"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"targetType"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"statusVal"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"statusType"</span><span class="token operator">:</span><span class="token string">"auto"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">590</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">540</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"d51aba5f9a808592"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"Number"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"4767c2f7095bee53"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Random Number"</span><span class="token punctuation">,</span><span class="token property">"minimum"</span><span class="token operator">:</span><span class="token string">"1"</span><span class="token punctuation">,</span><span class="token property">"maximum"</span><span class="token operator">:</span><span class="token string">"10"</span><span class="token punctuation">,</span><span class="token property">"roundTo"</span><span class="token operator">:</span><span class="token string">"0"</span><span class="token punctuation">,</span><span class="token property">"Floor"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">310</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">540</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"427c60f2c4f523b7"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"d9087436f4769691"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"4767c2f7095bee53"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"chart-data"</span><span class="token punctuation">,</span><span class="token property">"pt"</span><span class="token operator">:</span><span class="token string">"flow"</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">630</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">580</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"4dd97b29430ad2ba"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"http in"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"4767c2f7095bee53"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"url"</span><span class="token operator">:</span><span class="token string">"/data"</span><span class="token punctuation">,</span><span class="token property">"method"</span><span class="token operator">:</span><span class="token string">"get"</span><span class="token punctuation">,</span><span class="token property">"upload"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"swaggerDoc"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">200</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">640</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"b4f0eb085cc91834"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"7ca49e5465699355"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"http response"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"4767c2f7095bee53"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"statusCode"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"headers"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">670</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">640</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"b4f0eb085cc91834"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"4767c2f7095bee53"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Get the chart data from flow.chart-data"</span><span class="token punctuation">,</span><span class="token property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">"chart-data"</span><span class="token punctuation">,</span><span class="token property">"tot"</span><span class="token operator">:</span><span class="token string">"flow"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">440</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">640</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"7ca49e5465699355"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"af1535b39b74f94a"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_group"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Example"</span><span class="token punctuation">,</span><span class="token property">"tab"</span><span class="token operator">:</span><span class="token string">"14f1442eb7525190"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"disp"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token string">"6"</span><span class="token punctuation">,</span><span class="token property">"collapse"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"14f1442eb7525190"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_tab"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Home"</span><span class="token punctuation">,</span><span class="token property">"icon"</span><span class="token operator">:</span><span class="token string">"dashboard"</span><span class="token punctuation">,</span><span class="token property">"disabled"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"hidden"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">}</span><span class="token punctuation">]</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-102" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>We can now access the data by simply visiting the URL of the API.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/data-in-browser-J_qA5RRsz7-621.avif 621w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/data-in-browser-J_qA5RRsz7-621.webp 621w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="The chart data accessed via the API in a web browser" alt="The chart data accessed via the API in a web browser" loading="lazy" decoding="async" src="https://flowfuse.com/img/data-in-browser-J_qA5RRsz7-621.jpeg" width="621" height="147" /></picture></p>
<p>Bear in mind that you should secure the API as appropriate for the data. If you don't put security around the API, anyone on the same network as your Node-RED instance can access your chart data. Potentially that could give access to our data to the whole internet, so where needed take steps to keep your data safe. You can read more about securing Node-RED in our <a href="https://flowfuse.com/blog/2023/04/securing-node-red-in-production/">blog post here</a>.</p>
<p>We now need to get that data back into a Node-RED instance. We can do that by editing a node and pasting in the data we got from the API. The flow below shows where you can paste in your data, you will then need to deploy and manually trigger 'import data'.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/inject-the-json-8Pn1gTdION-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/inject-the-json-8Pn1gTdION-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Inject the data in JSON format" alt="Inject the data in JSON format" loading="lazy" decoding="async" src="https://flowfuse.com/img/inject-the-json-8Pn1gTdION-650.jpeg" width="650" height="774" /></picture></p>
<div style="position: relative">
<pre class="language-json"><code id="code-118" class="language-json"><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"6523e86042252710"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"4767c2f7095bee53"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"repeat"</span><span class="token operator">:</span><span class="token string">"1"</span><span class="token punctuation">,</span><span class="token property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"once"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"onceDelay"</span><span class="token operator">:</span><span class="token number">0.1</span><span class="token punctuation">,</span><span class="token property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">150</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">540</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"d51aba5f9a808592"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"427c60f2c4f523b7"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_chart"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"4767c2f7095bee53"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"group"</span><span class="token operator">:</span><span class="token string">"af1535b39b74f94a"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"height"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"label"</span><span class="token operator">:</span><span class="token string">"chart"</span><span class="token punctuation">,</span><span class="token property">"chartType"</span><span class="token operator">:</span><span class="token string">"line"</span><span class="token punctuation">,</span><span class="token property">"legend"</span><span class="token operator">:</span><span class="token string">"false"</span><span class="token punctuation">,</span><span class="token property">"xformat"</span><span class="token operator">:</span><span class="token string">"HH:mm:ss"</span><span class="token punctuation">,</span><span class="token property">"interpolate"</span><span class="token operator">:</span><span class="token string">"linear"</span><span class="token punctuation">,</span><span class="token property">"nodata"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"dot"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"ymin"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"ymax"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"removeOlder"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"removeOlderPoints"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"removeOlderUnit"</span><span class="token operator">:</span><span class="token string">"3600"</span><span class="token punctuation">,</span><span class="token property">"cutout"</span><span class="token operator">:</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"useOneColor"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"useUTC"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"colors"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"#1f77b4"</span><span class="token punctuation">,</span><span class="token string">"#aec7e8"</span><span class="token punctuation">,</span><span class="token string">"#ff7f0e"</span><span class="token punctuation">,</span><span class="token string">"#2ca02c"</span><span class="token punctuation">,</span><span class="token string">"#98df8a"</span><span class="token punctuation">,</span><span class="token string">"#d62728"</span><span class="token punctuation">,</span><span class="token string">"#ff9896"</span><span class="token punctuation">,</span><span class="token string">"#9467bd"</span><span class="token punctuation">,</span><span class="token string">"#c5b0d5"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"outputs"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"useDifferentColor"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">470</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">540</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"ba84cd1820120139"</span><span class="token punctuation">,</span><span class="token string">"d9087436f4769691"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"ba84cd1820120139"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"debug"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"4767c2f7095bee53"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"debug"</span><span class="token punctuation">,</span><span class="token property">"active"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"tosidebar"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"console"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"tostatus"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"complete"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"targetType"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"statusVal"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"statusType"</span><span class="token operator">:</span><span class="token string">"auto"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">590</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">540</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"d51aba5f9a808592"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"Number"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"4767c2f7095bee53"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Random Number"</span><span class="token punctuation">,</span><span class="token property">"minimum"</span><span class="token operator">:</span><span class="token string">"1"</span><span class="token punctuation">,</span><span class="token property">"maximum"</span><span class="token operator">:</span><span class="token string">"10"</span><span class="token punctuation">,</span><span class="token property">"roundTo"</span><span class="token operator">:</span><span class="token string">"0"</span><span class="token punctuation">,</span><span class="token property">"Floor"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">310</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">540</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"427c60f2c4f523b7"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"d9087436f4769691"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"4767c2f7095bee53"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"chart-data"</span><span class="token punctuation">,</span><span class="token property">"pt"</span><span class="token operator">:</span><span class="token string">"flow"</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">630</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">580</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"4dd97b29430ad2ba"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"http in"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"4767c2f7095bee53"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"url"</span><span class="token operator">:</span><span class="token string">"/data"</span><span class="token punctuation">,</span><span class="token property">"method"</span><span class="token operator">:</span><span class="token string">"get"</span><span class="token punctuation">,</span><span class="token property">"upload"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"swaggerDoc"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">200</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">660</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"b4f0eb085cc91834"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"7ca49e5465699355"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"http response"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"4767c2f7095bee53"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"statusCode"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"headers"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">670</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">660</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"b4f0eb085cc91834"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"4767c2f7095bee53"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Get the chart data from flow.chart-data"</span><span class="token punctuation">,</span><span class="token property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">"chart-data"</span><span class="token punctuation">,</span><span class="token property">"tot"</span><span class="token operator">:</span><span class="token string">"flow"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">440</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">660</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"7ca49e5465699355"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"d13d16b33ec638b2"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"4767c2f7095bee53"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"import data"</span><span class="token punctuation">,</span><span class="token property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"repeat"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"once"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"onceDelay"</span><span class="token operator">:</span><span class="token number">0.1</span><span class="token punctuation">,</span><span class="token property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"payload"</span><span class="token operator">:</span><span class="token string">"[{\"series\":[\"\"],\"data\":[[{\"x\":1684841975036,\"y\":8},{\"x\":1684841976037,\"y\":6},{\"x\":1684841977038,\"y\":7},{\"x\":1684841978037,\"y\":7}]],\"labels\":[\"\"]}]"</span><span class="token punctuation">,</span><span class="token property">"payloadType"</span><span class="token operator">:</span><span class="token string">"json"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">170</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">600</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"427c60f2c4f523b7"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"af1535b39b74f94a"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_group"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Example"</span><span class="token punctuation">,</span><span class="token property">"tab"</span><span class="token operator">:</span><span class="token string">"14f1442eb7525190"</span><span class="token punctuation">,</span><span class="token property">"order"</span><span class="token operator">:</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"disp"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"width"</span><span class="token operator">:</span><span class="token string">"6"</span><span class="token punctuation">,</span><span class="token property">"collapse"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"className"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"14f1442eb7525190"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"ui_tab"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Home"</span><span class="token punctuation">,</span><span class="token property">"icon"</span><span class="token operator">:</span><span class="token string">"dashboard"</span><span class="token punctuation">,</span><span class="token property">"disabled"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"hidden"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">}</span><span class="token punctuation">]</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-118" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>Each of these solutions has strengths and weaknesses but there are many other ways to persist your chart data. You should consider which approach is the best fit for your needs. To be as confident as possible that you data is safe, you may decide to push your data to dedicate external storage such as a database or backup solution.</p>
<h3 id="conclusion" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/persisting-chart-data-in-node-red/#conclusion"># </a> Conclusion</h3>
<p>Node-RED Dashboard allows you to easily make informative HMIs, but it's important to make sure the chart data you are showing is stored safely. The approaches we have discussed above should give you a good start in ensuring your charts are populated with the correct data, even if your Node-RED instance crashes or you need to move it to a new hosting location.</p>
https://flowfuse.com/blog/2023/05/integrating-modbus-with-node-red/Best Practices Integrating a Modbus Device With Node-REDIntegrate Modbus with Node-RED2023-05-16T00:00:00Z<p>The world of industrial automation is slow to adopt new technology. With legacy equipment already working and in place, paralyzing down-time costs, and fears of introducing instability into a plant, technology change has a cautious pace.</p>
<!--more-->
<p>Node-RED provides a way to extend the capabilities of the simpler, proven technology, allowing connections with modern systems. However, the same fundamentals that have made industrial equipment dependable, must be incorporated into your Node-RED architecture. And, inversely, the same abstraction and simplicity that makes a low-code, Node-RED environment fast, and easy to work with, can also make it difficult to interface with a lower-level system.</p>
<p>Modbus is a widely adopted protocol for accessing data from existing legacy manufacturing equipment. Node-RED makes it very easy to connect to Modbus enabled equipment. However, there are some best practices we have developed to maintain system integrity when integrating Modbus devices with Node-RED:</p>
<h3 id="add-watchdogs-to-node-red-flows" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/integrating-modbus-with-node-red/#add-watchdogs-to-node-red-flows"># </a> Add Watchdogs to Node-RED Flows</h3>
<p>To keep your automation system running with peace of mind and little human intervention, use a watchdog timer. A watchdog timer is typically used to detect and recover from system malfunctions. In Node-RED a watchdog timer can be tied to a broadcast messaging system to get push alerts directly to cell phones, as well as to an auto-reset to try to get your Flows back online automatically. A simple implementation of this is to just put two Trigger nodes in a loop, the first one to send an alert when it hasn’t seen any recent events, and the second to to reset the first one.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/integrating-modbus-3-f6a8PYlGTC-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/integrating-modbus-3-f6a8PYlGTC-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Example watchdog flow" alt="Example watchdog flow" loading="lazy" decoding="async" src="https://flowfuse.com/img/integrating-modbus-3-f6a8PYlGTC-650.jpeg" width="650" height="158" /></picture></p>
<p>Each of the trigger nodes are setup with similar parameters, only the delay values differ.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/integrating-modbus-14-fs5fznKpWS-504.avif 504w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/integrating-modbus-14-fs5fznKpWS-504.webp 504w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Trigger node configuration" alt="Trigger node configuration" loading="lazy" decoding="async" src="https://flowfuse.com/img/integrating-modbus-14-fs5fznKpWS-504.jpeg" width="504" height="580" /></picture></p>
<p>Sending a payload of {"connectorType":"TCP"} to the Modbus Flex Connector is enough to reset the connection without needing to send all the other parameters.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/integrating-modbus-10-XnEUdOl20m-508.avif 508w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/integrating-modbus-10-XnEUdOl20m-508.webp 508w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Change node configuration" alt="Change node configuration" loading="lazy" decoding="async" src="https://flowfuse.com/img/integrating-modbus-10-XnEUdOl20m-508.jpeg" width="508" height="305" /></picture></p>
<h3 id="choosing-a-safe-poll-rate" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/integrating-modbus-with-node-red/#choosing-a-safe-poll-rate"># </a> Choosing a Safe Poll Rate</h3>
<p>Be careful when adding new traffic to an industrial network, which might not be able to handle the extra load. Some networks have low-bandwidth, especially at large plants that might be using antiquated IP devices and long-distance, Wi-Fi bridges in electrically noisy environments. Furthermore, some PLCs and other Modbus devices have limits as to how many other devices can connect to them, and a new connection might not work, or worse, bump off an old connection. A PLC’s general operation is to poll its inputs every cycle and react accordingly, running logic and triggering outputs as quickly as possible. The general use-case for Node-RED with a PLC is to create an HMI or broader, SCADA system. A poll rate of every second suffices for a simple HMI. For dashboards published to a greater audience, rather than just the operator, poll rates of several minutes to hours might be adequate. If this is a new integration, it’s better to start slow and make sure the current infrastructure can handle the extra load.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/integrating-modbus-7-dvJrM-bPkB-638.avif 638w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/integrating-modbus-7-dvJrM-bPkB-638.webp 638w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Modbus node configuration" alt="Modbus node configuration" loading="lazy" decoding="async" src="https://flowfuse.com/img/integrating-modbus-7-dvJrM-bPkB-638.jpeg" width="638" height="579" /></picture></p>
<h3 id="coil%2Fregister-grouping" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/integrating-modbus-with-node-red/#coil%2Fregister-grouping"># </a> Coil/Register Grouping</h3>
<p>Modbus works more efficiently when it is reading and writing addresses as groups. Creating banks of consecutively numbered coils or registers can help with this. If Modbus is already in use, perhaps for an existing HMI, but for your Node-RED dashboard you just want a selection of these addresses and they are too scattered to be read all at once, pick a starting address numbered far higher than what you will use for any HMI work and create a new bank of coils or registers just for the Node-RED dashboard. The PLC can handle this easily and it greatly simplifies the polling for your Node-RED dashboard. On the Node-RED side of the connection, it’s a good idea to parse and to filter this data as soon as it enters the flow. Below, the first node creates an appropriate message for each coil, with a topic name and a true/false payload. This message is then filtered by the “block unless value changes” mode in the filter node and finally a switch (by topic) node separates out each message. In this example, every Tag coming in from the PLC only triggers downstream nodes when there is a change and each Tag has its own output to connect a wire, and subsequent nodes to.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/integrating-modbus-5-DhQsCJ4DmR-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/integrating-modbus-5-DhQsCJ4DmR-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Using a switch node to separate the messages" alt="Using a switch node to separate the messages" loading="lazy" decoding="async" src="https://flowfuse.com/img/integrating-modbus-5-DhQsCJ4DmR-650.jpeg" width="650" height="321" /></picture></p>
<p>The filter node blocks redundant data from triggering subsequent nodes.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/integrating-modbus-12-gz6pP3MHqg-502.avif 502w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/integrating-modbus-12-gz6pP3MHqg-502.webp 502w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Filter node configuration" alt="Filter node configuration" loading="lazy" decoding="async" src="https://flowfuse.com/img/integrating-modbus-12-gz6pP3MHqg-502.jpeg" width="502" height="332" /></picture></p>
<p>The function node, “modbusMapArray,” creates messages that are much more user-friendly in the Node-RED environment.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/integrating-modbus-1-6QTaCpI4_f-480.avif 480w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/integrating-modbus-1-6QTaCpI4_f-480.webp 480w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Modbus function node" alt="Modbus function node" loading="lazy" decoding="async" src="https://flowfuse.com/img/integrating-modbus-1-6QTaCpI4_f-480.jpeg" width="480" height="369" /></picture></p>
<p>Quick tip: If your PLC environment has limits on the number of addresses allowed and you want to read a lot of coils, you can work with registers bitwise and stuff 16 coils into one register.</p>
<h3 id="reading-data-types" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/integrating-modbus-with-node-red/#reading-data-types"># </a> Reading Data Types</h3>
<p>No matter what data type the PLC is sending over Modbus, it’s going to be sent using the 16-bit registers. For example, to send 1234.5678 as a 32-bit Float (little-endian), the payload from the PLC will be a seemingly unhelpful array, [21035,17562]. I can simulate this with the <a href="https://www.automationdirect.com/adc/overview/catalog/software_products/programmable_controller_software/productivity_suite_programming_software">Productivity Suite Programming Software</a> from Automation Direct set to simulator mode. Below, I have created a 32-bit float “Tag,” named “mySampleFloat32,” using modbus registers 40001 and 40002, and set the “Init Value” to 1234.5678.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/integrating-modbus-11-1m6PlssSX0-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/integrating-modbus-11-1m6PlssSX0-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Productivity Suite Programming Software" alt="Productivity Suite Programming Software" loading="lazy" decoding="async" src="https://flowfuse.com/img/integrating-modbus-11-1m6PlssSX0-650.jpeg" width="650" height="180" /></picture></p>
<p>Node-RED is typically used at a much higher level, but luckily there is still a way to work with this low-level data. Node-RED uses the Buffer Class to work with this type of data stream, but it’s a little tricky. First the 16-bit registers have to be broken into 8-bit chunks, here we use msg.responseBuffer.buffer to retrieve each octet. Once our buffer is properly filled, there are many built-in functions to reconstruct the data into the actual number you are looking for.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/integrating-modbus-4-nP2o5Cqoi_-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/integrating-modbus-4-nP2o5Cqoi_-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Using msg.responseBuffer.buffer to retrieve each octet" alt="Using msg.responseBuffer.buffer to retrieve each octet" loading="lazy" decoding="async" src="https://flowfuse.com/img/integrating-modbus-4-nP2o5Cqoi_-650.jpeg" width="650" height="341" /></picture></p>
<p>Notice below that to read these 2 registers at 400001 and 400002 I have set my Modbus-Read node to start at “Address” 0 and ready “Quantity” 2 registers. Unfortunately, there are two different standards for writing Modbus addresses and my PLC uses the traditional convention (400001 to 465536) and this Modbus node uses the hexadecimal convention (4x0000 to 4xFFFF).</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/integrating-modbus-8-qb3m74O87u-643.avif 643w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/integrating-modbus-8-qb3m74O87u-643.webp 643w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Modbus node configuration" alt="Modbus node configuration" loading="lazy" decoding="async" src="https://flowfuse.com/img/integrating-modbus-8-qb3m74O87u-643.jpeg" width="643" height="581" /></picture></p>
<p>In this example the byte order from msg.responseBuffer.buffer doesn’t quite match the data type, so we have to rebuild the buffer.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/integrating-modbus-13-eweuMnerwW-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/integrating-modbus-13-eweuMnerwW-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Mapping the data in a function node" alt="Mapping the data in a function node" loading="lazy" decoding="async" src="https://flowfuse.com/img/integrating-modbus-13-eweuMnerwW-650.jpeg" width="650" height="380" /></picture></p>
<p>Amazingly after all that work we get the response: 1234.5677490234375. This is the shortcoming of the 32-bit float data type. Although it can handle a huge range of values, they aren’t very accurate. For this reason, many times PLCs will send a number as an integer, say 12345678, and the documentation will prescribe 4 decimal place accuracy to bring the number back to 1234.5678. Find out more ways to work with a Buffer at <a href="https://nodejs.org/dist/latest-v10.x/docs/api/buffer.html">https://nodejs.org/dist/latest-v10.x/docs/api/buffer.html</a>.</p>
<h3 id="general-architecture" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/integrating-modbus-with-node-red/#general-architecture"># </a> General Architecture</h3>
<p>Although you can off-load some of the higher-level logic from the PLC into Node-RED, it’s important to remember that Node-RED augments, but doesn’t create a replacement for a PLC’s IDE and the IEC 61131-3 suite of languages. Make a conscious distinction between the type of work the PLC should handle and what you expect from Node-RED. Any real-time responses to inputs should strictly be handled by the PLC.</p>
<h3 id="security" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/integrating-modbus-with-node-red/#security"># </a> Security</h3>
<p>Connecting Node-RED to your PLC also creates a larger attack surface for cyber threats. Make sure that you follow the guidelines found on the Node-RED.org site at <a href="https://nodered.org/docs/user-guide/runtime/securing-node-red">Securing Node-RED</a>. Node-RED’s strength is its ability to make connections where they weren’t possible before, but this can be taken advantage of by a hacker. For instance, maybe it’s tempting to make Node-RED a transparent gateway and make a RESTful API fully exposing a modbus-flex-write node. This is amazingly easy and powerful with Node-RED, but anyone who can access your IP could send http://<yourIP>:1880/careful?value=true&fc=15&unitid=1&address=0&quantity=10 and remotely turn on and off whatever they wanted.</yourIP></p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/integrating-modbus-6-IlBo-XIeSX-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/integrating-modbus-6-IlBo-XIeSX-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Example endpoint flow" alt="Example endpoint flow" loading="lazy" decoding="async" src="https://flowfuse.com/img/integrating-modbus-6-IlBo-XIeSX-650.jpeg" width="650" height="125" /></picture></p>
<p>Instead, a better practice would be to more narrowly define what you want to accomplish and only allow Node-RED to do exactly that. In this case you might send http://<yourIP>:1880/honkTheLunchHorn?honk=true</yourIP></p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/integrating-modbus-2-MBwGYVknXw-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/integrating-modbus-2-MBwGYVknXw-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Locking down the endpoint" alt="Locking down the endpoint" loading="lazy" decoding="async" src="https://flowfuse.com/img/integrating-modbus-2-MBwGYVknXw-650.jpeg" width="650" height="127" /></picture></p>
<h3 id="final-thoughts" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/integrating-modbus-with-node-red/#final-thoughts"># </a> Final Thoughts</h3>
<p>If not done right, there could be some hard lessons, so it’s best to monitor the processes to help track down bugs. Add a log, keep your eyes out, and as a community let’s work to create stable systems.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/integrating-modbus-9-u3WWUnJO-p-642.avif 642w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/integrating-modbus-9-u3WWUnJO-p-642.webp 642w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Logging failures" alt="Logging failures" loading="lazy" decoding="async" src="https://flowfuse.com/img/integrating-modbus-9-u3WWUnJO-p-642.jpeg" width="642" height="353" /></picture></p>
<p>How readily upper management gives an “okay” to this new technology comes with how well it is implemented. There will be some growing pains, but by the end, you will have supercharged your plant, bringing it into the 21st century.</p>
https://flowfuse.com/blog/2023/05/flowforge-1-7-released/FlowFuse 1.7 Now Available with Remote Node-RED Editor AccessFurther improving fleet management and maintenance of remote Node-RED instances2023-05-11T00:00:00ZMarian Demme<p>FlowFuse 1.7 adds new support for accessing the Node-RED Editor on Devices via FlowFuse.</p>
<!--more-->
<h2 id="further-improving-fleet-management-and-maintenance-of-remote-node-red-instances" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/flowforge-1-7-released/#further-improving-fleet-management-and-maintenance-of-remote-node-red-instances"># </a> Further improving fleet management and maintenance of remote Node-RED instances</h2>
<p>We are excited to introduce a new feature that will simplify the process of debugging and developing flows for devices. Our latest feature, "Editing Flows on Devices" allows users to access the editor directly on their device without the need for complex network configurations or firewalls. This feature will significantly improve the user experience, making it easier and more efficient to work with devices.</p>
<p>This update is a part of our ongoing commitment to making FlowFuse the best possible solution for developing your Node-RED flows, no matter where they're running. In fact, as part of our last release 1.6, we already introduced the feature: <a href="https://flowfuse.com/blog/2023/04/flowforge-1-6-released/#access-node-red-logs-from-remote-devices">"Access Node-RED logs from remote devices"</a>. This feature made it easy for users to troubleshoot and debug. Building on that, we've taken the next step, and it's now possible to access the Device Editor.</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/zS6P3RR86vE" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
<h2 id="device-status-visualisation" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/flowforge-1-7-released/#device-status-visualisation"># </a> Device Status Visualisation</h2>
<p>This FlowFuse version upgrades device monitoring. It's made easier to manage your devices effectively, especially when there's many of them. Now we offer an intuitive, user-friendly method for users to keep an eye on their devices' status and evaluate the health of their team's devices overall. Creating an overview of your fleet's health, however large your fleet might be.</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/S--viuPhrS8" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
<h2 id="auto-restart-for-hung-node-red-instances" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/flowforge-1-7-released/#auto-restart-for-hung-node-red-instances"># </a> Auto Restart for Hung Node-RED Instances</h2>
<p>This enhancement ensures a more robust and reliable experience when working with Node-RED flows. The launcher now actively monitors the Node-RED process to detect if it has become unresponsive or hung, in addition to the existing checks for start-up and unexpected process exits. This advancement takes us one step further in improving the availability of our Node-RED instances.</p>
<h2 id="ongoing-topics" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/flowforge-1-7-released/#ongoing-topics"># </a> Ongoing Topics</h2>
<h3 id="high-availability" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/flowforge-1-7-released/#high-availability"># </a> High Availability</h3>
<p>We're actively progressing on the topic of enhancing High Availability in FlowFuse for Node-RED. Our initial tasks and modifications have been identified, specifically pertaining to the operation of Node-RED instances within the k8s environment. These adjustments are aimed at constructing a more resilient system. Stay tuned for a comprehensive update regarding our advancements in High Availability.</p>
<h3 id="soc2-certification" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/flowforge-1-7-released/#soc2-certification"># </a> SOC2 Certification</h3>
<p>Dedicated to upholding the highest levels of security and privacy, our company acknowledges the significance of industry-standard certifications like SOC2 in fostering trust with our customers and partners. We aim to achieve SOC2 Type 1 certification by the end of Q2 and subsequently maintain a continuous SOC2 Type 2 certification. We will keep you informed on our progress as we reach essential milestones in our SOC2 certification journey. Rest assured, our commitment to delivering the utmost security and privacy for our customers and partners remains unwavering.</p>
<h3 id="aws-marketplace-onboarding" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/flowforge-1-7-released/#aws-marketplace-onboarding"># </a> AWS Marketplace onboarding</h3>
<p>We are excited to provide an update on our ongoing task of onboarding Node-RED instances to AWS Marketplace via FlowFuse Cloud, which we have started in this Iteration. By offering Node-RED instances through AWS Marketplace, we aim to simplify the deployment process for our customers.</p>
<p>One of the significant challenges we are currently addressing is handling our current payment system in parallel with a new method. This will ensure a seamless billing experience for our customers, as they will be able to manage their Node-RED instance subscriptions through their existing AWS accounts.</p>
<h2 id="contributors" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/flowforge-1-7-released/#contributors"># </a> Contributors</h2>
<p>We'd like the thank the following for their contributions to this release:</p>
<ul>
<li><a href="https://github.com/andreikop">@andreikop</a> for their work on the <a href="https://github.com/FlowFuse/flowforge-driver-k8s/pull/80">flowforge-driver-k8s #80</a> and <a href="https://github.com/FlowFuse/helm/pull/125">flowforge/helm #125</a></li>
<li><a href="https://github.com/elenaviter">@elenaviter</a> for their work on <a href="https://github.com/FlowFuse/helm/pull/126">flowforge/helm #126</a></li>
</ul>
<p>As an open-source project, we welcome community involvement in what we're building. If you're interested in contributing, checkout our <a href="https://flowfuse.com/docs/contribute/">guide in the docs</a>.</p>
<h2 id="what's-next%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/flowforge-1-7-released/#what's-next%3F"># </a> What's next?</h2>
<p>We're always working to enhance your experience with FlowFuse. Here's how you can stay informed and contribute:</p>
<ul>
<li><strong>Roadmap Overview</strong>: Check out our <a href="https://flowfuse.com/product/roadmap/">Product Roadmap Page</a> to see what we're planning for future updates.</li>
<li><strong>Entire Roadmap</strong>: Visit our <a href="https://github.com/orgs/FlowFuse/projects/5">Roadmap on GitHub</a> to follow our progress and contribute your ideas.</li>
<li><strong>Feedback</strong>: We're interested in your thoughts about FlowFuse. Your feedback is crucial to us, and we'd love to hear about your experiences with the new features and improvements. Please share your thoughts, suggestions, or report any <a href="https://github.com/FlowFuse/flowfuse/issues/new/choose">issues on GitHub</a>.</li>
</ul>
<p>Together, we can make FlowFuse better with each release!</p>
<h2 id="bug-fixes" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/flowforge-1-7-released/#bug-fixes"># </a> Bug Fixes</h2>
<p>Incorrect number of days displayed when adding a new license <a href="https://github.com/FlowFuse/flowfuse/issues/1895">#1895</a></p>
<p>Users were unable to upgrade modules in Manage Palette, even after restarting Node-RED. <a href="https://github.com/FlowFuse/flowfuse/issues/2005">#2005</a></p>
<p>Enable 'Delete Team' Button <a href="https://github.com/FlowFuse/flowfuse/issues/2031">#2031</a></p>
<p>Triggering a Node-RED restart using the action button resulted in two instances of Node-RED running in the container, causing one instance to crash due to port 1880 being already in use. <a href="https://github.com/FlowFuse/flowfuse/issues/1860">#2031</a></p>
<p>Error deleting instance with missing subscription <a href="https://github.com/FlowFuse/flowfuse/issues/2080">#2080</a></p>
<p>Snapshot Rollback no longer working <a href="https://github.com/FlowFuse/flowfuse/issues/2026">#2026</a></p>
<p>Users receiving an unauthorized error when attempting to switch to a team in which they are a member <a href="https://github.com/FlowFuse/flowfuse/issues/1845">#1845</a></p>
<p>Cannot select "Member" option when inviting a team member <a href="https://github.com/FlowFuse/flowfuse/issues/2084">#2084</a></p>
<h2 id="try-it-out" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/flowforge-1-7-released/#try-it-out"># </a> Try it out</h2>
<p>We're confident you can have self managed FlowFuse running locally in under 30 minutes.
You can install our <a href="https://flowfuse.com/docs/install/local/">local build</a>, use <a href="https://flowfuse.com/docs/install/docker/">Docker</a>, or <a href="https://flowfuse.com/docs/install/kubernetes/">Kubernetes</a>.</p>
<p>If you'd rather use our hosted offering: <a href="https://app.flowfuse.com/account/create">Get started for free</a> on FlowFuse Cloud.</p>
<h2 id="upgrading-flowfuse" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/flowforge-1-7-released/#upgrading-flowfuse"># </a> Upgrading FlowFuse</h2>
<p><a href="https://app.flowfuse.com/">FlowFuse Cloud</a> is already running 1.7.</p>
<p>If you installed a previous version of FlowFuse and want to upgrade, our documentation provides a
guide for <a href="https://flowfuse.com/docs/upgrade/">upgrading your FlowFuse instance</a>.</p>
<h2 id="getting-help" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/flowforge-1-7-released/#getting-help"># </a> Getting help</h2>
<p>Please check FlowFuse's <a href="https://flowfuse.com/docs/">documentation</a> as the answers to many questions are covered there.</p>
<p>If you hit any problems with the platform please raise an <a href="https://github.com/FlowFuse/flowfuse/issues">issue on GitHub</a>.
That's also a great place to send us any feedback or feature requests.</p>
<p>You can also get help on <a href="https://discourse.nodered.org/">the Node-RED forums</a></p>
<p>As well as in the <a href="https://github.com/FlowFuse/flowfuse/discussions">forum within our Github project</a></p>
<p>Chat with us on the <code>#flowfuse</code> channel on the <a href="https://nodered.org/slack">Node-RED Slack workspace</a></p>
<p>You can raise a support ticket by emailing <a href="mailto:support@flowfuse.com">support@flowfuse.com</a></p>
<p>We've also added a live chat widget to our website, you can access it using the icon on the bottom right corner of our website. We'd love to hear from you.</p>
https://flowfuse.com/blog/2023/05/visualize-production-data-via-modbus-in-node-red/Using Node-RED to Visualize Industrial Production Data via ModbusUsing Node-RED to Visualize Industrial Production Data via Modbus.2023-05-10T00:00:00Z<p>In manufacturing companies there is often a small set of production data, currently only available to an equipment operator through the HMI, which would be enormously valuable to a greater audience if there were some way to easily display and share it.</p>
<!--more-->
<p>Node-RED, along with Modbus and Dashboard modules, can easily create a web-based dashboard, shareable with a weblink and viewable on any web browser on the network. Imagine the advantages of digital signage in the breakroom spurring healthy competition or a manager being able to check daily totals and live process values from the phone in their pocket.</p>
<h2 id="what-is-modbus" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/visualize-production-data-via-modbus-in-node-red/#what-is-modbus"># </a> What is Modbus</h2>
<p>Modbus is a serial protocol that is often found in the industrial world to allow devices to communicate. Originally developed by Schneider Electric, it is an open protocol and has been adopted by brands across the industry. <a href="https://www.simplymodbus.ca/">Simply Modbus</a> is a terrific resource to learn more about how the communication is structured. The beauty of Node-RED’s low-code environment is that a user only has to understand Modbus at the highest level to be able to implement it.</p>
<p>The transport layer for Modbus can be either TCP over the Internet or RTU over RS-485/422/232. There is a client-server relationship among devices where the clients read and write data which is stored by server using a numerical address. There are four types of these addresses, 1) Output Coil and 2) Discrete Input addresses, which hold 1-bit data, and 3) Input Register and 4) Holding Register addresses, which hold 16-bit data. Typically a PLC will be the Server and an HMI will be the client, reading and writing to the memory in the PLC, in order to give an operator control over machinery.</p>
<h2 id="what-is-an-hmi" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/visualize-production-data-via-modbus-in-node-red/#what-is-an-hmi"># </a> What is an HMI</h2>
<p>An HMI, or human machine interface, is a piece of software that allows an operator to use a machine. An HMI development environment typically allows programmers to choose among an array of digital assets to visualize the machine on the screen and create an intuitive interface to control the machine. The HMI software may also offload some of the high-level logic from the PLC, however, the time-critical lower-level logic should stay on the PLC. Node-RED can take this a step further, you may use it to create a simple HMI, but its real strength comes from its internet based heritage, and its ability to help share data from the PLC to the cloud.</p>
<p>Let’s look at the details of how you would use Node-RED for HMI and Modbus to
build an HMI with Node-RED to connect Modbus data to a dashboard accessible from any web browser.</p>
<h2 id="installation-of-the-modbus-package" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/visualize-production-data-via-modbus-in-node-red/#installation-of-the-modbus-package"># </a> Installation of the Modbus package</h2>
<p>The most popular package used for connecting Modbus devices is <a href="https://flows.nodered.org/node/node-red-contrib-modbus">node-red-contrib-modbus</a>; it has a wide range of configuration options and is well-documented in many blogs. On its own, this Modbus package just provides the means of communicating the 1-bit and 16-bit data. In doing so, your flow will be able to write 1-bit and 16-bit data to the PLC and read 1-bit and 16-bit data, which will arrive in an array. So, just like with other protocols (MQTT, HTTP, etc) fully integrating Modbus into your flow requires data manipulation and a well-thought-out schema for how this data will be packed into your msg objects. For example, below a payload of [false,false,false] comes in from a “Modbus Read” node, but how do you turn that into useful information? Maybe, you want to work with all alarms as a group, use a “Change” node to create a payload that is an object holding the related keys, with a topic that lets us know that these are all “alarms.”</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/modbus-1-13-OtIu22fClr-619.avif 619w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/modbus-1-13-OtIu22fClr-619.webp 619w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Configuring the Modbus node" alt="Configuring the Modbus node" loading="lazy" decoding="async" src="https://flowfuse.com/img/modbus-1-13-OtIu22fClr-619.jpeg" width="619" height="652" /></picture></p>
<p>Note: for an even more comprehensive node to parse this data, check out <a href="https://flows.nodered.org/node/node-red-contrib-buffer-parser">node-red-contrib-buffer-parser</a> by Flowforge’s own, Steve McLaughlin.
To install, first click on the hamburger menu in the upper right of the Node-RED editor and then click on “Manage palette.”</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/modbus-1-8-EDNZJ_OKrf-532.avif 532w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/modbus-1-8-EDNZJ_OKrf-532.webp 532w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Accessing the palette manager" alt="Accessing the palette manager" loading="lazy" decoding="async" src="https://flowfuse.com/img/modbus-1-8-EDNZJ_OKrf-532.jpeg" width="532" height="665" /></picture></p>
<p>Next, click on the “Install” tab, search for “modbus” in the search bar, and click on the “install” button next to <a href="https://flows.nodered.org/node/node-red-contrib-modbus">node-red-contrib-modbus</a>. As you can see there are many other custom nodes, but this one is a great jumping off point. It's always good to try other options too, and see what the community has to offer.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/modbus-1-10-0ppgPFLd5_-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/modbus-1-10-0ppgPFLd5_-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Installing the custom node" alt="Installing the custom node" loading="lazy" decoding="async" src="https://flowfuse.com/img/modbus-1-10-0ppgPFLd5_-650.jpeg" width="650" height="480" /></picture></p>
<p>Finally, click on the “Install” button in the pop-up.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/modbus-1-1-IE6PH82Eta-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/modbus-1-1-IE6PH82Eta-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Installing the custom node" alt="Installing the custom node" loading="lazy" decoding="async" src="https://flowfuse.com/img/modbus-1-1-IE6PH82Eta-650.jpeg" width="650" height="216" /></picture></p>
<p>Success, your new set of nodes are ready to use.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/modbus-1-6-VfIdnOgSv3-235.avif 235w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/modbus-1-6-VfIdnOgSv3-235.webp 235w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="The new nodes are now in the palette" alt="The new nodes are now in the palette" loading="lazy" decoding="async" src="https://flowfuse.com/img/modbus-1-6-VfIdnOgSv3-235.jpeg" width="235" height="488" /></picture></p>
<h2 id="configuring-of-modbus-nodes" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/visualize-production-data-via-modbus-in-node-red/#configuring-of-modbus-nodes"># </a> Configuring of modbus nodes</h2>
<p>Here is a sample set of data on a PLC running a motor turning a belt with a belt scale.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/modbus-1-14-WlxMwMPVPx-345.avif 345w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/modbus-1-14-WlxMwMPVPx-345.webp 345w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Example data from Modbus" alt="Example data from Modbus" loading="lazy" decoding="async" src="https://flowfuse.com/img/modbus-1-14-WlxMwMPVPx-345.jpeg" width="345" height="169" /></picture></p>
<p>All of this data is related so it has been grouped by consecutive numbers to make acquiring the data simpler. You can also group data by the rate you expect to be polling for it, so that your Modbus nodes don’t have to make several calls to collect the data. In the Modbus protocol the client specifies a start address and a number of subsequent addresses to read, and the server responds with all of this data at once. Creating groups allows much more efficient communication.</p>
<p>This PLC uses the coil/register numbering convention with output coils in the 0nnnnn format and the holding registers in the 4nnnnn format. Our Modbus nodes in Node-RED use a data address numbering convention which is zero-based, so we will have to remember to subtract 1 from the coils and registers.</p>
<p>Two “Modbus Read” nodes will work to capture these two types of data, coils and registers. Drag them into the flow and double click on one to start configuring them. First we will have to specify our Modbus Server, so click on the pencil icon to “add new.” In the next “Modbus Read” node we configure, we can just select our newly added server from the drop-down menu.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/modbus-1-3-g4soQ3Dluo-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/modbus-1-3-g4soQ3Dluo-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Adding a Modbus server" alt="Adding a Modbus server" loading="lazy" decoding="async" src="https://flowfuse.com/img/modbus-1-3-g4soQ3Dluo-650.jpeg" width="650" height="394" /></picture></p>
<p>Let’s assume that your PLC is connected to your local area network and we will be communicating over TCP. Enter in the IP address of the PLC, the rest of the configuration can be left as-is. 502 is the default port for Modbus and generally the Unit-Id is 1, sometimes 0, sometimes ignored. The “Queues” and “Optionals” can stay as-is as well.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/modbus-1-2-IhizjTbNoZ-646.avif 646w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/modbus-1-2-IhizjTbNoZ-646.webp 646w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Setting the protocol and IP address" alt="Setting the protocol and IP address" loading="lazy" decoding="async" src="https://flowfuse.com/img/modbus-1-2-IhizjTbNoZ-646.jpeg" width="646" height="659" /></picture></p>
<p>Click On “Add” and you will see your new server selected in the drop-down menu. Now let’s set this “Modbus Read” node to read our Coils once every second.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/modbus-1-5-JR_I_Z0FvY-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/modbus-1-5-JR_I_Z0FvY-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Setting how often data is read in the first Modbus read node" alt="Setting how often data is read in the first Modbus read node" loading="lazy" decoding="async" src="https://flowfuse.com/img/modbus-1-5-JR_I_Z0FvY-650.jpeg" width="650" height="587" /></picture></p>
<p>Similarly, set up the other “Modbus Read” node to read the holding registers. Click on the “Done” Button. Why the Modbus standard uses FC 3 to read the 4nnnnn registers and why there is both a zero-based and one-based convention is just a painful reality when using Modbus.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/modbus-1-15-f_gnEx6wI4-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/modbus-1-15-f_gnEx6wI4-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Setting how often data is read in the second Modbus read node" alt="Setting how often data is read in the second Modbus read node" loading="lazy" decoding="async" src="https://flowfuse.com/img/modbus-1-15-f_gnEx6wI4-650.jpeg" width="650" height="594" /></picture></p>
<p>You can add some “Modbus Response” nodes to the “Modbus Read” nodes and click “Deploy” in order to see the data coming through, right in the editor.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/modbus-1-7-eEQmfsXjpR-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/modbus-1-7-eEQmfsXjpR-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Checking the data is arriving OK" alt="Checking the data is arriving OK" loading="lazy" decoding="async" src="https://flowfuse.com/img/modbus-1-7-eEQmfsXjpR-650.jpeg" width="650" height="273" /></picture></p>
<h2 id="simple-visualization" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/visualize-production-data-via-modbus-in-node-red/#simple-visualization"># </a> Simple visualization</h2>
<p>Finally, let’s create a dashboard of this incoming data using node-red-dashboard.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/modbus-1-11-hRgCa3DDxh-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/modbus-1-11-hRgCa3DDxh-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Example dashboard showing the data" alt="Example dashboard showing the data" loading="lazy" decoding="async" src="https://flowfuse.com/img/modbus-1-11-hRgCa3DDxh-650.jpeg" width="650" height="226" /></picture></p>
<p>“Change” nodes are an easy way to split apart the arrays of coils and registers into discrete messages.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/modbus-1-9-1xFvffsigC-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/modbus-1-9-1xFvffsigC-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Splitting up the data using change node" alt="Splitting up the data using change nodes" loading="lazy" decoding="async" src="https://flowfuse.com/img/modbus-1-9-1xFvffsigC-650.jpeg" width="650" height="395" /></picture></p>
<p>The msg.payload is set to the entry at the correct index of the incoming msg.payload array, and the msg.fontColor is set using conditional formatting of “green” and “red”, for true and false, respectively.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/modbus-1-4-Wq2utY-dqj-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/modbus-1-4-Wq2utY-dqj-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Configuring the change node" alt="Configuring the change node" loading="lazy" decoding="async" src="https://flowfuse.com/img/modbus-1-4-Wq2utY-dqj-650.jpeg" width="650" height="383" /></picture></p>
<p>The HTML in the “text” node for the dashboard can be entered directly into the “Value format” field using the msg.fontColor and msg.payload from the “change” node.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/modbus-1-12-8gpQMUo9lc-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/modbus-1-12-8gpQMUo9lc-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Configuring the text output in the dashboard" alt="Configuring the text output in the dashboard" loading="lazy" decoding="async" src="https://flowfuse.com/img/modbus-1-12-8gpQMUo9lc-650.jpeg" width="650" height="417" /></picture></p>
<p>Similarly, for the “chart” node in the dashboard it is good to assign a msg.topic value so that if more data is charted, each line will be in a separate color, and hovering over the lines on the UI will display all the topics and values at that point.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/modbus-1-16-LvQ5FjDyHc-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/modbus-1-16-LvQ5FjDyHc-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Charting more than one data set to the same line chart" alt="Charting more than one data set to the same line chart" loading="lazy" decoding="async" src="https://flowfuse.com/img/modbus-1-16-LvQ5FjDyHc-650.jpeg" width="650" height="386" /></picture></p>
<h2 id="final-thoughts" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/visualize-production-data-via-modbus-in-node-red/#final-thoughts"># </a> Final thoughts</h2>
<p>The way that we set up this example worked well for the small sample size and quickly getting content on the dashboard, but as you work through your own needs, think about the data structures that will be the most conducive to efficiently working with your data. Also, this dashboard is somewhat ephemeral, and even the “chart” node was only set to keep an hour's worth of information. The next step after building a live dashboard, is to build a historical database, and see trends that happen over even longer periods.</p>
<p>The amazing thing about this dashboard you just created is that you can send the URL, http://<your_server_ip>:1880/ui, to someone else on your network and they will be able to see this same visualization in their own browser, whether on a computer, smartphone, or even show it on a smartTV. And this is just the beginning, with Node-RED you can keep pushing and pulling data from other sources and reconcile it with the local data from your plant.</p>
<p>Using Node-RED allows you to innovate how you use and visualize data from your factory floor. Maybe there is even information about the power grid or daily weather that affects production in ways you would never have thought of until you saw it visualized side-by-side with the industrial data we’ve now connected to. Various services can be used to push critical notifications to your phone, as well, so you don’t have to continually look at the UI. This is the power of the internet of things, and now, with Node-RED, you have it.</p>
https://flowfuse.com/blog/2023/05/community-news-05/Community News May 2023Your monthly update for the FlowFuse and Node-RED communities2023-05-04T00:00:00ZRob Marcer<p>Welcome to the FlowFuse newsletter for May 2023, a monthly roundup of what’s been happening with both FlowFuse and the wider Node-RED community.</p>
<!--more-->
<h2 id="upcoming-events" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/community-news-05/#upcoming-events"># </a> Upcoming events</h2>
<h3 id="ask-me-anything-about-debugging-node-red" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/community-news-05/#ask-me-anything-about-debugging-node-red"># </a> Ask Me Anything about Debugging Node-RED</h3>
<p>Our monthly Node-RED AMA session will have a special focus on debugging. Nick and Rob will lead us through some useful debug workflows to show how they approach debugging Node-RED applications. During the live coding sessions there will be opportunities for attendees to ask questions in real-time. Join us to learn from the experts on the tips and tricks for debugging Node-RED flows. <a href="https://flowfuse.com/ask-me-anything/ama-nodered-may/">Sign-up today to participate</a>.</p>
<h3 id="getting-started-with-node-red-dashboard" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/community-news-05/#getting-started-with-node-red-dashboard"># </a> Getting Started with Node-RED Dashboard</h3>
<p>How can you use Node-RED to create dashboards and interactive graphs of your data? The answer is the Node-RED Dashboard node, the most popular node in the Node-RED community. In this webinar, Rob Marcer will take you through the steps of how to get started with the Node-RED Dashboard. <a href="https://flowfuse.com/webinars/2023/getting-started-nodered-dashboard/">Register today</a>.</p>
<h2 id="from-our-blog" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/community-news-05/#from-our-blog"># </a> From our Blog</h2>
<p><a href="https://flowfuse.com/blog/2023/05/chatgpt-nodered-fcn-node/">Chat GPT in Node-RED Function Nodes</a> - Use Chat GPT to write Node-RED functions directly in the Node-RED interface.</p>
<p><a href="https://flowfuse.com/blog/2023/04/securing-node-red-in-production/">Securing Node-RED</a> - A look at how you can secure Node-RED deployments.</p>
<p><a href="https://flowfuse.com/blog/2023/04/nodered-community-health/">Node-RED Community Health</a> - Some key community metrics for the Node-RED community.</p>
<p><a href="https://flowfuse.com/blog/2023/04/hannover-messe/">FlowFuse's visit to Hannover Messe 2023</a> - Our CEO and Product Manager visited Hannover Messe in Germany; one of the largest trade shows for manufacturing.</p>
<p><a href="https://flowfuse.com/blog/2023/04/flowforge-1-6-released/">FlowFuse 1.6 Now Available</a> - FlowFuse 1.6 included support for multi-instance Node-RED within a single application as well as support for logging from remote devices.</p>
<p><a href="https://flowfuse.com/blog/2023/04/3-quick-node-red-tips-6/">Node-RED Tips - Subflows, Link Nodes, and the Range Node</a></p>
<h2 id="from-the-community" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/community-news-05/#from-the-community"># </a> From the Community</h2>
<p>Jsonata is a very useful and often underutilised tool built into Node-RED. Steve over at <a href="https://stevesnoderedguide.com/">Steve's Node-RED Guide</a> has published a great beginners guide. If you are new to Jsonata and want to learn more we recommend you <a href="https://stevesnoderedguide.com/node-red-and-jsonata-for-beginners">take a look</a>.</p>
<h3 id="custom-node-spotlight---node-red-contrib-queue-gate" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/community-news-05/#custom-node-spotlight---node-red-contrib-queue-gate"># </a> Custom Node Spotlight - node-red-contrib-queue-gate</h3>
<p><a href="https://flows.nodered.org/node/node-red-contrib-queue-gate">Queue Gate</a> is a handy custom node which allows you to control the flow of messages. You might wish to queue up all the messages in a flow and then release them all, once an hour. Maybe you want to release just one message at a time and wait until the prior message completed a section of your flow. Queue Gate makes message queuing really easy without the need to use an external queue solution.</p>
<h2 id="join-our-team" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/community-news-05/#join-our-team"># </a> Join Our Team</h2>
<p>FlowFuse is expanding our team. Check out the current openings:</p>
<ul>
<li>
<p><strong><a href="https://boards.greenhouse.io/flowfuse/jobs/4798023004">Developer Advocate - Manufacturing & Industrial Automation</a></strong></p>
</li>
<li>
<p><strong><a href="https://boards.greenhouse.io/flowfuse/jobs/4843566004">Sales Representative</a></strong></p>
</li>
</ul>
https://flowfuse.com/blog/2023/05/chatgpt-nodered-fcn-node/Chat GPT in Node-RED Function NodesNew Node-RED function with embedded ChatGPT is now open-sourced and available to use!2023-05-02T12:00:00ZJoe PavittSteve McLaughlin<p>Recently we <a href="https://www.linkedin.com/posts/flowforge_chatgpt-with-node-red-function-nodes-activity-7052725869684953088-2yOA?utm_source=share&utm_medium=member_desktop">posted a demo of ChatGPT integration in a Node-RED function node</a>
onto our social media accounts. We have now <a href="https://github.com/FlowFuse/node-red-function-gpt" target="_blank">open-sourced</a> this for all to play with, and <strong>welcome any and all contributions</strong>.</p>
<!--more-->
<h2 id="how-it-works---prompt-engineering" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/chatgpt-nodered-fcn-node/#how-it-works---prompt-engineering"># </a> How it Works - Prompt Engineering</h2>
<p>OpenAI make a collection of their <a href="https://platform.openai.com/docs/models">Generative AI models</a> available
via an API. We are wrapping OpenAI's <a href="https://www.npmjs.com/package/openai">node.js module</a>, and in particular
using the <code>openai.createChatCompletion()</code> functionality. For this API, you provide a chat history, and ChatGPT will
respond with the next entry in that conversation.</p>
<p>In order to "train" ChatGPT for our use case of populating Node-RED function nodes, we first tried a collection of prompts, defining specific
requirements for the contents, e.g. <em>"Always write Javascript"</em>, <em>"Never include the wrapping function definition"</em>,
<em>"Assume the input is always msg"</em>.</p>
<p>It turns out though, that we were over-engineering it, we were not getting reliable results and ended up
realising that ChatGPT's existing knowledge of Node-RED was sufficient such that we could use that as a prompt:</p>
<p>Here's what we settled on:</p>
<div style="position: relative">
<pre class="language-javascript"><code id="code-19" class="language-javascript"><span class="token literal-property property">messages</span><span class="token operator">:</span> <span class="token punctuation">[</span><br /> <span class="token punctuation">{</span><span class="token literal-property property">role</span><span class="token operator">:</span> <span class="token string">"system"</span><span class="token punctuation">,</span> <span class="token literal-property property">content</span><span class="token operator">:</span> <span class="token string">"always respond with content for a Node-RED function node, and don't add any commentary, always use const or let instead of var. Always return msg, unless told otherwise."</span><span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token punctuation">{</span><span class="token literal-property property">role</span><span class="token operator">:</span> <span class="token string">"user"</span><span class="token punctuation">,</span> <span class="token literal-property property">content</span><span class="token operator">:</span> prompt<span class="token punctuation">}</span><br /><span class="token punctuation">]</span><span class="token punctuation">,</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-19" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>Here we send a <code>system</code> prompt in order to setup ChatGPT, and then follow that immediately with whatever the user has typed.
From our (limited) testing, this has given us fairly reliable results.</p>
<p>Breaking this prompt down:</p>
<ul>
<li><em><strong>"Always respond with content for a Node-RED function node"</strong></em>: Ensured no surrounding <code>function () {}</code> definition and set expectations that the function would deal with a <code>msg</code> and likely <code>msg.payload</code> object.</li>
<li><em><strong>"Don't add any commentary"</strong></em>: ChatGPT likes to, well, chat. It would always return raw text justifying decisions, etc. Here, we just wanted the code.</li>
<li><em><strong>"Always use const or let instead of var"</strong></em>: This was Steve being picky.</li>
<li><em><strong>"Always return msg, unless told otherwise"</strong></em>: We found this wasn't mostly required, but occasionally it would try to return a different variable, and we'd lose context of <code>msg.payload</code>, or other data stored in <code>msg</code>. So this just made sure we had the consistency.</li>
</ul>
<p>The response from this API call is then populated into the contents of the active tab in the function node:</p>
<img width="1728" alt="Screenshot 2023-04-21 at 16 08 47" src="https://user-images.githubusercontent.com/99246719/233671631-fefa36c1-6db4-4392-a057-314c16fd91b7.png" />
<p>In order to use it yourself, you will need a <a href="https://platform.openai.com/account/api-keys">valid API Key from OpenAI</a>.</p>
<h2 id="additional-features" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/chatgpt-nodered-fcn-node/#additional-features"># </a> Additional Features</h2>
<p>This was built in about a day by Steve and Joe, and we had plenty of ideas on what we'd like to add to it. We've
<a href="https://github.com/FlowFuse/node-red-function-gpt">open-sourced</a> it, and will add these as issues to the repo, but if anyone want so take a stab at contributing - that'd be most welcome!</p>
<ul>
<li>
<p><strong>Insert at Cursor (<a href="https://github.com/FlowFuse/node-red-function-gpt/issues/11">issue</a>):</strong> Currently, the Ask GPT call will replace <em>all</em> of the content of that tab. Would be great
to have the code insert wherever the cursor last was in order to add to existing code.</p>
</li>
<li>
<p><strong>Retain Conversation History (<a href="https://github.com/FlowFuse/node-red-function-gpt/issues/12">issue</a>):</strong> Each time a new prompt is provided by the Node-RED user, we send a fresh conversation to OpenAI,
meaning that knowledge of previously asked questions are not retained.</p>
</li>
<li>
<p><strong>Client side ChatGPT Config (<a href="https://github.com/FlowFuse/node-red-function-gpt/issues/13">issue</a>):</strong> Currently, when you add a new "function-gpt" node you need to select the ChatGTP
Config node and click "Deploy" before you can ask it a question. Our ChatGPT interaction operates server-side (to
protect your API key), so Node-RED needs that in the runtime first, before a call to ChatGPT can be made. Ideally,
we'd be smarter here and pass client-side creds along with the call such that we can use any changes made by the
user at the time of the call.</p>
</li>
</ul>
https://flowfuse.com/blog/2023/05/device-agent-as-a-service/Running the FlowFuse Device Agent as a service on a Raspberry PiStep by step guide to run the device agent as a service2023-05-02T00:00:00ZRob Marcer<p>FlowFuse's device agent allows you to manage and run your Node-RED instances on
your own hardware such as a Raspberry Pi. This can be very useful where an
application you've written needs to run flows with direct access to hardware sensors.</p>
<p>In this article I'm going to explain the steps to configure our device agent to run as a service in Raspbian OS,
or any other OS that uses systemd.</p>
<!--more-->
<h2 id="why-run-the-device-agent-as-a-service%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/device-agent-as-a-service/#why-run-the-device-agent-as-a-service%3F"># </a> Why run the device agent as a service?</h2>
<p>The standard process for running FlowFuse's device agent is to start it on the
command line using the command <code>flowforge-device-agent</code>. This works fine for testing
but for long-term installations it's useful to run the device agent as a service.
Once running as a service, the device agent will continue to run even if your
device is restarted or your SSH connection to your Pi fails.</p>
<h2 id="set-up-steps" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/device-agent-as-a-service/#set-up-steps"># </a> Set up steps</h2>
<h3 id="create-the-service-file" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/device-agent-as-a-service/#create-the-service-file"># </a> Create the Service File</h3>
<p>The first step is creating the systemd unit file for your service. You can start by creating a new file in the
<code>/etc/systemd/system</code> directory with a .service file extension:</p>
<p><code>sudo nano /etc/systemd/system/flowforge-device-agent.service</code></p>
<h3 id="define-the-service" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/device-agent-as-a-service/#define-the-service"># </a> Define the Service</h3>
<p>In the service file, you'll need to define the following parameters:</p>
<ul>
<li><code>Description</code>: A brief description of what the service does.</li>
<li><code>ExecStart</code>: The command(s) to execute to start the service.</li>
<li><code>User and Group</code>: The user and group that the service runs as.</li>
<li><code>Type</code>: Whether the service is a simple or a forking type.</li>
</ul>
<p>We've created the content you'll need for this file and shared it via <a href="https://github.com/FlowFuse/device-agent/blob/main/service/flowforge-device.service">this GitHub page</a>.</p>
<p>Copy the code from that page into the nano window you created in step 1, then save and exit out of nano.</p>
<h3 id="starting-the-service-on-boot-(optional)" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/device-agent-as-a-service/#starting-the-service-on-boot-(optional)"># </a> Starting the service on boot (optional)</h3>
<p>If you want Node-RED to run when the Pi is turned on, or re-booted, you can enable the service to autostart by running the command:</p>
<p><code>sudo systemctl enable flowforge-device-agent.service</code></p>
<p>To disable the service, run the command:</p>
<p><code>sudo systemctl disable flowforge-device-agent.service</code></p>
<h3 id="using-your-new-service" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/device-agent-as-a-service/#using-your-new-service"># </a> Using your new service</h3>
<p>You can now start your service with the start command:</p>
<p><code>sudo systemctl start flowforge-device-agent</code></p>
<p>You can check the current status with the status command:</p>
<p><code>sudo systemctl status flowforge-device-agent</code></p>
<p>Finally, if you need to stop your agent you can do so with the command:</p>
<p><code>sudo systemctl stop flowforge-device-agent</code></p>
<h2 id="further-reading" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/05/device-agent-as-a-service/#further-reading"># </a> Further reading</h2>
<p>If you'd like to learn about using services via the systemctl command you can access
the help text by running <code>systemctl -h</code> from your Pi terminal.</p>
https://flowfuse.com/blog/2023/04/3-quick-node-red-tips-6/Node-RED Tips - Subflows, Link Nodes, and the Range NodeSave yourself time when working on Node-RED with these three tips.2023-04-20T12:00:00ZRob Marcer<p>There is usually more than one way to complete a given task in software, and Node-RED is no exception. In each of this series of blog posts, we are going to share three useful tips to save yourself time when working on your flows.</p>
<!--more-->
<h3 id="1.-subflows" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/04/3-quick-node-red-tips-6/#1.-subflows"># </a> 1. Subflows</h3>
<p>Subflows are a great way to reuse sections of your flows. Once you have created a subflow, it can easily be dropped into your workspace one or more times.</p>
<h4 id="why-use-subflows%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/04/3-quick-node-red-tips-6/#why-use-subflows%3F"># </a> Why use subflows?</h4>
<p>Without using a subflow, you can copy and paste a flow into each place you need to use it. This takes up quite a bit of workspace, and makes it harder to update your flow in the future as you'll have to update each copy.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/no-subflow-so_eb_1yrd-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/no-subflow-so_eb_1yrd-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Duplication of the flow" alt="Duplication of the flow" loading="lazy" decoding="async" src="https://flowfuse.com/img/no-subflow-so_eb_1yrd-650.jpeg" width="650" height="114" /></picture></p>
<p>If we instead put the flow into a subflow we'll save a lot of workspace and it will be easier to update the reused sections of the flow if we need to in the future.</p>
<h4 id="creating-a-subflow" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/04/3-quick-node-red-tips-6/#creating-a-subflow"># </a> Creating a subflow</h4>
<p>You can create a subflow using the burger menu in the top right corner of Node-RED, select Subflows, then Create Subflow. Lay out your subflow, making sure you create an input and output. You can even have more than one output if you want.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/subflow-o35EcqkRGg-648.avif 648w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/subflow-o35EcqkRGg-648.webp 648w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Contents of the subflow" alt="Contents of the subflow" loading="lazy" decoding="async" src="https://flowfuse.com/img/subflow-o35EcqkRGg-648.jpeg" width="648" height="185" /></picture></p>
<p>You can now drop the subflow into your workspace as needed, saving space and making it easier to manage changes to your flow.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/using-the-subflow-RFYw0Gcbmg-549.avif 549w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/using-the-subflow-RFYw0Gcbmg-549.webp 549w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Using the subflow to reduce duplication of flows" alt="Using the subflow to reduce duplication of flows" loading="lazy" decoding="async" src="https://flowfuse.com/img/using-the-subflow-RFYw0Gcbmg-549.jpeg" width="549" height="146" /></picture></p>
<h3 id="2.-link-nodes" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/04/3-quick-node-red-tips-6/#2.-link-nodes"># </a> 2. Link Nodes</h3>
<p>Link Nodes allow you to separate your flows into distinct sections. The wires between the link nodes are not visible until you select that part of the flow. You can also link flows on different tabs together.</p>
<p>Formatting your flows into distinct sections using link nodes can make it easier to read and update your work.</p>
<p>To use the link node, drag a link in and out node into your flow's workspace. Now draw a wire as you usually would to link to two nodes together. You should see a link between the nodes but it only shows when you have the link nodes selected.</p>
<p><picture><source type="image/gif" srcset="https://flowfuse.com/img/wiring-link-nodes-cpOBhO5AWV-532.gif 532w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Linking two link nodes together" alt="Linking two link nodes together" loading="lazy" decoding="async" src="https://flowfuse.com/img/wiring-link-nodes-cpOBhO5AWV-532.webp" width="532" height="164" /></picture></p>
<p>In this example below, the first and second flows have the same nodes and functionality. In the second image of the workspace I've split the flow into specific groups of nodes.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/flow-without-link-nodes-31s3ij8hgA-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/flow-without-link-nodes-31s3ij8hgA-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="A flow without link nodes" alt="A flow without link nodes" loading="lazy" decoding="async" src="https://flowfuse.com/img/flow-without-link-nodes-31s3ij8hgA-650.jpeg" width="650" height="130" /></picture></p>
<p>It's easier to read and understand the flow once it's split up using the link nodes and groups.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/flow-with-link-nodes-HtwYHBuz1O-606.avif 606w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/flow-with-link-nodes-HtwYHBuz1O-606.webp 606w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="The same flow as above, now split up using link nodes" alt="The same flow as above, now split up using link nodes" loading="lazy" decoding="async" src="https://flowfuse.com/img/flow-with-link-nodes-HtwYHBuz1O-606.jpeg" width="606" height="507" /></picture></p>
<h3 id="3.-range-node" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/04/3-quick-node-red-tips-6/#3.-range-node"># </a> 3. Range Node</h3>
<p>Sometimes you might need to map one numbering scale onto another. For example, where a user has selected a value between 0 and 10 but you want to use and store their response as a percentage. The Range node makes this task very easy.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/flow-using-range-a94pDcg-0n-484.avif 484w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/flow-using-range-a94pDcg-0n-484.webp 484w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Example of using the range node" alt="Example of using the range node" loading="lazy" decoding="async" src="https://flowfuse.com/img/flow-using-range-a94pDcg-0n-484.jpeg" width="484" height="153" /></picture></p>
<p>To configure the node, set it up as follows:</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/range-config-60KH-Yu6vB-487.avif 487w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/range-config-60KH-Yu6vB-487.webp 487w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Configuration of the range node" alt="Configuration of the range node" loading="lazy" decoding="async" src="https://flowfuse.com/img/range-config-60KH-Yu6vB-487.jpeg" width="487" height="332" /></picture></p>
<p>You should now see that the input values are translated to the appropriate value out of 100.</p>
<p><picture><source type="image/gif" srcset="https://flowfuse.com/img/range-demo-YJkC_wcNmy-534.gif 534w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="The range note in use" alt="The range note in use" loading="lazy" decoding="async" src="https://flowfuse.com/img/range-demo-YJkC_wcNmy-534.webp" width="534" height="164" /></picture></p>
<p>We hope you found these tips useful, if you'd like to suggest some of your own tips which you think we should share in our future blog posts please <a href="mailto:contact@flowfuse.com">get in touch</a>. You can also read some of our previous Node-RED tips using the links below.</p>
<p><a href="https://flowfuse.com/blog/2023/03/3-quick-node-red-tips-5/">Node-RED Tips - Importing, Exporting, and Grouping Flows</a><br />
<a href="https://flowfuse.com/blog/2023/03/3-quick-node-red-tips-4/">Node-RED Tips - Smooth, Catch, and Maths</a><br />
<a href="https://flowfuse.com/blog/2023/03/3-quick-node-red-tips-3/">Node-RED Tips - Exec, Filter, and Debug</a><br />
<a href="https://flowfuse.com/blog/2023/02/3-quick-node-red-tips-2/">Node-RED Tips - Deploying, Debugging, and Delaying</a><br />
<a href="https://flowfuse.com/blog/2023/02/3-quick-node-red-tips-1/">Node-RED Tips - Wiring Shortcuts</a></p>
https://flowfuse.com/blog/2023/04/hannover-messe/FlowFuse's visit to Hannover Messe 2023A recap of FlowFuse's visit to Hannover Messe2023-04-20T00:00:00ZMarian Demme<p>"Do you use Node-RED?" This simple question became our favorite conversation opener as ZJ and I attended Hannover Messe, the world's leading industrial trade fair.</p>
<!--more-->
<p>To our delight, the answer was almost always "Yes." This allowed us to dive into truly fruitful discussions with Node-RED experts, exploring the latest industry trends, connecting with potential partners, and sharing our vision for the future of Node-RED in the manufacturing sector. During our visit, we had the pleasure of engaging with several vendors, including Bosch Rexroth, Siemens, Wago, Weidmüller, RevolutionPi, and more. It was genuinely inspiring to see the widespread adoption and usage of Node-RED across the entire industry. See also our <a href="https://flowfuse.com/blog/2023/03/integration-platform-for-edge-computing/#the-standard-for-edge-computing-and-plcs">arcticle</a> about the adoption of Node-RED for PLCs and Gateways.</p>
<p>FlowFuse's innovative solutions, such as remote deployment of Node-RED instances, seamless updates, effortless rollbacks, and built-in security, are already addressing many challenges faced by Node-RED users in the industry today. The positive feedback we received at Hannover Messe has bolstered our commitment to making Node-RED more accessible and production-ready for industrial and enterprise scenarios. As we forge ahead, we are eager to collaborate with more partners, learn from industry leaders, and remain at the forefront of Node-RED development. Together, we can build a more connected, efficient, and innovative manufacturing industry. With each new booth we visited and every conversation we had, it became increasingly clear that Node-RED and FlowFuse are well on their way to becoming an integral part of the industrial landscape.</p>
https://flowfuse.com/blog/2023/04/nodered-community-health/Node-RED Community HealthNode-RED community metrics2023-04-13T00:00:00Z<p>It is often a challenge to measure the health of an open source project, like Node-RED. Individuals can download and use Node-RED without any indication or feedback to their ongoing satisfaction or usage. However, it is still interesting to look at a variety of metrics to understand the size of the Node-RED community.</p>
<!--more-->
<p><strong>GitHub Stars</strong></p>
<p>A popular method for demonstrating popularity of an open source project are GitHub stars. Node-RED has over 16K stars and when <a href="https://synodus.com/blog/low-code/open-source-low-code-platforms/">compared to other low-code platforms</a> on GitHub has a strong showing. FWIW, GitHub stars are open to gaming so it is not a great long-term indicator of community health and engagement.</p>
<p><strong>Node-RED Library</strong></p>
<p>At the core of the Node-RED community is the library of nodes and flows that have been developed by community members. The current library has over <a href="https://flows.nodered.org/search?type=node&sort=downloads">4300 nodes available</a>, some of the more popular nodes are downloaded more than 10K times per week. The large library of community nodes supports a wide range of protocols, data sources, data stores, and much more. This makes Node-RED more relevant and useful to many more potential users.</p>
<p><strong>Node-RED Website Traffic</strong></p>
<p>In the last year, Node-RED has had over 1.9 million unique visitors to the <a href="https://nodered.org/">nodered.org</a> website, over 160K on a monthly basis. The most popular pages, after the home page, are the getting started pages. This demonstrates a strong interest in learning more about how to use Node-RED.</p>
<p><strong>NPM Downloads & Docker Pull Requests</strong></p>
<p>Node-RED is installed by lots of people using Docker and NPM. The project averages over 500K/month pull requests from <a href="https://hub.docker.com/r/nodered/node-red">Docker Hub</a> and 100K/month pull requests on <a href="https://npm-stat.com/charts.html?package=node-red&from=2017-03-22&to=2023-03-22">NPM</a>.</p>
<p><strong>Node-RED Forums</strong></p>
<p>The <a href="https://discourse.nodered.org/">Node-RED community forum</a> is the go to place to get community support. It is a very popular community with over 900K page views per month. The amazing thing is that a very large percentage of questions receive replies from other community members. A great sign of a healthy community.</p>
<p>Overall, the Node-RED community is large, healthy and engaged.</p>
https://flowfuse.com/blog/2023/04/flowforge-1-6-released/FlowFuse v1.6 Now AvailableFlowFuse Now Supports Multi-Instance Node-RED for Complex Application Development2023-04-13T00:00:00Z<p>The new FlowFuse 1.6 adds new support for multi-instance Node-RED within a single application and support for logging from remote devices.</p>
<!--more-->
<h2 id="flowfuse-applications-can-now-support-multi-instance-node-red" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/04/flowforge-1-6-released/#flowfuse-applications-can-now-support-multi-instance-node-red"># </a> FlowFuse Applications Can Now Support Multi-Instance Node-RED</h2>
<p>FlowFuse 1.6 expands the scope of applications to now allow for multiple instances of Node-RED. For complex Node-RED applications, it is common to have different flows interacting with other flows or flows deployed to different target environments. The ability to associate all these different flows with a single application makes it easier for the development, test and deployment of these types of complex applications.</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/OHChdWeRI9Q" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
<h2 id="access-node-red-logs-from-remote-devices" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/04/flowforge-1-6-released/#access-node-red-logs-from-remote-devices"># </a> Access Node-RED logs from remote devices</h2>
<p>FlowFuse makes it easy to deploy Node-RED out to remote devices. However, once Node-RED has been deployed to the remote device it is often difficult to troubleshoot or debug. Now with FlowFuse 1.6, you can get access to the Node-RED logs from remote devices. This makes it much easier to understand and debug the behavior of a remote device.</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/yW1zxwiCmto" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
<h2 id="other-improvements" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/04/flowforge-1-6-released/#other-improvements"># </a> Other Improvements</h2>
<p>Update email address verification <a href="https://github.com/FlowFuse/flowfuse/issues/813">#813</a></p>
<p>Reminder email about trial doesn't include a link to FF Cloud <a href="https://github.com/FlowFuse/flowfuse/issues/1815">#1815</a></p>
<p>Sign-up coupons improvement <a href="https://github.com/FlowFuse/flowfuse/issues/1788">#1788</a></p>
<p>New FF_Instance_* envvars inline with new terminology <a href="https://github.com/FlowFuse/flowfuse/issues/1844">#1844</a></p>
<p>Deprecate FF_PROJECT_* envvars <a href="https://github.com/FlowFuse/flowfuse/issues/1844">#1844</a></p>
<p>Integrate with PostHog events <a href="https://github.com/FlowFuse/flowfuse/pull/1922">#1922</a></p>
<p>Introduce search bar to docs/handbook <a href="https://github.com/FlowFuse/website/pull/620">#620</a></p>
<h2 id="bug-fixes" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/04/flowforge-1-6-released/#bug-fixes"># </a> Bug Fixes</h2>
<p>Deleting instances from the instance list fails <a href="https://github.com/FlowFuse/flowfuse/issues/1859">#1859</a></p>
<p>Removing old projects with missing subscriptions fails <a href="https://github.com/FlowFuse/flowfuse/issues/1837">#1837</a></p>
<p>Changing to a team as a member shows unauthorized error <a href="https://github.com/FlowFuse/flowfuse/issues/1845">#1845</a></p>
<p>Application Overview: “Open Editor” shouldn’t show (or should be disabled) if in “Starting” state <a href="https://github.com/FlowFuse/flowfuse/issues/1931">#1931</a></p>
<h2 id="try-it-out" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/04/flowforge-1-6-released/#try-it-out"># </a> Try it out</h2>
<p>We're confident you can have self managed FlowFuse running locally in under 30 minutes.
You can install our <a href="https://flowfuse.com/docs/install/local/">local build</a>, use <a href="https://flowfuse.com/docs/install/docker/">Docker</a>, or <a href="https://flowfuse.com/docs/install/kubernetes/">Kubernetes</a>.</p>
<p>If you'd rather use our hosted offering: <a href="https://app.flowfuse.com/account/create">Get started for free</a> on FlowFuse Cloud.</p>
<h2 id="upgrading-flowfuse" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/04/flowforge-1-6-released/#upgrading-flowfuse"># </a> Upgrading FlowFuse</h2>
<p><a href="https://app.flowfuse.com/">FlowFuse Cloud</a> is already running 1.6.</p>
<p>If you installed a previous version of FlowFuse and want to upgrade, our documentation provides a
guide for <a href="https://flowfuse.com/docs/upgrade/">upgrading your FlowFuse instance</a>.</p>
<h2 id="getting-help" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/04/flowforge-1-6-released/#getting-help"># </a> Getting help</h2>
<p>Please check FlowFuse's <a href="https://flowfuse.com/docs/">documentation</a> as the answers to many questions are covered there.</p>
<p>If you hit any problems with the platform please raise an <a href="https://github.com/FlowFuse/flowfuse/issues">issue on GitHub</a>.
That's also a great place to send us any feedback or feature requests.</p>
<p>You can also get help on <a href="https://discourse.nodered.org/">the Node-RED forums</a></p>
<p>As well as in the <a href="https://github.com/FlowFuse/flowfuse/discussions">forum within our Github project</a></p>
<p>Chat with us on the <code>#flowfuse</code> channel on the <a href="https://nodered.org/slack">Node-RED Slack workspace</a></p>
<p>You can raise a support ticket by emailing <a href="mailto:support@flowfuse.com">support@flowfuse.com</a></p>
<p>We've also added a live chat widget to our website, you can access it using the icon on the bottom right corner of our website. We'd love to hear from you.</p>
https://flowfuse.com/blog/2023/04/securing-node-red-in-production/Securing Node-REDIn this blog post, I will cover some of the key steps to securing Node-RED projects.2023-04-05T00:00:00ZRob Marcer<p>Node-RED is very easy to get up and running. Whether you run it locally, in Docker, on a Raspberry Pi, or on a service such as FlowFuse Cloud you can have a project up and running in minutes.</p>
<!--more-->
<p>One thing that can get overlooked is the security of Node-RED. From personal experience, the first few times I installed Node-RED I was more focussed on the possibilities of what I could do with this new tool than I was keeping my projects secure.</p>
<p>In this article I’m going to look at some easy ways to make your Node-RED project more secure, even when first learning about it in a hobby environment.</p>
<h2 id="protecting-access-from-your-lan-to-node-red" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/04/securing-node-red-in-production/#protecting-access-from-your-lan-to-node-red"># </a> Protecting access from your LAN to Node-RED</h2>
<p>Once you have an instance of Node-RED running it can usually be accessed from anywhere on your LAN (local area network) by pointing a web browser to the relevant IP address and port.</p>
<p><code>http://192.168.0.3:1880</code></p>
<p>With a URL similar to the one above, depending on your specific network and Node-RED configuration, anyone on your LAN can view but more importantly edit your flows. This can be really useful when you are first learning about Node-RED but it’s always a good idea to get into the habit of locking down access to the editor, even if you trust everyone who can access your LAN.</p>
<p>One of the easiest ways to protect your flows is to add a username and password to your Node-RED instance.</p>
<p>The first step is to find your Node-RED settings.js file. It's not always in the same place but on a default Debian Linux installation it can be found in this directory.</p>
<p><code>cd ~/.node-red</code></p>
<p>If you list that directory you should now see something like this:</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/ls-VheSi69Vkw-460.avif 460w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/ls-VheSi69Vkw-460.webp 460w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Where your settings.js should show" alt="Where your settings file should show" loading="lazy" decoding="async" src="https://flowfuse.com/img/ls-VheSi69Vkw-460.jpeg" width="460" height="83" /></picture></p>
<p>We now need to edit settings.js, I'm going to use my favourite text editor, <a href="https://www.nano-editor.org/">Nano</a> to do that.</p>
<p><code>nano settings.js</code></p>
<p>We now need to find and edit the following section of the settings file:</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/without-password-de1eEHQJqJ-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/without-password-de1eEHQJqJ-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="The settings file before being edited" alt="The settings file before being edited" loading="lazy" decoding="async" src="https://flowfuse.com/img/without-password-de1eEHQJqJ-650.jpeg" width="650" height="158" /></picture></p>
<p>For this example, I'm going to add a password and uncomment the relevant section of the settings file, you could also change the username for additional security.</p>
<p>To create the password we'll need to use a command line tool which is included in Node-RED. Open a second terminal then run this command:</p>
<p><code>node-red admin hash-pw</code></p>
<p>Put in your new password, I'll use the password 'flowforge' in this example. The tool returns your password in a hashed format:</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/password-gCQL2VRvN3-582.avif 582w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/password-gCQL2VRvN3-582.webp 582w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="The Node-RED tool outputs the hashed password" alt="The Node-RED tool outputs the hashed password" loading="lazy" decoding="async" src="https://flowfuse.com/img/password-gCQL2VRvN3-582.jpeg" width="582" height="44" /></picture></p>
<p>We can now return to the other terminal window, uncomment the section then paste in the new password, this is how it looks for me:</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/with-password-d89DtLr4sL-635.avif 635w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/with-password-d89DtLr4sL-635.webp 635w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="The settings file with the relevant section uncommented and the password set" alt="The settings file with the relevant section uncommented and the password set" loading="lazy" decoding="async" src="https://flowfuse.com/img/with-password-d89DtLr4sL-635.jpeg" width="635" height="170" /></picture></p>
<p>We can now save and exit out of the settings file.</p>
<p>The last step is to restart Node-RED, I'm using Debian so the command is:</p>
<p><code>node-red-restart</code></p>
<p>Now, when we try to access Node-RED I will need to provide a username and password.</p>
<p><picture><source type="image/gif" srcset="https://flowfuse.com/img/login-3GmZ2r8Qmg-650.gif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Using the username and password to login to Node-RED" alt="Using the username and password to login to Node-RED" loading="lazy" decoding="async" src="https://flowfuse.com/img/login-3GmZ2r8Qmg-650.webp" width="650" height="437" /></picture></p>
<p>You might also want to consider turning off the editor interface once you are happy with your flows. This can make it a little harder to make changes to your project but it also gives you peace of mind that nobody has accidentally or deliberately changed your flows. You can turn off the editor interface as follows.</p>
<p>Edit your settings.js file as explained above, look for the following section:</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/editor-on-M3f-n-l62D-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/editor-on-M3f-n-l62D-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="The setting file before turning off the editor" alt="The setting file before turning off the editor" loading="lazy" decoding="async" src="https://flowfuse.com/img/editor-on-M3f-n-l62D-650.jpeg" width="650" height="77" /></picture></p>
<p>All you need to do is uncomment the bottom line then change the value from false to true, once done it should look something like this:</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/editor-off-0USfc9mOKz-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/editor-off-0USfc9mOKz-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="The setting file after turning off the editor" alt="The setting file after turning off the editor" loading="lazy" decoding="async" src="https://flowfuse.com/img/editor-off-0USfc9mOKz-650.jpeg" width="650" height="85" /></picture></p>
<p>Now restart Node-RED as covered above, then try accessing your Node-RED instance again. You will no longer be able to edit or view your flows.</p>
<p>Using these two features, we now have much better control over who can access the design interface for Node-RED.</p>
<h2 id="traffic-to-your-node-red-instance-is-unencrypted" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/04/securing-node-red-in-production/#traffic-to-your-node-red-instance-is-unencrypted"># </a> Traffic to your Node-RED instance is unencrypted</h2>
<p>Hopefully, we all know the importance of encrypting your connections between devices to stop people intercepting your traffic. This isn't a huge concern when working on your home LAN but what if you want to access your Node-RED instance from a remote location?</p>
<p>There are two obvious options, HTTPS, and a VPN (Virtual Private Network).</p>
<p>We could setup your Node-RED traffic to run over HTTPS, this solution ensures that all traffic to and from your Node-RED is encrypted. The downside to this approach is it's quite complex to set up. We will need to have a domain name, open up ports on our LAN's firewall, use a HTTPS certificate provider and then make sure we remember to renew the certificates as needed. It's doable if you are comfortable with those concepts (I covered how to do this as part of my blog <a href="https://flowfuse.com/blog/2022/12/flowforge-gcp-https-set-up/">hosting FlowFuse on Google Cloud</a>) but there is an easier way to get started, using a VPN.</p>
<p>A VPN provides a lot of security advantages depending on which you are using and how it is configured. To secure my traffic I'm going to use a great service call <a href="https://tailscale.com/">Tailscale</a> which is free for personal projects.</p>
<p>I'm going to install Tailscale on the Raspberry Pi I'm running Node-RED on as well as any other devices I want to access my project from. Once that's done I can access Node-RED from anywhere with internet access but more importantly the traffic to and from my devices is also encrypted.</p>
<p>Before we start, it's important to remember that a VPN is only as secure as the company who runs it. You should always consider if you trust the VPN provider as they could potentially access your devices. I trust Tailscale but please do your own research before using a VPN provider.</p>
<p>The first step we need to take is creating a Tailscale account, <a href="https://login.tailscale.com/start">you can sign up for free here</a>. We next need to add our devices to our VPN using their software, I'm installing Tailscale on my Apple laptop, Google phone as well as the Raspberry Pi I'm running Node-RED on.</p>
<p>The install process is really easy, even on the Pi running Raspbian the steps you need to take are well explained in the <a href="https://tailscale.com/download/linux/debian-bullseye">Tailscale docs</a>.</p>
<p>For the Pi, these are the commands we need to run.</p>
<ol>
<li>Add Tailscale to the Apt package manager.</li>
</ol>
<p><code>curl -fsSL https://pkgs.tailscale.com/stable/debian/bullseye.noarmor.gpg | sudo tee /usr/share/keyrings/tailscale-archive-keyring.gpg >/dev/null</code></p>
<p><code>curl -fsSL https://pkgs.tailscale.com/stable/debian/bullseye.tailscale-keyring.list | sudo tee /etc/apt/sources.list.d/tailscale.list</code></p>
<p><code>sudo apt-get update</code></p>
<ol start="2">
<li>Install Tailscale</li>
</ol>
<p><code>sudo apt-get install tailscale</code></p>
<ol start="3">
<li>Start Tailscale and connect your device</li>
</ol>
<p><code>sudo tailscale up</code></p>
<p>After running the last command, we need to follow the on screen prompts to link our devices to your VPN.</p>
<p>One last thing which you might want to consider doing, every few months you will need to reconnect your devices to your VPN, if you are only going to be accessing your Node-RED device over the VPN you should consider <a href="https://tailscale.com/kb/1028/key-expiry/">disabling your Tailscale key expiry</a>.</p>
<p>OK, now we've got our devices all connected you should see something like this in the Tailscale dashboard.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/tailscale-gWgiIEvXOI-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/tailscale-gWgiIEvXOI-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Tailscale dashboard showing my three devices" alt="Tailscale dashboard showing my three devices" loading="lazy" decoding="async" src="https://flowfuse.com/img/tailscale-gWgiIEvXOI-650.jpeg" width="650" height="260" /></picture></p>
<p>I can now access Node-RED on my Pi from my laptop and phone by pointing a browser to the correct IP address (as shown in the image above) with the port for Node-RED:</p>
<p><code>http://100.71.28.60:1880</code></p>
<p>I’ve now secured all traffic between my devices and Node-RED project, I can access Node-RED from anywhere on the internet.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/nr-via-vpn-a-FM4nwfLO-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/nr-via-vpn-a-FM4nwfLO-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Accessing Node-RED via the VPN" alt="Accessing Node-RED via the VPN" loading="lazy" decoding="async" src="https://flowfuse.com/img/nr-via-vpn-a-FM4nwfLO-650.jpeg" width="650" height="272" /></picture></p>
<p>If you follow these steps you should be on the right path to running a more secure Node-RED instance. There is a lot more you can do and I recommend you read the <a href="https://nodered.org/docs/user-guide/runtime/securing-node-red">relevant docs on the Node-RED</a> website to gain some more ideas.</p>
<h2 id="what-about-hosting-node-red-on-a-cloud-solution-such-as-flowfuse%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/04/securing-node-red-in-production/#what-about-hosting-node-red-on-a-cloud-solution-such-as-flowfuse%3F"># </a> What about hosting Node-RED on a cloud solution such as FlowFuse?</h2>
<p>In this article, I've focussed on hosting Node-RED on a Pi on your own LAN but if you use FlowFuse Cloud to host Node-RED the solutions discussed above are either ready out of the box or are not needed.</p>
<p>By default, the editor for Node-RED is protected using your FlowFuse user credentials. You can also use SSO to further protect your user accounts and give access to Node-RED to your team members.</p>
<p>All traffic to FlowFuse and your Node-RED instances is protected by HTTPS. FlowFuse has set up the domain name and manages the certificates so you can spend time on your flows rather than configuring security.</p>
<p>FlowFuse has a <a href="https://app.flowfuse.com/account/create">free trial</a> if you'd like to see how we've made secure hosting of Node-RED easy.</p>
<h2 id="conclusion" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/04/securing-node-red-in-production/#conclusion"># </a> Conclusion</h2>
<p>How ever you host Node-RED, it's a great idea to get into good security practices as early as possible to ensure that no unsecured Node-RED instances are exposed to the internet. I hope some of the tips above help you get started down the path to creating more secure Node-RED projects.</p>
https://flowfuse.com/blog/2023/04/community-news-04/Community News April 2023Your monthly update for the FlowFuse and Node-RED communities2023-04-05T00:00:00Z<p>Welcome to the FlowFuse newsletter for April 2023, a monthly roundup of what’s been happening with both FlowFuse and the wider Node-RED community.</p>
<!--more-->
<h2 id="upcoming-events" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/04/community-news-04/#upcoming-events"># </a> Upcoming events</h2>
<h3 id="node-red-ask-me-anything" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/04/community-news-04/#node-red-ask-me-anything"># </a> Node-RED Ask Me Anything</h3>
<p>Back by popular demand, FlowFuse is hosting a monthly Node-RED Ask Me Anything session on April 13th. This is a great opportunity to ask Nick O’Leary, co-creator of Node-RED & FlowFuse CTO, and Rob Marcer, Node-RED FlowFuse Developer Educator your questions about Node-RED. <a href="https://flowfuse.com/ask-me-anything/ama-nodered-april/">Sign-up today to participate</a>.</p>
<h3 id="connect%2C-integrate%2C-visual-industrial-production-metrics-with-node-red" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/04/community-news-04/#connect%2C-integrate%2C-visual-industrial-production-metrics-with-node-red"># </a> Connect, Integrate, Visual Industrial Production Metrics with Node-RED</h3>
<p>Join Steve McLaughlin from FlowFuse as he showcases how easy it is to use Node-RED to visualize popular production metrics using Node-RED. <a href="https://flowfuse.com/webinars/2023/industrial-data-node-red/">Register today</a>.</p>
<h2 id="from-our-blog" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/04/community-news-04/#from-our-blog"># </a> From our Blog</h2>
<p><a href="https://flowfuse.com/blog/2023/03/comparing-node-red-dashboards/">Comparing Node-RED Dashboards Solutions</a> - A popular article comparing Node-RED Dashboard, uibuilder and FlexDash.</p>
<p><a href="https://flowfuse.com/blog/2023/03/ibmcloud-starter-removed/">IBM Cloud removes Node-RED starter application</a> - IBM has discontinued their Node-RED Starter Application, discover how to migrate to FlowFuse.</p>
<p><a href="https://flowfuse.com/blog/2023/03/why-should-you-use-node-red-function-nodes/">The benefits and drawbacks of using Node-RED function nodes</a> - Node-RED function nodes provide a great deal of flexibility in Node-RED. Discover the benefits and drawbacks of using them.</p>
<p><a href="https://flowfuse.com/blog/2023/03/flowforge-1-5-0-released/">FlowFuse 15. Now Available</a> - FlowFuse 1.5 included updates to the UI and architecture to allow for future features.</p>
<p>Node-RED Quick Tips - Rob Marcer, FlowFuse Developer Educator has a weekly series of Node-RED hints and tips</p>
<ul>
<li><a href="https://flowfuse.com/blog/2023/03/3-quick-node-red-tips-5/">Node-RED Tips - Importing, Exporting, and Grouping Flows</a></li>
<li><a href="https://flowfuse.com/blog/2023/03/3-quick-node-red-tips-4/">Node-RED Tips - Smooth, Catch, and Math</a></li>
</ul>
<h2 id="from-the-community" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/04/community-news-04/#from-the-community"># </a> From the Community</h2>
<h3 id="quantum-for-node-red" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/04/community-news-04/#quantum-for-node-red"># </a> Quantum for Node-RED</h3>
<p>Discover how you can incorporate <a href="https://theailaboratory.wordpress.com/2023/03/24/quantum-for-everyone/">quantum technologies</a> into your Node-RED flows.</p>
<h3 id="image-recognition-within-node-red" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/04/community-news-04/#image-recognition-within-node-red"># </a> Image recognition within Node-RED</h3>
<p>Kazuhito Yokoi, a researcher at Hitachi, has published an <a href="https://kazuhitoyokoi.medium.com/sharing-node-red-flow-of-image-recognition-application-on-github-4d667cdea9f7">interesting article</a> detailing how to incorporate TensorFlow into a Node-RED application to do image recognition.</p>
<h3 id="custom-node-spotlight---node-red-contrib-web-worldmap" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/04/community-news-04/#custom-node-spotlight---node-red-contrib-web-worldmap"># </a> Custom Node Spotlight - node-red-contrib-web-worldmap</h3>
<p>If you would like to include a map in your next project Worldmap is a really good place to start. You can pass coordinates in to set the map to a location or you can use the built in search tool to find a location. As a user manipulates the map a stream of updated coordinates can be passed back to your flows to trigger additional actions. It's a really useful tool, take a <a href="https://flows.nodered.org/node/node-red-contrib-web-worldmap">look here</a>.</p>
<h2 id="join-our-team" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/04/community-news-04/#join-our-team"># </a> Join Our Team</h2>
<p>FlowFuse is expanding our team. Check out the current openings:</p>
<ul>
<li><strong><a href="https://boards.greenhouse.io/flowfuse/jobs/4798023004">Developer Advocate - Manufacturing & Industrial Automation</a></strong></li>
</ul>
https://flowfuse.com/blog/2023/03/ibmcloud-starter-removed/IBM Cloud removes Node-RED starter applicationGet up and running with a Starter Application for Node-RED with FlowFuse or migrate your existing flows from IBM Cloud2023-03-29T12:00:00ZJoe Pavitt<p>IBM Cloud has <a href="https://www.ibm.com/cloud/blog/announcements/deprecation-of-ibm-cloud-starter-kits">recently announced</a> that they will no longer be providing their Cloud App Service Starter Kits, including the <a href="https://developer.ibm.com/tutorials/how-to-create-a-node-red-starter-application/">Node-RED Starter Application</a>.</p>
<!--more-->
<h2 id="node-red-starter-application" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/ibmcloud-starter-removed/#node-red-starter-application"># </a> Node-RED Starter Application</h2>
<p>If you're looking for an alternative place to get started with Node-RED then FlowFuse, founded by Node-RED co-creator Nick O'Leary, are here to help you with Cloud-hosted Node-RED as well as infrastructure and tooling to scale your Node-RED instances in production.</p>
<p>As an ex-IBM Employee myself, over the years, I've been very dependant upon the Node-RED Starter Application in IBM Cloud. I'd used it dozens of times with clients to showcase the value of Node-RED and how easy it is to spin up integrations between hardware devices, APIs and online services.</p>
<p>If you're now looking for somewhere to rely on in order to easily spin up new instance of Node-RED, then FlowFuse is the obvious answer. If you're completely new for Node-RED too, we can also help you there with our <a href="https://flowfuse.com/blog/2023/01/getting-started-with-node-red/">Getting Started</a> guide.</p>
<p>You can sign up for a <a href="https://app.flowfuse.com/account/create">free FlowFuse Cloud Account</a> where you'll be given one small Node-RED instance for free, for your first month.</p>
<h2 id="integrations" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/ibmcloud-starter-removed/#integrations"># </a> Integrations</h2>
<p>If you've seen the excellent <a href="https://developer.ibm.com/tutorials/how-to-create-a-node-red-starter-application/">"Create a Node-RED starter application"</a> article on IBM Developer, you'll probably be looking to connect up to a Cloudant Instance, or other IBM Cloud Services. Don't worry. All of that is still available through Node-RED on FlowFuse.</p>
<p>You can install the relevant nodes in one of two places:</p>
<ol>
<li><strong>Node-RED Palette Manager:</strong> Click "Menu > Manage Palette > Install". The menu is available via the icon in the top-right of your running Node-RED Instance)</li>
</ol>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/nr-manage-palette-cloudant-Tc-yCYJBZ1-650.avif 650w, https://flowfuse.com/img/nr-manage-palette-cloudant-Tc-yCYJBZ1-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/nr-manage-palette-cloudant-Tc-yCYJBZ1-650.webp 650w, https://flowfuse.com/img/nr-manage-palette-cloudant-Tc-yCYJBZ1-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/nr-manage-palette-cloudant-Tc-yCYJBZ1-650.jpeg 650w, https://flowfuse.com/img/nr-manage-palette-cloudant-Tc-yCYJBZ1-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Screenshot of Node-RED's Manage Palette menu" alt="Screenshot of Node-RED's Manage Palette menu" loading="lazy" decoding="async" src="https://flowfuse.com/img/nr-manage-palette-cloudant-Tc-yCYJBZ1-650.jpeg" width="1300" height="753" /></picture></p>
<ol start="2">
<li><strong>FlowFuse Instance Settings:</strong> For a given Instance in FlowFuse, click "Settings > Palette". You can then define the npm module name and versions explicitely in the "Installed Modules" section</li>
</ol>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/ff-installed-modules-0p01ZkDzWv-650.avif 650w, https://flowfuse.com/img/ff-installed-modules-0p01ZkDzWv-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/ff-installed-modules-0p01ZkDzWv-650.webp 650w, https://flowfuse.com/img/ff-installed-modules-0p01ZkDzWv-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/ff-installed-modules-0p01ZkDzWv-650.jpeg 650w, https://flowfuse.com/img/ff-installed-modules-0p01ZkDzWv-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Screenshot of FlowFuse's 'Installed Modules' option in Instance > Settings > Palette" alt="Screenshot of FlowFuse's "Installed Modules" option in Instance > Settings > Palette" loading="lazy" decoding="async" src="https://flowfuse.com/img/ff-installed-modules-0p01ZkDzWv-650.jpeg" width="1300" height="753" /></picture></p>
<p>It's also easy to setup <a href="https://flowfuse.com/blog/2023/01/environment-variables-in-node-red/">Environment Variables</a> for Node-RED in FlowFuse for when you integrate with external services like APIs too.</p>
<h2 id="security" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/ibmcloud-starter-removed/#security"># </a> Security</h2>
<p>As with IBM Cloud, FlowFuse makes it very easy to secure your Node-RED Applications. <a href="https://flowfuse.com/docs/user/instance-settings/#security">FlowFuse offers three tiers of security</a> options on your Node-RED Instances to secure any exposed HTTP routes on your Node-RED instance, e.g. REST API endpoints or Node-RED Dashboard.</p>
<ul>
<li><strong>None</strong>: Anyone will be able to access the exposed routes.</li>
<li><strong>Basic Auth</strong>: Setup a single, dedicated username and password combination that is required in order to access the routes.</li>
<li><strong>FlowFuse Credentials</strong>: Visitors can use their FlowFuse username/password in order to access the endpoints. This also includes SSO if you have that configured for your FlowFoerge Team.</li>
</ul>
<h2 id="migrating-existing-instances" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/ibmcloud-starter-removed/#migrating-existing-instances"># </a> Migrating Existing Instances</h2>
<p>If you're looking to move your Node-RED applications from IBM Cloud, then you can do so through one of two options:</p>
<h3 id="node-red-tools-plugin" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/ibmcloud-starter-removed/#node-red-tools-plugin"># </a> Node-RED Tools Plugin</h3>
<p>You can use our Node-RED Tools plugin to migrate your flows and credentials over to FlowFuse. You can read the details in our <a href="https://flowfuse.com/docs/migration/introduction/">Migration Guide</a>, which also includes instructions on how to export your environment variables too.</p>
<h3 id="manual-import" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/ibmcloud-starter-removed/#manual-import"># </a> Manual Import</h3>
<p>This will only enable you to import your Flows, not the associated credentials.</p>
<ol>
<li>Export your existing <code>flows.json</code> from your IBM Cloud-hosted Node-RED instance by choosing "Export > All Flows > Download" within Node-RED</li>
<li>Create a new Application on FlowFuse</li>
<li>Once created, click the Node-RED instance that has been generated within your Application</li>
<li>Click "Settings"</li>
<li>Scroll down and select the "Import Instance" option</li>
<li>Choose your <code>flows.json</code> file that you downloaded earlier.</li>
</ol>
<p><em>If you have any questions about the above, or more generally about Node-RED or FlowFuse, then please do reach out and <a href="https://flowfuse.com/contact-us">get in touch</a>.</em></p>
https://flowfuse.com/blog/2023/03/3-quick-node-red-tips-5/Node-RED Tips - Importing, Exporting, and Grouping FlowsSave yourself time when working on Node-RED with these three tips.2023-03-27T12:00:00ZRob Marcer<p>There is usually more than one way to complete a given task in software, and Node-RED is no exception. In each of this series of blog posts, we are going to share three useful tips to save yourself time when working on your flows.</p>
<!--more-->
<h3 id="1.-copy-and-share-your-flows-using-export-and-import" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/3-quick-node-red-tips-5/#1.-copy-and-share-your-flows-using-export-and-import"># </a> 1. Copy and share your flows using Export and Import</h3>
<p>Node-RED provides both import and export features that allow you to save your flows and settings as compressed JSON files. You can use these features to easily move your flows between multiple Node-RED instances or to back up your work.</p>
<p>To import a flow, follow these steps:</p>
<ol>
<li>Click on the three horizontal lines in the upper right corner of the Node-RED editor and click on "Import".</li>
<li>Select the JSON file that contains the flow you want to import.</li>
<li>Click on "Import" and the flow will be imported into the current instance of Node-RED.</li>
</ol>
<p>To export a flow, follow these steps:</p>
<ol>
<li>Click on the three horizontal lines in the upper right corner of the Node-RED editor and click on "Export".</li>
<li>Select the type of export you want to perform - this can be either the "Clipboard" or "File".</li>
<li>If you chose "File" you will be prompted to save a compressed JSON file to your computer; if you chose "Clipboard" the flow JSON will be copied to your clipboard.</li>
<li>Use the exported file or clipboard content to import into a different instance of Node-RED.</li>
</ol>
<p><picture><source type="image/gif" srcset="https://flowfuse.com/img/import-export-0NdC7AzIu7-650.gif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Import and export your flows" alt="Import and export your flows" loading="lazy" decoding="async" src="https://flowfuse.com/img/import-export-0NdC7AzIu7-650.webp" width="650" height="315" /></picture></p>
<p>Keep in mind that some nodes or flows may require additional setup or node installation on the Node-RED instance you import your flow to.</p>
<h3 id="2.-import-helpful-example-flows-provided-with-custom-nodes" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/3-quick-node-red-tips-5/#2.-import-helpful-example-flows-provided-with-custom-nodes"># </a> 2. Import helpful example flows provided with custom nodes</h3>
<p>In Node-RED, custom nodes can include examples that provide users with a starting point for using the node. These examples can help users understand how a node works and how it can be integrated into their flows.</p>
<p>To use example flows in custom nodes, follow these steps:</p>
<ol>
<li>Open the Node-RED editor and drag the custom node you want to use into your flow.</li>
<li>Double-click on the node to open its configuration panel.</li>
<li>Look for an "Examples" menu or button within the node configuration panel. The name and location of the Examples button can vary depending on the node.</li>
<li>Click on the "Examples" button to bring up a list of example flows included with the node.</li>
<li>Select the example flow you want to use and click on "Import" to add the example flow to your Node-RED workspace.</li>
</ol>
<p>Once the example flow has been added to your workspace, you can modify it to fit your specific needs.</p>
<p><picture><source type="image/gif" srcset="https://flowfuse.com/img/example-lX-HGizzlx-650.gif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Using the example flow included in the moment node" alt="Using the example flow included in the moment node" loading="lazy" decoding="async" src="https://flowfuse.com/img/example-lX-HGizzlx-650.webp" width="650" height="315" /></picture></p>
<p>It's important to note that while custom node examples can be a useful starting point, they may not always work seamlessly with your other flows or nodes. Be sure to thoroughly test any custom node examples before incorporating them into a production environment.</p>
<h3 id="3.-group-nodes-together-to-make-your-flows-easier-to-read" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/3-quick-node-red-tips-5/#3.-group-nodes-together-to-make-your-flows-easier-to-read"># </a> 3. Group nodes together to make your flows easier to read</h3>
<p>The group feature in Node-RED allows users to visually group nodes together within the workspace. This feature offers several benefits:</p>
<ol>
<li>
<p>Improved organisation: The group feature allows you to group related nodes visually, which can make your flow easier to understand and navigate. This can be particularly helpful for larger, more complex flows.</p>
</li>
<li>
<p>Simplified editing: When you group nodes together, you can edit or move them as a single unit, rather than individually. This can save time and reduce the chance of errors.</p>
</li>
<li>
<p>Easier sharing: When you share your flow with others, the group feature allows you to package related nodes together, making it easier for others to understand and use your flow.</p>
</li>
<li>
<p>Reduced clutter: Grouping nodes can help reduce the visual clutter in your workspace, making it easier to focus on key aspects of your flow.</p>
</li>
</ol>
<p><picture><source type="image/gif" srcset="https://flowfuse.com/img/groups-edGmydKG4z-650.gif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Grouping your nodes to make them easier to read" alt="Grouping your nodes to make them easier to read" loading="lazy" decoding="async" src="https://flowfuse.com/img/groups-edGmydKG4z-650.webp" width="650" height="315" /></picture></p>
<p>Overall, the group feature in Node-RED is a valuable tool that can help users better organise, edit, and share their flows.</p>
<p>We hope you found these tips useful, if you'd like to suggest some of your own tips which you think we should share in our future blog posts please <a href="mailto:contact@flowfuse.com">get in touch</a>.</p>
<p>You can read our previous Node-RED tips here.</p>
<p><a href="https://flowfuse.com/blog/2023/03/3-quick-node-red-tips-4/">Node-RED Tips - Smooth, Catch, and Math</a><br />
<a href="https://flowfuse.com/blog/2023/03/3-quick-node-red-tips-3/">Node-RED Tips - Exec, Filter, and Debug</a><br />
<a href="https://flowfuse.com/blog/2023/02/3-quick-node-red-tips-2/">Node-RED Tips - Deploying, Debugging, and Delaying</a><br />
<a href="https://flowfuse.com/blog/2023/02/3-quick-node-red-tips-1/">Node-RED Tips - Wiring Shortcuts
</a></p>
https://flowfuse.com/blog/2023/03/why-should-you-use-node-red-function-nodes/The benefits and drawbacks of using Node-RED function nodesIn this blog post, I will discuss some of the benefits and drawbacks of using Function nodes in your next Node-RED project.2023-03-20T00:00:00ZRob Marcer<p>Function nodes are an essential part of Node-RED. They allow you to write custom JavaScript functions that can be used in your Node-RED flows. In this blog post, I will discuss some of the benefits and drawbacks of using Function nodes in your next project.</p>
<!--more-->
<h2 id="5-benefits-of-using-function-nodes%3A" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/why-should-you-use-node-red-function-nodes/#5-benefits-of-using-function-nodes%3A"># </a> 5 Benefits of using Function Nodes:</h2>
<p><picture><source type="image/gif" srcset="https://flowfuse.com/img/function-example-8Dq7hif9AK-642.gif 642w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Example of using a function node" alt="Example of using a function node" loading="lazy" decoding="async" src="https://flowfuse.com/img/function-example-8Dq7hif9AK-642.webp" width="642" height="394" /></picture></p>
<ol>
<li>
<p><strong>Customisation:</strong> Function nodes allow you to write custom JavaScript functions that can be tailored to your specific needs. You can create complex functions that perform a variety of tasks, the only limit is your programming skills.</p>
</li>
<li>
<p><strong>Reusability:</strong> Function nodes can be reused in multiple flows, saving you time and effort. You can create a library of custom functions that can be easily accessed and reused in different flows.</p>
</li>
<li>
<p><strong>Debugging:</strong> Function nodes provide an easy way to debug your code. You can use console.log statements to output debug information to the Node-RED debug panel, making it easier to identify and fix issues.</p>
</li>
<li>
<p><strong>Performance:</strong> Function nodes can be more performant than using multiple nodes to achieve the same result. By combining multiple tasks into a single function, you can improve performance, assuming your code is efficient.</p>
</li>
<li>
<p><strong>Flexibility:</strong> Function nodes provide a high degree of flexibility. You can use them to perform tasks that are not possible using a single, standard Node-RED node, such as complex data manipulation.</p>
</li>
</ol>
<h2 id="5-benefits-of-avoiding-function-nodes%3A" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/why-should-you-use-node-red-function-nodes/#5-benefits-of-avoiding-function-nodes%3A"># </a> 5 Benefits of avoiding Function Nodes:</h2>
<p><picture><source type="image/gif" srcset="https://flowfuse.com/img/no-function-example-z0eOdJ5sSc-642.gif 642w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Example of not using a function node" alt="Example of not using a function node" loading="lazy" decoding="async" src="https://flowfuse.com/img/no-function-example-z0eOdJ5sSc-642.webp" width="642" height="394" /></picture></p>
<ol>
<li>
<p><strong>Simplicity:</strong> Not using function nodes can make your flows simpler and easier to understand. By using standard Node-RED nodes, you can create flows that are easy to follow and maintain for both you and your team.</p>
</li>
<li>
<p><strong>Ease of Use:</strong> Standard Node-RED nodes are easy to use and require no programming knowledge. This makes it easier for non-technical users to create and maintain flows.</p>
</li>
<li>
<p><strong>Modularity:</strong> By using standard Node-RED nodes, you can create modular flows that can be easily modified and extended. This makes it easier to add new functionality to your flows as your needs change.</p>
</li>
<li>
<p><strong>Community Support:</strong> Standard Node-RED nodes have a large and active community, providing support and resources for users. This can make it easier to find solutions to common problems and share knowledge with others.</p>
</li>
<li>
<p><strong>Compatibility:</strong> Standard Node-RED nodes are usually compatible with all versions of Node-RED, making it easier to migrate flows between different environments.</p>
</li>
</ol>
<h2 id="conclusion%3A" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/why-should-you-use-node-red-function-nodes/#conclusion%3A"># </a> Conclusion:</h2>
<p>Function nodes are particularly useful for users with programming experience who need to perform complex tasks in their flows. They offer a wide range of possibilities, from data manipulation to integration with external APIs. Additionally, function nodes can be more performant than using multiple nodes to achieve the same result, which can be beneficial for users who need to optimise their flows for speed.</p>
<p>On the other hand, standard Node-RED nodes offer a simpler and more accessible approach to flow creation. They are easy to use and require no programming knowledge, making them ideal for non-technical users. Standard nodes also provide modularity, allowing users to create modular flows that can be easily modified and extended. Additionally, standard nodes have a large and active community, providing support and resources for users.</p>
<p>Ultimately, the decision to use function nodes or not will depend on your specific needs and preferences. If you require a high degree of customisation and flexibility, function nodes may be the best choice for you. However, if you prefer simplicity and ease of use, standard Node-RED nodes may be a better fit.</p>
https://flowfuse.com/blog/2023/03/flowforge-1-5-0-released/FlowFuse v1.5 Now AvailableUpdates to UI and architecture to allow for future features and Node-RED 3.1.0 Beta Available!2023-03-16T15:00:00ZJoe Pavitt<p>For FlowFuse 1.5 we have been busy making a lot of UX changes and upgrading our underlying architecture to enable future innovations on the FlowFuse platform.</p>
<!--more-->
<p>With our recently announced <a href="https://flowfuse.com/blog/2023/03/terminology-changes/">Terminology Changes</a>, we have introduced some new concepts into FlowFuse.</p>
<ul>
<li><strong>Application</strong>: A group of Node-RED Instances Each instance can run locally (in FlowFuse) or remotely (on Devices)</li>
<li><strong>Instances</strong>: We renamed "Projects" to "Instances" to be more inline with the terminology used in the Node-RED community</li>
</ul>
<p>As such, our User Experience has been updated to reflect these changes, and allow for further functionality to be introduced with our plans for <a href="https://github.com/FlowFuse/flowfuse/issues/1689">Multiple Instances per Application</a>.</p>
<h3 id="%22applications%22-view" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/flowforge-1-5-0-released/#%22applications%22-view"># </a> "Applications" View</h3>
<p>At the top-level in FlowFuse, you can now see a list of your "Appications". In FlowFuse 1.5, as we still have a 1:1 relationship of Applications to Local Instances, this will be the same as the list of "Projects" that you're used to seeing.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/screenshot-applications-F0eiZcyMDi-650.avif 650w, https://flowfuse.com/img/screenshot-applications-F0eiZcyMDi-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/screenshot-applications-F0eiZcyMDi-650.webp 650w, https://flowfuse.com/img/screenshot-applications-F0eiZcyMDi-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/screenshot-applications-F0eiZcyMDi-650.jpeg 650w, https://flowfuse.com/img/screenshot-applications-F0eiZcyMDi-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Screenshot to show the new "Applications" view" loading="lazy" decoding="async" src="https://flowfuse.com/img/screenshot-applications-F0eiZcyMDi-650.jpeg" width="1300" height="752" /></picture></p>
<figcaption class="-mt-6 text-center"><b>"Applications" view in FlowFuse, listing all available Applications</b></figcaption>
<p>For 1.5, all of your settings, environment variables, etc. are all now at the "Instance" level. Applications will gain a lot more functionality in future releases.</p>
<h3 id="%22instances%22-view" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/flowforge-1-5-0-released/#%22instances%22-view"># </a> "Instances" View</h3>
<p>When clicking on one of your Applications, you will see a list of Node-RED instances bound to that Application.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/screenshot-instances-uSfQsBqISo-650.avif 650w, https://flowfuse.com/img/screenshot-instances-uSfQsBqISo-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/screenshot-instances-uSfQsBqISo-650.webp 650w, https://flowfuse.com/img/screenshot-instances-uSfQsBqISo-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/screenshot-instances-uSfQsBqISo-650.jpeg 650w, https://flowfuse.com/img/screenshot-instances-uSfQsBqISo-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Screenshot to show the new "Instances" view" loading="lazy" decoding="async" src="https://flowfuse.com/img/screenshot-instances-uSfQsBqISo-650.jpeg" width="1300" height="753" /></picture></p>
<figcaption class="-mt-6 text-center"><b>A list of Instances contained within a single Application.</b></figcaption>
<p>Clicking on this Instance, will open up the "Instance" view, this is an exact replica of the "Project" view you'll be used to seeing in FlowFuse, and contains all of the same functionality:</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/screenshot-instance-lEuCoOgCM_-650.avif 650w, https://flowfuse.com/img/screenshot-instance-lEuCoOgCM_-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/screenshot-instance-lEuCoOgCM_-650.webp 650w, https://flowfuse.com/img/screenshot-instance-lEuCoOgCM_-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/screenshot-instance-lEuCoOgCM_-650.jpeg 650w, https://flowfuse.com/img/screenshot-instance-lEuCoOgCM_-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Screenshot to show the new "Instances" view" loading="lazy" decoding="async" src="https://flowfuse.com/img/screenshot-instance-lEuCoOgCM_-650.jpeg" width="1300" height="752" /></picture></p>
<figcaption class="-mt-6 text-center"><b>FlowFuse 1.5's "Instance" view. This contains all of the functionality previously found in the "Project" view.</b></figcaption>
<h3 id="devices-%26-managing-remote-instances" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/flowforge-1-5-0-released/#devices-%26-managing-remote-instances"># </a> Devices & Managing Remote Instances</h3>
<p>Devices are now bound to "Instances", you'll see these in the "Devices" view, and can be managed and deployed to in exactly the same way as before. Devices will run whatever you've selected as your "Target Snapshot" for this Instance.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/screenshot-devices-b7n0SGxT_Z-650.avif 650w, https://flowfuse.com/img/screenshot-devices-b7n0SGxT_Z-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/screenshot-devices-b7n0SGxT_Z-650.webp 650w, https://flowfuse.com/img/screenshot-devices-b7n0SGxT_Z-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/screenshot-devices-b7n0SGxT_Z-650.jpeg 650w, https://flowfuse.com/img/screenshot-devices-b7n0SGxT_Z-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Screenshot to show an Instance's "Devices" view" loading="lazy" decoding="async" src="https://flowfuse.com/img/screenshot-devices-b7n0SGxT_Z-650.jpeg" width="1300" height="752" /></picture></p>
<figcaption class="-mt-6 text-center"><b>"Devices" view, available for a given Node-RED Instance. This lists all of the connected devices to a given instance, that will automatically update when a new Target Snapshot is set.</b></figcaption>
<h2 id="node-red-3.1-beta-available" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/flowforge-1-5-0-released/#node-red-3.1-beta-available"># </a> Node-RED 3.1 Beta Available</h2>
<p>FlowFuse Cloud is a great place to try out the new Node-RED features, with FlowFuse Cloud now including the <a href="https://discourse.nodered.org/t/node-red-3-1-0-beta-2-released/76192">Node-RED 3.1.0-beta.2</a>. If you want to try this version you can <a href="https://flowfuse.com/docs/user/instance-settings/#copy-instance">duplicate your application</a> or <a href="https://flowfuse.com/docs/user/changestack/">upgrade your stack</a>.</p>
<h2 id="other-improvements" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/flowforge-1-5-0-released/#other-improvements"># </a> Other Improvements</h2>
<ul>
<li>Update to audit logs to improve usability [<a href="https://github.com/FlowFuse/flowfuse/issues/1800">#1800</a>] [<a href="https://github.com/FlowFuse/flowfuse/issues/1785">#1785</a>]</li>
<li>Improve how licensing works with overages, for easier scaling of FlowFuse and your Node-RED Instances [<a href="https://github.com/FlowFuse/flowfuse/issues/1639">#1639</a>] [<a href="https://github.com/FlowFuse/flowfuse/issues/1739">#1739</a>]</li>
</ul>
<h2 id="bug-fixes" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/flowforge-1-5-0-released/#bug-fixes"># </a> Bug Fixes</h2>
<ul>
<li>Device "Last Seen" status shows "never" even though it has previously been seen [<a href="https://github.com/FlowFuse/flowfuse/issues/1723">#1723</a>]</li>
<li>Improved Safe Mode launch for small projects [<a href="https://github.com/FlowFuse/flowfuse/issues/1579">#1579</a>]</li>
</ul>
<h2 id="try-it-out" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/flowforge-1-5-0-released/#try-it-out"># </a> Try it out</h2>
<p>We're confident you can have self managed FlowFuse running locally in under 30 minutes.
You can install our <a href="https://flowfuse.com/docs/install/local/">local build</a>, use <a href="https://flowfuse.com/docs/install/docker/">Docker</a>, or <a href="https://flowfuse.com/docs/install/kubernetes/">Kubernetes</a>.</p>
<p>If you'd rather use our hosted offering: <a href="https://app.flowfuse.com/account/create">Get started for free</a> on FlowFuse Cloud.</p>
<h2 id="upgrading-flowfuse" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/flowforge-1-5-0-released/#upgrading-flowfuse"># </a> Upgrading FlowFuse</h2>
<p><a href="https://app.flowfuse.com/">FlowFuse Cloud</a> is already running 1.5.</p>
<p>If you installed a previous version of FlowFuse and want to upgrade, our documentation provides a
guide for <a href="https://flowfuse.com/docs/upgrade/">upgrading your FlowFuse instance</a>.</p>
<h2 id="getting-help" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/flowforge-1-5-0-released/#getting-help"># </a> Getting help</h2>
<p>Please check FlowFuse's <a href="https://flowfuse.com/docs/">documentation</a> as the answers to many questions are covered there.</p>
<p>If you hit any problems with the platform please raise an <a href="https://github.com/FlowFuse/flowfuse/issues">issue on GitHub</a>.
That's also a great place to send us any feedback or feature requests.</p>
<p>You can also get help on <a href="https://discourse.nodered.org/">the Node-RED forums</a></p>
<p>As well as in the <a href="https://github.com/FlowFuse/flowfuse/discussions">forum within our Github project</a></p>
<p>Chat with us on the <code>#flowfuse</code> channel on the <a href="https://nodered.org/slack">Node-RED Slack workspace</a></p>
<p>You can raise a support ticket by emailing <a href="mailto:support@flowfuse.com">support@flowfuse.com</a></p>
<p>We've also added a live chat widget to our website, you can access it using the icon on the bottom right corner of our website. We'd love to hear from you.</p>
https://flowfuse.com/blog/2023/03/terminology-changes/Terminology ChangesApplications, Instances & Devices - the new way forward for FlowFuse2023-03-16T14:00:00ZJoe Pavitt<p>As a new product in the market, we constantly have to make choices on how to name things. Naming things is hard! As you name a thing, say "Project", it might be suitable now, but the product evolves, and may outgrow the name such that it doesn’t fit anymore.</p>
<!--more-->
<p>We are at this point with FlowFuse, and want to walk you through what we have planned, and why we are changing a couple of things.</p>
<h3 id="enter-the-%22application%22" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/terminology-changes/#enter-the-%22application%22"># </a> Enter the "Application"</h3>
<p>In <a href="https://flowfuse.com/blog/2023/03/flowforge-1-5-0-released/">FlowFuse 1.5</a>, we have introduced a new concept called an <strong>Application</strong>.</p>
<p>An Application will allow you to organize multiple Node-RED instances into a single managed group.</p>
<p>As of the 1.5 release, an Application can still only have a single Node-RED instance, but in future releases, Applications will allow for multiple Node-RED instances and will allow us to implement capabilities such as <strong>DevOps Pipelines</strong> and <strong>High Availability</strong>.</p>
<h3 id="%22projects%22-to-%22instances%22" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/terminology-changes/#%22projects%22-to-%22instances%22"># </a> "Projects" to "Instances"</h3>
<p>Until now, 'Project' encapsulated both the Node-RED instance that was running in FlowFuse, and the associated devices (remote instances), settings and environment variables. It was an overloaded term, and it caused confusion with our users.</p>
<p>To simplify things, and to adhere more to the terminology familiar with the Node-RED community, we are renaming Projects to <strong>Instances</strong>.</p>
<p>An <strong>Instance</strong> is a customized version of Node-RED that includes various FlowFuse plugins to integrate it with the FlowFuse platform. It can also be used to manage the environment variables used in your Node-RED flows.</p>
<p>Instances can either be:</p>
<ul>
<li><strong>Local</strong> - An instance of Node-RED running in FlowFuse.</li>
<li><strong>Remote</strong> - An instance of Node-RED, managed by FlowFuse, running on a Device.</li>
</ul>
<p>In future releases, environment variables will also be able to be stored at the Application level, and shared across multiple Node-RED Instances.</p>
<h3 id="devices" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/terminology-changes/#devices"># </a> Devices</h3>
<p>FlowFuse can also be used to manage remote Node-RED instances. This is typically useful when you have a number of remote devices that are required to run the same Node-RED instance, and may have variation in configuration or environment variables for example.</p>
<p>Devices are registered to an Instance, and can be configured to run <a href="https://flowfuse.com/docs/user/concepts/#instance-snapshot">Snapshots</a> of the Instance running in FlowFuse.</p>
<p>To accomplish this remote management capability, the <a href="https://github.com/FlowFuse/device-agent">FlowFuse Device Agent</a> needs to be installed on each device. Devices are registered with a Team, and then the appropriate device(s) are assigned to a Node-RED instance that should be deployed to the device(s). When the Node-RED instance is ready for deployment, a user creates a snapshot of the instance and marks it as a target snapshot for the device.</p>
<p>We hope these changes will simplify the FlowFuse terminology for our users and allow us to grow the FlowFuse platform. If you have any feedback or thoughts, please do reach out to us.</p>
https://flowfuse.com/blog/2023/03/3-quick-node-red-tips-4/Node-RED Tips - Smooth, Catch, and MathSave yourself time when working on Node-RED with these three tips.2023-03-13T12:00:00ZRob Marcer<p>There is usually more than one way to complete a given task in software, and Node-RED is no exception. In each of this series of blog posts, we are going to share three useful tips to save yourself time when working on your flows.</p>
<!--more-->
<h3 id="1.-use-the-smooth-node-to-get-the-minimum-and-maximum-values-of-your-payloads" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/3-quick-node-red-tips-4/#1.-use-the-smooth-node-to-get-the-minimum-and-maximum-values-of-your-payloads"># </a> 1. Use the Smooth node to get the minimum and maximum values of your payloads</h3>
<p>When taking data in from sensors sometimes a spurious value can be sent into your flow. This can result in oddities in a graph or even misfiring of actions such as turning on a heating system. The Smooth custom node allows you to store the min and max of a payload for the last few messages received.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/smooth-FvHv8Oic-h-503.avif 503w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/smooth-FvHv8Oic-h-503.webp 503w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Using the Smooth node to return highest value from the last 100 payloads" alt="Using the Smooth node to return highest value from the last 100 payloads" loading="lazy" decoding="async" src="https://flowfuse.com/img/smooth-FvHv8Oic-h-503.jpeg" width="503" height="523" /></picture></p>
<p>You can in turn use this to ignore values that deviate too far from the sample. To help demonstrate the Smooth node, I've created a flow you can import into Node-RED.</p>
<div style="position: relative">
<pre class="language-json"><code id="code-16" class="language-json"><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"9484c25a0120bd48"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"group"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"dd95c0bca1101c86"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Automatically outputs random value (temperature in Celcius) between 0 & 25 every second"</span><span class="token punctuation">,</span><span class="token property">"style"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token property">"label"</span><span class="token operator">:</span>!<span class="token number">0</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token property">"nodes"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"e4f972f9daad6246"</span><span class="token punctuation">,</span><span class="token string">"c7fc075a1915e87b"</span><span class="token punctuation">,</span><span class="token string">"966a772c46dc2888"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">34</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">59</span><span class="token punctuation">,</span><span class="token property">"w"</span><span class="token operator">:</span><span class="token number">574</span><span class="token punctuation">,</span><span class="token property">"h"</span><span class="token operator">:</span><span class="token number">82</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"e4f972f9daad6246"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"link out"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"dd95c0bca1101c86"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"9484c25a0120bd48"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"link out 1"</span><span class="token punctuation">,</span><span class="token property">"mode"</span><span class="token operator">:</span><span class="token string">"link"</span><span class="token punctuation">,</span><span class="token property">"links"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"33594c64783cdc45"</span><span class="token punctuation">,</span><span class="token string">"e6bf7b494b48861e"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">355</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">100</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"c7fc075a1915e87b"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"dd95c0bca1101c86"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"9484c25a0120bd48"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"repeat"</span><span class="token operator">:</span><span class="token string">"1"</span><span class="token punctuation">,</span><span class="token property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"once"</span><span class="token operator">:</span>!<span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"onceDelay"</span><span class="token operator">:</span><span class="token number">0.1</span><span class="token punctuation">,</span><span class="token property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">130</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">100</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"966a772c46dc2888"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"966a772c46dc2888"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"random"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"dd95c0bca1101c86"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"9484c25a0120bd48"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"low"</span><span class="token operator">:</span><span class="token string">"0"</span><span class="token punctuation">,</span><span class="token property">"high"</span><span class="token operator">:</span><span class="token string">"25"</span><span class="token punctuation">,</span><span class="token property">"inte"</span><span class="token operator">:</span><span class="token string">"true"</span><span class="token punctuation">,</span><span class="token property">"property"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">260</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">100</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"e4f972f9daad6246"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"37380f26e8bfc98a"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"group"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"dd95c0bca1101c86"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Calculate average, high and low, save to flow"</span><span class="token punctuation">,</span><span class="token property">"style"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token property">"label"</span><span class="token operator">:</span>!<span class="token number">0</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token property">"nodes"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"cc3978c7c4ea56ed"</span><span class="token punctuation">,</span><span class="token string">"e1819526a5f365c8"</span><span class="token punctuation">,</span><span class="token string">"33594c64783cdc45"</span><span class="token punctuation">,</span><span class="token string">"fea261a15b3b7683"</span><span class="token punctuation">,</span><span class="token string">"e28a69232f1cac53"</span><span class="token punctuation">,</span><span class="token string">"aecb1727be523240"</span><span class="token punctuation">,</span><span class="token string">"e30039ee13e480a8"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">34</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">259</span><span class="token punctuation">,</span><span class="token property">"w"</span><span class="token operator">:</span><span class="token number">552</span><span class="token punctuation">,</span><span class="token property">"h"</span><span class="token operator">:</span><span class="token number">142</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"cc3978c7c4ea56ed"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"dd95c0bca1101c86"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"37380f26e8bfc98a"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"high"</span><span class="token punctuation">,</span><span class="token property">"pt"</span><span class="token operator">:</span><span class="token string">"flow"</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"reg"</span><span class="token operator">:</span>!<span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">310</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">300</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"aecb1727be523240"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"e1819526a5f365c8"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"dd95c0bca1101c86"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"37380f26e8bfc98a"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"low"</span><span class="token punctuation">,</span><span class="token property">"pt"</span><span class="token operator">:</span><span class="token string">"flow"</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"tot"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"reg"</span><span class="token operator">:</span>!<span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">310</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">360</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"e30039ee13e480a8"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"33594c64783cdc45"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"link in"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"dd95c0bca1101c86"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"37380f26e8bfc98a"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"link in 1"</span><span class="token punctuation">,</span><span class="token property">"links"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"c07b2e101cecbd3b"</span><span class="token punctuation">,</span><span class="token string">"e4f972f9daad6246"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">75</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">320</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"e28a69232f1cac53"</span><span class="token punctuation">,</span><span class="token string">"fea261a15b3b7683"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"fea261a15b3b7683"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"smooth"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"dd95c0bca1101c86"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"37380f26e8bfc98a"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Min"</span><span class="token punctuation">,</span><span class="token property">"property"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"action"</span><span class="token operator">:</span><span class="token string">"min"</span><span class="token punctuation">,</span><span class="token property">"count"</span><span class="token operator">:</span><span class="token string">"100"</span><span class="token punctuation">,</span><span class="token property">"round"</span><span class="token operator">:</span><span class="token string">"2"</span><span class="token punctuation">,</span><span class="token property">"mult"</span><span class="token operator">:</span><span class="token string">"single"</span><span class="token punctuation">,</span><span class="token property">"reduce"</span><span class="token operator">:</span>!<span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">170</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">360</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"e1819526a5f365c8"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"e28a69232f1cac53"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"smooth"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"dd95c0bca1101c86"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"37380f26e8bfc98a"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Max"</span><span class="token punctuation">,</span><span class="token property">"property"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"action"</span><span class="token operator">:</span><span class="token string">"max"</span><span class="token punctuation">,</span><span class="token property">"count"</span><span class="token operator">:</span><span class="token string">"100"</span><span class="token punctuation">,</span><span class="token property">"round"</span><span class="token operator">:</span><span class="token string">"2"</span><span class="token punctuation">,</span><span class="token property">"mult"</span><span class="token operator">:</span><span class="token string">"single"</span><span class="token punctuation">,</span><span class="token property">"reduce"</span><span class="token operator">:</span>!<span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">170</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">300</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"cc3978c7c4ea56ed"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"aecb1727be523240"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"debug"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"dd95c0bca1101c86"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"37380f26e8bfc98a"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"debug 23"</span><span class="token punctuation">,</span><span class="token property">"active"</span><span class="token operator">:</span>!<span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"tosidebar"</span><span class="token operator">:</span>!<span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"console"</span><span class="token operator">:</span>!<span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"tostatus"</span><span class="token operator">:</span>!<span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"complete"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"targetType"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"statusVal"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"statusType"</span><span class="token operator">:</span><span class="token string">"auto"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">480</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">300</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"e30039ee13e480a8"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"debug"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"dd95c0bca1101c86"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"37380f26e8bfc98a"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"debug 25"</span><span class="token punctuation">,</span><span class="token property">"active"</span><span class="token operator">:</span>!<span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"tosidebar"</span><span class="token operator">:</span>!<span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"console"</span><span class="token operator">:</span>!<span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"tostatus"</span><span class="token operator">:</span>!<span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"complete"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"targetType"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"statusVal"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"statusType"</span><span class="token operator">:</span><span class="token string">"auto"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">480</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">360</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"ec11a9ee9148b0b5"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"group"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"dd95c0bca1101c86"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Evaluate if an incoming value is between flow.high and flow.low, if it is not, send the message down a different wire and show an alert in debug"</span><span class="token punctuation">,</span><span class="token property">"style"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token property">"label"</span><span class="token operator">:</span>!<span class="token number">0</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token property">"nodes"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"9393c22b2e3c1ec8"</span><span class="token punctuation">,</span><span class="token string">"1cd18307cb919159"</span><span class="token punctuation">,</span><span class="token string">"7c1f474e646765a7"</span><span class="token punctuation">,</span><span class="token string">"a209cd10f33ec401"</span><span class="token punctuation">,</span><span class="token string">"f4b15283e55babf4"</span><span class="token punctuation">,</span><span class="token string">"e6bf7b494b48861e"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">34</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">419</span><span class="token punctuation">,</span><span class="token property">"w"</span><span class="token operator">:</span><span class="token number">1032</span><span class="token punctuation">,</span><span class="token property">"h"</span><span class="token operator">:</span><span class="token number">162</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"9393c22b2e3c1ec8"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"switch"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"dd95c0bca1101c86"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"ec11a9ee9148b0b5"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Was the value between flow.high and flow.low?"</span><span class="token punctuation">,</span><span class="token property">"property"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"propertyType"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"t"</span><span class="token operator">:</span><span class="token string">"btwn"</span><span class="token punctuation">,</span><span class="token property">"v"</span><span class="token operator">:</span><span class="token string">"high"</span><span class="token punctuation">,</span><span class="token property">"vt"</span><span class="token operator">:</span><span class="token string">"flow"</span><span class="token punctuation">,</span><span class="token property">"v2"</span><span class="token operator">:</span><span class="token string">"low"</span><span class="token punctuation">,</span><span class="token property">"v2t"</span><span class="token operator">:</span><span class="token string">"flow"</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"t"</span><span class="token operator">:</span><span class="token string">"else"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"checkall"</span><span class="token operator">:</span><span class="token string">"true"</span><span class="token punctuation">,</span><span class="token property">"repair"</span><span class="token operator">:</span>!<span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"outputs"</span><span class="token operator">:</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">300</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">480</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"1cd18307cb919159"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token punctuation">[</span><span class="token string">"7c1f474e646765a7"</span><span class="token punctuation">,</span><span class="token string">"a209cd10f33ec401"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"1cd18307cb919159"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"debug"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"dd95c0bca1101c86"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"ec11a9ee9148b0b5"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"debug 15"</span><span class="token punctuation">,</span><span class="token property">"active"</span><span class="token operator">:</span>!<span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"tosidebar"</span><span class="token operator">:</span>!<span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"console"</span><span class="token operator">:</span>!<span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"tostatus"</span><span class="token operator">:</span>!<span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"complete"</span><span class="token operator">:</span><span class="token string">"false"</span><span class="token punctuation">,</span><span class="token property">"statusVal"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"statusType"</span><span class="token operator">:</span><span class="token string">"auto"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">560</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">460</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"7c1f474e646765a7"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"debug"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"dd95c0bca1101c86"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"ec11a9ee9148b0b5"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"debug 16"</span><span class="token punctuation">,</span><span class="token property">"active"</span><span class="token operator">:</span>!<span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"tosidebar"</span><span class="token operator">:</span>!<span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"console"</span><span class="token operator">:</span>!<span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"tostatus"</span><span class="token operator">:</span>!<span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"complete"</span><span class="token operator">:</span><span class="token string">"false"</span><span class="token punctuation">,</span><span class="token property">"statusVal"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"statusType"</span><span class="token operator">:</span><span class="token string">"auto"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">560</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">540</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"a209cd10f33ec401"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"dd95c0bca1101c86"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"ec11a9ee9148b0b5"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Alert to debug when value is outside of the range"</span><span class="token punctuation">,</span><span class="token property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">"The value was outside of the range"</span><span class="token punctuation">,</span><span class="token property">"tot"</span><span class="token operator">:</span><span class="token string">"str"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"reg"</span><span class="token operator">:</span>!<span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">690</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">500</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"f4b15283e55babf4"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"f4b15283e55babf4"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"debug"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"dd95c0bca1101c86"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"ec11a9ee9148b0b5"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"debug 17"</span><span class="token punctuation">,</span><span class="token property">"active"</span><span class="token operator">:</span>!<span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"tosidebar"</span><span class="token operator">:</span>!<span class="token number">0</span><span class="token punctuation">,</span><span class="token property">"console"</span><span class="token operator">:</span>!<span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"tostatus"</span><span class="token operator">:</span>!<span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"complete"</span><span class="token operator">:</span><span class="token string">"false"</span><span class="token punctuation">,</span><span class="token property">"statusVal"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"statusType"</span><span class="token operator">:</span><span class="token string">"auto"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">960</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">500</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"e6bf7b494b48861e"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"link in"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"dd95c0bca1101c86"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"ec11a9ee9148b0b5"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"link in 2"</span><span class="token punctuation">,</span><span class="token property">"links"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"e4f972f9daad6246"</span><span class="token punctuation">,</span><span class="token string">"c07b2e101cecbd3b"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">75</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">480</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"9393c22b2e3c1ec8"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"caf4214602d5f2c9"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"group"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"dd95c0bca1101c86"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Manually send a spurious value"</span><span class="token punctuation">,</span><span class="token property">"style"</span><span class="token operator">:</span><span class="token punctuation">{</span><span class="token property">"label"</span><span class="token operator">:</span>!<span class="token number">0</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token property">"nodes"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"14097fb7ba3a9ecc"</span><span class="token punctuation">,</span><span class="token string">"c07b2e101cecbd3b"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">34</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">159</span><span class="token punctuation">,</span><span class="token property">"w"</span><span class="token operator">:</span><span class="token number">232</span><span class="token punctuation">,</span><span class="token property">"h"</span><span class="token operator">:</span><span class="token number">82</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"14097fb7ba3a9ecc"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"dd95c0bca1101c86"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"caf4214602d5f2c9"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"repeat"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"once"</span><span class="token operator">:</span>!<span class="token number">1</span><span class="token punctuation">,</span><span class="token property">"onceDelay"</span><span class="token operator">:</span><span class="token number">0.1</span><span class="token punctuation">,</span><span class="token property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"payload"</span><span class="token operator">:</span><span class="token string">"75"</span><span class="token punctuation">,</span><span class="token property">"payloadType"</span><span class="token operator">:</span><span class="token string">"num"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">130</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">200</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"c07b2e101cecbd3b"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"c07b2e101cecbd3b"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"link out"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"dd95c0bca1101c86"</span><span class="token punctuation">,</span><span class="token property">"g"</span><span class="token operator">:</span><span class="token string">"caf4214602d5f2c9"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"link out 2"</span><span class="token punctuation">,</span><span class="token property">"mode"</span><span class="token operator">:</span><span class="token string">"link"</span><span class="token punctuation">,</span><span class="token property">"links"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"33594c64783cdc45"</span><span class="token punctuation">,</span><span class="token string">"e6bf7b494b48861e"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">225</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">200</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">]</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-16" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<h3 id="2.-perform-simple-maths-functions-using-jsonata-in-change-nodes" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/3-quick-node-red-tips-4/#2.-perform-simple-maths-functions-using-jsonata-in-change-nodes"># </a> 2. Perform simple maths functions using JSONata in Change nodes</h3>
<p>You can perform basic maths functions using the Change node and JSONata. Let's say you wanted to take a payload and multiply it by a value. You could use a custom node such as <a href="https://flows.nodered.org/node/node-red-contrib-calc">node-red-contrib-calc</a> but you can also easily complete the same task within a change node.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/jsonata-Mjsu67V8r0-503.avif 503w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/jsonata-Mjsu67V8r0-503.webp 503w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Using JSONata in a Change node to multiply a payload by 2.5" alt="Using JSONata in a Change node to multiply a payload by 2.5" loading="lazy" decoding="async" src="https://flowfuse.com/img/jsonata-Mjsu67V8r0-503.jpeg" width="503" height="314" /></picture></p>
<p>This will take the input payload, multiply it by 2.5 then output it as the new payload. You can try this out using the code below.</p>
<div style="position: relative">
<pre class="language-json"><code id="code-29" class="language-json"><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"6bbe9c1e81c4ee39"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"cfe9fec308e144db"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"repeat"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"once"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"onceDelay"</span><span class="token operator">:</span><span class="token number">0.1</span><span class="token punctuation">,</span><span class="token property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"payload"</span><span class="token operator">:</span><span class="token string">"2"</span><span class="token punctuation">,</span><span class="token property">"payloadType"</span><span class="token operator">:</span><span class="token string">"num"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">350</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">400</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"07aa636f3db17775"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"07aa636f3db17775"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"cfe9fec308e144db"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">"msg.payload * 2.5"</span><span class="token punctuation">,</span><span class="token property">"tot"</span><span class="token operator">:</span><span class="token string">"jsonata"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">520</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">440</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"8bde558e6e2f8551"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"8bde558e6e2f8551"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"debug"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"cfe9fec308e144db"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"debug 26"</span><span class="token punctuation">,</span><span class="token property">"active"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"tosidebar"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"console"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"tostatus"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"complete"</span><span class="token operator">:</span><span class="token string">"false"</span><span class="token punctuation">,</span><span class="token property">"statusVal"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"statusType"</span><span class="token operator">:</span><span class="token string">"auto"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">680</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">440</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"1c04633997beb150"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"cfe9fec308e144db"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"repeat"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"once"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"onceDelay"</span><span class="token operator">:</span><span class="token number">0.1</span><span class="token punctuation">,</span><span class="token property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"payload"</span><span class="token operator">:</span><span class="token string">"3"</span><span class="token punctuation">,</span><span class="token property">"payloadType"</span><span class="token operator">:</span><span class="token string">"num"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">350</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">440</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"07aa636f3db17775"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"bc52c3d2f38115b1"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"cfe9fec308e144db"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"repeat"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"once"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"onceDelay"</span><span class="token operator">:</span><span class="token number">0.1</span><span class="token punctuation">,</span><span class="token property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"payload"</span><span class="token operator">:</span><span class="token string">"4"</span><span class="token punctuation">,</span><span class="token property">"payloadType"</span><span class="token operator">:</span><span class="token string">"num"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">350</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">480</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"07aa636f3db17775"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">]</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-29" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<h3 id="3.-use-the-catch-node-to-trigger-flows-on-errors" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/3-quick-node-red-tips-4/#3.-use-the-catch-node-to-trigger-flows-on-errors"># </a> 3. Use the Catch node to trigger flows on errors</h3>
<p>Sometimes you might be working with nodes which don't output anything when they error or maybe output text directly to debug. This makes it difficult for you to run flows when something fails. For example, when using the Read File node, where the expected file is not found, it would be useful to be able to run a specific flow which sends an alert.</p>
<p>You can do this using the Catch node. Drop the node onto your workspace then select if you want errors from some or all nodes. For this example I am going to select just the Read File node. If I then rerun the flow I get an error message out of the Catch node every time there is an error with reading the file.</p>
<p><picture><source type="image/gif" srcset="https://flowfuse.com/img/catch-QA1YW4GT_n-650.gif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Catching an error from the Read File node and outputting a message to debug" alt="Catching an error from the Read File node and outputting a message to debug" loading="lazy" decoding="async" src="https://flowfuse.com/img/catch-QA1YW4GT_n-650.webp" width="650" height="181" /></picture></p>
<p>Note that there are no wires connecting the flow to the error output. This means you can have a single Catch node monitoring a whole project and logging errors as well as sending alerts as needed. You can import the flows from this example using the code below.</p>
<div style="position: relative">
<pre class="language-json"><code id="code-45" class="language-json"><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"d6399c6fddb572ef"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"debug"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"0c6a2ba248b5933f"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"debug 28"</span><span class="token punctuation">,</span><span class="token property">"active"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"tosidebar"</span><span class="token operator">:</span><span class="token boolean">true</span><span class="token punctuation">,</span><span class="token property">"console"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"tostatus"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"complete"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"targetType"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"statusVal"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"statusType"</span><span class="token operator">:</span><span class="token string">"auto"</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">1100</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">300</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"de70fda720070c57"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"inject"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"0c6a2ba248b5933f"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"props"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"repeat"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"crontab"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"once"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"onceDelay"</span><span class="token operator">:</span><span class="token number">0.1</span><span class="token punctuation">,</span><span class="token property">"topic"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">790</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">260</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"a18f9c8638c78e57"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"a18f9c8638c78e57"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"file in"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"0c6a2ba248b5933f"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"filename"</span><span class="token operator">:</span><span class="token string">"example.txt"</span><span class="token punctuation">,</span><span class="token property">"filenameType"</span><span class="token operator">:</span><span class="token string">"str"</span><span class="token punctuation">,</span><span class="token property">"format"</span><span class="token operator">:</span><span class="token string">"utf8"</span><span class="token punctuation">,</span><span class="token property">"chunk"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"sendError"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"encoding"</span><span class="token operator">:</span><span class="token string">"none"</span><span class="token punctuation">,</span><span class="token property">"allProps"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">930</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">260</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"2dbb0cc4bc10d0bc"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"catch"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"0c6a2ba248b5933f"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"scope"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token string">"a18f9c8638c78e57"</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"uncaught"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">790</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">300</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"b22988df6357a52a"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">{</span><span class="token property">"id"</span><span class="token operator">:</span><span class="token string">"b22988df6357a52a"</span><span class="token punctuation">,</span><span class="token property">"type"</span><span class="token operator">:</span><span class="token string">"change"</span><span class="token punctuation">,</span><span class="token property">"z"</span><span class="token operator">:</span><span class="token string">"0c6a2ba248b5933f"</span><span class="token punctuation">,</span><span class="token property">"name"</span><span class="token operator">:</span><span class="token string">"Debug message"</span><span class="token punctuation">,</span><span class="token property">"rules"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token property">"t"</span><span class="token operator">:</span><span class="token string">"set"</span><span class="token punctuation">,</span><span class="token property">"p"</span><span class="token operator">:</span><span class="token string">"payload"</span><span class="token punctuation">,</span><span class="token property">"pt"</span><span class="token operator">:</span><span class="token string">"msg"</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">"There was an error reading the file"</span><span class="token punctuation">,</span><span class="token property">"tot"</span><span class="token operator">:</span><span class="token string">"str"</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token property">"action"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"property"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"from"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"to"</span><span class="token operator">:</span><span class="token string">""</span><span class="token punctuation">,</span><span class="token property">"reg"</span><span class="token operator">:</span><span class="token boolean">false</span><span class="token punctuation">,</span><span class="token property">"x"</span><span class="token operator">:</span><span class="token number">940</span><span class="token punctuation">,</span><span class="token property">"y"</span><span class="token operator">:</span><span class="token number">300</span><span class="token punctuation">,</span><span class="token property">"wires"</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">"d6399c6fddb572ef"</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">}</span><span class="token punctuation">]</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-45" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>We hope you found these tips useful, if you'd like to suggest some of your own tips which you think we should share in our future blog posts please <a href="mailto:contact@flowfuse.com">get in touch</a>.</p>
https://flowfuse.com/blog/2023/03/comparing-node-red-dashboards/Comparing Node-RED Dashboards SolutionsOne of the most common features Node-RED users add to their flows is a dashboard, we compaure the 3 most popular options.2023-03-13T00:00:00ZRob Marcer<p>Dashboards are a great feature of Node-RED, allowing you to easily expose data visualisations and interactive elements of your flows to users via a web browser. I often see discussions in the community about which dashboard option is best for any given scenario, I wanted to compare the most popular options as they stand in early 2023.</p>
<!--more-->
<p><strong>UPDATE:</strong> A new project has been started on the next generation of Node-RED Dashboard. You can get the read more about it on the <a href="https://dashboard.flowfuse.com/">documentation site</a></p>
<h2 id="which-dashboards-am-i-going-to-consider%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/comparing-node-red-dashboards/#which-dashboards-am-i-going-to-consider%3F"># </a> Which dashboards am I going to consider?</h2>
<p>Based on their downloads per week and active development, I believe there are 3 main dashboards worth considering. In no particular order, they are <a href="https://flows.nodered.org/node/node-red-dashboard">Dashboard</a>, <a href="https://flows.nodered.org/node/node-red-contrib-uibuilder">uibuilder</a>, and <a href="https://flows.nodered.org/node/@flexdash/node-red-fd-corewidgets">FlexDash</a>.</p>
<p>It's not to say that there are not other options, I am focusing on the dashboards I believe are popular in the Node-RED community.</p>
<p>I'd like to take this opportunity to thank the project leads for each of the three dashboards for responding to me and providing their take on the current state and future development of each. Where possible I have quoted their words, either from their messages to me or from the projects' documentation. Thanks to <a href="https://github.com/dceejay">Dave</a>, <a href="https://github.com/TotallyInformation">Julian</a>, and <a href="https://github.com/tve">Thorsten</a> for their replies as well as all the work they've put into these great projects!</p>
<h2 id="methodology" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/comparing-node-red-dashboards/#methodology"># </a> Methodology</h2>
<p>To compare these dashboards, I am going to consider each of them based on the following factors:</p>
<ul>
<li>
<p><a href="https://flowfuse.com/blog/2023/03/comparing-node-red-dashboards/#how-easy-is-it-to-install%3F">How easy is it to install?</a></p>
</li>
<li>
<p><a href="https://flowfuse.com/blog/2023/03/comparing-node-red-dashboards/#how-easy-is-it-to-get-your-first-demo-dashboard-running%3F">How easy is it to get your first demo dashboard running?</a></p>
</li>
<li>
<p><a href="https://flowfuse.com/blog/2023/03/comparing-node-red-dashboards/#how-extensive-is-the-collection-of-ui-elements%3F">How extensive is the collection of UI elements?</a></p>
</li>
<li>
<p><a href="https://flowfuse.com/blog/2023/03/comparing-node-red-dashboards/#how-good-is-the-support-and-documentation%3F">How good is the support and documentation?</a></p>
</li>
<li>
<p><a href="https://flowfuse.com/blog/2023/03/comparing-node-red-dashboards/#how-'cloud-native'-is-the-dashboard%3F">How 'cloud native' is the dashboard?</a></p>
</li>
<li>
<p><a href="https://flowfuse.com/blog/2023/03/comparing-node-red-dashboards/#how-active-is-each-project's-development%3F">How active is each project's development?</a></p>
</li>
<li>
<p><a href="https://flowfuse.com/blog/2023/03/comparing-node-red-dashboards/#what-are-the-future-development-plans%3F">What are the future development plans?</a></p>
</li>
</ul>
<p>I am assuming the user is a low-code developer. They may have limited experience with coding and are most comfortable working in visual interfaces.</p>
<p>So, that's the methodology, let's get on with looking at the strengths of each project.</p>
<h2 id="how-easy-is-it-to-install%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/comparing-node-red-dashboards/#how-easy-is-it-to-install%3F"># </a> How easy is it to install?</h2>
<h3 id="uibuilder---1st-place" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/comparing-node-red-dashboards/#uibuilder---1st-place"># </a> uibuilder - 1st place</h3>
<p>A search on Google for uibuilder returns the correct custom node. When searching for the custom node in the palette manager there is only one result, this is great as users are very likely to install what they were searching for. Once you've found the correct custom node, the installation takes just a few moments using the palette manager.</p>
<h3 id="dashboard---2nd-place" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/comparing-node-red-dashboards/#dashboard---2nd-place"># </a> Dashboard - 2nd place</h3>
<p>As Dashboard is currently the most popular solution to build dashboards in Node-RED, it's very easy to find both in search engines and in the Node-RED interface. A Google search brings up the correct custom node. Finding this custom node in Node-RED's palette manager is not quite as easy, at the time of writing it's the third from top result for the search term 'dashboard'. Some users might not select the intended item from the palette manager on first attempt. However, once you have found the correct custom node, installation is easy and takes just a few moments.</p>
<h3 id="flexdash---3rd-place" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/comparing-node-red-dashboards/#flexdash---3rd-place"># </a> FlexDash - 3rd place</h3>
<p>When searching for 'FlexDash node red' on Google, the top result is the Node-RED website for the custom node. The issue with this, and this is also a problem when searching in the palette manager, is the project 'FlexDash' is apparently not what we actually need to install. When reading the readme for the project on Github it says <em>'You most likely do not want to explicitly install this package, you want to install the <a href="https://github.com/flexdash/node-red-fd-corewidgets">core widgets</a>, which will bring in this package and more and will provide a usable whole'.</em></p>
<p>Credit to the developers for adding in this helpful text but I suspect most users will start off by installing FlexDash then later discover that was not the correct way to proceed. It would be great if the custom node which needs to be installed was the one called 'FlexDash' in my opinion.</p>
<p>This problem is compounded by there being no help file at all for 'FlexDash' showing up on the Node-RED web site. That may well be a deliberate attempt to help users get the right custom node installed, but it was still a confusing start for me and I suspect other users will have a similar experience.</p>
<p>When setting up FlexDash, one thing that wasn't immediately obvious was that I needed to restart Node-RED before the custom node showed in the palette. This step is <a href="https://flexdash.github.io/docs/quick-start/#installing-flexdash-in-node-red">covered in the docs</a> but I suspect a lot of users will get stuck working out why the palette manager says the custom node is installed but nothing new has been added to the palette.</p>
<p>There is also an <a href="https://github.com/node-red/node-red/issues/569">ongoing discussion</a> about a way to resolve issue by changing how Node-RED deals with dependencies which sounds promising.</p>
<p>I believe a few improvements to the install process could make FlexDash a much more popular custom node.</p>
<h2 id="how-easy-is-it-to-get-your-first-demo-dashboard-running%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/comparing-node-red-dashboards/#how-easy-is-it-to-get-your-first-demo-dashboard-running%3F"># </a> How easy is it to get your first demo dashboard running?</h2>
<h3 id="flexdash---1st-place" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/comparing-node-red-dashboards/#flexdash---1st-place"># </a> FlexDash - 1st place</h3>
<p>Getting an example dashboard up and running in FlexDash is very easy thanks to the example flows which are included in the package. Simply go to 'Import', 'Examples' then select 'Hello-world' from the example flows. Now deploy and add /flexdash to the end of the URL of your Node-RED editor and you should have your first dashboard running.</p>
<h3 id="uibuilder---2nd-place" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/comparing-node-red-dashboards/#uibuilder---2nd-place"># </a> uibuilder - 2nd place</h3>
<p>It was quite simple to get an example dashboard up and running in uibuilder. As with FlexDash, there are examples you can import. Once we import an example we do start to see the significantly different approach to delivering dashboards with uibuilder to the other two solutions. The examples seem to demonstrate how you could build a dashboard rather than showing specific UI elements such as charts in use.</p>
<h3 id="dashboard---3rd-place" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/comparing-node-red-dashboards/#dashboard---3rd-place"># </a> Dashboard - 3rd place</h3>
<p>Getting your first dashboard running in Dashboard is quite easy, once installed you need to drag in a Dashboard UI element then assign that to a UI group and tab. The group and tab can be left as their default options (home) which I suspect most users will work out quickly.</p>
<p>You then need to deploy your flow and visit the dashboard using '/ui' on the end of the URL of your Node-RED editor and you are up and running.</p>
<p>Dashboard would benefit from some example flows as we see with the other two custom nodes.</p>
<h2 id="how-extensive-is-the-collection-of-ui-elements%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/comparing-node-red-dashboards/#how-extensive-is-the-collection-of-ui-elements%3F"># </a> How extensive is the collection of UI elements?</h2>
<h3 id="flexdash-and-dashboard---joint-1st-place" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/comparing-node-red-dashboards/#flexdash-and-dashboard---joint-1st-place"># </a> FlexDash and Dashboard - joint 1st place</h3>
<p>It's really hard to separate these two, when considering the UI elements they come with. They both have out of the box solutions for charts, gauges, buttons, drop downs, toggles, text etc. I think they both deserve 1st place in this category.</p>
<h3 id="uibuilder---3rd-place" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/comparing-node-red-dashboards/#uibuilder---3rd-place"># </a> uibuilder - 3rd place</h3>
<p>This is possibly a little unfair on uibuilder. Arguably by design, uibuilder does not currently include many UI elements. To add most useful elements (charts, gauges etc) to your dashboard, you will need to set out your design in HTML or look at using one of the supported frontend frameworks. This makes uibuilder more versatile for users who are comfortable using code to set out dashboards but for the low-coders among us it's less ideal.</p>
<h2 id="how-good-is-the-support-and-documentation%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/comparing-node-red-dashboards/#how-good-is-the-support-and-documentation%3F"># </a> How good is the support and documentation?</h2>
<h3 id="all-three---joint-first-place" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/comparing-node-red-dashboards/#all-three---joint-first-place"># </a> All three - joint first place</h3>
<p>All three projects have an active community and good support documentation. Where as I may have a personal preference about how I like documentation to be set out, I don't think that makes any one project better than the rest.</p>
<h2 id="how-'cloud-native'-is-the-dashboard%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/comparing-node-red-dashboards/#how-'cloud-native'-is-the-dashboard%3F"># </a> How 'cloud native' is the dashboard?</h2>
<p>In the words of the <a href="https://www.cncf.io/">Cloud Native Computing Foundation</a> '<em>Cloud native technologies empower organizations to build and run scalable applications in modern, dynamic environments such as public, private, and hybrid clouds. Containers, service meshes, microservices, immutable infrastructure, and declarative APIs exemplify this approach</em>'.</p>
<p>'<em>These techniques enable loosely coupled systems that are resilient, manageable, and observable. Combined with robust automation, they allow engineers to make high-impact changes frequently and predictably with minimal toil</em>'.</p>
<p>So, how well does each project conform to these ideals?</p>
<h3 id="dashboard---1st-place" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/comparing-node-red-dashboards/#dashboard---1st-place"># </a> Dashboard - 1st place</h3>
<p>Dashboard stores all configuration data within the Node-RED instance. When deploying an existing Node-RED project to a new instance everything just works exactly as it did previously.</p>
<h3 id="flexdash---2nd-place" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/comparing-node-red-dashboards/#flexdash---2nd-place"># </a> FlexDash - 2nd place</h3>
<p>As with Dashboard, everything required to define each dashboard is stored within Node-RED. This makes redeployment trivial. Unfortunately, as the Node-RED instance currently needs to be restarted before FlexDash works, it just missed out on joint first place. It would be great to see that issue resolved in future versions. There is also an <a href="https://github.com/node-red/node-red/issues/569">ongoing discussion</a> about a way to resolve issue by changing how Node-RED deals with dependencies.</p>
<h3 id="uibuilder---3rd-place-1" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/comparing-node-red-dashboards/#uibuilder---3rd-place-1"># </a> uibuilder - 3rd place</h3>
<p>uibuilder uses the filesystem of the host instance to store its configuration. In practice this means that if you migrate the Node-RED project files to a new location you probably will find your dashboard no longer works. This can be mitigated by also migrating the filesystem (for example using persistent storage in Docker) and re-deploying via a Docker registry but it would be great to see uibuilder move towards not being dependant on the filesystem as it will make DevOps tasks that much easier.</p>
<h2 id="how-active-is-each-project's-development%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/comparing-node-red-dashboards/#how-active-is-each-project's-development%3F"># </a> How active is each project's development?</h2>
<h3 id="uibuilder---1st-place-1" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/comparing-node-red-dashboards/#uibuilder---1st-place-1"># </a> uibuilder - 1st place</h3>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/uibuilder-activity-cLKzg3wBTI-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/uibuilder-activity-cLKzg3wBTI-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="uibuilder Github Commits" alt="uibuilder Github Commits" loading="lazy" decoding="async" src="https://flowfuse.com/img/uibuilder-activity-cLKzg3wBTI-650.jpeg" width="650" height="169" /></picture></p>
<p>uibuilder has has consistent commits to the project going back several years with even greater activity since the start of 2022.</p>
<h3 id="flexdash---2nd-place-1" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/comparing-node-red-dashboards/#flexdash---2nd-place-1"># </a> FlexDash - 2nd place</h3>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/flexdash-activity-0XsLHXnz45-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/flexdash-activity-0XsLHXnz45-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="FlexDash Github Commits" alt="FlexDash Github Commits" loading="lazy" decoding="async" src="https://flowfuse.com/img/flexdash-activity-0XsLHXnz45-650.jpeg" width="650" height="168" /></picture></p>
<p>The commits to FlexDash have been regular since mid 2022.</p>
<h3 id="dashboard---3rd-place-1" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/comparing-node-red-dashboards/#dashboard---3rd-place-1"># </a> Dashboard - 3rd place</h3>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/dashboard-activity-royMlOREn_-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/dashboard-activity-royMlOREn_-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Dashboard Github Commits" alt="Dashboard Github Commits" loading="lazy" decoding="async" src="https://flowfuse.com/img/dashboard-activity-royMlOREn_-650.jpeg" width="650" height="170" /></picture></p>
<p>Dashboard is now in a a maintenance only state. In the words of the project lead, <em>'Angular 1 (the framework used to build Dashboard) is now unsupported and it's just a matter of time before there is a serious security hole raised against it, for which there will be no fix. Of course we don't use all the features of it so we may be lucky that an exploit doesn't necessarily expose us directly but it will compromise any audits people may wish to do'</em>.</p>
<p>In practice, this means that sooner or later using Dashboard might become a significant security risk.</p>
<h2 id="what-are-the-future-development-plans%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/comparing-node-red-dashboards/#what-are-the-future-development-plans%3F"># </a> What are the future development plans?</h2>
<h3 id="uibuilder---joint-firstplace" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/comparing-node-red-dashboards/#uibuilder---joint-firstplace"># </a> uibuilder - joint firstplace</h3>
<p>During the writing of this article, uibuilder released a new version with some significant new features. In the words of the project lead when talking about version 6.1.0, '<em>It feels like uibuilder really is growing up. No more apologising for not being a direct Node-RED Dashboard replacement, uibuilder has its own path</em>.</p>
<p><em>You can now create and update visible web page elements direct from Node-RED data without needing to understand all of the intricacies and inconsistencies of HTML. You can create your own utility tools either in Node-RED or in front-end code that leverages the low-code UI features of uibuilder</em>'.</p>
<p>It's great to see projects under active development. My greatest difficulty when using uibuilder, is I found it hard to create the UI elements I needed based on low-code workflows. According to the <a href="https://totallyinformation.github.io/node-red-contrib-uibuilder/#/roadmap">development roadmap for uibuilder</a> the project should progress towards being easier and easier for low-coders to make use of.</p>
<p>To again quote the project lead, '<em>In general, the ongoing direction of travel is to enable more zero-code features that will work both in Node-RED flows and in front-end custom code. The low-code feature set is already quite mature now and is well documented enough that it can be used by other tools should anyone wish to do so. I will be making sure that both the zero-code and low-code features are as easy to use as possible both from Node-RED and front-end code for maximum flexibility</em>'.</p>
<h3 id="flexdash---joint-firstplace" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/comparing-node-red-dashboards/#flexdash---joint-firstplace"># </a> FlexDash - joint firstplace</h3>
<p>The project Lead for FlexDash had the following to say about the future development of the project. '<em>FlexDash currently has a fairly rigid overall page structure: there's a tab bar and each tab's content is organized in grids of widgets. The plan is to open this up fully so the user can start from a blank page and place containers which contain widgets. This way almost any layout could be implemented in FlexDash</em>'.</p>
<p>'<em>I also would like to improve the multi-user capabilities of FlexDash by supporting authentication and making it easier for users to implement flows that present per-user data in the dashboard</em>'.</p>
<p>After using FlexDash over the past couple of weeks and finding it to be already be a strong contender for all my Node-RED dashboard needs, it's great to see it continuing to be improved.</p>
<h3 id="dashboard---third-place" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/comparing-node-red-dashboards/#dashboard---third-place"># </a> Dashboard - third place</h3>
<p><strong>UPDATE:</strong> A new project has been started on the next generation of Node-RED Dashboard. You can get the read more about it on the <a href="https://dashboard.flowfuse.com/">documentation site</a></p>
<p>As mentioned above, Dashboard is no longer in active development. This is due to the framework upon which it was build <a href="https://angularjs.org/">(AngularJS)</a> now being unsupported as of the end of 2021. You can read a lot more detail on why ongoing development of Dashboard is not practical in this <a href="https://discourse.nodered.org/t/discussion-about-a-new-dashboard/51119/3">thread on the Node-RED forums</a>.</p>
<p>There could possibly be new effort put into porting Dashboard over to a new framework but that is a significant amount of work. I suspect it would take hundreds of hours development just to get the feature set back to the same state as the current version so I suspect it won't ever happen.</p>
<h2 id="conclusions" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/comparing-node-red-dashboards/#conclusions"># </a> Conclusions</h2>
<p>Personally, I was a little surprised by these results. I have used Dashboard for around 3 years and always found it to be a great tool for putting together quick and informative dashboards. That being said, when attempting to objectively compare it to uibuilder and FlexDash, the other two projects often are individually better in a given category. That coupled with the halt of development for Dashboard due to AngularJS being no longer supported, it's hard to recommend Dashboard for totally new Node-RED users in 2023, especially for commercial projects.</p>
<p>If you already use Dashboard, in a non-commercial setting you should probably continue to do so, you might find that its development slows down to a near stall due to the underlying framework now being abandoned but for at least as of right now it's a great solution to build your Node-RED dashboards in.</p>
<p>FlexDash is probably the best low-code solution for building dashboards in Node-RED. If you don't get blocked by the confusing install process I believe it's the one to pick up at the time of writing due to it's ongoing support and low-code interface.</p>
<p>uibuilder is currently not what I would consider a truly low-code option for creating dashboards but it is moving in that direction. It has some great features and is extremely flexible so it has a good chance of ending up as the most popular solution to build dashboards in Node-RED in the long term. That being said, as of time of writing unless you are a 'coder' you will may struggle to build a dashboard using it.</p>
https://flowfuse.com/blog/2023/03/3-quick-node-red-tips-3/Node-RED Tips - Exec, Filter, and DebugSave yourself time when working on Node-RED with these three tips.2023-03-07T12:00:00ZRob Marcer<p>There is usually more than one way to complete a given task in software, and Node-RED is no exception. In each of this series of blog posts, we are going to share three useful tips to save yourself time when working on your flows.</p>
<!--more-->
<h3 id="1.-the-exec-node-allows-you-to-interact-with-bash-from-node-red" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/3-quick-node-red-tips-3/#1.-the-exec-node-allows-you-to-interact-with-bash-from-node-red"># </a> 1. The Exec node allows you to interact with BASH from Node-RED</h3>
<p>Exec allows you to run Shell commands and receive the value back into your flow. This opens up almost any command which can be run on the host devices CLI to your Node-RED flows.</p>
<p><picture><source type="image/gif" srcset="https://flowfuse.com/img/exec-example-hv78c4k81r-650.gif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Example of using the Exec node" alt="Example of using the Exec node" loading="lazy" decoding="async" src="https://flowfuse.com/img/exec-example-hv78c4k81r-650.webp" width="650" height="176" /></picture></p>
<h3 id="2.-the-filter-node-helps-you-discard-duplicate-messages" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/3-quick-node-red-tips-3/#2.-the-filter-node-helps-you-discard-duplicate-messages"># </a> 2. The Filter node helps you discard duplicate messages</h3>
<p>It can be useful to only allow messages to proceed through a flow where their value is unique. Filter makes that task simple, no need to store the past values and check each new message against a list.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/filter-config-ik5kNh_YWD-497.avif 497w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/filter-config-ik5kNh_YWD-497.webp 497w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Configure the Filter node to only allow unique payloads through" alt="Configure the Filter node to only allow unique payloads through" loading="lazy" decoding="async" src="https://flowfuse.com/img/filter-config-ik5kNh_YWD-497.jpeg" width="497" height="264" /></picture></p>
<p>Once your filter is configured as shown above, try sending different payloads through to see the outcome.</p>
<p><picture><source type="image/gif" srcset="https://flowfuse.com/img/filter-example-IA4SrkFU78-650.gif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Demonstration showing the Filter node" alt="Demonstration showing the Filter node" loading="lazy" decoding="async" src="https://flowfuse.com/img/filter-example-IA4SrkFU78-650.webp" width="650" height="157" /></picture></p>
<h3 id="3.-counting-the-amount-of-messages-sent-to-a-debug-node" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/3-quick-node-red-tips-3/#3.-counting-the-amount-of-messages-sent-to-a-debug-node"># </a> 3. Counting the amount of messages sent to a Debug node</h3>
<p>The Debug node has a lot of great features that we don't see used that often. One example is the ability to show a count of how many messages have been sent to that Debug node since the last deploy.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/setup-counting-debug-FXnxDSSMHK-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/setup-counting-debug-FXnxDSSMHK-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Setting up the debug to count messages" alt="Setting up the debug to count messages" loading="lazy" decoding="async" src="https://flowfuse.com/img/setup-counting-debug-FXnxDSSMHK-650.jpeg" width="650" height="379" /></picture></p>
<p>Once you've setup the node as shown above, you will see a counter under the debug.</p>
<p><picture><source type="image/gif" srcset="https://flowfuse.com/img/counting-debug-Sp5DxbV6uM-650.gif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Each message sent to the debug node is counted" alt="Each message sent to the debug node is counted" loading="lazy" decoding="async" src="https://flowfuse.com/img/counting-debug-Sp5DxbV6uM-650.webp" width="650" height="269" /></picture></p>
<p>We hope you found these tips useful, if you'd like to suggest some of your own tips which you think we should share in our future blog posts please <a href="mailto:contact@flowfuse.com">get in touch</a>.</p>
https://flowfuse.com/blog/2023/03/integration-platform-for-edge-computing/Node-RED: The Integration Platform for IIoT Edge Computing & PLCs2023-03-06T00:00:00Z<p>Node-RED has become a widely adopted integration platform for IoT edge computing and PLCs. Discover why!</p>
<!--more-->
<h2 id="the-integration-platform-for-iiot-edge-computing-%26-plcs" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/integration-platform-for-edge-computing/#the-integration-platform-for-iiot-edge-computing-%26-plcs"># </a> The Integration Platform for IIoT Edge Computing & PLCs</h2>
<p>Node-RED is a widely adopted open-source low-code development tool that makes it easy to connect and integrate different sources of data. With a visual programming interface and drag-and-drop functionality, <a href="https://flowfuse.com/node-red/">Node-RED</a> makes it possible for software developers and non-professional software developers to create sophisticated applications.</p>
<p>In the manufacturing and industrial automation industry, the focus of the Industrial Internet of Things (IIoT) has been on integrating industrial processes and equipment to enable real-time monitoring, control, and analysis of data. For many use cases, instead of sending all the data to the cloud, the best practice for processing industrial data is to deploy the application to the edge of the network, referred to as edge computing. By processing the data closer to the data source, edge computing has many benefits, including reduced latency, limited downtime, conserving bandwidth, and increased privacy, and security.</p>
<h2 id="how-node-red-fits-into-iiot-edge-computing" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/integration-platform-for-edge-computing/#how-node-red-fits-into-iiot-edge-computing"># </a> How Node-RED fits into IIoT Edge Computing</h2>
<p>A key challenge for IIoT edge computing is the wide variety of different hardware platforms, protocols and sources of data and processes. Over the years, the Node-RED community has built <a href="https://flows.nodered.org/">thousands of nodes and flow</a>s to support a wider range of these sources of data, including support for <a href="https://flows.nodered.org/node/node-red-contrib-modbus">Modbus</a>, <a href="https://flows.nodered.org/node/node-red-contrib-opcua">OPC-UA</a>, <a href="https://flows.nodered.org/node/node-red-contrib-s7">S7</a>, <a href="https://cookbook.nodered.org/mqtt/">MQTT</a>, etc. Node-RED also has nodes for graphics and dashboards to make it trivial to visualize industrial data.</p>
<p>Node-RED’s visual programming environment makes it accessible to non-developers. Manufacturing, mechanical, and electrical engineers in the factories are typically the domain experts in understanding the existing systems and often lead IIoT initiatives. Node-RED enables these engineers to quickly innovate and create real value for their organizations. This makes it a popular choice for engineers looking to create edge computing solutions.</p>
<h2 id="plc-and-iot-gateway-vendors-embrace-node-red" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/integration-platform-for-edge-computing/#plc-and-iot-gateway-vendors-embrace-node-red"># </a> PLC and IoT Gateway Vendors Embrace Node-RED</h2>
<p>PLC and IoT Gateway vendors are at the forefront of promoting edge computing. They see edge computing as a way to modernize hardware in the factory and for remote asset management. PLC and IoT gateways often sit in front of old legacy systems that don’t have the connectivity or compute platform to enable IIoT applications.</p>
<p>Many of these hardware vendors realized they need an application delivery platform for their devices. Traditional OT hardware vendors often implement proprietary software stacks that are often difficult to use and closed to integrating with other hardware and software. Forward thinking hardware vendors realized having an open platform is the future of their industry and customers have begun to demand more open platforms. Node-RED’s ease of use, open community and open source license provided the solution many of these hardware vendors were looking for.</p>
<h2 id="the-standard-for-edge-computing-and-plcs" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/integration-platform-for-edge-computing/#the-standard-for-edge-computing-and-plcs"># </a> The Standard for Edge Computing and PLCs</h2>
<p>Today, Node-RED has been adopted by some of the leading PLC and IoT Gateway vendors. The hardware vendor community appears to have standardized on Node-RED as being the edge computing platform for IIoT.</p>
<p>Below is a sample of the vendors offering a Node-RED solution:</p>
<ol>
<li><a href="https://www.advantech.com/en-eu/products/node-red-gateways/sub_fb7246cc-cc10-486f-806b-30bb50a90f28">Advantech</a> Node-RED Field Gateway</li>
<li><a href="https://infosys.beckhoff.com/english.php?content=../content/1033/tf6720_tc3_iot_data_agent/3260672139.html&id=">Bechhoff</a> TwinCAT</li>
<li><a href="https://www.bivocom.com/products/iot-gateways/edge-iot-gateway-tg452">Bivocom</a> TG452 IoT Edge Gateway</li>
<li><a href="https://www.bliiot.com/edge-computing-gateway-p00359p1.html">BLIIOT Edge Computing Gateway</a> EdgeCom BL302</li>
<li><a href="https://developer.community.boschrexroth.com/t5/Store-and-How-to/ctrlX-CORE-Node-RED-App/ba-p/22366">Bosch CtrlX Core</a></li>
<li><a href="https://www.broadsens.com/wireless-gateway/">Broadsens</a> GU200 & GU 200S</li>
<li><a href="https://www.emerson.com/documents/automation/product-datasheet-pacedge-software-computing-devices-pacsystems-en-7205588.pdf">Emerson</a> PACEdge</li>
<li><a href="https://github.com/HilscherAutomation/netPI-nodered">Hilscher Automation</a></li>
<li><a href="https://developer.opto22.com/nodered/general/">Opto22</a> groov RIO & EPIC</li>
<li><a href="https://www.parallaxav.com/controlsystem/">Parallax AV</a> Control System</li>
<li><a href="https://docs.particle.io/reference/cloud-apis/node-red/">Particle.io</a> Particle</li>
<li><a href="https://www.pepperl-fuchs.com/usa/en/classid_199.htm?view=productdetails&prodid=93839">Pepperl+Fuchs</a> AS-Interface gateway</li>
<li><a href="https://projects.raspberrypi.org/en/projects/getting-started-with-node-red">Raspberry Pi</a></li>
<li><a href="https://www.renesas.com/us/en/products/programmable-mixed-signal-asic-ip-products/mixed-signal-asics/communication-asics/ftclick-mikrobus-compatible-interface-module">Renesas</a> FT Click</li>
<li><a href="https://revolutionpi.com/revpi-connect/">Revolution Pi</a> RevPi Connect</li>
<li><a href="https://shop.exchange.se.com/en-US/apps/59823/ecostruxure-plant-data-expert/features">Schneider Electric</a> ExoStructure Plant Data Expert</li>
<li><a href="https://github.com/SIMATICmeetsLinux/IOT2050-NodeRed-OPCUA-Server">Siemens</a> S7 PLC</li>
<li><a href="https://st-one.io/en/hardware/">ST-One</a></li>
<li><a href="https://support.tulip.co/docs/using-node-red-with-edge-mc">Tulip</a> Edge MC & Edge IO</li>
<li><a href="https://www.wago.com/us/edge-devices">Wago</a> Edge Controller & Computer</li>
<li><a href="https://catalog.weidmueller.com/procat/Group.jsp;jsessionid=C885C404E7B4B798B23B8A9BB2200513?groupId=(%22group14048963834797%22)&page=Group">Weidmueller</a> control web</li>
</ol>
<p>There are several key reason Node-RED is so popular for IIoT edge computing, including:</p>
<ul>
<li>Easy User-friendly interface that makes it accessible to manufacturing engineers that might not have a lot of programming experience.</li>
<li>Large community of open source nodes that integrate with many different OT hardware and protocols.</li>
<li>Open source community and license making it vendor neutral so competing hardware vendors feel comfortable embracing the platform.</li>
</ul>
<h2 id="conclusion" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/integration-platform-for-edge-computing/#conclusion"># </a> Conclusion</h2>
<p>IIoT and edge computing is making software more critical to the manufacturing industry. The flexibility to integrate data from different sources to create innovative data centric solutions is primarily software driven. In partnership with OT hardware vendors, Node-RED’s flexible and easy to use environment provides the platform for manufacturing companies to embrace software to develop IIoT solutions.</p>
https://flowfuse.com/blog/2023/03/community-news-03/Community News March 2023Your monthly update for the FlowFuse and Node-RED communities2023-03-02T00:00:00Z<p>Welcome to the FlowFuse newsletter for March 2023, a monthly roundup of what’s been happening with both FlowFuse and the wider Node-RED community.</p>
<!--more-->
<h2 id="upcoming-events" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/community-news-03/#upcoming-events"># </a> Upcoming events</h2>
<h3 id="node-red-ask-me-anything" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/community-news-03/#node-red-ask-me-anything"># </a> Node-RED Ask Me Anything</h3>
<p>Back by popular demand, FlowFuse is hosting a monthly Node-RED Ask Me Anything session on March 9th. This is a great opportunity to ask Nick O’Leary, co-creator of Node-RED & FlowFuse CTO, and Rob Marcer, Node-RED FlowFuse Developer Educator your questions about Node-RED. <a href="https://flowfuse.com/ask-me-anything/ama-nodered/">Sign-up today to participate</a>.</p>
<h3 id="devops-for-node-red%3A-an-introduction-to-flowfuse-webinar" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/community-news-03/#devops-for-node-red%3A-an-introduction-to-flowfuse-webinar"># </a> DevOps for Node-RED: An Introduction to FlowFuse Webinar</h3>
<p>Join Nick O'Leary, FlowFuse CTO, as he presents an Introduction to FlowFuse and demonstrates FlowFuse’s platform for providing DevOps for Node-RED. This webinar will be on March 30th. <a href="https://flowfuse.com/webinars/2023/introduction-to-flowforge/">Register today</a>.</p>
<h2 id="from-our-blog" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/community-news-03/#from-our-blog"># </a> From our Blog</h2>
<p><a href="https://flowfuse.com/blog/2023/02/highly-available-node-red/">Toward Highly Available Node-RED</a> - High availability is an often requested feature for Node-RED. This post from FlowFuse CEO discusses our approach to HA for Node-RED.</p>
<p><a href="https://flowfuse.com/blog/2023/02/ming-blog/">MING Stack for IoT</a> - MING technology stack include M (Mosquitto/MQTT), InfluxDB, Node-RED and Grafana. Ian Skerrett, FlowFuse Head of Marketing discusses how this tech stack is used for IoT.</p>
<p><a href="https://www.youtube.com/watch?v=47EvfmJji-k">Introduction to Node-RED</a> - An in-depth webinar recording on key Node-RED concepts and demonstration on how to get started with Node-RED.</p>
<p>Node-RED Quick Tips - Rob Marcer, FlowFuse Developer Educator has a weekly series of Node-RED hints and tips</p>
<ul>
<li><a href="https://flowfuse.com/blog/2023/02/3-quick-node-red-tips-1/">Tips #1</a></li>
<li><a href="https://flowfuse.com/blog/2023/02/3-quick-node-red-tips-2/">Tips #2</a></li>
</ul>
<h2 id="from-the-community" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/community-news-03/#from-the-community"># </a> From the Community</h2>
<h3 id="node-red-community-survey" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/community-news-03/#node-red-community-survey"># </a> Node-RED Community Survey</h3>
<p>The Node-RED open source project is running an Node-RED Community Survey. Give your <a href="https://nodered.org/blog/2023/02/23/community-survey">feedback on how you are using Node-RED</a>.</p>
<h3 id="good-alternatives-to-pis-for-your-next-project" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/community-news-03/#good-alternatives-to-pis-for-your-next-project"># </a> Good alternatives to Pis for your next project</h3>
<p>Raspberry Pis continue to be difficult to purchase. Eben Upton of the Raspberry Pi Foundation has said that <a href="https://www.raspberrypi.com/news/supply-chain-update-its-good-news/">supply should improve this year</a> but in the mean-time there are some good alternatives you could consider. The Youtube channel <a href="https://www.youtube.com/@ExplainingComputers">ExplainingComputers</a> has shared a <a href="https://www.youtube.com/watch?v=k8clrUclPIs">great video covering some of the most popular SBCs</a> you could use for your next project, it’s worth a watch.</p>
<h3 id="custom-node-spotlight---node-red-contrib-os" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/community-news-03/#custom-node-spotlight---node-red-contrib-os"># </a> Custom Node Spotlight - node-red-contrib-os</h3>
<p><a href="https://flows.nodered.org/node/node-red-contrib-os">OS</a> is a great custom node which allows you to monitor the performance of the device you are running Node-RED on. It can check RAM usage, disk space, CPU load, and a lot more. It’s really easy to use, we recommend you <a href="https://flows.nodered.org/node/node-red-contrib-os">take a look</a>.</p>
<h2 id="join-our-team" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/03/community-news-03/#join-our-team"># </a> Join Our Team</h2>
<p>FlowFuse is expanding our team. We have two openings right now:</p>
<ul>
<li><strong><a href="https://boards.greenhouse.io/flowfuse/jobs/4798023004">Developer Advocate - Manufacturing & Industrial Automation</a></strong></li>
<li><strong><a href="https://boards.greenhouse.io/flowfuse/jobs/4796271004">DevOps Engineer</a></strong></li>
</ul>
https://flowfuse.com/blog/2023/02/webinar-1-missed-questions/Some questions we didn't get to in our first webinarThere were some great questions from our first webinar that we didn't get time to answer, we wanted to share those questions and our answers here.2023-02-27T18:00:00ZRob Marcer<p>There were some great questions from our <a href="https://www.youtube.com/watch?v=47EvfmJji-k">first webinar</a> that we didn't get time to answer, we wanted to share those questions and our answers here.</p>
<!--more-->
<h3 id="irvin-asks%2C-'is-it-possible-to-save-the-debug-information-or-data-flow-to-a-storage-like-splunk-or-sql'%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/02/webinar-1-missed-questions/#irvin-asks%2C-'is-it-possible-to-save-the-debug-information-or-data-flow-to-a-storage-like-splunk-or-sql'%3F"># </a> Irvin asks, 'is it possible to save the debug information or data flow to a storage like Splunk or SQL'?</h3>
<p>Hi Irvin, thanks for the question. I suspect you might be better using a custom node which is designed for logging data rather than capturing the debug node content to a database.</p>
<p>I've come across <a href="https://flows.nodered.org/node/node-red-contrib-flogger">Flogger</a> which seems to do a good job of logging, including support for multiple log files, and built in support for log rotation.</p>
<p><picture><source type="image/webp" srcset="https://flowfuse.com/img/flogger-1dLFtSrSrQ-650.webp 650w, https://flowfuse.com/img/flogger-1dLFtSrSrQ-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/gif" srcset="https://flowfuse.com/img/flogger-1dLFtSrSrQ-650.gif 650w, https://flowfuse.com/img/flogger-1dLFtSrSrQ-1300.gif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Capturing debug to a log file using Flogger" alt="Capturing debug to a log file using Flogger" loading="lazy" decoding="async" src="https://flowfuse.com/img/flogger-1dLFtSrSrQ-650.webp" width="1300" height="512" /></picture></p>
<p>If you really wanted to log to a database rather than a log file you could create your own logging subflow. Once that's in place you can drop it into your flow as needed to capture your debug data for later consumption.</p>
<h3 id="anonymous-asks-'can-we-make-an-mobile-application-with-node-red-or-can-the-content-only-be-accessed-through-a-web-browser'%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/02/webinar-1-missed-questions/#anonymous-asks-'can-we-make-an-mobile-application-with-node-red-or-can-the-content-only-be-accessed-through-a-web-browser'%3F"># </a> Anonymous asks 'can we make an mobile application with Node-RED or can the content only be accessed through a web browser'?</h3>
<p>Hello Anon', it would be great if a Node-RED flow could be built into a mobile app. Sadly, there isn't a simple way to do so at the time of writing.</p>
<p>Assuming you want an easy way to package up and distribute the functionality you might be best creating a link to where the application is hosted. Both <a href="https://www.macrumors.com/how-to/add-a-web-link-to-home-screen-iphone-ipad/">iOS</a> and <a href="https://www.androidauthority.com/add-website-android-iphone-home-screen-3181682/">Android</a> support making a home icon. Once added using them is basically the same user experience as a locally installed application.</p>
<h3 id="john-asks-'from-the-random-node-example-in-the-webinar%2C-the-node-connected-to-four-different-nodes.-is-there-an-order-to-which-is-invoked-first%3F-can-that-be-controlled'%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/02/webinar-1-missed-questions/#john-asks-'from-the-random-node-example-in-the-webinar%2C-the-node-connected-to-four-different-nodes.-is-there-an-order-to-which-is-invoked-first%3F-can-that-be-controlled'%3F"># </a> John asks 'From the random node example in the webinar, the node connected to four different nodes. Is there an order to which is invoked first? Can that be controlled'?</h3>
<p>Hi John, interesting question, thanks for sending it in. For the sake of any readers who were not an the webinar here is what you are describing.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/chart-flow-GUNRkaNFOO-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/chart-flow-GUNRkaNFOO-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Flow where the random number generator sends a message to 4 nodes at the same time" alt="Flow where the random number generator sends a message to 4 nodes at the same time" loading="lazy" decoding="async" src="https://flowfuse.com/img/chart-flow-GUNRkaNFOO-650.jpeg" width="650" height="162" /></picture></p>
<p>All downstream nodes linked to the same prior node will be triggered at practically the same time.</p>
<p>You could use a delay node if you want to ensure a particular node is triggered first. It might also make sense to wire your flow in series rather than parallel. This would allow your functions to all execute in a specific order. That being said, in this case all but one of the nodes do not have outputs so using delays might be the only practical option.</p>
<h3 id="abdelhamid-asks%2C-'how-can-i-delete-a-subflow'%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/02/webinar-1-missed-questions/#abdelhamid-asks%2C-'how-can-i-delete-a-subflow'%3F"># </a> Abdelhamid asks, 'How can I delete a subflow'?</h3>
<p>Thanks Abdelhamid, that's actually really easy to do. Double click the subflow you want to delete, then select 'delete subflow' from the top of your workspace.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/delete-subflow-NeWOHmVuKF-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/delete-subflow-NeWOHmVuKF-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="How to delete a subflow" alt="How to delete a subflow" loading="lazy" decoding="async" src="https://flowfuse.com/img/delete-subflow-NeWOHmVuKF-650.jpeg" width="650" height="169" /></picture></p>
<p>Thanks again to everyone who attended and participated in our first webinar. We have lots of other useful live content coming up soon, you can view and register for future events on our website's <a href="https://flowfuse.com/webinars/">webinars page</a>.</p>
https://flowfuse.com/blog/2023/02/3-quick-node-red-tips-2/Node-RED Tips - Deploying, Debugging, and DelayingSave yourself time when working on Node-RED with these three tips.2023-02-23T18:00:00ZRob Marcer<p>There is usually more than one way to complete a given task in software, and Node-RED is no exception. In each of this series of blog posts, we are going to share three useful tips to save yourself time when working on your flows.</p>
<!--more-->
<h3 id="1.-deploy-just-what-you've-changed" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/02/3-quick-node-red-tips-2/#1.-deploy-just-what-you've-changed"># </a> 1. Deploy just what you've changed</h3>
<p>When deploying your changes, the default option is deploy everything which also restarts all your flows. You can also select to deploy just the nodes you edited or just the flows in which any changes were made.</p>
<p>This allows you to update part of your flow without restarting other sections. This can be really handy when you have different flows spread across your workspace or tabs but you don't want to reload them all each time you deploy.</p>
<p><picture><source type="image/gif" srcset="https://flowfuse.com/img/deploy-PFoWtpQ_d0-650.gif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Deploying only the changed nodes" alt="Deploying only the changed nodes" loading="lazy" decoding="async" src="https://flowfuse.com/img/deploy-PFoWtpQ_d0-650.webp" width="650" height="233" /></picture></p>
<h3 id="2.-find-which-debug-node-generated-an-entry-in-the-log" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/02/3-quick-node-red-tips-2/#2.-find-which-debug-node-generated-an-entry-in-the-log"># </a> 2. Find which debug node generated an entry in the log</h3>
<p>Once your flow has a few debug nodes it can become challenging to see which particular node generated an entry in the log. To quickly track an entry back to its source, click the text 'node: debug' and you will be whisked back to the specific debug node, even it it's elsewhere on you workspace or even on a different tab.</p>
<p><picture><source type="image/gif" srcset="https://flowfuse.com/img/debug-jump-OcDhuaA0Wv-650.gif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Find the debug node which generated the log line" alt="Find the debug node which generated the log line" loading="lazy" decoding="async" src="https://flowfuse.com/img/debug-jump-OcDhuaA0Wv-650.webp" width="650" height="186" /></picture></p>
<h3 id="3.-the-delay-node-can-be-used-as-a-rate-limiter" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/02/3-quick-node-red-tips-2/#3.-the-delay-node-can-be-used-as-a-rate-limiter"># </a> 3. The delay node can be used as a rate limiter</h3>
<p>Sometimes it's useful to be able to limit messages to only allow one every so many minutes. You may for example send alerts when a temperature sensor goes above a particular threshold but you don't want your email or instant messaging inbox being swamped with repeated alerts for the same issue.</p>
<p>You can use the delay node to limit how many messages can pass through in a given period of time.</p>
<p>Open the delay node settings, select Rate Limit then select 1 message per 15 minutes, then select 'Drop intermediate messages'. This flow will now output a maximum of one message every quarter of an hour, all others will be deleted.</p>
<p><picture><source type="image/gif" srcset="https://flowfuse.com/img/rate-limit-wspGm-Gn8r-650.gif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Limit how many alerts are sent" alt="Limit how many alerts are sent" loading="lazy" decoding="async" src="https://flowfuse.com/img/rate-limit-wspGm-Gn8r-650.webp" width="650" height="253" /></picture></p>
<p>We hope you found these tips useful, if you'd like to suggest some of your own tips which you think we should share in our future blog posts please <a href="mailto:contact@flowfuse.com">get in touch</a>.</p>
https://flowfuse.com/blog/2023/02/ming-blog/MING Stack for IoTA technology stack for IoT2023-02-23T00:00:00Z<p>The folks at Balena have created a bundle they call the <a href="https://hub.balena.io/organizations/marc6/apps/MING">MING stack</a>, (Mosquitto/MQTT, InfluxDB, Node-RED and Grafana) which first appeared back in <a href="https://forums.balena.io/t/ming-an-iot-sensor-stack-mosquitto-influxdb-nodered-grafana/36540">2019</a>. It is an interesting way to look at the IoT tech stack and a pattern I have seen used many times.</p>
<!--more-->
<p>In the early days of the web, the <a href="https://en.wikipedia.org/wiki/LAMP_(software_bundle)">LAMP stack</a> was popularized as being the open source tech stack for hosting web sites. First used in 1998, LAMP stood for Linux, Apache, MySQL and Python/Perl/PHP. The LAMP stack did a lot to popularize open source software and create architecture patterns for building web applications. The LAMP stack did a lot to simplify a confusing technology landscape back in the early days of the web.</p>
<p>Can the IoT industry benefit from a MING stack? There is a fair amount of complexity building IoT systems. Therefore, having defined architecture patterns might help reduce some of the confusion. In fact, MING does bring together the key open source components of an IoT system:</p>
<ul>
<li><a href="https://mosquitto.org/">Mosquitto</a> is the popular open source MQTT broker. MQTT has become the default protocol for IoT communications. The MQTT pub/sub protocol solves a lot for the communication challenges for IoT applications. In fact, I would define the M as being MQTT since there are a lot of MQTT broker implementations available.</li>
<li><a href="https://www.influxdata.com/">InfluxDB</a> is the popular open source time series database. Many IoT use cases are based on analyzing trends from different IoT devices. The classic examples is preventive maintenance of factory equipment. Having a time series database in your IoT architecture to record trending information will solve a lot of your data problems.</li>
<li><a href="https://flowfuse.com/node-red/">Node-RED</a> is the popular low-code development environment that helps create flows of data. IoT systems are often pulling data from many different sources. The data needs to be filtered, analysed or transformed before being forward to another service. Node-RED has a large community of data nodes that makes it easy to collect data from a wide variety of sources. For instance in the industrial world, Node-RED nodes are available for OPC-UA, Modbus, S7, MQTT, various PLC platforms like Opto22, etc, etc.</li>
<li>Finally <a href="https://grafana.com/">Grafana</a> is a popular open source visualization platform. Real time monitoring of IoT data is often the first applications deployed for IoT systems. Having graphing and dashboard technology available in your architecture makes perfect sense.</li>
</ul>
<p>Another important feature of MING is that it can be deployed on the edge or in the cloud. IoT systems are inheritenty distributed so having the same technology available at different tiers is useful for lower barriers to adoption.</p>
<p>The LAMP stack was successful because it was:</p>
<ul>
<li>Open source and freely available for anyone to adopt and use.</li>
<li>Highly flexible and customizable that allowed developers to adopt the stack to their use case.</li>
<li>Back by large developer communities creating plugins/extensions, documentation, tutorials, etc.</li>
<li>Easy to learn for developers with limited experience.</li>
</ul>
<p>The MING stack has all the same characteristics. All four technologies are open source, highly flexible, back by large developer communities and relatively easy to learn. There are a lot of similarities between MING and LAMP.</p>
<p>Is MING relevant for IoT use cases? In my experience, people building IoT solutions are using 3-4 of the MING components. What is your experience?</p>
https://flowfuse.com/blog/2023/02/flowforge-1-4-0-released/FlowFuse v1.4 with device provisioning in bulk and staged development processOur second release of 2023 with some great new features to try out.2023-02-16T14:00:00Z<p>Deploy Node-RED to many devices quickly, and allow a staged development process with the latest release of FlowFuse v1.4.</p>
<!--more-->
<p>Keep reading for the details of what's in this release or you can watch our 1 minute roundup video of the new release above.</p>
<p>To make it easy for everyone to experience FlowFuse, we are introducing a new free 30-day trial. You can now experience the power of using FlowFuse to quickly deliver Node-RED applications in a reliable, repeatable, collaborative, and secure manner. To get your free trial simply <a href="https://app.flowfuse.com/account/create">sign up for FlowFuse Cloud;</a> no credit card is required!</p>
<h2 id="new-user-features" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/02/flowforge-1-4-0-released/#new-user-features"># </a> New User Features</h2>
<p><strong>Automatic Device Provisioning</strong></p>
<p>Most prominently, FlowFuse 1.4 features automatic device onboarding for fleets. Simply download a FlowFuse device provisioning credential to allow quick roll-out to a whole fleet, without the need to have device specific configuration. When the agent starts, the FlowFuse agent and the Node-RED snapshot will automatically be provisioned to the device and start operations. <a href="https://github.com/FlowFuse/flowfuse/issues/1212">Issue #1212</a></p>
<div><iframe width="560" height="315" src="https://www.youtube.com/embed/XTVw4O4-Crg" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
<p><strong>Support for Staged Development</strong></p>
<p>A new feature of 1.4 is the ability to setup staged deployments. This makes it possible to simply move a project between a Development > Test > Production for your Node-RED application delivery. <a href="https://github.com/FlowFuse/flowfuse/issues/1580">Issue #1580</a></p>
<div><iframe width="560" height="315" src="https://www.youtube.com/embed/6QOmotlrwWw" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
<h2 id="improvements" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/02/flowforge-1-4-0-released/#improvements"># </a> Improvements</h2>
<ul>
<li>
<p>It's now much easier to change the resources available to your Node-RED instance. With a few clicks a resource intensive workload can be processed faster by changing between small, medium, or large instance types. <a href="https://github.com/FlowFuse/flowfuse/issues/595">#595</a></p>
</li>
<li>
<p>Last release allows users to capture flows in a shared library to reuse in another flow, now it's possible to preview the stored flows. <a href="https://github.com/FlowFuse/flowfuse/issues/1657">#1657</a></p>
</li>
<li>
<p>Add a synchronous mode for the FlowFuse persisted context store, next to the asynchronous mode already available. <a href="https://github.com/FlowFuse/flowforge-nr-persistent-context/issues/17">#17</a></p>
</li>
<li>
<p>Add a Last Seen status for devices connecting to FlowFuse. <a href="https://github.com/FlowFuse/flowfuse/issues/1599">#1599</a></p>
</li>
<li>
<p>Added a check to ensure the team slug is unique. <a href="https://github.com/FlowFuse/flowfuse/issues/1609">#1609</a></p>
</li>
<li>
<p>Optionally set snapshot as target at creation, to quickly roll out changes to remote deployments <a href="https://github.com/FlowFuse/flowfuse/issues/1527">#1527</a></p>
</li>
<li>
<p>Agents are more rugged when starting up if they're unable to connect to FlowFuse, and will retry to connect.</p>
</li>
<li>
<p>With FlowFuse v1.4 some changes were made under the hood to speed up the recovery
of Node-RED instances. On terminal failures of an instance it will now be
automatically be redeployed with the correct flows. This uses Kubernetes features
and is also available if you've installed through <a href="https://flowfuse.com/docs/install/kubernetes/">kubernetes</a>.
To migrate the old style of deployments to this system a restart or stack upgrade is needed.</p>
</li>
</ul>
<h2 id="bug-fixes" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/02/flowforge-1-4-0-released/#bug-fixes"># </a> Bug Fixes</h2>
<p>We've fixed the following bugs in this release.</p>
<ul>
<li>Deleting your only team, doesn't exit from the team UI. <a href="https://github.com/FlowFuse/flowfuse/issues/1630">#1630</a></li>
<li>Async Team Slug Check. <a href="https://github.com/FlowFuse/flowfuse/issues/1609">#1609</a></li>
<li>Improve communication of Device Last Seen and Status <a href="https://github.com/FlowFuse/flowfuse/issues/1599">#1599</a></li>
</ul>
<h2 id="contributors" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/02/flowforge-1-4-0-released/#contributors"># </a> Contributors</h2>
<p>We'd like the thank the following for their contributions to this release:</p>
<ul>
<li><a href="https://github.com/UlisesGascon">UlisesGascon</a> for their work on <a href="https://github.com/FlowFuse/installer/pull/74">#74</a></li>
</ul>
<p>As an open-source project, we welcome community involvement in what we're building.
If you're interested in contributing, checkout our <a href="https://flowfuse.com/docs/contribute/">guide in the docs</a>.</p>
<h2 id="try-it-out" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/02/flowforge-1-4-0-released/#try-it-out"># </a> Try it out</h2>
<p>We're confident you can have self managed FlowFuse running locally in under 30 minutes.
You can install our <a href="https://flowfuse.com/docs/install/local/">local build</a>, use <a href="https://flowfuse.com/docs/install/docker/">Docker</a>, or <a href="https://flowfuse.com/docs/install/kubernetes/">Kubernetes</a>.</p>
<p>If you'd rather use our hosted offering: <a href="https://app.flowfuse.com/account/create">Get started for free</a> on FlowFuse Cloud.</p>
<h2 id="upgrading-flowfuse" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/02/flowforge-1-4-0-released/#upgrading-flowfuse"># </a> Upgrading FlowFuse</h2>
<p><a href="https://app.flowfuse.com/">FlowFuse Cloud</a> is already running 1.4.</p>
<p>If you installed a previous version of FlowFuse and want to upgrade, our documentation provides a
guide for <a href="https://flowfuse.com/docs/upgrade/">upgrading your FlowFuse instance</a>.</p>
<h2 id="getting-help" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/02/flowforge-1-4-0-released/#getting-help"># </a> Getting help</h2>
<p>Please check FlowFuse's <a href="https://flowfuse.com/docs/">documentation</a> as the answers to many questions are covered there.</p>
<p>If you hit any problems with the platform please raise an <a href="https://github.com/FlowFuse/flowfuse/issues">issue on GitHub</a>.
That's also a great place to send us any feedback or feature requests.</p>
<p>You can also get help on <a href="https://discourse.nodered.org/">the Node-RED forums</a></p>
<p>As well as in the <a href="https://github.com/FlowFuse/flowfuse/discussions">forum within our Github project</a></p>
<p>Chat with us on the <code>#flowfuse</code> channel on the <a href="https://nodered.org/slack">Node-RED Slack workspace</a></p>
<p>You can raise a support ticket by emailing <a href="mailto:support@flowfuse.com">support@flowfuse.com</a></p>
<p>We've also added a live chat widget to our website, you can access it using the icon on the bottom right corner of our website. We'd love to hear from you.</p>
</div></div>https://flowfuse.com/blog/2023/02/highly-available-node-red/Toward Highly Available Node-REDHow mission critical use-cases can be supported through FlowFuse soon2023-02-15T00:00:00ZZJ van de Weg<p>Over the past few months we've held a lot of product discovery sessions and a topic
which keeps coming up is "HA Node-RED". All software will have failures, with
HA (high availability) the intent is to allow the workload to be processed
regardless. There's quite a few considerations which are often not covered
during product discovery calls, I'm going to discuss some of those points in this article.</p>
<!--more-->
<p>When my job title was software engineer I was fortunate to design and
implement a HA system. It's an incredibly challenging and rewarding task for
any software engineer. As a topic, it's studied when obtaining a Computer Science
Bachelors degree, masters and even PhD. When tasked
to make a HA system, it took me a good month to define what our goals
were, and what we were willing to exchange for the properties sought. This
might be extra hardware, engineering hours, as well as organisational challenges.
For now, let's focus on the first two.</p>
<p>Let's start with defining the goal; reduce the impact of a Node-RED instance
being unresponsive for an arbitrary reason. In many use-cases the MTTR (Mean Time To
Recovery) is what's measured. When for example a hardware failure takes down the instance and the time to
detection is zero, it will likely still take a few hours to recover. Most of
the recovery work is also manual, and knowledge on how to recover is usually
<a href="https://en.wikipedia.org/wiki/Tribal_knowledge">tribal knowledge</a>. If the right
person is on-site, the right hardware is available, you kept great backups,
and are able to deploy the new hardware right away without support from other
functions you might just achieve an MTTR of 120 minutes!</p>
<h3 id="5-10-minute-mean-time-to-recovery" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/02/highly-available-node-red/#5-10-minute-mean-time-to-recovery"># </a> 5-10 minute Mean Time to Recovery</h3>
<p>What's needed to bring this back to say 10 minutes? First, adopting FlowFuse will
help massively here. FlowFuse can be installed on-premise, or you can use our
managed Cloud offering. The software is the same, provided the on-premise
install uses our <a href="https://flowfuse.com/docs/install/kubernetes/">Kubernetes install</a> method.</p>
<p>The key of the installation is the fact that the hardware layer is generalized
as a fleet. Detecting failures is included in the install, and very fast. Comparing
that to most alerting systems currently, it's usually a difference between night
and day. Furthermore, to decrease the recovery time significantly
there's a requirement to make software responsible for the whole procedure. Human intervention is much too slow.</p>
<p>To get the MTTR down to 5 minutes there's a requirement to either make hardware
automatically available to the fleet, or to over-provision (more hardware is
available than is needed at any given moment). When a hardware failure occurs
FlowFuse is configured to ensure all Node-RED instances that are KIA are
replaced. Bringing down the time to recovery to about 5 minutes.
For many use-cases a MTTR of 5 minutes is <em>good enough</em>.</p>
<h3 id="sub-minute-mttr" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/02/highly-available-node-red/#sub-minute-mttr"># </a> Sub minute MTTR</h3>
<p>To go below the minute, or dare I say go below 10 seconds, we'll need to increase
the number of running Node-RED instances. Let's start with a hot-spare. Meaning
there's a running Node-RED instance with the flows exactly the same as another,
ready to pick up the work when the first has some failure. Note this isn't like
a relay race, there's no baton being passed from one Node-RED to the other. While
some data and messages might be lost, it's possible to redirect all workload from
the plagued Node-RED to the hot-spare in a matter of seconds. Hot-spares taking
over are usually only observed by humans a good few minutes after they replace a failed instance.</p>
<h3 id="sub-second!" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/02/highly-available-node-red/#sub-second!"># </a> Sub second!</h3>
<p>Before this post turns into a theoretical exercise we'd really need to understand
which trade-offs are acceptable to you. There's the <a href="https://en.wikipedia.org/wiki/CAP_theorem">CAP Theorem</a>
which states 3 guarantees are wanted: Consistency, Availability, and Partition Tolerance. You get to pick
only two. In manufacturing the line must never be stopped due to a software failure where possible,
so Availability is the most important. The question is, what comes next? Is it Consistency meaning
all 3 instances have the same view of the global state? Or maybe Partition Tolerance where it's vital for each instance need to be able to predict the intended action even if it can't communicate to the others?</p>
<p>Whichever 2 you choose will dictate engineering choices in the pursuit of a great HA solution.</p>
<h3 id="the-roadmap" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/02/highly-available-node-red/#the-roadmap"># </a> The roadmap</h3>
<p>With FlowFuse v1.4, released February 2023, a 5 minute mean time to recovery is
achieved for all flows running locally, that is: in the cluster. Going beyond this
milestone requires your input! I'd love to chat about your challenges, please
<a href="https://meetings-eu1.hubspot.com/zeger-jan">pick a timeslot to discuss your requirements</a>!</p>
https://flowfuse.com/blog/2023/02/service-disruption-report-2023-01-27/Service Disruption Report for January 27th, 20232023-02-10T00:00:00ZNick O'Leary<p>On January 27th, 2023, we were alerted to an issue on FlowFuse Cloud where a user
was not able to access a newly created Node-RED Project, receiving a 404 error
instead. This post examines the issue that was hit, the timeline of events and
what we've done to resolve it.</p>
<!--more-->
<h2 id="summary" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/02/service-disruption-report-2023-01-27/#summary"># </a> Summary</h2>
<p>We hit a limit in the AWS Load Balancer that capped how many projects could be
exposed to the internet within our FlowFuse Cloud deployment. The result of this
was that users could create a new Node-RED project, but they would not be able
to access the editor.</p>
<p>We freed up capacity on the platform to allow user projects to be created without
hitting the limit, whilst also asking AWS to increase the limit in question which
they duly did.</p>
<p>However, we later discovered a second limit that was also being applied. That limit
was not one AWS permits us to change.</p>
<p>We successfully completely deployment of a change to our platform architecture
today that removes these limits from our environment.</p>
<p>In total, this lead to approximately 2 hours of disruptions on January 27th 2023 and again
on February 8th 2023 during which newly created Node-RED projects were not accessible.</p>
<p>Our logs show that two users were impacted during these times.</p>
<h2 id="technical-details" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/02/service-disruption-report-2023-01-27/#technical-details"># </a> Technical Details</h2>
<p>When running FlowFuse within a Kubernetes environment, each project creates a
new Ingress Object configuration to tell the platform how to route HTTP traffic
to that project.</p>
<p>Our FlowFuse Cloud deployment runs within Amazon Elastic Kubernetes Service (EKS)
and uses the Application Load Balancer (ALB) service as its ingress controller.</p>
<p>When the FlowFuse platform creates the new Ingress Object configuration, EKS passes
that to ALB to generate the necessary configuration, which, given the configuration we
were using, created both a Target Group and Rule object.</p>
<p>With a default of limit of 100 Target Groups and Rules, that meant we had a technical
limit of 100 Node-RED projects within the FlowFuse Cloud environment. Increasing
the Rule limit did not solve the problem as the Target Group limit still applied.</p>
<p>Our initial mitigation was to delete any Node-RED projects we had created for
our own internal testing. We also identified that we could safely delete any rules
for suspended projects. A suspended project is one that is not actively running
in the platform. The code that resumes a suspended project would recreate any ingress
objects needed - so deleting the rule whilst suspended would not have any impact
on the project.</p>
<p>This gave us a small amount of headroom on the platform which crucially meant we
had time to develop a longer term solution.</p>
<h2 id="resolution" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/02/service-disruption-report-2023-01-27/#resolution"># </a> Resolution</h2>
<p>There were two possible routes we could take to resolve this issue:</p>
<ul>
<li>
<p>Investigate how to reuse existing Target Groups rather than create one for each project</p>
<p>Our intial research was inconclusive on how to achieve this. The AWS docs weren't
clear enough to give us a definitive answer we felt comfortable to invest our time
in.</p>
</li>
<li>
<p>Move away from ALB in favour of nginx to provide our ingress load balancing.</p>
<p>This was always our long term strategy as it was a prerequisite to FlowFuse
features we have in the roadmap such as providing custom domains to projects.
However it was potentially a large piece of work with a complicated migration
for the existing environment.</p>
</li>
</ul>
<p>Given it fitted with our longer-term strategic goals, we decided to move ahead
with replacing ALB with nginx.</p>
<p>After some initial development work and experimentation, we felt comfortable that
the migration was not as complicated as initially feared. We would have to manually
copy the existing ALB rules over - something that could be scripted. Once we had
nginx deployed we could push a small code change to FlowFuse to use it rather than
ALB, and also switch over the DNS entry to point at nginx.</p>
<p>Following a successful run through in our testing/staging environment, we decided
to move ahead updating the production environment.</p>
<p>This change was applied today, whilst we closely monitored the system to ensure
no further disruption occurred. We have validated that new projects can be
created without issue and everything is working as it should.</p>
<h2 id="next-steps" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/02/service-disruption-report-2023-01-27/#next-steps"># </a> Next Steps</h2>
<p>With FlowFuse Cloud updated to use the new load balancer, we'll be closely monitoring
it over the next few days to ensure it operates normally.</p>
<p>We will also be taking on some follow-up activities to minimise the risk of this
type of issue happening again:</p>
<ol>
<li>Review all AWS limits within our architecture. Identify any that pose a potential
issue in the future. Ensure they are documented and a plan put in place to mitigate
the impact based on our expected platform growth.</li>
<li>Add additional external monitoring for project liveness.</li>
<li>Review all logging around k8s apis</li>
</ol>
<h2 id="timeline" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/02/service-disruption-report-2023-01-27/#timeline"># </a> Timeline</h2>
<p><em>All times are GMT.</em></p>
<p><strong>2023-01-27 22:15</strong> : (Friday evening) Customer reports via our support channel a newly created project was not accessible and returning a 404 error.</p>
<p><strong>2023-01-27 22:22</strong> : We start examining the platform logs</p>
<p><strong>2023-01-27 22:47</strong> : We identify we've hit the default Rules limit on the AWS Application Load Balancer</p>
<p><strong>2023-01-27 23:15</strong> : To free-up capacity on the platform we delete any ununsed internal projects we were using for general testing. We also identify we can safely delete any rules associated with suspended projects.</p>
<p><strong>2023-01-27 23:41</strong> : We complete deleting rules to give us enough head-room to see us through the weekend.</p>
<p><strong>2023-01-30 10:00</strong> : We submit a request to AWS to increase the rule limit to 200 which is accepted and actioned later that day.</p>
<p>...</p>
<p><strong>2023-02-08 14:05</strong> : Another customer reports seeing a newly created project returning a 404 error. We examine the ALB configuration and whilst it reports the new limit has been changed to 200, it appears to still be limiting at 100. We start identifing more suspended projects we can delete the rules for to free up capacity.</p>
<p><strong>2023-02-08 14:20</strong> : Sufficient capacity is freed to enable the customer's projects to be accessible.</p>
<p><strong>2023-02-08 15:00</strong> : We identify we've hit the ALB Target Group limit. This is a hard limit that AWS does not allow you to change. We begin researching options.</p>
<p><strong>2023-02-09</strong> : Commited to plan to replace ALB with nginx. Successful migration of our staging environment.</p>
<p><strong>2023-02-10</strong> : Change applied to production, FlowFuse 1.3.3 deployed and DNS updated to use the new load balancer.</p>
https://flowfuse.com/blog/2023/02/3-quick-node-red-tips-1/Node-RED Tips - Wiring ShortcutsSave yourself time when working on Node-RED with these three tips.2023-02-07T18:00:00ZRob Marcer<p>There is usually more than one way to complete a given task in software and Node-RED is no exception. In this blog post we are going to share three useful tips to save yourself time when working on your flows.</p>
<!--more-->
<h3 id="1.-use-control%2Bleft-click-to-search-your-nodes" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/02/3-quick-node-red-tips-1/#1.-use-control%2Bleft-click-to-search-your-nodes"># </a> 1. Use control+left-click to search your nodes</h3>
<p>Sometimes it's quicker to search for a node using its name rather than scrolling through the palette. Simply hold control then left-click to bring up a searchable list.</p>
<p><picture><source type="image/gif" srcset="https://flowfuse.com/img/load-node-icrUMTTLfp-650.gif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Select a node without having to use the palette" alt="Select a node without having to use the palette" loading="lazy" decoding="async" src="https://flowfuse.com/img/load-node-icrUMTTLfp-650.webp" width="650" height="267" /></picture></p>
<h3 id="2.-split-sections-of-your-code-using-the-link-nodes" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/02/3-quick-node-red-tips-1/#2.-split-sections-of-your-code-using-the-link-nodes"># </a> 2. Split sections of your code using the link nodes</h3>
<p>If you want to separate your flow into two distinct sections, link nodes are a great way to format your work. As we covered in our blog on <a href="https://flowfuse.com/blog/2022/12/node-red-flow-best-practice">Node-RED best practices</a>, the combination of link nodes and grouped flows is very powerful.</p>
<p>To split your flow select the input and output nodes then right click, select 'Show Action List' and then type 'split'. Select 'Split wire with link nodes'.</p>
<p><picture><source type="image/gif" srcset="https://flowfuse.com/img/split-with-link-0ciXwYQY_N-650.gif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Split your nodes with link nodes" alt="Split your nodes with link nodes" loading="lazy" decoding="async" src="https://flowfuse.com/img/split-with-link-0ciXwYQY_N-650.webp" width="650" height="393" /></picture></p>
<h3 id="3.-link-multiple-inputs-and-outputs-in-one-command" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/02/3-quick-node-red-tips-1/#3.-link-multiple-inputs-and-outputs-in-one-command"># </a> 3. Link multiple inputs and outputs in one command</h3>
<p>Once a switch node has several outputs it can be slow to manually wire each to the new node. Using the action menu (right click), select 'Show Action List' then 'Wire Node to Multiple' this option will join everything up in one step.</p>
<p><picture><source type="image/gif" srcset="https://flowfuse.com/img/join-wires-in1O07LX1I-538.gif 538w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Quickly link multiple nodes in Node-RED" alt="Link multiple inputs and outputs in one command" loading="lazy" decoding="async" src="https://flowfuse.com/img/join-wires-in1O07LX1I-538.webp" width="538" height="362" /></picture></p>
<p>We hope you found these tips useful, if you'd like to suggest some of your own tips which you think we should share in our future blog posts please <a href="mailto:contact@flowfuse.com">get in touch</a>.</p>
https://flowfuse.com/blog/2023/02/community-news-02/Community News February 2023Your monthly update for the FlowFuse and Node-RED communities2023-02-02T00:00:00ZRob Marcer<p>Welcome to the FlowFuse newsletter for February 2023, a monthly roundup of what’s been happening with both FlowFuse and the wider Node-RED community.</p>
<!--more-->
<p>If you've got something that you think we should share on our newsletters please <a href="mailto:contact@flowfuse.com">get in touch</a>.</p>
<h2 id="news" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/02/community-news-02/#news"># </a> News</h2>
<h3 id="node-red-ask-me-anything" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/02/community-news-02/#node-red-ask-me-anything"># </a> <a href="https://flowfuse.com/ask-me-anything/ama-nodered/">Node-RED Ask Me Anything</a></h3>
<p><a href="https://flowfuse.com/ask-me-anything/ama-nodered/"><picture><source type="image/avif" srcset="https://flowfuse.com/img/ama-feb-B_sib6yUmF-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/ama-feb-B_sib6yUmF-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="AMA Session with Nick O'Leary and Rob Marcer" loading="lazy" decoding="async" src="https://flowfuse.com/img/ama-feb-B_sib6yUmF-650.jpeg" width="650" height="341" /></picture></a></p>
<p>Do you have any questions about Node-RED or need some advice on a tricky issue using Node-RED? Here is your opportunity to get help from the experts.</p>
<p>Nick O'Leary, co-founder of Node-RED & CTO of FlowFuse, and Rob Marcer, Node-RED community member & Developer Educator at FlowFuse, will be hosting an interactive Ask Me Anything session. This is a great opportunity to ask questions of the Node-RED experts. If you have any questions for Nick and Rob you can send them in before the session using <a href="https://docs.google.com/forms/d/e/1FAIpQLSdfPq4lAQjdvqhTpoYtKiMNgP8vcMhZsAf_AG0MHuVMRK83_Q/viewform">this form</a>.</p>
<h3 id="free-flowfuse-project-for-30-days%2C-no-catches" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/02/community-news-02/#free-flowfuse-project-for-30-days%2C-no-catches"># </a> <a href="https://app.flowfuse.com/account/create">Free FlowFuse project for 30 days, no catches</a></h3>
<p>To make it easy for everyone to experience FlowFuse, we are introducing a new <a href="https://app.flowfuse.com/account/create">free 30-day trial</a>. With this trial, you can experience the power of using FlowFuse to quickly deliver Node-RED applications in a reliable, repeatable, collaborative, and secure manner. To get your trial simply <a href="https://app.flowfuse.com/account/create">sign up for a new FlowFuse team</a>.</p>
<h3 id="1.3-released" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/02/community-news-02/#1.3-released"># </a> <a href="https://flowfuse.com/blog/2023/01/flowforge-1-3-0-released">1.3 Released</a></h3>
<p>Version 1.3 of FlowFuse was released on 19th January. Our first release of 2023 included some great new features such as the ability to share flows via a <a href="https://www.youtube.com/watch?v=B7XK3TUklUU">team library</a>, <a href="https://www.youtube.com/watch?v=JRk-Cf7eNIo">control access to your Node-RED dashboards</a> using FlowFuse credentials, and <a href="https://www.youtube.com/watch?v=p0Vuy5x42Go">filtering on your audit logs</a> for easier reading. We also added the ability to use FlowFuse on devices which cannot access npm, we think this will be really valuable to users of networks with limited access to the internet.</p>
<p>We're now working towards release 1.4 which is due on 16th February. You can see what we are planning to deliver in that release and beyond on <a href="https://github.com/orgs/FlowFuse/projects/5">FlowFuse's project board</a>.</p>
<p>If you’d like to learn more about what else was included in 1.3 you can do so on our <a href="https://flowfuse.com/blog/2023/01/flowforge-1-3-0-released/">blog post</a>, <a href="https://github.com/FlowFuse/flowfuse/releases/tag/v1.3.0">GitHub release page</a>, and <a href="https://www.youtube.com/watch?v=ey3xv5j5x7k">Youtube channel</a>.</p>
<h3 id="team-news" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/02/community-news-02/#team-news"># </a> <a href="https://flowfuse.com/team">Team News</a></h3>
<p>We are currently recruiting <a href="https://boards.greenhouse.io/flowfuse/jobs/4463977004">NodeJS Developers</a> as well as a <a href="https://boards.greenhouse.io/flowfuse/jobs/4785058004">Graphic Designer</a> to join our team. You can view any of the roles we currently have open and apply on our <a href="https://boards.greenhouse.io/flowfuse">Jobs page</a>.</p>
<h2 id="node-red-in-the-community" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/02/community-news-02/#node-red-in-the-community"># </a> Node-RED in the Community</h2>
<h3 id="twitch-streamer-beats-elden-ring-boss-using-mind-control-(and-a-little-node-red)" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/02/community-news-02/#twitch-streamer-beats-elden-ring-boss-using-mind-control-(and-a-little-node-red)"># </a> <a href="https://www.vice.com/en/article/bvmqmm/watch-an-elden-ring-streamer-beat-a-boss-using-her-thoughts">Twitch Streamer beats Elden Ring boss using mind control (and a little Node-RED)</a></h3>
<p><a href="https://www.vice.com/en/article/bvmqmm/watch-an-elden-ring-streamer-beat-a-boss-using-her-thoughts"><picture><source type="image/avif" srcset="https://flowfuse.com/img/twitch-slgwXSc2_C-500.avif 500w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/twitch-slgwXSc2_C-500.webp 500w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Twitch Streamer beats Elden Ring boss using mind control (and a little Node-RED)" loading="lazy" decoding="async" src="https://flowfuse.com/img/twitch-slgwXSc2_C-500.jpeg" width="500" height="281" /></picture></a>
Streamer <a href="https://www.twitch.tv/videos/1717013810">Perrikaryal</a> used an electroencephalography (EEG) headset to read her brain activity which in turn sends commands via Node-RED to her gaming computer. She then proceeded to use that control method to beat one of the harder bosses in Elden Ring, a notoriously difficult game to start with. The end result is a great example of how Node-RED can link disparate tech together easily. You can <a href="https://www.twitch.tv/videos/1722048787">watch the full stream on Twitch</a>.</p>
<h3 id="run-node-red-in-a-web-browser%2C-client-side!" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/02/community-news-02/#run-node-red-in-a-web-browser%2C-client-side!"># </a> <a href="https://www.linkedin.com/posts/kazuhitoyokoi_nodered-webassembly-activity-7015696090112958464-F3MA/?utm_source=share&utm_medium=member_android">Run Node-RED in a web browser, client side!</a></h3>
<p><a href="https://www.linkedin.com/in/kazuhitoyokoi/">Kazuhito Yokoi</a> has implemented an early prototype of Node-RED runtime for WebAssembly. As a demonstration, he built a simple flow which shows the current location of the International Space Station (ISS). This proof-of-concept shows that an entire Node-RED flow can be executed in a browser. We think this could be a very useful option for running Node-RED in places where it wasn’t previously practical. You can view his work on this <a href="https://github.com/kazuhitoyokoi/node-red-wasm">GitHub project</a>.</p>
<h3 id="custom-node-spotlight---moment" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/02/community-news-02/#custom-node-spotlight---moment"># </a> <a href="https://flows.nodered.org/node/node-red-contrib-moment">Custom Node Spotlight - Moment</a></h3>
<p><a href="https://flows.nodered.org/node/node-red-contrib-moment"><picture><source type="image/avif" srcset="https://flowfuse.com/img/moment-74qvydlV7--650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/moment-74qvydlV7--650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Moment converting a timestamp to ISO standard date and time" loading="lazy" decoding="async" src="https://flowfuse.com/img/moment-74qvydlV7--650.jpeg" width="650" height="106" /></picture></a>
Being able to easily switch dates and times from one format to another is a huge timesaver, node-red-contrib-moment makes those tasks a breeze. The package actually includes two custom nodes, the first ‘Moment’ produces a nicely formatted Date/Time string using the Moment.JS library. The second custom node ‘Humanizer’ converts time durations (time spans) into textual descriptions (e.g. 2 minutes). We recommend you keep it in mind for any flows working with time conversions.</p>
https://flowfuse.com/blog/2023/01/flowforge-story/Telling the FlowFuse StoryFlowFuse helps organizations reliably deliver Node-RED applications2023-02-02T00:00:00Z<p>During my first month at FlowFuse, I have been helping to refine the FlowFuse story. Trying to answer the questions: What is the value FlowFuse brings to our customers and what features does FlowFuse want to offer the Node-RED community?</p>
<!--more-->
<p>People love Node-RED because it makes it trivial to connect different types of services and data, create flows of the data, and store/forward data to the cloud or a database. The Node-RED <a href="https://flows.nodered.org/">library of nodes and flows</a> enables connections to almost anything. The speed and ease of use of Node-RED allows non-traditional programmers to accelerate their innovation and exploration of what is possible.</p>
<p>Node-RED is great for individuals to unlock what is possible for an organization. However, there are some challenges if you want to scale Node-RED into a corporate development platform. Challenges like how do you set up a development -> test -> production delivery pipeline, how to share instances with different developers, how do you create repeatable release processes, how can you deploy the same Node-RED instance out to multiple target environments (devices or servers).</p>
<p>Today, we see many industrial engineers using Node-RED to collect and integrate data from different factory and industrial equipment. Many PLC vendors, like Opto22, are enabling this by making Node-RED as a development environment for the PLC platform. In the manufacturing and industrial automation industries, benefits like reliability and security are important for the continuous operation of these facilities. This is why we believe these types of organizations will be looking for tools that improve their software development lifecycle.</p>
<p>In the larger software development community, DevOps tools are being used to address many of these same challenges. DevOps is all about increasing the reliability and speed of the software development lifecycle. Using tools that increase automation of the software development process and improve collaboration and communication between developers. These are also many of the same challenges that FlowFuse solves for Node-RED users.</p>
<p>For these reasons, we see FlowFuse as being the DevOps platform for Node-RED. We believe FlowFuse enables a more reliable way to deliver Node-RED applications in a repeatable, collaborative and secure manner. What FlowFuse adds to Node-RED are some key features:</p>
<ul>
<li>Tools for collaborative Node-RED development</li>
<li>The ability to manage remote deployments of Node-RED instances</li>
<li>A more streamline way to deliver Node-RED applications</li>
<li>FlowFuse Cloud provides a hosted Node-RED platform but FlowFuse can also be self-hosted</li>
<li>FlowFuse also offers professional technical support to organizations that require the assurance of receiving help with production deployments.</li>
</ul>
<p>We will be rolling out this new way of talking about FlowFuse over the next couple of days and weeks. We are always open to feedback about FlowFuse and would love to hear about your experience of using Node-RED.</p>
https://flowfuse.com/blog/2023/01/environment-variables-in-node-red/Using Environment Variables in Node-REDPredefined data to be used in your Node-RED instance2023-01-27T16:11:47ZZJ van de Weg<p>Programs, written with Node-RED or otherwise, need to sometimes retrieve information that wasn’t decided on during the creation of the program.</p>
<!--more-->
<p>Contextual data like configuration, which user is executing the code, differentiate based on what device is executing a flow, or sometimes secrets which shouldn’t be exposed in the code. This is usually done through environment variables. These are pairs of strings, a key with an attached value, which are accessed by their key. Say you want to access an API endpoint with a key, you’d save the key as <code>API_KEY</code> with the value set to <code>yoursupersecretkey</code>. FlowFuse allows setting environment variables. Let’s start using them to understand how they work.</p>
<p>One of the options for the <code>inject</code> node is to inject a <code>env variable</code>, short for; you guessed it: Environment Variable. In this case we’re going to one that’s pre-defined by Node-RED: <code>NR_FLOW_NAME</code>. The name of each variable is in all caps by convention. When connecting this inject to a debug it prints “Flow 1” for me.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/node-red-use-env-var-wdx7VXtR52-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/node-red-use-env-var-wdx7VXtR52-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Using an environment variable in Node-RED" alt="Using an environment variable in Node-RED" loading="lazy" decoding="async" src="https://flowfuse.com/img/node-red-use-env-var-wdx7VXtR52-650.jpeg" width="650" height="551" /></picture></p>
<p>Leveraging environment variables can also be done with other nodes, like for example <code>change</code>, <code>switch</code>. Note however; you can set the <code>inject</code> node to output the value for <code>FOO</code> even when it doesn’t exist, but it doesn’t allow you to check in the switch node for example if <code>FOO</code> exists.</p>
<p>Node-RED allows you to set environment variables, but not to change them when executing flows. If you want to update data during execution, look into using <a href="https://flowfuse.com/docs/user/persistent-context/">persistent context</a>. Node-RED doesn’t support Environment Variables like other programming environments do. When the flow is deployed the environment variables are replaced with the known values at that time. This is the biggest gotcha for most developers.</p>
<h3 id="predefined-variables" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/01/environment-variables-in-node-red/#predefined-variables"># </a> Predefined variables</h3>
<p>Our first example was using a predefined variable, exposed by Node-RED. As of 3.0 it exposes a few environment variables among which <code>NR_NODE_NAME</code>, <code>NR_GROUP_NAME</code>, and <code>NR_FLOW_NAME</code>.</p>
<p>FlowFuse extends this list with for example a <code>FF_PROJECT_ID</code> allowing you to for example understand what group of instances sent a certain message, but also sets them for each <a href="https://flowfuse.com/docs/user/devices/">device agent</a>. This allows users to pinpoint which device sent a message, for example to update a dashboard accordingly.</p>
<h3 id="managing-environments-variables" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/01/environment-variables-in-node-red/#managing-environments-variables"># </a> Managing environments variables</h3>
<p>In FlowFuse it’s easy to manage variables set for instances. Under settings in the environment tab it’s a form to set them. You’ll have to restart your instances to make them available in the cloud, and update the target snapshot for devices. When done, these are available.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/flowforge-set-env-var-DORJCSNpE8-650.avif 650w, https://flowfuse.com/img/flowforge-set-env-var-DORJCSNpE8-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/flowforge-set-env-var-DORJCSNpE8-650.webp 650w, https://flowfuse.com/img/flowforge-set-env-var-DORJCSNpE8-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/flowforge-set-env-var-DORJCSNpE8-650.jpeg 650w, https://flowfuse.com/img/flowforge-set-env-var-DORJCSNpE8-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="set env var using FlowFuse" alt="Setting a environment variable in FlowFuse" loading="lazy" decoding="async" src="https://flowfuse.com/img/flowforge-set-env-var-DORJCSNpE8-650.jpeg" width="1300" height="393" /></picture></p>
https://flowfuse.com/blog/2023/01/getting-started-with-node-red/Getting Started with Node-REDNode-RED is one of the easiest ways to program ever created but everyone needs a little help2023-01-23T00:00:00ZRob Marcer<p>Node-RED is a visual programming tool for working with IoT devices and web services. It allows users to create flows using a drag-and-drop interface, making it easy to connect different nodes together to build powerful automations.</p>
<!--more-->
<p>In this blog post, we'll take a look at how to get started with Node-RED and create some basic flows. Additionally, we will explore the use of the palette manager, a powerful feature that allows users to install and manage additional nodes for Node-RED.</p>
<h3 id="installing-node-red" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/01/getting-started-with-node-red/#installing-node-red"># </a> Installing Node-RED</h3>
<p>First, you'll need to get an installation of Node-RED up and running. There are several ways to do this, we would suggest you use FlowFuse as it's very easy to get Node-RED running. You can also install Node-RED locally using npm (Node Package Manager), which comes with Node.js.</p>
<h4 id="flowfuse" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/01/getting-started-with-node-red/#flowfuse"># </a> FlowFuse</h4>
<p>To get Node-RED running on FlowFuse <a href="https://app.flowfuse.com/account/create">sign up as a new user</a>.
New users are enrolled in a trial and a Node-RED will be started for you within a minute.</p>
<p>Once that instance has booted up you access Node-RED by pressing "Open Editor".</p>
<h4 id="npm" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/01/getting-started-with-node-red/#npm"># </a> npm</h4>
<p>To install Node-RED locally using npm, open up your terminal and type the following command:</p>
<div style="position: relative">
<pre class="language-bash"><code id="code-28" class="language-bash"><span class="token function">npm</span> <span class="token function">install</span> <span class="token parameter variable">-g</span> node-red</code></pre>
<button class="code-copy " data-clipboard-target="#code-28" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>Once Node-RED is installed, you can start it by running the following command:</p>
<div style="position: relative">
<pre class="language-bash"><code id="code-32" class="language-bash">node-red</code></pre>
<button class="code-copy " data-clipboard-target="#code-32" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>This will start the Node-RED server and open up the <a href="http://localhost:1880/">editor in your web browser</a>. You can also specify a different port or a settings file if you want to.</p>
<h3 id="first-flow" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/01/getting-started-with-node-red/#first-flow"># </a> First Flow</h3>
<p>Now that you have Node-RED running, let's take a look at how to create a simple flow. In this example, we'll create a simple "Hello World" endpoint. To do this, we'll use the <code>http in</code>, <code>http response</code>, and the <code>change</code> nodes, which can be found in the common nodes menu on the left of Node-RED.</p>
<p>First, drag an <code>http in</code> node into the editor. This node will listen for incoming HTTP requests. Next drag in the "change" and the <code>http response</code> node into the editor. Connect the <code>http in</code> node to the <code>change</code> node and connect the <code>change</code> node to the <code>http response</code> node. Hopefully your flow looks similar to this:</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/three-nodes-BCZadG3HQ2-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/three-nodes-BCZadG3HQ2-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="The three nodes we need to build this flow" loading="lazy" decoding="async" src="https://flowfuse.com/img/three-nodes-BCZadG3HQ2-650.jpeg" width="650" height="169" /></picture></p>
<p>To configure the <code>http in</code> node, double-click on it to open its properties. Here, you can set the URL that the node will listen to, as well as the method (GET, POST, etc.). In this example, we'll set the URL to <code>/hello</code> and the method to <code>GET</code>.</p>
<p>Now we need to set what the endpoint will respond with, we will do that in the <code>change</code> node.
Double-click the <code>change</code> node then add "Hello World" to the field which says "to the value". It should look like this:</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/set-reply-0Y7r7JtsCl-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/set-reply-0Y7r7JtsCl-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Configure the change node to output Hello World" loading="lazy" decoding="async" src="https://flowfuse.com/img/set-reply-0Y7r7JtsCl-650.jpeg" width="650" height="408" /></picture></p>
<p>To configure the <code>http response</code> node, double-click on it to open its properties. Here, you should set the "Status Code" to be 200. This is not vital for the demo to work but it's good practice to return the correct codes when something connects to an API. Status code 200 means the API responded OK. This is how your <code>http response</code> node should look:</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/response-code-cMASPVLuiT-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/response-code-cMASPVLuiT-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="We should send back a 200 response code" loading="lazy" decoding="async" src="https://flowfuse.com/img/response-code-cMASPVLuiT-650.jpeg" width="650" height="343" /></picture></p>
<p>You can read more about HTTP response codes in <a href="https://en.wikipedia.org/wiki/List_of_HTTP_status_codes">this article</a>.</p>
<h3 id="testing-your-flow" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/01/getting-started-with-node-red/#testing-your-flow"># </a> Testing Your Flow</h3>
<p>Now that we have our flow set up, we can deploy it by clicking the "Deploy" button in the top right corner of the editor. Once the flow is deployed, you can test it by opening up a web browser, if you installed Node-RED using npm navigate to "http://localhost:1880/hello". If you are working on FlowFuse take the URL of your project and add "/hello" to the end, it should looks something like this "https://your-instance-name.flowfuse.cloud/hello". You should see "Hello World!" displayed in the browser.</p>
<h3 id="debug-output" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/01/getting-started-with-node-red/#debug-output"># </a> Debug Output</h3>
<p>One of the most powerful features in Node-RED is the ability to debug your flow, this can be done by adding a debug node to your flow and connecting it to the nodes you want to debug. When a message is sent through the connected node, the debug node will print the message in the debug sidebar in the right side of the editor. This can be very helpful when trying to understand how a flow is working or troubleshoot any issues.</p>
<h3 id="the-palette-manager" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/01/getting-started-with-node-red/#the-palette-manager"># </a> The Palette Manager</h3>
<p>In addition to the built-in nodes, Node-RED also has a palette manager feature which allows users to easily install and manage additional nodes from the community. To access the palette manager, go to the menu in the top right corner and select "Manage Palette". Here, you can search for and install new nodes, as well as update or remove existing ones. This is a great way to extend the functionality of Node-RED and add new capabilities to your flows.</p>
<h3 id="import-the-flow" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/01/getting-started-with-node-red/#import-the-flow"># </a> Import the flow</h3>
<p>If you want to view this flow you can import it using the code below. Copy the code then select Import from the top right menu in Node-RED. Paste the code into the field then press Import.</p>
<div style="position: relative">
<pre class="language-json"><code id="code-90" class="language-json"><span class="token punctuation">[</span><br /> <span class="token punctuation">{</span><br /> <span class="token property">"id"</span><span class="token operator">:</span> <span class="token string">"a742e7a95697bb40"</span><span class="token punctuation">,</span><br /> <span class="token property">"type"</span><span class="token operator">:</span> <span class="token string">"http in"</span><span class="token punctuation">,</span><br /> <span class="token property">"z"</span><span class="token operator">:</span> <span class="token string">"9e9af3caa4dc14d3"</span><span class="token punctuation">,</span><br /> <span class="token property">"name"</span><span class="token operator">:</span> <span class="token string">""</span><span class="token punctuation">,</span><br /> <span class="token property">"url"</span><span class="token operator">:</span> <span class="token string">"/hello"</span><span class="token punctuation">,</span><br /> <span class="token property">"method"</span><span class="token operator">:</span> <span class="token string">"get"</span><span class="token punctuation">,</span><br /> <span class="token property">"upload"</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span><br /> <span class="token property">"swaggerDoc"</span><span class="token operator">:</span> <span class="token string">""</span><span class="token punctuation">,</span><br /> <span class="token property">"x"</span><span class="token operator">:</span> <span class="token number">180</span><span class="token punctuation">,</span><br /> <span class="token property">"y"</span><span class="token operator">:</span> <span class="token number">200</span><span class="token punctuation">,</span><br /> <span class="token property">"wires"</span><span class="token operator">:</span> <span class="token punctuation">[</span><br /> <span class="token punctuation">[</span><br /> <span class="token string">"883e7d597f7c7c4b"</span><br /> <span class="token punctuation">]</span><br /> <span class="token punctuation">]</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token punctuation">{</span><br /> <span class="token property">"id"</span><span class="token operator">:</span> <span class="token string">"aca024dcb79bdb92"</span><span class="token punctuation">,</span><br /> <span class="token property">"type"</span><span class="token operator">:</span> <span class="token string">"http response"</span><span class="token punctuation">,</span><br /> <span class="token property">"z"</span><span class="token operator">:</span> <span class="token string">"9e9af3caa4dc14d3"</span><span class="token punctuation">,</span><br /> <span class="token property">"name"</span><span class="token operator">:</span> <span class="token string">""</span><span class="token punctuation">,</span><br /> <span class="token property">"statusCode"</span><span class="token operator">:</span> <span class="token string">"200"</span><span class="token punctuation">,</span><br /> <span class="token property">"headers"</span><span class="token operator">:</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token property">"x"</span><span class="token operator">:</span> <span class="token number">500</span><span class="token punctuation">,</span><br /> <span class="token property">"y"</span><span class="token operator">:</span> <span class="token number">200</span><span class="token punctuation">,</span><br /> <span class="token property">"wires"</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><br /> <span class="token punctuation">}</span><span class="token punctuation">,</span><br /> <span class="token punctuation">{</span><br /> <span class="token property">"id"</span><span class="token operator">:</span> <span class="token string">"883e7d597f7c7c4b"</span><span class="token punctuation">,</span><br /> <span class="token property">"type"</span><span class="token operator">:</span> <span class="token string">"change"</span><span class="token punctuation">,</span><br /> <span class="token property">"z"</span><span class="token operator">:</span> <span class="token string">"9e9af3caa4dc14d3"</span><span class="token punctuation">,</span><br /> <span class="token property">"name"</span><span class="token operator">:</span> <span class="token string">""</span><span class="token punctuation">,</span><br /> <span class="token property">"rules"</span><span class="token operator">:</span> <span class="token punctuation">[</span><br /> <span class="token punctuation">{</span><br /> <span class="token property">"t"</span><span class="token operator">:</span> <span class="token string">"set"</span><span class="token punctuation">,</span><br /> <span class="token property">"p"</span><span class="token operator">:</span> <span class="token string">"payload"</span><span class="token punctuation">,</span><br /> <span class="token property">"pt"</span><span class="token operator">:</span> <span class="token string">"msg"</span><span class="token punctuation">,</span><br /> <span class="token property">"to"</span><span class="token operator">:</span> <span class="token string">"Hello World"</span><span class="token punctuation">,</span><br /> <span class="token property">"tot"</span><span class="token operator">:</span> <span class="token string">"str"</span><br /> <span class="token punctuation">}</span><br /> <span class="token punctuation">]</span><span class="token punctuation">,</span><br /> <span class="token property">"action"</span><span class="token operator">:</span> <span class="token string">""</span><span class="token punctuation">,</span><br /> <span class="token property">"property"</span><span class="token operator">:</span> <span class="token string">""</span><span class="token punctuation">,</span><br /> <span class="token property">"from"</span><span class="token operator">:</span> <span class="token string">""</span><span class="token punctuation">,</span><br /> <span class="token property">"to"</span><span class="token operator">:</span> <span class="token string">""</span><span class="token punctuation">,</span><br /> <span class="token property">"reg"</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span><br /> <span class="token property">"x"</span><span class="token operator">:</span> <span class="token number">340</span><span class="token punctuation">,</span><br /> <span class="token property">"y"</span><span class="token operator">:</span> <span class="token number">200</span><span class="token punctuation">,</span><br /> <span class="token property">"wires"</span><span class="token operator">:</span> <span class="token punctuation">[</span><br /> <span class="token punctuation">[</span><br /> <span class="token string">"aca024dcb79bdb92"</span><br /> <span class="token punctuation">]</span><br /> <span class="token punctuation">]</span><br /> <span class="token punctuation">}</span><br /><span class="token punctuation">]</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-90" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<h3 id="what's-next%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/01/getting-started-with-node-red/#what's-next%3F"># </a> What's Next?</h3>
<p>Well done, hopefully you've now got your first flow up and running and your mind is racing with all the possibilities of what comes next. Enjoy using Node-RED and thanks for reading.</p>
https://flowfuse.com/blog/2023/01/flowforge-1-3-0-released/FlowFuse 1.3 is now available, share your flows through our new team libraries and much moreOur first release of 2023 with some great new features to try out, happy new year from everyone at FlowFuse!2023-01-19T18:00:00ZRob Marcer<p>Share your flows via team libraries, control access to your Node-RED dashboards using FlowFuse credentials, and filter your audit logs by users and actions.</p>
<!--more-->
<p>We're pleased to announce version 1.3 is now available! Due to the recent holiday season, most of our team have been away from their desks but we still have some great new features to share. Keep reading for the details of what's in this release or you can watch our 1 minute roundup video of the new release above.</p>
<p>To make it easy for everyone to experience FlowFuse, we are introducing a new <a href="https://app.flowfuse.com/account/create">free 30-day trial</a>. With this trial, you can experience the power of using FlowFuse to quickly deliver Node-RED applications in a reliable, repeatable, collaborative, and secure manner. To get your trial simply <a href="https://app.flowfuse.com/account/create">sign up for a new FlowFuse team</a>.</p>
<h2 id="features" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/01/flowforge-1-3-0-released/#features"># </a> Features</h2>
<p><a href="https://github.com/FlowFuse/flowfuse/issues/237">Share your flows via team libraries</a> <br />
FlowFuse has now added the ability for you to share your flows via the import and export features in Node-RED. Once you export a flow everyone else in your FlowFuse team will be able to import your work into their projects. You can see a demonstration of this new feature in <a href="https://youtu.be/B7XK3TUklUU">the video</a> below.</p>
<div><iframe width="560" height="315" src="https://www.youtube.com/embed/B7XK3TUklUU" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
<p><a href="https://github.com/FlowFuse/flowfuse/issues/1325">Control access to your Node-RED dashboards using FlowFuse credentials</a> <br />
In FlowFuse 0.10 we added the ability to secure endpoints created within your FlowFuse projects. This allows you to create dashboards or APIs and limit who can access them. In 1.3 we've added the ability for you to limit access to those same resources based on the visitor having a user account on your FlowFuse team. You can see a demonstration of this new feature in <a href="https://youtu.be/JRk-Cf7eNIo">the video</a> below.</p>
<div><iframe width="560" height="315" src="https://www.youtube.com/embed/JRk-Cf7eNIo" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
<p><a href="https://github.com/FlowFuse/flowfuse/issues/1448">Filter your audit logs for easier reading</a> <br />
In FlowFuse 1.3 we’ve added the ability to filter your admin logs by user or action type. We think this is a great new feature which will help admins have confidence that they will be able to review the audit logs quickly when needed. You can see a demonstration of this new feature in <a href="https://youtu.be/p0Vuy5x42Go">the video</a> below.</p>
<div><iframe width="560" height="315" src="https://www.youtube.com/embed/p0Vuy5x42Go" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
<h2 id="improvements" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/01/flowforge-1-3-0-released/#improvements"># </a> Improvements</h2>
<p><a href="https://github.com/FlowFuse/device-agent/issues/45">Allow installation of FlowFuse on devices which can't access npm</a> <br />
We've had feedback from customers that in some cases they want to use FlowFuse devices on hardware which cannot access <a href="https://www.npmjs.com/">Node Package Manager</a> (npm). In a standard configuration of Node-RED, access to npm is mandatory to run your flows. In FlowFuse 1.3.0 we've added the ability for you to import all the data usually installed from npm without your devices having access to the npm service.</p>
<h2 id="bug-fixes" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/01/flowforge-1-3-0-released/#bug-fixes"># </a> Bug Fixes</h2>
<p>We've fixed the following bugs in this release.</p>
<ul>
<li>Project status UI sometimes getting stuck when restarting <a href="https://github.com/FlowFuse/flowfuse/issues/1232">#1232</a></li>
<li>SSO users asked to click link in email to verify <a href="https://github.com/FlowFuse/flowfuse/issues/1543">#1543</a></li>
<li>SSO users unable to edit settings <a href="https://github.com/FlowFuse/flowfuse/issues/1542">#1542</a></li>
<li>SSO users not redirected to editor when signing in <a href="https://github.com/FlowFuse/flowfuse/issues/1481">#1481</a></li>
</ul>
<h2 id="contributors" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/01/flowforge-1-3-0-released/#contributors"># </a> Contributors</h2>
<p>We'd like to thank the following for their contributions to this release:</p>
<p><a href="https://github.com/flecoufle">flecoufle</a> for their work on <a href="https://github.com/FlowFuse/helm/pull/89">#89</a></p>
<p>As an open-source project, we welcome community involvement in what we're building.
If you're interested in contributing, checkout our <a href="https://flowfuse.com/docs/contribute/">guide in the docs</a>.</p>
<h2 id="try-it-out" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/01/flowforge-1-3-0-released/#try-it-out"># </a> Try it out</h2>
<p>We're confident you can have self managed FlowFuse running locally in under 30 minutes.
You can install our <a href="https://flowfuse.com/docs/install/local/">local build</a>, use <a href="https://flowfuse.com/docs/install/docker/">Docker</a>, or <a href="https://flowfuse.com/docs/install/kubernetes/">Kubernetes</a>.</p>
<p>If you'd rather use our hosted offering: <a href="https://app.flowfuse.com/account/create">Get started for free</a> on FlowFuse Cloud.</p>
<h2 id="upgrading-flowfuse" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/01/flowforge-1-3-0-released/#upgrading-flowfuse"># </a> Upgrading FlowFuse</h2>
<p><a href="https://app.flowfuse.com/">FlowFuse Cloud</a> is already running 1.3.</p>
<p>If you installed a previous version of FlowFuse and want to upgrade, our documentation provides a
guide for <a href="https://flowfuse.com/docs/upgrade/">upgrading your FlowFuse instance</a>.</p>
<h2 id="getting-help" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/01/flowforge-1-3-0-released/#getting-help"># </a> Getting help</h2>
<p>Please check FlowFuse's <a href="https://flowfuse.com/docs/">documentation</a> as the answers to many questions are covered there.</p>
<p>If you hit any problems with the platform please raise an <a href="https://github.com/FlowFuse/flowfuse/issues">issue on GitHub</a>.
That's also a great place to send us any feedback or feature requests.</p>
<p>You can also get help on <a href="https://discourse.nodered.org/">the Node-RED forums</a></p>
<p>AS well as in the <a href="https://github.com/FlowFuse/flowfuse/discussions">forum within our Github project</a></p>
<p>Chat with us on the <code>#flowfuse</code> channel on the <a href="https://nodered.org/slack">Node-RED Slack workspace</a></p>
<p>You can raise a support ticket by emailing <a href="mailto:support@flowfuse.com">support@flowfuse.com</a></p>
<p>We've also added a live chat widget to our website, you can access it using the icon on the bottom right corner of our website. We'd love to hear from you.</p>
</div></div></div>https://flowfuse.com/blog/2023/01/flowforge-1.2.1-released/FlowFuse 1.2.1 releasedRelease includes fix for emailing new user2023-01-12T12:00:00ZBen Hardill<p>We've published a maintenance release containing a fix for new users.</p>
<!--more-->
<p>This release fixes an <a href="https://github.com/FlowFuse/flowfuse/issues/1537">issue</a> introduced in FlowFuse 1.2 where users were not being sent their welcome email when they first sign up to the platform. As the sign-up page asks them to click on the link in that email, it left them waiting for an email that wasn't going to arrive.</p>
<p>The same fix also addresses an <a href="https://github.com/FlowFuse/flowfuse/issues/1514">issue</a> where users could not sign up using an email with a <code>+</code> in it. This is a restriction we apply to users signing up with Single Sign-On enabled email domains - but the check was being applied to everyone.</p>
<h3 id="upgrading-flowfuse" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/01/flowforge-1.2.1-released/#upgrading-flowfuse"># </a> Upgrading FlowFuse</h3>
<p>This release has already been rolled out to <a href="https://app.flowfuse.com/">FlowFuse Cloud</a>.</p>
<p>If you installed a previous version of FlowFuse and want to upgrade, our documentation provides a
guide for <a href="https://flowfuse.com/docs/upgrade/">upgrading your FlowFuse instance</a></p>
<h3 id="getting-help" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2023/01/flowforge-1.2.1-released/#getting-help"># </a> Getting help</h3>
<p>Please check FlowFuse's <a href="https://flowfuse.com/docs/">documentation</a> as the answers to many questions are covered there.</p>
<p>If you hit any problems with the platform, please raise an <a href="https://github.com/FlowFuse/flowfuse/issues">issue on GitHub</a>.
That also includes if you have any feedback or feature requests.</p>
<p>Chat with us on the <code>#flowfuse</code> channel on the <a href="https://nodered.org/slack">Node-RED Slack workspace</a>.</p>
<p>You can also raise a support ticket by emailing <a href="mailto:support@flowfuse.com">support@flowfuse.com</a></p>
https://flowfuse.com/blog/2023/01/community-news-12/Community News December 2022News from the FlowFuse and Node-RED communities2023-01-12T00:00:00ZRob Marcer<p>Welcome to the FlowFuse newsletter for December 2022, a monthly roundup of what’s been happening with both FlowFuse and the wider Node-RED community. 2022 was a really exciting year for the development of both Node-RED and FlowFuse. Node-RED released version 3, another major milestone for the project. FlowFuse hit version 1, leaving the beta development stage. We are excited to see what the community can achieve in 2023!</p>
<!--more-->
<p>If you've got something that you think we should share on our newsletters please <a href="mailto:contact@flowfuse.com">get it touch</a>.</p>
<p><a href="https://github.com/node-red/node-red/milestone/19"><strong>Node-RED Nears 3.1 Release</strong></a>
The release of Node-RED 3.1 is expected very soon. 3.1 includes lots of great new features such as support for <a href="https://github.com/node-red/node-red/pull/3938">locking flows in the editor</a> and <a href="https://github.com/node-red/node-red/pull/3930">improving the user experience around hiding flows</a>. As an open source project the development of Node-RED is entirely dependent on individuals and companies giving their time to work towards each new release. If you'd like to know how you can get involved you can read more on the <a href="https://nodered.org/about/contribute/">Node-RED web site</a>.</p>
<p><a href="https://flowfuse.com/blog/2022/12/flowforge-1-2-0-released/"><strong>FlowFuse 1.2 Released</strong></a><br />
Version 1.2 of FlowFuse was released on 23rd December. Our last release of the year included some great new features such as <a href="https://flowfuse.com/docs/cloud/introduction/#single-sign-on">Single Sign-On</a> to make it easier for your team to access your projects and <a href="https://flowfuse.com/docs/cloud/introduction/#node-red-context">Persistent Context</a> which allows you to retain context values even when restarting projects. We're now working towards our first release of 2023 which is due on 19th January. You can see what we are planning to deliver in that release and beyond on <a href="https://github.com/orgs/FlowFuse/projects/5">FlowFuse's project board</a>.</p>
<p>If you’d like to learn more about what else was included in 1.2 you can do so on our <a href="https://flowfuse.com/blog/2022/12/flowforge-1-2-0-released/">blog post</a>, <a href="https://github.com/FlowFuse/flowfuse/releases/tag/v1.2.0">GitHub release page</a>, and <a href="https://www.youtube.com/watch?v=u7TjqUAub1g">Youtube channel</a>.</p>
<p><a href="https://iot-analytics.com/5-iot-sensor-technologies/"><strong>5 IoT Sensor Technologies to Watch</strong></a><br />
According to this detailed article from iot-analytics.com, on average, four new sensors are connected with every new IoT device that comes online. With approximately 14 billion current IoT connections, this means more than 50 billion connected sensors have been deployed. IoT sensor technology plays a crucial role in the IoT tech stack because these sensors collect data from the physical world and convert it into digital signals. We think <a href="https://iot-analytics.com/5-iot-sensor-technologies/">their article</a> is worth a read.</p>
<p><a href="https://flows.nodered.org/node/node-red-contrib-string"><strong>Custom Node Spotlight - node-red-contrib-string</strong></a>
String manipulation is the bread and butter of so many programming tasks. Node-RED has a lot of tools to help you edit your strings including support for <a href="https://jsonata.org/">JSONata</a> and using the trusty function node. For those of us who prefer to keep things 'no-code' <a href="https://flows.nodered.org/node/node-red-contrib-string">node-red-contrib-string</a> allows you to stack string manipulations together quickly and easily. It has a huge library of ready to use functions.</p>
<p><a href="https://flowfuse.com/team/"><strong>FlowFuse Team News</strong></a><br />
We’d like to welcome two new members to the FlowFuse team. <a href="https://twitter.com/ianskerrett">Ian Skerrett</a> has joined as our Head of Marketing and <a href="https://www.linkedin.com/in/tracyanthonyfernandez/">Tracy Anthony</a> has joined as our HR Manager. FlowFuse continues to grow and we are becoming a truly global team.</p>
<p>Would you like to work for FlowFuse? We are currently recruiting <a href="https://boards.greenhouse.io/flowfuse/jobs/4463977004">NodeJS Developers</a> to join our team. You can view any of the roles we currently have open and apply on our <a href="https://boards.greenhouse.io/flowfuse">Jobs page</a>.</p>
<p><a href="https://app.flowfuse.com/account/create?code=FF12"><strong>Try FlowFuse for Free</strong></a><br />
As a thank you for reading our newsletters we’d like to offer you a free, small project for one month on our managed FlowFuse platform when you create a new team. To get this discount please follow <a href="https://app.flowfuse.com/account/create?code=FF12">this link</a> or use the code FF12 when on the payment page after creating a new team. As an open source project you can also use <a href="https://flowfuse.com/docs/install/">FlowFuse</a> for free, forever.</p>
https://flowfuse.com/blog/2022/12/flowforge-1-2-0-released/FlowFuse 1.2 is now available with single sign on and persistent context storageOur final release for 2022 with some great new features to try out2022-12-22T18:00:00ZRob Marcer<p>Control access to FlowFuse using single sign-on and retain context values when restarting projects.</p>
<!--more-->
<p>We're pleased to announce version 1.2 is now available! The latest release of the FlowFuse application contains new features, improvements, better documentation, and bug fixes.</p>
<p>We've put a great deal of work in this release to make it easier to run your own self-managed instance of FlowFuse. That includes significant improvements for FlowFuse in <a href="https://flowfuse.com/docs/install/kubernetes/">Kubernetes</a> and <a href="https://flowfuse.com/docs/install/docker/">Docker</a>.</p>
<p>Keep reading for the details of what's in this release or you can watch our 1 minute roundup video of the new release above.</p>
<h2 id="features" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/12/flowforge-1-2-0-released/#features"># </a> Features</h2>
<p><a href="https://github.com/FlowFuse/flowfuse/issues/226">Single Sign-On</a> Single sign-on (SSO) is a method of authentication that allows a user to access multiple applications or systems with a single set of login credentials, improving security, productivity, and user experience, and reducing IT overhead. We've implemented SSO using the Security Assertion Markup Language <a href="https://en.wikipedia.org/wiki/Security_Assertion_Markup_Language">(SAML)</a> framework. This allows users of FlowFuse Cloud, Premium and the open source edition to easily access their FlowFuse projects.</p>
<p><a href="https://github.com/FlowFuse/flowfuse/issues/212">Persistent Context</a> Node-RED provides a way to store information that can be shared between different nodes and flow executions without using the messages that pass through a flow. This is called ‘context’. You can now select if context should be stored in memory or in persistent storage. Persistent storage allows the stored values to be recalled after a restart of your project. You can see a demonstration of this feature on our <a href="https://youtu.be/ma2vYrXmssc">Youtube channel</a>.</p>
<h2 id="improvements" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/12/flowforge-1-2-0-released/#improvements"># </a> Improvements</h2>
<ul>
<li>
<p>In FlowFuse 1.1 we added logging of user actions. In 1.2 we’ve <a href="https://github.com/FlowFuse/flowfuse/issues/517">improved the audit log interface</a> to help you read the recorded user actions.
<picture><source type="image/avif" srcset="https://flowfuse.com/img/audit-log-LCeMmtLjRn-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/audit-log-LCeMmtLjRn-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="An image of the new audit log interface" loading="lazy" decoding="async" src="https://flowfuse.com/img/audit-log-LCeMmtLjRn-650.jpeg" width="650" height="342" /></picture></p>
</li>
<li>
<p>Configuring DNS for FlowFuse has historically been challenging as for most FlowFuse installs you'll need two entries. One for the FlowFuse application, and one for the Node-RED projects. There's been updates to the documentation to make it much easier to set this up, and much faster. Please checkout the new <a href="https://flowfuse.com/docs/install/dns-setup/">documentation</a>.</p>
</li>
<li>
<p>We've updated our documentation to always link to the latest build (older builds are still available).</p>
</li>
<li>
<p>Previously customers were asked to build their own containers for the main FlowFuse applications, as well as the Node-RED ones. For the Node-RED containers this allows customers to pre-install packages in the container they intent to use. For FlowFuse Cloud these containers are build by FlowFuse. These containers are now published to the <a href="https://hub.docker.com/u/flowforge">Docker Hub</a>. This makes it much easier to get up and running with your first containers.</p>
</li>
<li>
<p>We are now pushing our Docker builds to Docker Hub, this saves users from having to build the Docker images when installing or updating. These containers are used by default by <code>docker-compose</code>.</p>
</li>
<li>
<p>Setting up MQTT for inter-project communication and communication with devices has been simplified. Please read the improved the documentation around configuration of <a href="https://github.com/FlowFuse/flowfuse/issues/1397">MQTT</a>.</p>
</li>
</ul>
<h2 id="bug-fixes" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/12/flowforge-1-2-0-released/#bug-fixes"># </a> Bug Fixes</h2>
<p>We've fixed the following bugs in this release.</p>
<ul>
<li>
<p>Unable to edit 'Prevent Install of External nodes' template option <a href="https://github.com/FlowFuse/flowfuse/issues/1376">#1376</a></p>
</li>
<li>
<p>Self-managed FlowFuse needs an external email server to deliver email to users. FlowFuse should be able deal with the email server being offline and gracefully recover once it is back online. <a href="https://github.com/FlowFuse/flowfuse/issues/1159">#1159</a></p>
</li>
<li>
<p>Duplicate Activity Log for Project whose state is in flight <a href="https://github.com/FlowFuse/flowfuse/issues/1461">#1461</a></p>
</li>
</ul>
<h2 id="contributors" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/12/flowforge-1-2-0-released/#contributors"># </a> Contributors</h2>
<p>We'd like the thank the following for their contributions to this release:</p>
<p><a href="https://github.com/flecoufle">flecoufle</a> for their work on <a href="https://github.com/FlowFuse/docker-compose/pull/59">#59</a></p>
<p><a href="https://github.com/sumanpaikdev">sumanpaikdev</a> for their work on <a href="https://github.com/FlowFuse/docker-compose/pull/53">#53</a></p>
<p><a href="https://github.com/sdirosa">sdirosa</a> for their work on <a href="https://github.com/FlowFuse/flowfuse/pull/1326">#1326</a></p>
<p>As an open-source project, we welcome community involvement in what we're building.
If you're interested in contributing, checkout our <a href="https://flowfuse.com/docs/contribute/">guide in the docs</a>.</p>
<h3 id="try-it-out" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/12/flowforge-1-2-0-released/#try-it-out"># </a> Try it out</h3>
<p>In 1.2 we've continued to improve the experience of running your own self managed FlowFuse installation. We're confident you can have self managed FlowFuse running locally in under 30 minutes.
You can install our <a href="https://flowfuse.com/docs/install/local/">local build</a>, through <a href="https://flowfuse.com/docs/install/docker/">Docker</a>, or <a href="https://flowfuse.com/docs/install/kubernetes/">Kubernetes</a>.</p>
<p>If you'd rather use our hosted offering: <a href="https://app.flowfuse.com/account/create?code=FF12">Sign up for FlowFuse Cloud</a>
with the coupon <strong>FF12</strong> to get your first project free for a month.</p>
<h3 id="upgrading-flowfuse" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/12/flowforge-1-2-0-released/#upgrading-flowfuse"># </a> Upgrading FlowFuse</h3>
<p><a href="https://app.flowfuse.com/">FlowFuse Cloud</a> is already running 1.2. To use
persistent context you'll need to upgrade your projects stack.</p>
<p>If you installed a previous version of FlowFuse and want to upgrade, our documentation provides a
guide for <a href="https://flowfuse.com/docs/upgrade/">upgrading your FlowFuse instance</a>.</p>
<h3 id="getting-help" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/12/flowforge-1-2-0-released/#getting-help"># </a> Getting help</h3>
<p>Please check FlowFuse's <a href="https://flowfuse.com/docs/">documentation</a> as the answers to many questions are covered there.</p>
<p>If you hit any problems with the platform please raise an <a href="https://github.com/FlowFuse/flowfuse/issues">issue on GitHub</a>.
That also includes if you have any feedback or feature requests.</p>
<p>Chat with us on the <code>#flowfuse</code> channel on the <a href="https://nodered.org/slack">Node-RED Slack workspace</a>.</p>
<p>You can raise a support ticket by emailing <a href="mailto:support@flowfuse.com">support@flowfuse.com</a>.</p>
<p>We've also added a live chat widget to our website, you can access it using the icon on the bottom right corner of our website. We'd love to hear from you.</p>
https://flowfuse.com/blog/2022/12/what-flowforge-adds-to-node-red/Why you need FlowFuse when you already have Node-RED?FlowFuse makes developer collaboration, flow deployment, and scaling of infrastructure easy when working with Node-RED2022-12-15T00:00:00ZRob Marcer<p>Many organisations face challenges in IT/OT convergence. There are many protocols, disparate devices, and everything is a brownfield project. Furthermore, skilled engineers are hard to find. Many organisations find themselves maintaining systems and integrations, and have little time left to improve continuously.</p>
<!--more-->
<p>This is why Node-RED is adopted so widely, it makes a world of difference through two of its properties: Low-Code Development and the ability to integrate with a wide range of hardware and software systems. Node-RED makes it easy to program data collection, then use that data for decision making, and provide feedback to both your digital platform and the physical reality of your business. Furthermore, Node-RED is unrivalled in making data accessible. The data previously locked in a walled garden of your hardware providers is now accessible and obtainable. With that, more data is available and better decisions are made, faster.</p>
<p>FlowFuse makes developer collaboration, flow deployment, and scaling of infrastructure easy when working with Node-RED. It offers an intuitive user interface for creating, deploying, monitoring, and managing multiple Node-RED projects. FlowFuse also provides one-click deployment to thousands of devices, making it easy to manage large-scale environments.</p>
<p>These features make FlowFuse a valuable tool for organisations using Node-RED to build applications and automate processes. Enabling for further adoption of Node-RED to integrate more systems, for even better decisions.</p>
<p>This not only reduces operational costs but it also allows an organisation to be far more agile with their Node-RED projects than was possible without FlowFuse.</p>
<p>We would be happy to talk to you more about how FlowFuse can help you get the most value from Node-RED. Please <a href="https://flowfuse.com/contact-us/">contact us</a> to learn more.</p>
https://flowfuse.com/blog/2022/12/flowforge-joins-openjs-foundation/FlowFuse Inc. becomes a member of the OpenJS FoundationSupporting the foundation that has given Node-RED a great home2022-12-13T12:00:00ZNick O'Leary<p>We're pleased to share the news we've joined the OpenJS Foundation to bolster our
support for the Node-RED community.</p>
<!--more-->
<p>One of our <a href="https://flowfuse.com/handbook/company/principles/#open-source-stewardship">founding principles</a> is
the importance of Open Source being at the core of what we do.</p>
<p>Node-RED has been part of the <a href="https://openjsf.org/">OpenJS Foundation</a> since it was formed in 2019.
The Foundation provides the project a vendor-neutral home and enables its open governance model that
allows anyone to get involved.</p>
<p>It also provides some vitally important resources to the community, such as the hosting for the
<a href="https://discourse.nodered.org/">community forum</a>, which regularly gets over 1.5 Million page views a
month.</p>
<p>With my Node-RED Project Lead hat on, I regularly see the impact the foundation has had on the growth
of the Node-RED community. These are things that may not always be obvious to our end users, but
we wouldn't be where we are today with them.</p>
<p>The success of what we're building with FlowFuse relies on a strong and healthy Node-RED community.
Becoming members of the Foundation allows us to provide more yet more support to Node-RED and the wider
JavaScript communities represented by the foundation.</p>
<p>For more information about this news, check out the <a href="https://openjsf.org/announcement/2022/12/13/welcoming-flowforge-to-the-openjs-foundation/">OpenJS Foundation blog post</a>.</p>
https://flowfuse.com/blog/2022/12/flowforge-1-1-2-released/FlowFuse 1.1.2 releasedRelease includes a fix for installing additional nodes into Node-RED.2022-12-09T12:00:00ZNick O'Leary<p>We've published a maintenance fix with an important fix for the Palette Manager in Node-RED.</p>
<!--more-->
<p>A <a href="https://github.com/FlowFuse/flowfuse/issues/1367">bug</a> was reported this week
where a user was unable to install additional nodes into their Node-RED project
using the editor's palette manager.</p>
<p>We tracked it down to an issue that was introduced in the 1.1 release, where the
project template lets you list nodes that should be blocked from being installed.
It was interpreting an empty list to mean <em>disallow everything</em>! Not quite the
intended behaviour.</p>
<p>Whilst tracking this down, we also spotted a bug (<a href="https://github.com/FlowFuse/flowfuse/issues/1379">#1379</a>)
around editing this same setting that made it tricky to work around without this
release being published.</p>
<p>These issues have now been fixed and FlowFuse 1.1.2 published.</p>
<h2 id="bug-fixes" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/12/flowforge-1-1-2-released/#bug-fixes"># </a> Bug Fixes</h2>
<p>In additional to the above issues, this release includes some further fixes around
the docker and helm components:</p>
<ul>
<li>Fix fileStore hostname by @flecoufle in <a href="https://github.com/FlowFuse/docker-compose/pull/59">#59</a></li>
<li>Fix healthcheck <a href="https://github.com/FlowFuse/docker-compose/pull/62">#62</a> <a href="https://github.com/FlowFuse/docker-compose/pull/63">#63</a> <a href="https://github.com/FlowFuse/helm/pull/74">#74</a></li>
</ul>
<h2 id="contributors" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/12/flowforge-1-1-2-released/#contributors"># </a> Contributors</h2>
<p>We'd like to thank the following people for their contributions to this release:</p>
<p><a href="https://github.com/flecoufle">flecoufle</a> for their work on <a href="https://github.com/FlowFuse/docker-compose/pull/59">#59</a></p>
<p>As an open-source project, we welcome community involvement in what we're building.
If you're interested in contributing, checkout our <a href="https://flowfuse.com/docs/contribute/">guide in the docs</a>.</p>
<h3 id="upgrading-flowfuse" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/12/flowforge-1-1-2-released/#upgrading-flowfuse"># </a> Upgrading FlowFuse</h3>
<p>This release has already been rolled out to <a href="https://app.flowfuse.com/">FlowFuse Cloud</a>.</p>
<p>If you installed a previous version of FlowFuse and want to upgrade, our documentation provides a
guide for <a href="https://flowfuse.com/docs/upgrade/">upgrading your FlowFuse instance</a></p>
<h3 id="getting-help" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/12/flowforge-1-1-2-released/#getting-help"># </a> Getting help</h3>
<p>Please check FlowFuse's <a href="https://flowfuse.com/docs/">documentation</a> as the answers to many questions are covered there.</p>
<p>If you hit any problems with the platform, please raise an <a href="https://github.com/FlowFuse/flowfuse/issues">issue on GitHub</a>.
That also includes if you have any feedback or feature requests.</p>
<p>Chat with us on the <code>#flowfuse</code> channel on the <a href="https://nodered.org/slack">Node-RED Slack workspace</a>.</p>
<p>You can also raise a support ticket by emailing <a href="mailto:support@flowfuse.com">support@flowfuse.com</a></p>
https://flowfuse.com/blog/2022/12/flowforge-gcp-https-set-up/Configure FlowFuse in Docker to secure all trafficUse Let's Encrypt and Acme Companion to quickly set up FlowFuse to encrypt all traffic2022-12-09T00:00:00ZRob Marcer<p>Following on from our <a href="https://flowfuse.com/blog/2022/10/ff-docker-gcp/">previous article</a> in which we covered how to run FlowFuse in Docker on Google’s Cloud Platform, today we are going to look at how to secure HTTP traffic to your FlowFuse server.</p>
<!--more-->
<h3 id="introduction" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/12/flowforge-gcp-https-set-up/#introduction"># </a> Introduction</h3>
<p>When we wrote the first part of this series FlowFuse didn't have an easy path to secure HTTP traffic. Happily, two versions of FlowFuse later and at least partially inspired by these blogs, we have added the configuration you need in Docker to use HTTPS with minimal work.</p>
<p>That addition makes our job of explaining this setup a lot easier, credit to our developers for seeing the value of having an easy implementation of HTTPS in FlowFuse as part of our <a href="https://flowfuse.com/blog/2022/10/flowforge-1-released/">1.0 build</a>.</p>
<p>To achieve secure HTTPS traffic we are employing a great service called <a href="https://letsencrypt.org/">Let's Encrypt</a>. In their own words, "Let’s Encrypt is a free, automated, and open certificate authority (CA), run for the public’s benefit". In practice Let's Encrypt will allow us to easily secure HTTPS traffic.</p>
<p>We are also utilising a Docker image called <a href="https://github.com/nginx-proxy/acme-companion">acme-companion</a> which makes the configuration of Let's Encrypt a breeze. To quote the project's own Github page "acme-companion is a lightweight companion container for nginx-proxy. It handles the automated creation, renewal and use of SSL certificates for proxied Docker containers through the ACME protocol". It's a great project and credit to the team over there for making it a lot easier to secure the internet.</p>
<p>Now we've covered our goals and the tools we are going to use let's configure our existing GCP VM to secure all web traffic.</p>
<h3 id="prerequisites" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/12/flowforge-gcp-https-set-up/#prerequisites"># </a> Prerequisites</h3>
<p>As mentioned above, you will need to be running FlowFuse version 1.0 or higher to follow this guide. If you are using an older version you can upgrade now using the <a href="https://flowfuse.com/docs/upgrade/">instructions here</a>.</p>
<h3 id="update-docker-compose" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/12/flowforge-gcp-https-set-up/#update-docker-compose"># </a> Update Docker Compose</h3>
<p>The first step is to edit our Docker compose file. We're using Nano again to edit files so we will run this command:</p>
<pre><code>sudo nano /opt/flowforge/docker-compose-1.1.1/docker-compose.yml
</code></pre>
<p>In the docker-compose.yml file, un-comment the following lines:</p>
<div style="position: relative">
<pre class="language-yaml"><code id="code-38" class="language-yaml"><span class="token punctuation">-</span> <span class="token string">"./certs:/etc/nginx/certs"</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-38" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<div style="position: relative">
<pre class="language-yaml"><code id="code-39" class="language-yaml"><span class="token punctuation">-</span> <span class="token string">"443:443"</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-39" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<div style="position: relative">
<pre class="language-yaml"><code id="code-40" class="language-yaml"> <span class="token key atrule">acme</span><span class="token punctuation">:</span><br /> <span class="token key atrule">image</span><span class="token punctuation">:</span> nginxproxy/acme<span class="token punctuation">-</span>companion<br /> <span class="token key atrule">volumes</span><span class="token punctuation">:</span><br /> <span class="token punctuation">-</span> <span class="token string">"/var/run/docker.sock:/var/run/docker.sock:ro"</span><br /> <span class="token punctuation">-</span> <span class="token string">"./acme:/etc/acme.sh"</span><br /> <span class="token key atrule">volumes_from</span><span class="token punctuation">:</span><br /> <span class="token punctuation">-</span> nginx<span class="token punctuation">:</span>rw<br /> <span class="token key atrule">environment</span><span class="token punctuation">:</span><br /> <span class="token punctuation">-</span> <span class="token string">"DEFAULT_EMAIL=mail@example.com"</span><br /> <span class="token key atrule">depends_on</span><span class="token punctuation">:</span><br /> <span class="token punctuation">-</span> <span class="token string">"nginx"</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-40" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>We should also redirect all traffic to use HTTPS, to do that un-comment the following in the nginx service section:</p>
<div style="position: relative">
<pre class="language-yaml"><code id="code-44" class="language-yaml"><span class="token key atrule">Environment</span><span class="token punctuation">:</span><br /> <span class="token punctuation">-</span> <span class="token string">"HTTPS_METHOD=redirect"</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-44" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>We now need to add the configuration for LetsEncrypt, edit the following lines to include a valid email address and the correct domain for where you are hosting your FlowFuse server:</p>
<div style="position: relative">
<pre class="language-yaml"><code id="code-48" class="language-yaml"><span class="token punctuation">-</span> <span class="token string">"DEFAULT_EMAIL=mail@example.com"</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-48" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<div style="position: relative">
<pre class="language-yaml"><code id="code-49" class="language-yaml"><span class="token punctuation">-</span> <span class="token string">"LETSENCRYPT_HOST=mqtt.example.com"</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-49" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<div style="position: relative">
<pre class="language-yaml"><code id="code-50" class="language-yaml"><span class="token punctuation">-</span> <span class="token string">"LETSENCRYPT_HOST=forge.example.com"</span></code></pre>
<button class="code-copy " data-clipboard-target="#code-50" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>Save and exit from that file, in Nano you can do that by pressing ‘control x’ then ‘y’ then the Return key.</p>
<h3 id="update-flowforge.yml" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/12/flowforge-gcp-https-set-up/#update-flowforge.yml"># </a> Update flowforge.yml</h3>
<p>Next, we need to edit the public_url for the MQTT broker:</p>
<pre><code>sudo nano /opt/flowforge/docker-compose-1.1.1/docker-compose.yml
</code></pre>
<p>Then replace ws:// with wss://</p>
<div style="position: relative">
<pre class="language-yaml"><code id="code-64" class="language-yaml"><span class="token key atrule">public_url</span><span class="token punctuation">:</span> wss<span class="token punctuation">:</span>//mqtt.flowforge<span class="token punctuation">-</span>demo.com</code></pre>
<button class="code-copy " data-clipboard-target="#code-64" style="position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none; opacity: 0.8;" title="Copy">
<span>
<span style="font-size: 15px; opacity: 0.8;" class="mdi mdi-content-copy"></span>
</span>
</button>
</div>
<p>Save and exit from that file, in Nano you can do that by pressing ‘control x’ then ‘y’ then the Return key.</p>
<h3 id="restart-your-docker-containers" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/12/flowforge-gcp-https-set-up/#restart-your-docker-containers"># </a> Restart your Docker containers</h3>
<p>OK, we should be ready to restart the Docker containers, run the command:</p>
<pre><code>sudo docker compose -p flowforge up -d
</code></pre>
<p>If you reload your FlowFuse root directory in a web browser you should now see that your traffic is encrypted using LetsEncypt.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/https-working-JYJ_qo7R2Z-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/https-working-JYJ_qo7R2Z-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="A screenshot from Safari web browser showing that the traffic to FlowFuse is encrypted" loading="lazy" decoding="async" src="https://flowfuse.com/img/https-working-JYJ_qo7R2Z-650.jpeg" width="650" height="553" /></picture></p>
<p>Nice! That’s it, you can now access your FlowFuse installation securely.</p>
<p>In the next and final part of this series of articles, we are going to look at how we can actually use FlowFuse including how to build flows and deploy and update them on Devices linked to a project.</p>
https://flowfuse.com/blog/2022/12/create-http-trigger-with-authentication/Create HTTP triggers with authenticationFrom any browser or command line you now have the ability to securely trigger your flows2022-12-07T00:00:00ZRob Marcer<p>Having an HTTP endpoint trigger your flows is very useful. From any browser or command line you now have the ability to trigger your flows.</p>
<!--more-->
<p>Doing so safely with authentication is slightly harder, but not a lot. FlowFuse makes it rather easy to accomplish.</p>
<h3 id="creating-the-http-flow" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/12/create-http-trigger-with-authentication/#creating-the-http-flow"># </a> Creating the HTTP flow</h3>
<p>When you start a project on FlowFuse, remember the project name. For this how-to we’ll use <code>example</code>. Open the editor and drag in the HTTP In node as well as the HTTP response node. Connect them, and add a debug node, which is connected to the “HTTP in” node.</p>
<p>First off; let’s set the HTTP in node properties:</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/edit-http-node-jVuc28Cc_x-512.avif 512w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/edit-http-node-jVuc28Cc_x-512.webp 512w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Shows the UI to edit the node's properties" loading="lazy" decoding="async" src="https://flowfuse.com/img/edit-http-node-jVuc28Cc_x-512.jpeg" width="512" height="320" /></picture></p>
<p>You can import this flow into your own project if you’d like:</p>
<pre><code>[{"id":"4faa84d37a52bb28","type":"group","z":"3c6e2dc732ada815","name":"Allow HTTP Post request to trigger a flow","style":{"label":!0},"nodes":["1fa26e0ed3ddec1a","45a180052e1a2f43","09347881f4fa4057"],"x":34,"y":79,"w":472,"h":122},{"id":"1fa26e0ed3ddec1a","type":"http in","z":"3c6e2dc732ada815","g":"4faa84d37a52bb28","name":"HTTP Trigger","url":"/http-trigger","method":"post","upload":!1,"swaggerDoc":"","x":130,"y":120,"wires":[["45a180052e1a2f43","09347881f4fa4057"]]},{"id":"45a180052e1a2f43","type":"http response","z":"3c6e2dc732ada815","g":"4faa84d37a52bb28","name":"Empty HTTP response","statusCode":"200","headers":{},"x":360,"y":120,"wires":[]},{"id":"09347881f4fa4057","type":"debug","z":"3c6e2dc732ada815","g":"4faa84d37a52bb28","name":"Print HTTP Request","active":!0,"tosidebar":!0,"console":!1,"tostatus":!1,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":360,"y":160,"wires":[]}]
</code></pre>
<p>Now I’ve opened a terminal and executed:</p>
<pre><code>curl -X POST https://example.flowforge.com/http-trigger
</code></pre>
<p>When there’s no output, that means it’s all good! There should be an empty message in the debug console in the Node-RED editor though</p>
<h3 id="securing-the-http-trigger-with-a-username-and-password" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/12/create-http-trigger-with-authentication/#securing-the-http-trigger-with-a-username-and-password"># </a> Securing the HTTP trigger with a username and password</h3>
<p>The problem with our trigger is that anyone with internet access could trigger it. That’s not a great idea. So let’s secure this endpoint with HTTP Basic Authentication. There are various ways to include a secure endpoint in Node-RED, we’ve built authentication directly into FlowFuse to make it easier for all users. On the FlowFuse project, go to settings and then to ‘Editor’. Under the section HTTP Auth you can set a username and password. You should generate both by a random string generator, and store the credentials somewhere safe. Restart the project to have the runtime pick up the changes, and the endpoint is secured!</p>
<p>Let’s validate the endpoint that worked a minute ago doesn’t anymore:</p>
<pre><code>curl -X POST https://example.flowforge.cloud/http-trigger
=> Unauthorized
</code></pre>
<p>Let’s get it working again: (replace <username> and <password> with the details from the sticky note)</password></username></p>
<pre><code>curl -X POST https://<username>:<password>@example.flowforge.cloud/http-trigger
</code></pre>
<p>That’s it! You now have a flow that’s protected by a username and password combination!</p>
https://flowfuse.com/blog/2022/12/node-red-flow-best-practice/Format your Node-RED flows for better team collaborationFrom formatting your flows for readability to providing clear comments on nodes and groups, a little bit of effort upfront can save your team a lot of headaches down the road2022-12-05T00:00:00ZRob Marcer<p>When it comes to working on Node-RED flows as part of a team, there are a few best practices that can make things go more smoothly.</p>
<!--more-->
<p>From formatting your flows for readability to providing clear comments on nodes and groups, a little bit of effort upfront can save your team a lot of headaches down the road. In this post, we'll cover some of the main things to keep in mind when working on Node-RED flows as part of a team.</p>
<h3 id="give-your-groups-descriptive-names" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/12/node-red-flow-best-practice/#give-your-groups-descriptive-names"># </a> Give your groups descriptive names</h3>
<p>Let’s start with <a href="https://nodered.org/docs/user-guide/editor/workspace/groups">grouping your flows</a> and giving each group a clear explanation of what it does. Compare the first to the second example below and consider how much more quickly you can understand what the flow is doing.</p>
<h4 id="this-is-not-helpful%2C-'time'-doesn't-tell-you-enough-to-understand-the-flow's-purpose." tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/12/node-red-flow-best-practice/#this-is-not-helpful%2C-'time'-doesn't-tell-you-enough-to-understand-the-flow's-purpose."># </a> This is not helpful, 'Time' doesn't tell you enough to understand the flow's purpose.</h4>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/name-bad-r0MRGV-oz5-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/name-bad-r0MRGV-oz5-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="This is not helpful, 'Time' doesn't tell you enough to understand the flow's purpose." loading="lazy" decoding="async" src="https://flowfuse.com/img/name-bad-r0MRGV-oz5-650.jpeg" width="650" height="104" /></picture></p>
<h4 id="this-is-much-better%2C-we-know-what-the-flow-is-doing-without-inspecting-the-nodes." tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/12/node-red-flow-best-practice/#this-is-much-better%2C-we-know-what-the-flow-is-doing-without-inspecting-the-nodes."># </a> This is much better, we know what the flow is doing without inspecting the nodes.</h4>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/name-good-NfYokdlmdu-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/name-good-NfYokdlmdu-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="This is much better, we know what the flow is doing without inspecting the nodes." loading="lazy" decoding="async" src="https://flowfuse.com/img/name-good-NfYokdlmdu-650.jpeg" width="650" height="98" /></picture></p>
<h3 id="explain-what-your-switches-do" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/12/node-red-flow-best-practice/#explain-what-your-switches-do"># </a> Explain what your switches do</h3>
<p>Try to make it obvious what each switch does without having to open the node editor. Ask a question in the switch's name and make a positive answer the top connection out.</p>
<h4 id="this-is-not-easy-to-understand%2C-what-does-the-switch-do%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/12/node-red-flow-best-practice/#this-is-not-easy-to-understand%2C-what-does-the-switch-do%3F"># </a> This is not easy to understand, what does the switch do?</h4>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/switch-bad-hMtSmGSxyO-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/switch-bad-hMtSmGSxyO-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="This is not easy to understand, what does the switch do?" loading="lazy" decoding="async" src="https://flowfuse.com/img/switch-bad-hMtSmGSxyO-650.jpeg" width="650" height="142" /></picture></p>
<h4 id="this-is-a-lot-better%2C-we-can-see-that-the-top-debug-should-be-triggered." tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/12/node-red-flow-best-practice/#this-is-a-lot-better%2C-we-can-see-that-the-top-debug-should-be-triggered."># </a> This is a lot better, we can see that the top debug should be triggered.</h4>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/switch-good-volyDrf83p-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/switch-good-volyDrf83p-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="This is a lot better, we can see that the top debug should be triggered." loading="lazy" decoding="async" src="https://flowfuse.com/img/switch-good-volyDrf83p-650.jpeg" width="650" height="118" /></picture></p>
<h3 id="where-possible-your-flows-should-work-down-the-canvas" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/12/node-red-flow-best-practice/#where-possible-your-flows-should-work-down-the-canvas"># </a> Where possible your flows should work down the canvas</h3>
<p>It makes it so much easier to understand what happens and in which order if your flows start at the top of the canvas and work down to the bottom.</p>
<h4 id="this-is-almost-unreadable%2C-it's-very-hard-to-work-out-the-order-of-the-groups." tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/12/node-red-flow-best-practice/#this-is-almost-unreadable%2C-it's-very-hard-to-work-out-the-order-of-the-groups."># </a> This is almost unreadable, it's very hard to work out the order of the groups.</h4>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/flowdown-bad-zh02DeDK7C-613.avif 613w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/flowdown-bad-zh02DeDK7C-613.webp 613w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="This is almost unreadable, it's very hard to work out the order of the groups." loading="lazy" decoding="async" src="https://flowfuse.com/img/flowdown-bad-zh02DeDK7C-613.jpeg" width="613" height="414" /></picture></p>
<h4 id="where-as-this-is-so-much-easier-to-understand." tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/12/node-red-flow-best-practice/#where-as-this-is-so-much-easier-to-understand."># </a> Where as this is so much easier to understand.</h4>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/flowdown-good--XV3bghhxA-477.avif 477w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/flowdown-good--XV3bghhxA-477.webp 477w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Where as this is so much easier to understand." loading="lazy" decoding="async" src="https://flowfuse.com/img/flowdown-good--XV3bghhxA-477.jpeg" width="477" height="515" /></picture></p>
<h3 id="use-link-nodes-rather-than-wires-to-join-groups" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/12/node-red-flow-best-practice/#use-link-nodes-rather-than-wires-to-join-groups"># </a> Use link nodes rather than wires to join groups</h3>
<p>Groups should not be joined using wires, it just looks untidy and quickly reduces readability of your flows.</p>
<h4 id="the-wire-is-blocking-the-title%2C-it-only-gets-worse-as-you-add-more-wires." tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/12/node-red-flow-best-practice/#the-wire-is-blocking-the-title%2C-it-only-gets-worse-as-you-add-more-wires."># </a> The wire is blocking the title, it only gets worse as you add more wires.</h4>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/link-bad-0c5UXs0s41-633.avif 633w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/link-bad-0c5UXs0s41-633.webp 633w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="The wire is blocking the title, it only gets worse as you add more wires." loading="lazy" decoding="async" src="https://flowfuse.com/img/link-bad-0c5UXs0s41-633.jpeg" width="633" height="252" /></picture></p>
<h4 id="you-can-see-the-group-titles-easily-now." tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/12/node-red-flow-best-practice/#you-can-see-the-group-titles-easily-now."># </a> You can see the group titles easily now.</h4>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/link-good-xNEmSp9xSF-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/link-good-xNEmSp9xSF-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="You can see the group titles easily now." loading="lazy" decoding="async" src="https://flowfuse.com/img/link-good-xNEmSp9xSF-650.jpeg" width="650" height="247" /></picture></p>
<h3 id="keep-your-groups-compact" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/12/node-red-flow-best-practice/#keep-your-groups-compact"># </a> Keep your groups compact</h3>
<p>Keeping your groups compact will save time when reading the flow. This is especially helpful if when viewed on a smaller screen.</p>
<h4 id="consider-how-hard-a-flow-made-of-groups-spaced-out-like-this-would-be-to-read-on-a-smaller-laptop-screen." tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/12/node-red-flow-best-practice/#consider-how-hard-a-flow-made-of-groups-spaced-out-like-this-would-be-to-read-on-a-smaller-laptop-screen."># </a> Consider how hard a flow made of groups spaced out like this would be to read on a smaller laptop screen.</h4>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/compact-bad-6HRfnPNsXO-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/compact-bad-6HRfnPNsXO-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Consider how hard a flow made of groups spaced out like this would be to read on a smaller laptop screen." loading="lazy" decoding="async" src="https://flowfuse.com/img/compact-bad-6HRfnPNsXO-650.jpeg" width="650" height="328" /></picture></p>
<h4 id="this-now-takes-up-less-space-and-is-arguably-easier-to-read-on-any-screen-size." tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/12/node-red-flow-best-practice/#this-now-takes-up-less-space-and-is-arguably-easier-to-read-on-any-screen-size."># </a> This now takes up less space and is arguably easier to read on any screen size.</h4>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/compact-good-iZ_Y8ErhrM-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/compact-good-iZ_Y8ErhrM-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="This now takes up less space and is arguably easier to read on any screen size." loading="lazy" decoding="async" src="https://flowfuse.com/img/compact-good-iZ_Y8ErhrM-650.jpeg" width="650" height="103" /></picture></p>
<h3 id="don%E2%80%99t-cross-beams-wires" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/12/node-red-flow-best-practice/#don%E2%80%99t-cross-beams-wires"># </a> Don’t cross <s>beams</s> wires</h3>
<p>Crossed wires are not only hard to read, they can lead to misinterpretation of what a flow actually does. Where possible don’t cross your wires, where you can’t avoid it try to make sure it’s easy for the reader to understand where wires cross as rather than join.</p>
<h4 id="this-is-confusing%2C-which-change-node-does-the-top-switch-output-link-to%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/12/node-red-flow-best-practice/#this-is-confusing%2C-which-change-node-does-the-top-switch-output-link-to%3F"># </a> This is confusing, which change node does the top switch output link to?</h4>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/wires-bad-lzzHDQMS8t-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/wires-bad-lzzHDQMS8t-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="This is confusing, which change node does the top switch output link to?" loading="lazy" decoding="async" src="https://flowfuse.com/img/wires-bad-lzzHDQMS8t-650.jpeg" width="650" height="103" /></picture></p>
<h4 id="this-is-better%2C-much-less-chance-of-confusing-the-change-nodes." tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/12/node-red-flow-best-practice/#this-is-better%2C-much-less-chance-of-confusing-the-change-nodes."># </a> This is better, much less chance of confusing the change nodes.</h4>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/wires-good-PQ2GBOwjuh-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/wires-good-PQ2GBOwjuh-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="This is better, much less chance of confusing the change nodes." loading="lazy" decoding="async" src="https://flowfuse.com/img/wires-good-PQ2GBOwjuh-650.jpeg" width="650" height="104" /></picture></p>
<h3 id="don%E2%80%99t-use-link-nodes-in-groups-where-avoidable" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/12/node-red-flow-best-practice/#don%E2%80%99t-use-link-nodes-in-groups-where-avoidable"># </a> Don’t use link nodes in groups where avoidable</h3>
<p>Excessive link nodes within groups can make a flow much harder to understand, where possible use wires to join nodes within a group.</p>
<h4 id="this-is-hard-to-read-and-you-will-end-up-checking-the-link-nodes-again-and-again." tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/12/node-red-flow-best-practice/#this-is-hard-to-read-and-you-will-end-up-checking-the-link-nodes-again-and-again."># </a> This is hard to read and you will end up checking the link nodes again and again.</h4>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/groupwires-bad-FQGzfBOIY6-575.avif 575w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/groupwires-bad-FQGzfBOIY6-575.webp 575w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="This is hard to read and you will end up checking the link nodes again and again." loading="lazy" decoding="async" src="https://flowfuse.com/img/groupwires-bad-FQGzfBOIY6-575.jpeg" width="575" height="235" /></picture></p>
<h4 id="functionally-identical-to-the-example-above%2C-it-should-only-take-a-few-seconds-to-understand-this-flow-now." tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/12/node-red-flow-best-practice/#functionally-identical-to-the-example-above%2C-it-should-only-take-a-few-seconds-to-understand-this-flow-now."># </a> Functionally identical to the example above, it should only take a few seconds to understand this flow now.</h4>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/groupwires-good-_NUcSy-4kN-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/groupwires-good-_NUcSy-4kN-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Functionally identical to the example above, it should only take a few seconds to understand this flow now." loading="lazy" decoding="async" src="https://flowfuse.com/img/groupwires-good-_NUcSy-4kN-650.jpeg" width="650" height="104" /></picture></p>
<h3 id="conclusion" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/12/node-red-flow-best-practice/#conclusion"># </a> Conclusion</h3>
<p>Working on Node-RED flows as part of a team doesn't have to be a headache. By following some simple best practices you can make collaboration smooth sailing for everyone involved. So next time you're starting work on a new Node-RED flow, remember these tips and make life easier for yourself and your teammates.</p>
https://flowfuse.com/blog/2022/12/community-news-11/Community News November 2022News from the FlowFuse and Node-RED communities2022-12-02T00:00:00ZRob Marcer<p>Welcome to the FlowFuse newsletter for November 2022, a monthly roundup of what’s been happening with both FlowFuse and the wider Node-RED community.</p>
<!--more-->
<p>If you've got something that you think we should share on our newsletters please <a href="mailto:contact@flowfuse.com">get it touch</a>.</p>
<p><a href="https://github.com/node-red/node-red/milestone/19"><strong>Node-RED Nears 3.1 Release</strong></a>
As we mentioned last month, the release of Node-RED 3.1 is expected very soon. 3.1 includes lots of great new features such as support for <a href="https://github.com/node-red/node-red/pull/3938">locking flows in the editor</a> and <a href="https://github.com/node-red/node-red/pull/3930">improving the user experience around hiding flows</a>. As an open source project the development of Node-RED is entirely dependent on individuals and companies giving their time to work towards each new release. If you'd like to know how you can get involved you can read more on the <a href="https://nodered.org/about/contribute/">Node-RED web site</a>.</p>
<p><a href="https://flowfuse.com/blog/2022/11/flowforge-1-1-released/"><strong>FlowFuse 1.1 Released</strong></a><br />
Version 1.1 of FlowFuse was released on 24th November. Our latest release included some great new features such as <a href="https://github.com/FlowFuse/flowfuse/issues/998">Persistent file storage</a>, the ability to <a href="https://flowfuse.com/docs/migration/node-red-tools/">import Node-RED snapshots</a> from outside of FlowFuse and a much improved interface to <a href="https://github.com/FlowFuse/flowfuse/issues/1046">deploy projects to your devices</a>. We're now working towards our final release of 2022 which is due just before Christmas. You can see what we are planning to deliver in that release and beyond on <a href="https://github.com/orgs/FlowFuse/projects/5">FlowFuse's project board</a>.</p>
<p>If you’d like to learn more about what else was included in 1.1 you can do so on our <a href="https://flowfuse.com/blog/2022/11/flowforge-1-1-released">blog post</a>, <a href="https://github.com/FlowFuse/flowfuse/releases/tag/v1.1.0">GitHub release page</a>, and <a href="https://www.youtube.com/watch?v=134iljE_urI">Youtube channel</a>.</p>
<p><a href="https://github.com/playfultechnology/node-redscape"><strong>Node-Redscape - 100% Free, Open-Source Escape Room Control Software</strong></a><br />
As we'll come to later in this newsletter, FlowFuse visited an Escape Room in Winchester as part of our team meet-up. Co-incidentally, a great Node-RED project came up a few days after our visit which we thought was worth sharing. In their own words <a href="https://github.com/playfultechnology/node-redscape">Node-Redscape</a> 'provides a set of templates, flows, and examples that turn Node-RED into a complete Escape Room automation system'. Very topical for us and also seems like a great project. You can learn more about the project on <a href="https://www.youtube.com/watch?v=f9yYDxqK_2E">Youtube</a> as well as on <a href="https://github.com/playfultechnology/node-redscape">Github</a>.</p>
<p><strong>FlowFuse team meetup</strong>
FlowFuse is a fully remote team, we currently have a strong skew towards western Europe but we are in the process of adding team members in each of the continents. On that point, any great Product Managers who live in Antarctica are encouraged to <a href="https://boards.greenhouse.io/flowfuse/jobs/4717778004">apply for a job with us</a>! Remote work is great but it's also valuable to get everyone together in the real world from time to time. FlowFuse had such a meet up last month in Winchester, UK. We came from near and far and took the opportunity to have productive round-table discussions about some features we are working towards in 1.2 and beyond. We also dropped into <a href="https://cluecapers.co.uk/">Clue Capers</a>, a great Escape Room in the center of Winchester who provided the photo below to mark the occasion.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/clue-capers-vokh-bWOum-650.avif 650w, https://flowfuse.com/img/clue-capers-vokh-bWOum-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/clue-capers-vokh-bWOum-650.webp 650w, https://flowfuse.com/img/clue-capers-vokh-bWOum-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/clue-capers-vokh-bWOum-650.jpeg 650w, https://flowfuse.com/img/clue-capers-vokh-bWOum-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="The FlowFuse team pictured during our visit to Clue Capers" loading="lazy" decoding="async" src="https://flowfuse.com/img/clue-capers-vokh-bWOum-650.jpeg" width="1300" height="886" /></picture></p>
<p><a href="https://flowfuse.com/team/"><strong>FlowFuse Team News</strong></a><br />
We are currently recruiting a <a href="https://boards.greenhouse.io/flowfuse/jobs/4717778004">Product Manager</a>, and a <a href="https://boards.greenhouse.io/flowfuse/jobs/4700809004">Senior Community Manager</a>. You can view any of the roles we currently have open and apply on our <a href="https://boards.greenhouse.io/flowfuse">Jobs page</a>.</p>
<p><a href="https://app.flowfuse.com/account/create?code=RELEASE11"><strong>Try FlowFuse for Free</strong></a><br />
As a thank you for reading our newsletters we’d like to offer you a free, small project for one month on our managed FlowFuse platform when you create a new team. To get this discount please follow <a href="https://app.flowfuse.com/account/create?code=RELEASE11">this link</a> or use the code RELEASE11 when on the payment page after creating a new team. As an open source project you can also use <a href="https://flowfuse.com/docs/install/">FlowFuse</a> for free, forever.</p>
https://flowfuse.com/blog/2022/11/scaling-node-red-with-diy-tooling/Challenges scaling Node-RED with DIY toolingNode-RED is very easy to get up and running for your first instance but what about your 100th?2022-11-30T00:00:00ZZJ van de Weg<p>In this post, I'm going to share some of the challenges customers face when
scaling Node-RED with Do-It-Yourself tooling.</p>
<!--more-->
<p>Specifically, we'll talk about
common threads in their journey building their own tooling around Node-RED, its
flows, and deploying them. Node-RED is a visual programming environment for
wiring together hardware devices, APIs and online services in a single
application. It's great because it's flexible enough to be used by both
beginners and experts alike; however, going from one instance of Node-RED to 100
isn't for the faint-hearted.</p>
<h3 id="zero-to-hero-in-a-few-days" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/11/scaling-node-red-with-diy-tooling/#zero-to-hero-in-a-few-days"># </a> Zero to hero in a few days</h3>
<p>If you’re new to Node-RED and are just getting started, the first step is simple:
go to <a href="https://nodered.org/">nodered.org</a>, download, install and run. There’s no
need to configure anything or set up credentials or security or alerts. You can
get started with Node-RED straight away by simply running it on your machine.
The guides and scripts provided on Node-RED or are more than enough to get
started. You'll dive right in and start developing your flows.</p>
<h3 id="onto-the-second-instance" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/11/scaling-node-red-with-diy-tooling/#onto-the-second-instance"># </a> Onto the second instance</h3>
<p>The next instance is a simple copy of the first. You'll need to make sure that
you are installing the same version on both instances, and that any
configuration files (such as the <code>settings.js</code>) are also in sync.</p>
<p>The second instance improves the first equally. Docs are read again,
improvements are made, and copied over. Life's good! Although there's a slight
itch to start automating the setup, it's ignored. Just too many open questions
on how to achieve it: write scripts in bash? Or can we use Node-RED to manage
Node-RED? Automation can wait, there's new flows to implement!</p>
<h3 id="wake-up-call%3B-how-many-of-them-do-we-have%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/11/scaling-node-red-with-diy-tooling/#wake-up-call%3B-how-many-of-them-do-we-have%3F"># </a> Wake-up call; how many of them do we have?</h3>
<p>There's nothing like a good ol' wake-up call to get you back on track. One of
our team members asked a questions about a buggy flow you've got no recollection
of. During the investigation there's issues left and right; it's running a much
older version, missing standard packages, the settings are out of date, and the
timezone not set to UTC? Adoption of Node-RED is going quite well, it's useful
and effective. Gets the job done without fuss. But now there's toil in
maintaining them; ensure the right tooling is build, properly documented, it
needs dashboards and overviews, lots of work to be done. Not quite business
related, but Node-RED is important for the company, the bosses sure would
approve spending 2 months building these tools!</p>
<p>But then something happened—there was a higher priority project to be picked up.
Some tooling could be written for a couple of hours a month, but not two
dedicated months to get it in tip top shape. Better than nothing! Built a
dashboard in Node-RED to keep track of all devices, there's some scripts and a
few flows that aid in monitoring and maintenance. Scaling further is possible,
but confidence in the tooling isn't sky high.</p>
<h3 id="data-extraction-at-scale%3B-now-there's-over-100" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/11/scaling-node-red-with-diy-tooling/#data-extraction-at-scale%3B-now-there's-over-100"># </a> Data extraction at scale; now there's over 100</h3>
<p>At FlowFuse we've got regular conversations with customers managing 100s of
devices. Scaling to that many devices and runtimes requires hours of development
each week alongside monitoring, maintenance, and auditing.</p>
<p>As a side effect of investing more time into Node-RED and its ecosystem the
organisation has developed a few standards. Standard custom nodes that are
pre-installed (👋 <code>moment.js</code>), a style guide published for developing flows,
maybe even flow linting: https://github.com/node-red/nrlint</p>
<p>The security model is fairly decent. One just hopes the
<a href="https://nl.wikipedia.org/wiki/Chief_Information_Security_Officer">CISO</a> doesn't
inspects them, but it's a fair bet they won't; we're far away from the
headquarters, right?</p>
<p>Many other edge cases itch in the back of our heads, but we can't focus on those right now.</p>
<h3 id="conclusion" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/11/scaling-node-red-with-diy-tooling/#conclusion"># </a> Conclusion</h3>
<p>Node-RED is a great tool, it's got many built-in features that make it easy to
get started with no coding experience necessary. Running it at scale, in a
production environment can require a lot of sys-ops and dev-ops time and we
think FlowFuse is a great solution to keep that admin and tech debt in check.</p>
<p>If you're running into these challenges we believe we can help, you can adopt
our <a href="https://flowfuse.com/docs/install/">free and open source edition</a>.</p>
https://flowfuse.com/blog/2022/11/respin-docker-compose-01/Re-spin of Docker-Compose install packageAdding ability to locally build file-server container2022-11-25T00:00:00ZBen Hardill<p>After <a href="https://flowfuse.com/blog/2022/11/flowforge-1-1-released/">yesterdays 1.1.0 FlowFuse release</a> we noticed a few minor issues with the docker-compose install instructions.</p>
<p>We had relied on the fact we are now publishing container images to Docker Hub to install the new <code>flowforge/file-server</code> container. At this time we are only building images for amd64 and arm64. Further, it was only tagged them with the current release number.</p>
<p>To remedy this we tagged v1.1.1 of the docker-compose project in which we have included the required <code>Dockerfile</code> and resources to build the <code>flowforge/file-server</code> locally, updated the <code>build-containers.sh</code> script to build this container. We will also build the published containers for armv7 and include a latest tag going forward.</p>
https://flowfuse.com/blog/2022/11/flowforge-1-1-released/FlowFuse 1.1 released with persistent file storageA new set of features to improve FlowFuse as the best solution for running Node-RED in production in a secure, scalable, and team-based environment.2022-11-24T18:00:00ZRob Marcer<p>Persist files on your FlowFuse Projects, publish locally developed flows to dozens of Devices in a few clicks, and use our new interface for managing Project Deployments.</p>
<!--more-->
<p>We're pleased to announce version 1.1 is now available! The latest release of the FlowFuse application contains new features, many improvements, and bug fixes. Keep reading for the details of what's in this release or you can watch our 1 minute roundup video of the new release above.</p>
<h2 id="features" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/11/flowforge-1-1-released/#features"># </a> Features</h2>
<p><a href="https://github.com/FlowFuse/flowfuse/issues/998">Persistent File Storage</a> We've had a great deal of feedback
from our customers that being able to persist files in a project is a vital feature
in Node-RED. In FlowFuse 1.1 flows can now create and persist files within
your Projects. We know those files are used in many creative ways and we're looking
forward to seeing how users improve their Projects using this new feature.</p>
<p><a href="https://flowfuse.com/docs/migration/node-red-tools/">Import Snapshots from Outside FlowFuse</a> Developers may wish to
work on Node-RED in a local environment but want an easy path to share that with their team. You can now link your Node-RED instances running outside of FlowFuse and push Snapshots directly into your FlowFuse Projects to leverage FlowFuse fully. With this new feature we've made it effortless to push a local build of a project to FlowFuse for deployment to your staging and production FlowFuse instances.</p>
<h2 id="improvements" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/11/flowforge-1-1-released/#improvements"># </a> Improvements</h2>
<p><a href="https://github.com/FlowFuse/flowfuse/issues/1046">Project Deployments UX</a>
We've reworked the interface for managing your FlowFuse Deployments of Node-RED.
We are seeing FlowFuse users deploying their Projects to edge devices at scale.
This is another step towards making it easier for users to manage a large quantity
of devices in their Projects.</p>
<p>When users change their username, email address, or password they'll now be
notified through email of changes to ensure they were made by the
user.</p>
<p>In this release a lot of effort went into the install process, specifically the
local install method. First and foremost; a default Stack and Template will be
installed automatically. That will ensure users get up and running with
Node-RED more quickly. Administrators of each platform can still change Stacks
and Templates when needed. Secondly, the installer now auto generates the
configuration file for Mosquitto, the MQTT broker FlowFuse uses. This again should save
administrators time when installing FlowFuse.</p>
<h2 id="bug-fixes" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/11/flowforge-1-1-released/#bug-fixes"># </a> Bug Fixes</h2>
<p>The v1.0.1 release included a bug fix where <a href="https://github.com/FlowFuse/flowfuse/issues/1186">snapshot rollbacks</a>
didn't work, which has also been included in v1.1 onwards.</p>
<p>We've fixed the following bugs in this release.</p>
<ul>
<li>
<p>When installing the stack during a FlowFuse installation the process would quit on Windows <a href="https://github.com/FlowFuse/installer/issues/62">#62</a></p>
</li>
<li>
<p>After accepting an invite to join a team, users are no longer seeing a blank page <a href="https://github.com/FlowFuse/flowfuse/issues/1208">#1208</a></p>
</li>
<li>
<p>Pagination on device deployments wasn't showing all devices <a href="https://github.com/FlowFuse/flowfuse/issues/1207">#1207</a></p>
</li>
<li>
<p>Markdown rendering when selecting the project type wasn't quite working, fixed now! <a href="https://github.com/FlowFuse/flowfuse/issues/1171">#1171</a></p>
</li>
<li>
<p>Continuous spinner in UI body when entering a new (short) password <a href="https://github.com/FlowFuse/flowfuse/issues/1280">#1280</a></p>
</li>
<li>
<p>Friendly stack name not shown in the Change Project Stack option list <a href="https://github.com/FlowFuse/flowfuse/issues/1169">#1169</a></p>
</li>
<li>
<p>The stacks view in the admin area didn't render properly <a href="https://github.com/FlowFuse/flowfuse/issues/1260">#1260</a></p>
</li>
<li>
<p>Like the deployments page, pagination for stacks was broken. <a href="https://github.com/FlowFuse/flowfuse/issues/1164">#1164</a></p>
</li>
<li>
<p>Several UX and UI bugs got polished away!</p>
</li>
</ul>
<h2 id="contributors" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/11/flowforge-1-1-released/#contributors"># </a> Contributors</h2>
<p>We'd like the thank the following for their contributions to this release:</p>
<p><a href="https://github.com/mikermcneil">mikermcneil</a> for their work on <a href="https://github.com/FlowFuse/flowfuse/pull/1301">#1301</a></p>
<p>As an open-source project, we welcome community involvement in what we're building.
If you're interested in contributing, checkout our <a href="https://flowfuse.com/docs/contribute/">guide in the docs</a>.</p>
<h3 id="try-it-out" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/11/flowforge-1-1-released/#try-it-out"># </a> Try it out</h3>
<p>As said before, a lot of effort went into the local installer. We're confident
you can have your own FlowFuse running locally in about 30 minutes.
<a href="https://flowfuse.com/docs/install/local/">Get started right away!</a>
(<a href="https://flowfuse.com/docs/install/docker/">Docker</a> and <a href="https://flowfuse.com/docs/install/kubernetes/">Kubernetes</a>
are available too!)</p>
<p>If you'd rather use our hosted offering: <a href="https://app.flowfuse.com/account/create?code=RELEASE11">Sign up for FlowFuse Cloud</a>
with the coupon <strong>RELEASE11</strong> to get your first project free for a month.</p>
<h3 id="upgrading-flowfuse" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/11/flowforge-1-1-released/#upgrading-flowfuse"># </a> Upgrading FlowFuse</h3>
<p><a href="https://app.flowfuse.com/">FlowFuse Cloud</a> is already running 1.1. To use
persisted files you'll need to upgrade your projects stack. You'll be prompted
to do so on the project page.</p>
<p>If you installed a previous version of FlowFuse and want to upgrade, our documentation provides a
guide for <a href="https://flowfuse.com/docs/upgrade/">upgrading your FlowFuse instance</a></p>
<h3 id="getting-help" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/11/flowforge-1-1-released/#getting-help"># </a> Getting help</h3>
<p>Please check FlowFuse's <a href="https://flowfuse.com/docs/">documentation</a> as the answers to many questions are covered there.</p>
<p>If you hit any problems with the platform please raise an <a href="https://github.com/FlowFuse/flowfuse/issues">issue on GitHub</a>.
That also includes if you have any feedback or feature requests.</p>
<p>Chat with us on the <code>#flowfuse</code> channel on the <a href="https://nodered.org/slack">Node-RED Slack workspace</a>.</p>
<p>You can also raise a support ticket by emailing <a href="mailto:support@flowfuse.com">support@flowfuse.com</a></p>
https://flowfuse.com/blog/2022/11/community-news-10/Community News October 2022News from the FlowFuse and Node-RED communities2022-11-04T00:00:00ZRob Marcer<p>Welcome to the FlowFuse newsletter for October 2022, a monthly roundup of what’s happening with both FlowFuse and the wider Node-RED community.</p>
<!--more-->
<p>If you've got something that you'd like us to share please email <a href="mailto:contact@flowfuse.com">contact@flowfuse.com</a>.</p>
<p><a href="https://flowfuse.com/blog/2022/10/flowforge-1-released/"><strong>FlowFuse 1.0 Released</strong></a><br />
Version 1.0 was released on 27th October. Our latest release represents our vision of the base set of features needed for you to get great value from using FlowFuse in a production environment. That's not to say we are done, we will continue to add features, improve our interfaces and fix bugs with the same enthusiasm as we've worked towards 1.0. We'd like to hear your feedback on what we will be including in <a href="https://github.com/orgs/FlowFuse/projects/5">1.1 and beyond</a>.</p>
<p>If you’d like to learn more about what else was included in 1.0 you can do so on our <a href="https://flowfuse.com/blog/2022/10/flowforge-1-released">blog post</a>, on our <a href="https://github.com/FlowFuse/flowfuse/releases/tag/v1.0.0">GitHub release page</a> and on our <a href="https://www.youtube.com/watch?v=5TLT7CQR7iI">Youtube channel</a>. We’d also love for more of you to get involved in the development of FlowFuse, <a href="https://github.com/FlowFuse/flowfuse/blob/main/CONTRIBUTING.md">contributions to the code</a> and <a href="https://github.com/FlowFuse/flowfuse/issues">bug reports</a> are really appreciated.</p>
<p><a href="https://github.com/node-red/node-red/milestone/19"><strong>Node-RED Nears 3.1 Release</strong></a>
The next release of Node-RED has some great new features including support for <a href="https://github.com/node-red/node-red/pull/3938">locking flows in the editor</a> and <a href="https://github.com/node-red/node-red/pull/3930">improving the user experience around hiding flows</a>. We'd expect the first 3.1 beta to be available in November with a full release following shortly afterwards.</p>
<p><a href="https://flowfuse.com/blog/2022/10/seed-round-bring-node-red-to-enterprise/"><strong>FlowFuse raises $7.25M to bring Node-RED to the Enterprise</strong></a><br />
Earlier this week, we announced a $7.25M seed round led by <a href="https://www.cotacapital.com/knowledgecapital/flowforge-closes-the-gap-between-it-and-ot">Cota Capital</a>, joined by Westwave Capital, Uncorrelated Ventures, and Open Core Ventures. This brings a huge amount of extensive knowledge and experience in IoT, open source, enterprise-ready software solutions. You can read more about what this investment means for FlowFuse in this <a href="https://techcrunch.com/2022/11/03/flowforge-nabs-7-2m-to-help-companies-integrate-iot-using-node-red">TechCrunch article</a>.</p>
<p><a href="https://stevesnoderedguide.com/node-red-dashboard"><strong>Node-Red Dashboard - Beginners Guide</strong></a><br />
It's great to see members of the Node-RED community taking their personal time to help us all build better projects. This write up takes you through the basics of creating your first Dashboard through to more advanced techniques to help your interfaces look professional and provide great user experiences.</p>
<p><a href="https://flowfuse.com/team/"><strong>FlowFuse Team News</strong></a><br />
We are currently recruiting <a href="https://boards.greenhouse.io/flowfuse/jobs/4463977004">NodeJS Developers</a>, a <a href="https://boards.greenhouse.io/flowfuse/jobs/4717778004">Product Manager</a>, a <a href="https://boards.greenhouse.io/flowfuse/jobs/4687876004">Recruiter / PeopleOps Manager</a> and a <a href="https://boards.greenhouse.io/flowfuse/jobs/4700809004">Senior Community Manager</a>. You can view any of the roles we currently have open and apply on our <a href="https://boards.greenhouse.io/flowfuse">Jobs page</a>.</p>
<p>We'd also like to welcome <a href="https://github.com/Pezmc">Pez Cuckow</a> who joined FlowFuse as a Senior Software Engineer in October.</p>
<p><a href="https://app.flowfuse.com/account/create?code=RELEASE1"><strong>Try FlowFuse for Free</strong></a><br />
As a thank you for reading our newsletters we’d like to offer you a free, small project for one month on our managed FlowFuse platform when you create a new team. To get this discount please follow <a href="https://app.flowfuse.com/account/create?code=RELEASE010">this link</a> or use the code RELEASE1 when on the payment page after creating a new team. As an open source project you can also use <a href="https://flowfuse.com/docs/install/">FlowFuse</a> for free, forever.</p>
https://flowfuse.com/blog/2022/10/seed-round-bring-node-red-to-enterprise/FlowFuse raises $7.25M Seed Round to bring Node-RED to the EnterpriseAllowing all developers to integrate IT and OT through low-code2022-11-03T17:00:00ZZJ van de Weg<p>Since the <a href="https://flowfuse.com/blog/2021/04/first-deploy/">launch of FlowFuse</a> in April 2021 our goal has been to
build a low-code, enterprise-ready development platform based on Node-RED. We
wanted to make it easier for enterprises to adopt, integrate, and scale Node-RED
into their existing environments. We published our <a href="https://flowfuse.com/blog/2022/01/flowforge-01-released/">first version</a>
at the start of this year and have continued the journey to the
<a href="https://flowfuse.com/blog/2022/10/flowforge-1-released/">launch of FlowFuse v1.0</a> just last week. Each of these releases
has moved us towards our goal of creating a platform for integrating the
IT and OT for all organizations, built around an open core.</p>
<!--more-->
<h3 id="flowfuse-is-node-red-for-the-enterprise" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/10/seed-round-bring-node-red-to-enterprise/#flowfuse-is-node-red-for-the-enterprise"># </a> FlowFuse is Node-RED for the enterprise</h3>
<p>Node-RED is an incredible tool that has allowed many organizations to quickly
and easily integrate both their IT and OT. The sheer range and variety of
solutions created with Node-RED today go far beyond what we imagined. But we’ve
also seen the challenges faced by companies wanting to take their Node-RED
solutions into production and beyond.</p>
<p>This is where FlowFuse comes in. It addresses those challenges by adding
security, collaboration and deployment capabilities.</p>
<h3 id="our-%247.25m-seed-round" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/10/seed-round-bring-node-red-to-enterprise/#our-%247.25m-seed-round"># </a> Our $7.25M Seed Round</h3>
<p>Today, we’re super excited to announce a $7.25M seed round led by Cota Capital,
joined by Westwave Capital, Uncorrelated Ventures, and Open Core Ventures. This
brings a huge amount of extensive knowledge and experience in IoT, open source,
enterprise-ready software solutions.</p>
<p>This investment will enable us to continue growing the team and platform to
realize our vision of FlowFuse being the best way to achieve enterprise-ready
Node-RED. It will enable us to invest back into the core Node-RED project to
further its development. One of our core company principles is around Open
Source Stewardship - the success of FlowFuse relies on a strong and successful
Node-RED community.</p>
<p>We’ll be bringing more collaboration features to the FlowFuse platform to
enable true collaborative, team-based working. We’ll expand our
<a href="https://flowfuse.com/docs/user/concepts/#device">Devices offering</a> to make it
far easier to run Node-RED wherever it suits your use-case, from data center to
remote edge locations.</p>
<p>Above all, we’ll be building a company that is open, sustainable, and fun to
work at. We already have some job openings available - check out our
<a href="https://boards.greenhouse.io/flowfuse">jobs board</a> if you’re interested in joining our
team.</p>
<p>If you’re interested in learning more about what we’re doing, or have any
questions, please do <a href="https://flowfuse.com/contact-us/">get in touch</a>!</p>
https://flowfuse.com/blog/2022/10/flowforge-1-released/FlowFuse 1.0 releasedFlowFuse at 1.0, a huge milestone for us.2022-10-27T18:00:00ZRob Marcer<p>Predefined environment variables for your Instances and Devices, manage your Project's modules and import your existing flows (and credentials) into your FlowFuse <a href="https://flowfuse.com/docs/user/concepts/#instance">Projects</a>.</p>
<!--more-->
<!-- Keep reading for the details of what's in this release or you can watch our 1 minute roundup video of the new release above. -->
<p>We're pleased to announce version 1.0 FlowFuse is now available. Keep reading for a promotion code to get your first month free on FlowFuse. Version 1.0 represents our vision of the base set of features needed for you to get great value from using FlowFuse in a production environment. That's not to say we are done, we will continue to add features, improve our interfaces and fix bugs with the same enthusiasm as we've worked towards 1.0. We'd like to hear your feedback on what we will be including in <a href="https://github.com/orgs/FlowFuse/projects/5">1.1 and beyond</a>.</p>
<h2 id="features" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/10/flowforge-1-released/#features"># </a> Features</h2>
<p><a href="https://github.com/FlowFuse/flowfuse/issues/841">Standard Environment Variables set for both Projects and Devices</a></p>
<p>Projects now get a set of predefined environment variables that can be used by their flows. These give your flows access to the projects unique id and name. When the flows are deployed to <a href="https://flowfuse.com/docs/user/concepts/#device">devices</a>, they also get the device's id and name. That makes is easier to deploy flows across multiple devices and have each able to identify itself.</p>
<p><a href="https://github.com/FlowFuse/flowfuse/issues/405">Add additional node modules to your projects</a>
This feature allows you to pre-define additional Node-RED nodes and node modules you may want to be installed in your FlowFuse project, making it easier to manage.</p>
<p><a href="https://github.com/FlowFuse/flowfuse/issues/835">Import existing projects into FlowFuse</a></p>
<p>You can now import your existing flow and credentials files straight into your FlowFuse project - making it really easy to move your existing projects into the platform.</p>
<h2 id="improvements" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/10/flowforge-1-released/#improvements"># </a> Improvements</h2>
<p>We've made a number of improvements to the overall experience of running FlowFuse.</p>
<ul>
<li>Editable Stack labels <a href="https://github.com/FlowFuse/flowfuse/issues/915">#915</a></li>
<li>Check for suitable version of Node on Devices <a href="https://github.com/FlowFuse/device-agent/issues/37">#37</a></li>
<li>Realtime Project status details in Project overview <a href="https://github.com/FlowFuse/flowfuse/issues/990">#990</a></li>
<li>Improve Template creation & Edit Project Settings UX <a href="https://github.com/FlowFuse/flowfuse/issues/1041">#1041</a></li>
</ul>
<h2 id="bug-fixes" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/10/flowforge-1-released/#bug-fixes"># </a> Bug Fixes</h2>
<p>We've fixed the following bugs in this release.</p>
<ul>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/1143">Pressing return in search box reloads page</a></li>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/1126">Vue Router Warn</a></li>
<li><a href="https://github.com/FlowFuse/forge-ui-components/issues/58">Kebab menu in Settings breaks</a></li>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/1096">flowforge-nr-launcher missing try/catch on http request</a></li>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/1145">Invite with + in email address is incorrectly sanitised</a></li>
<li><a href="https://github.com/FlowFuse/forge-ui-components/issues/59">Table does not sort correctly when empty fields are present</a></li>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/929">4xx Errors not shown in App</a></li>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/1076">Inconsistent errors returned from the API</a></li>
<li><a href="https://github.com/FlowFuse/flowforge-nr-launcher/issues/77">Module install not working on windows</a></li>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/1038">Avatar lettering is mis-allinged when only rendering 1 character</a></li>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/968">it.only is not prohibited</a></li>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/966">No feedback when an API error occurs editing user</a></li>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/1040">Start action is available on a running project</a></li>
<li></li>
</ul>
<h2 id="contributors" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/10/flowforge-1-released/#contributors"># </a> Contributors</h2>
<p>We'd like the thank the following for their contributions to this release:</p>
<p><a href="https://github.com/Jozefik">Jozefik</a> for their work on <a href="https://github.com/FlowFuse/flowfuse/pull/1082">Adding limits to admin panel</a>.</p>
<p>As an open-source project, we welcome community involvement in what we're building. If you're interested in contributing, checkout our <a href="https://flowfuse.com/docs/contribute/">guide in the docs</a>.</p>
<h3 id="try-it-out" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/10/flowforge-1-released/#try-it-out"># </a> Try it out</h3>
<p><a href="https://app.flowfuse.com/account/create?code=RELEASE1">Sign up for FlowFuse-Managed Premium</a> with this link or at the checkout enter the code <strong>RELEASE1</strong> to get your first project free for a month. As an open source project you can also use <a href="https://flowfuse.com/docs/install/">FlowFuse-Community</a> for free, forever.</p>
<h3 id="upgrading-flowfuse" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/10/flowforge-1-released/#upgrading-flowfuse"># </a> Upgrading FlowFuse</h3>
<p>Our managed <a href="https://app.flowfuse.com/">FlowFuse</a> is already running 1.0. Upgrade your project Stacks to the latest version to make sure you get all the latest changes.</p>
<p>If you installed a previous version of FlowFuse and want to upgrade, our documentation provides a
guide for <a href="https://flowfuse.com/docs/upgrade/#upgrading-flowfuse">upgrading FlowFuse on a local server</a>.</p>
<h3 id="getting-help" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/10/flowforge-1-released/#getting-help"># </a> Getting help</h3>
<p>If you hit any problems with the platform, or have questions to ask, please raise an <a href="https://github.com/FlowFuse/flowfuse/issues">issue on GitHub</a>.
That also includes if you have any feedback or feature requests.</p>
<p>Customers of FlowFuse Cloud can raise a ticket by emailing support@flowfuse.com</p>
<p>We also have a <code>#flowfuse</code> channel on the <a href="https://nodered.org/slack">Node-RED Slack workspace</a>.</p>
https://flowfuse.com/blog/2022/10/db-migration-01/Scheduled maintenance: Database encryption October 2022Moving to encrypted PostgreSQL storage2022-10-18T00:00:00ZBen Hardill<p>As part of an on-going security <a href="https://flowfuse.com/product/security/#data-at-rest">review</a> of the FlowFuse Cloud offering we discovered that the backend database was not using encrypted storage. In keeping with industry best practices we plan to migrate the database to a new instance using encrypted at rest storage.</p>
<!--more-->
<h2 id="impact" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/10/db-migration-01/#impact"># </a> Impact</h2>
<p>Customers' Node-RED instances will remain running, though any features that depend on FlowFuse will not operate as expected during the migration. This includes user sessions, project and team management, as well as the project nodes for inter-project communication.</p>
<p>Self-hosted installations are unaffected by this change.</p>
<h2 id="when" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/10/db-migration-01/#when"># </a> When</h2>
<p>The migration will be on 26 October 2022 at 22:00 UTC and is expected to take under 2 hours. The platform will be available as soon as the migration is complete.</p>
<p>We will post updates during the migration period to our Twitter account <a href="https://twitter.com/flowforgeinc">@FlowFuseInc</a>.</p>
https://flowfuse.com/blog/2022/10/ff-docker-gcp/Install FlowFuse Docker on Google CloudStep by step instructions to get FlowFuse Docker running on Google Cloud2022-10-14T00:00:00ZRob Marcer<p>As part of our preparations for FlowFuse 1.0 we have been testing various real world scenarios to see where we can add to our documentation and where we might be able to improve our releases to make the install process easier for users. As a benefit of that testing we have been able to hone these installation processes and we wanted to share one of those with you today.</p>
<!--more-->
<p>In this first of three articles, we are going to run through the process for installing FlowFuse on Google Cloud Platform (GCP) within a virtual machine (VM) using Docker.</p>
<p>We have set ourselves the goal of delivering a production environment. We want this installation benefit from:</p>
<ul>
<li>Email alerts (emails to users when they are added to teams etc)</li>
<li>HTTPS access to the install</li>
<li>FlowFuse <a href="https://flowfuse.com/docs/user/concepts/#device">Device</a> deployment via the included MQTT server that comes in our Docker build</li>
</ul>
<p>We will follow up with a second article covering the process of getting HTTPS running then we will close out the series by covering how to use key features of FlowFuse including <a href="https://flowfuse.com/docs/user/concepts/#device">Devices</a>.</p>
<h1 id="prerequisites" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/10/ff-docker-gcp/#prerequisites"># </a> Prerequisites</h1>
<ul>
<li>A domain name - We've registered flowforge-demo.com to demonstrate these steps</li>
<li>A DNS provider - Our Domain registrar provides a basic DNS service for free</li>
<li>A GCP account - Google will often give you free service credits on sign up so setting up FlowFuse on GCP should not cost you anything for at least a few weeks</li>
<li>An email provider which will allow SMTP connections to send email - To manage users on your FlowFuse platform you will need to be able to send emails to them. We have used a Google Workspace account for this purpose</li>
</ul>
<h1 id="gcp-vm-creation" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/10/ff-docker-gcp/#gcp-vm-creation"># </a> GCP VM Creation</h1>
<p>Create a GCP account, once logged in navigate to Compute Engine then VM Instances. Select Create Instance you should now be <a href="https://console.cloud.google.com/compute/instancesAdd?project">here</a>.</p>
<p>Give your instance a name, select a Region and Zone. I have found that the default machine configuration works fine but depending on your project you may wish to change the resources.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/1-2iwAT9cmjZ-565.avif 565w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/1-2iwAT9cmjZ-565.webp 565w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="GCP Create VM interface" loading="lazy" decoding="async" src="https://flowfuse.com/img/1-2iwAT9cmjZ-565.jpeg" width="565" height="607" /></picture></p>
<p>You now need to allow access to your FlowFuse installation from the internet. In the Firewall section tick Allow HTTP traffic and Allow HTTPS traffic.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/2-NnppdgkreY-537.avif 537w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/2-NnppdgkreY-537.webp 537w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="GCP Create VM interface" loading="lazy" decoding="async" src="https://flowfuse.com/img/2-NnppdgkreY-537.jpeg" width="537" height="122" /></picture></p>
<p>Next up, assigna static IP address to the VM. Click Advanced options, then Networking. Now scroll down until you see Network interfaces and click on default to expand that section. In External IPv4 address select Create IP Address, give it a name than press Reserve.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/3-vqBZBbWboS-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/3-vqBZBbWboS-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="GCP Create VM interface" loading="lazy" decoding="async" src="https://flowfuse.com/img/3-vqBZBbWboS-650.jpeg" width="650" height="846" /></picture></p>
<p>Once you have reserved your IP it will be shown in the External IPv4 address field, write it down as we will need it later to create the DNS records. Our IP address was 34.125.156.130.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/4-5_Hcq0Ziym-495.avif 495w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/4-5_Hcq0Ziym-495.webp 495w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="GCP Create VM interface" loading="lazy" decoding="async" src="https://flowfuse.com/img/4-5_Hcq0Ziym-495.jpeg" width="495" height="59" /></picture></p>
<p>You are now ready to create and boot your VM, scroll to the bottom of the page and press Create. It can take a minute or two for the VM to be ready to use.</p>
<h1 id="dns-set-up" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/10/ff-docker-gcp/#dns-set-up"># </a> DNS Set Up</h1>
<p>So that you can run FlowFuse on your newly created GCP VM you will need to set up 2 DNS records. These records are slightly different to what is suggested in the FlowFuse install docs. We were keen to be able to run other services on this domain so we set up the following records.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/5-U70Zi0GX3B-644.avif 644w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/5-U70Zi0GX3B-644.webp 644w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="DNS interface" loading="lazy" decoding="async" src="https://flowfuse.com/img/5-U70Zi0GX3B-644.jpeg" width="644" height="283" /></picture></p>
<p>DNS changes need to propagate, and depending on your DNS provider, ISP, and other factors, this can take anywhere between a few seconds to 4 hours. Our’s were in place very quickly. To validate the DNS records you can use <code>dig</code> on either a Mac or Linux.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/6-FjA4QESL4_-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/6-FjA4QESL4_-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Dig command" loading="lazy" decoding="async" src="https://flowfuse.com/img/6-FjA4QESL4_-650.jpeg" width="650" height="615" /></picture></p>
<p>The DNS records are set to the IP record we noted down earlier, so we're good to continue.</p>
<h1 id="flowfuse-docker-installation" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/10/ff-docker-gcp/#flowfuse-docker-installation"># </a> FlowFuse Docker Installation</h1>
<p>The next step is to install Docker on our GCP VM. If you return to GCP you should see that your VM is now up and running, you can now click on SSH to connect to your VM. This will open up a browser based SSH session to your VM.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/7-mYM--JfUvg-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/7-mYM--JfUvg-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Access SSH in GCP" loading="lazy" decoding="async" src="https://flowfuse.com/img/7-mYM--JfUvg-650.jpeg" width="650" height="124" /></picture></p>
<p>Once you have a Secure Shell (SSH) session open, the first step is to install Docker using the following commands.</p>
<p><code>sudo apt-get update</code></p>
<pre><code>sudo apt-get install \
ca-certificates \
curl \
gnupg \
lsb-release
</code></pre>
<p><code>sudo mkdir -p /etc/apt/keyrings</code></p>
<p><code>curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg</code></p>
<pre><code>echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
</code></pre>
<p><code>sudo apt-get update</code></p>
<p><code>sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin</code></p>
<p>You can read a lot more detail about what each these commands actually do <a href="https://docs.docker.com/engine/install/debian/">here</a>.</p>
<h1 id="download-flowfuse%E2%80%99s-latest-docker-build" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/10/ff-docker-gcp/#download-flowfuse%E2%80%99s-latest-docker-build"># </a> Download FlowFuse’s latest Docker build</h1>
<p>The next step is to get the codebase for FlowFuse onto your VM, to do so you will need to run the following commands. Please note that we are working with our 0.10.0 build, you will need to update the version number in the commands below if you are working with a newer build.</p>
<p>Use curl to download the files we need.</p>
<p><code>sudo curl -L https://github.com/FlowFuse/docker-compose/archive/refs/tags/v0.10.1.tar.gz -o v0.10.1.tar.gz</code></p>
<p>Make the directory where we will store FlowFuse.</p>
<p><code>sudo mkdir /opt/flowforge</code></p>
<p>Uncompress FlowFuse and save it to the directory.</p>
<p><code>sudo tar zxf v0.10.1.tar.gz --directory /opt/flowforge</code></p>
<p>You should now have all the code you need for FlowFuse in the directory <code>/opt/flowforge/docker-compose-0.10.1</code>, it should look something like this.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/8-VQIuM51uhR-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/8-VQIuM51uhR-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="List command output" loading="lazy" decoding="async" src="https://flowfuse.com/img/8-VQIuM51uhR-650.jpeg" width="650" height="269" /></picture></p>
<h1 id="configure-flowfuse" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/10/ff-docker-gcp/#configure-flowfuse"># </a> Configure FlowFuse</h1>
<p>We can now configure FlowFuse on your VM. We are going to need to edit two files. Firstly we need to switch into the directory where we just placed FlowFuse.</p>
<p><code>cd /opt/flowforge/docker-compose-0.10.1</code></p>
<p>Then we need to edit the flowforge.yml file, we're using Nano to do that.</p>
<p><code>sudo nano /opt/flowforge/docker-compose-0.10.1/etc/flowforge.yml</code></p>
<p>At the top of the file you need to update the domain and base_url to match your domain</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/9-fq6g179_er-494.avif 494w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/9-fq6g179_er-494.webp 494w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Domain config" loading="lazy" decoding="async" src="https://flowfuse.com/img/9-fq6g179_er-494.jpeg" width="494" height="163" /></picture></p>
<p>Next we will need to edit the Email Configuration section to match your SMTP provider. Set enabled to true then add in the details provider by your email provider. For example in this case I am using our Google Workspace account.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/10-z1cSwwzHXQ-405.avif 405w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/10-z1cSwwzHXQ-405.webp 405w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Email config" loading="lazy" decoding="async" src="https://flowfuse.com/img/10-z1cSwwzHXQ-405.jpeg" width="405" height="215" /></picture></p>
<p>Finally, you need to update the <code>public_url</code> for your mqtt broker to match your DNS record.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/11-7CI9XBq2PI-370.avif 370w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/11-7CI9XBq2PI-370.webp 370w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="MQTT config" loading="lazy" decoding="async" src="https://flowfuse.com/img/11-7CI9XBq2PI-370.jpeg" width="370" height="55" /></picture></p>
<p>You can now save and close that file, in Nano you can do that by pressing ‘control x’ then ‘y’ then the Return key.</p>
<p>Now we need to edit the <code>docker-compose.yml</code> file. We will use Nano again to do that.</p>
<p><code>sudo nano /opt/flowforge/docker-compose-0.10.1/docker-compose.yml</code></p>
<p>We need to edit the file to add in to the domain as follows.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/12-xO2b_hIwE5-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/12-xO2b_hIwE5-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Virtual Hosts config" loading="lazy" decoding="async" src="https://flowfuse.com/img/12-xO2b_hIwE5-650.jpeg" width="650" height="748" /></picture></p>
<p>Save and exit from that file, in Nano you can do that by pressing ‘control x’ then ‘y’ then the Return key.</p>
<h1 id="start-flowfuse" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/10/ff-docker-gcp/#start-flowfuse"># </a> Start FlowFuse</h1>
<p>We are now ready to start up FlowFuse for the first time, to do so we will use the following command.</p>
<p><code>sudo docker compose -p flowforge up -d</code></p>
<p>The build process will take a few minutes, once it’s completed let’s make sure all the docker containers are running.</p>
<p><code>sudo docker ps</code></p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/13-O_BeRnUDb_-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/13-O_BeRnUDb_-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="Docker PS output" loading="lazy" decoding="async" src="https://flowfuse.com/img/13-O_BeRnUDb_-650.jpeg" width="650" height="75" /></picture></p>
<p>You should see 4 running Docker containers.</p>
<p>If everything went well you should now be able to access your FlowFuse server via the DNS record you created.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/14-0HT-Ly1_ym-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/14-0HT-Ly1_ym-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="FF Login page" loading="lazy" decoding="async" src="https://flowfuse.com/img/14-0HT-Ly1_ym-650.jpeg" width="650" height="721" /></picture></p>
<p>Nice, you now have a working instance of FlowFuse running on GCP but remember that all traffic is currently running on HTTP so we still have some work to do.</p>
<p>In the next article we will cover how to add HTTPS support to this FlowFuse installation.</p>
https://flowfuse.com/blog/2022/10/community-news-09/Community News September 2022News from the FlowFuse and Node-RED communities2022-10-07T00:00:00ZRob Marcer<p>Welcome to the FlowFuse newsletter, a regular roundup of what’s happening with both FlowFuse and the wider Node-RED community.</p>
<!--more-->
<p>If you've got something that you'd like us to share please email <a href="mailto:contact@flowfuse.com">contact@flowfuse.com</a>.</p>
<p><a href="https://flowfuse.com/blog/2022/09/flowforge-010-released/"><strong>FlowFuse 0.10</strong></a>
Version 0.10 was released on 30th September. Our latest release includes some great new features, quality of life improvements and bug fixes. Notable additions included the ability to <a href="https://github.com/FlowFuse/flowfuse/pull/893">Secure your HTTP endpoints</a>, <a href="https://github.com/FlowFuse/flowfuse/issues/657">Add read-only users to your projects</a> and <a href="https://flowfuse.com/docs/cloud/introduction/#ip-addresses">use our static IP address for outbound connections</a></p>
<p>If you’d like to learn more about what else was included in 0.10 you can do so on our <a href="https://flowfuse.com/blog/2022/09/flowforge-010-released/">blog post</a>, on our <a href="https://github.com/FlowFuse/flowfuse/releases/tag/v0.10.0">GitHub release page</a> and on our <a href="https://youtube.com/watch?v=mjR1iiEFiBg">Youtube channel</a>. We’d also love for more of you to get involved in the development of FlowFuse, <a href="https://github.com/FlowFuse/flowfuse/blob/main/CONTRIBUTING.md">contributions to the code</a> and <a href="https://github.com/FlowFuse/flowfuse/issues">bug reports</a> are really appreciated.</p>
<p><a href="https://nrcon.nodered.org/"><strong>Node-RED Con 2022</strong></a><br />
We are happy to again be involved in Node-RED con. The event is being held online on 7th October, with content for both English and Japanese speakers including our colleagues Nick O'Leary and Sam Machin. You can find out more on the <a href="https://nrcon.nodered.org/">Node-RED Con website</a>.</p>
<p><a href="https://flowforge.com/team/"><strong>FlowFuse Team News</strong></a><br />
We are currently recruiting <a href="https://boards.greenhouse.io/flowfuse/jobs/4463977004">NodeJS Developers</a>, if you’re interested in joining our team please <a href="https://boards.greenhouse.io/flowfuse/jobs/4463977004#app">apply here</a>.</p>
<p>We are also looking for a <a href="https://boards.greenhouse.io/flowfuse/jobs/4687876004">PeopleOps Manager</a> to help us grow our team. You can <a href="https://boards.greenhouse.io/flowfuse/jobs/4687876004#app">apply here</a> for that position.</p>
<p><a href="https://hackster.io/user102774/fight-fire-wild-fire-prediction-using-tinyml-df7572"><strong>Forest Fire Alerts Using ML, IOT and Node-RED</strong></a><br />
This fascinating project came up a few days ago and we wanted to share it with you all. The concept is to use a mesh network of IoT devices to monitor various indicators of potential and current wildfires and report data back to the relevant authorities. The system will use ML to predict wildfire risk levels and hopefully send warnings before a fire actually starts. The two developers <a href="https://linkedin.com/in/zainmfd/">Muhammed</a> and <a href="https://linkedin.com/in/salmanfarisvp/">Salman</a> are planning to use Node-RED to manage the reporting of fires to the authorities.</p>
<p><a href="https://app.flowfuse.com/account/create"><strong>Try FlowFuse for Free</strong></a><br />
As a thank you for reading our newsletters we’d like to offer you a free, small project for one month on FlowFuse when you create a new team. To get this discount please follow <a href="https://app.flowfuse.com/account/create?code=RELEASE010">this link</a> or use the code RELEASE010 when on the payment page after creating a new team.</p>
https://flowfuse.com/blog/2022/09/flowforge-010-released/FlowFuse 0.10 releasedSecure HTTP end points, Read-only users and Static outbound IPs2022-09-30T12:00:00ZRob Marcer<p>Secure your HTTP endpoints, create read-only users in your teams and use our static IP address for outbound traffic</p>
<!--more-->
<p>Keep reading for the details of what's in this release or you can watch our 1 minute roundup video of the new release above.</p>
<p>We're pleased to announce version 0.10 is now available. The next release of the FlowFuse application containing new features, a number of improvements, and bug fixes. Keep reading for a promotion code to get your first month free on FlowFuse Cloud.</p>
<h2 id="features" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/09/flowforge-010-released/#features"># </a> Features</h2>
<p><a href="https://github.com/FlowFuse/flowfuse/issues/578">Secure HTTP Endpoints</a>
We've added the ability for you to secure your HTTP endpoints. You can now control who can access Dashboards or API endpoints you create in FlowFuse.</p>
<p><a href="https://github.com/FlowFuse/flowfuse/issues/657">Read-only Users</a>
We've added a new user role for Read-only access. This will allow users to login to your FlowFuse project and view the Node-RED flows without them being able to edit anything.</p>
<p><a href="https://flowfuse.com/docs/cloud/introduction/#ip-addresses">Static Outbound IP Addresses</a>
We've updated FlowFuse Cloud so that all outbound traffic from your projects now comes from a single IP address. When trying to access a remote resource such as a database it is often a requirement for the IP address the traffic comes from to be fixed.</p>
<h2 id="improvements" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/09/flowforge-010-released/#improvements"># </a> Improvements</h2>
<p>We've made a number of improvements to the overall experience of running FlowFuse.</p>
<ul>
<li>Allow both key and component in a ff-data-table column definition <a href="https://github.com/FlowFuse/forge-ui-components/issues/43">#43</a></li>
<li>Default Stack and Templates <a href="https://github.com/FlowFuse/flowfuse/issues/989">#989</a></li>
<li>Provide platform containers and base stack container for administrators <a href="https://github.com/FlowFuse/flowfuse/issues/917">#917</a></li>
</ul>
<h2 id="bug-fixes" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/09/flowforge-010-released/#bug-fixes"># </a> Bug Fixes</h2>
<p>We've fixed the following bugs in this release.</p>
<ul>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/917">Provide platform containers and base stack container for administrators</a></li>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/983">User names can be same (but different case)</a></li>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/463">User list not refreshing after changing user details</a></li>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/986">Navigating directly to a device page gets the wrong team selected</a></li>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/941">Node-RED Isn't ready when FlowFuse app says it is running following a project restart</a></li>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/923">Invitations left for deleted teams</a></li>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/1024">Following email verification link twice throws error</a></li>
<li><a href="https://github.com/FlowFuse/device-agent/issues/21">Agent does not log stderr from the Node-RED process</a></li>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/948">On Kubernetes project names can not start with a number</a></li>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/930">When creating projects stack options do not wrap</a></li>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/979">Save button in admin user-edit dialog doesn't close dialog</a></li>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/911">Setting UI doesn't allow me to update settings</a></li>
</ul>
<h2 id="contributors" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/09/flowforge-010-released/#contributors"># </a> Contributors</h2>
<p>We'd like the thank the following for their contributions to this release:</p>
<p><a href="https://github.com/Pezmc">Pezmc</a> for their work on <a href="https://github.com/FlowFuse/flowfuse/pull/949">Add device count and project counts by type to admin</a></p>
<p><a href="https://github.com/ArshErgon">ArshErgon</a> for their work on <a href="https://github.com/FlowFuse/flowfuse/pull/977">Update vue component name for NoVerifiedEmail.vue</a></p>
<p>As an open-source project, we welcome the community involvement in what we're building. If you're interested in contributing, checkout our <a href="https://flowfuse.com/docs/contribute/">guide in the docs</a>.</p>
<h3 id="try-it-out" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/09/flowforge-010-released/#try-it-out"># </a> Try it out</h3>
<p><a href="https://app.flowfuse.com/account/create?code=RELEASE010">Sign up for FlowFuse Cloud</a> with this link or at the checkout enter the code <strong>RELEASE010</strong> to get your first project free for a month.</p>
<h3 id="upgrading-flowfuse" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/09/flowforge-010-released/#upgrading-flowfuse"># </a> Upgrading FlowFuse</h3>
<p><a href="https://app.flowfuse.com/">FlowFuse Cloud</a> is already running 0.10 and the stacks updated. Upgrade your project stacks to the latest version to make sure you get all the latest changes.</p>
<p>If you installed a previous version of FlowFuse and want to upgrade, our documentation provides a
guide for <a href="https://flowfuse.com/docs/upgrade/#upgrading-flowfuse">upgrading FlowFuse on a local server</a>.</p>
<h3 id="getting-help" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/09/flowforge-010-released/#getting-help"># </a> Getting help</h3>
<p>If you hit any problems with the platform, or have questions to ask, please do
raise an <a href="https://github.com/FlowFuse/flowfuse/issues">issue on GitHub</a>.
That also includes if you have any feedback or feature requests.</p>
<p>Customers of FlowFuse Cloud can raise a ticket by emailing support@flowfuse.com</p>
<p>We also have a <code>#flowfuse</code> channel on the <a href="https://nodered.org/slack">Node-RED Slack workspace</a>.</p>
https://flowfuse.com/blog/2022/09/static-ips/Static Outbound IP AddressesStatic IP addresses are here for your FlowFuse Cloud projects’ outbound connections2022-09-27T00:00:00ZRob Marcer<p>On Friday last week we updated FlowFuse Cloud to use a static IP address for outbound traffic. This will allow you to predict which IP address your traffic will come from for example when traversing a firewall or accessing a remote database.</p>
<!--more-->
<p>You will need to manually suspend then start each of your projects (a restart will not move your projects to the fixed IP address). Once that action is completed all outbound connections will come from one of our static IP address.</p>
<p>Any inbound traffic should still use the hostname assigned to each of your projects, you cannot use our IP address to route http traffic to your projects.</p>
<p>You can view our IP address in the <a href="https://flowfuse.com/docs/cloud/introduction/#ip-addresses">Docs</a> section of our website.</p>
<p>If you’d like to stay up to date with our latest releases you can do so on <a href="https://flowfuse.com/blog">our blog</a>.</p>
https://flowfuse.com/blog/2022/09/community-news-08/Community News August 2022News from the FlowFuse and Node-RED communities2022-09-16T00:00:00ZRob Marcer<p>Welcome to the FlowFuse newsletter, a regular roundup of what’s happening with both FlowFuse and the wider Node-RED community.</p>
<!--more-->
<p>If you've got something that you'd like us to share please email <a href="mailto:contact@flowfuse.com">contact@flowfuse.com</a>.</p>
<p><a href="https://flowfuse.com/blog/2022/09/flowforge-09-released/"><strong>FlowFuse 0.9</strong></a><br />
Version 0.9 was released on 1st September. Our latest release includes some great new features, quality of life improvements and bug fixes. Notable additions included the ability to <a href="https://github.com/FlowFuse/flowfuse/pull/893">suspend your projects</a>, <a href="https://github.com/FlowFuse/flowfuse/pull/856">login with your email</a> and <a href="https://github.com/FlowFuse/flowfuse/issues/774">define custom paths for your dashboards</a>.</p>
<p>If you’d like to learn more about what else was included in 0.9 you can do so on our <a href="https://flowfuse.com/blog/2022/09/flowforge-09-released/">blog post</a>, on our <a href="https://github.com/FlowFuse/flowfuse/releases/tag/v0.9.0">GitHub release page</a> and on our <a href="https://www.youtube.com/watch?v=d23Pmyc0k7I">Youtube channel</a>. We’d also love for more of you to get involved in the development of FlowFuse, <a href="https://github.com/FlowFuse/flowfuse/blob/main/CONTRIBUTING.md">contributions to the code</a> and <a href="https://github.com/FlowFuse/flowfuse/issues">bug reports</a> are really appreciated.</p>
<p><a href="https://nrcon.nodered.org/"><strong>Node-RED Con 2022</strong></a><br />
We are happy to again be involved in Node-RED con. The event is being held online on 7th October, with content for both English and Japanese speakers. You can find out more on the <a href="https://nrcon.nodered.org/">Node-RED Con website</a>.</p>
<p><a href="https://flowfuse.com/team/"><strong>FlowFuse Team News</strong></a><br />
We’d like to welcome Rob Marcer to the FlowFuse team. Rob has joined as our Developer Educator, he's going to work to help you get the best value from FlowFuse by developing our documentation and community support.</p>
<p>We are also recruiting for <a href="https://boards.greenhouse.io/flowfuse/jobs/4463977004">NodeJS Developers</a>, if you’re interested in joining our team please <a href="https://boards.greenhouse.io/flowfuse/jobs/4463977004#app">apply here</a>.</p>
<p><a href="https://twitter.com/Docker/status/1559919666721693699?t=QBzGGzY2kJ12Z5aoi1QPTA"><strong>Official Node-RED Docker Image Passes Milestone</strong></a><br />
Docker has <a href="https://twitter.com/Docker/status/1559919666721693699?t=QBzGGzY2kJ12Z5aoi1QPTA">announced</a> that the Node-RED Docker image has now been downloaded over 100 million times. They have also created a <a href="https://www.docker.com/blog/build-retail-store-items-detection-system-no-code-ai/?utm_campaign=2022-08-17-brnd-nocode&utm_medium=social&utm_source=twitter">guide to using Node-RED</a> to Build and Deploy a Retail Store Items Detection System Using No-Code AI Vision at the Edge. We think it’s worth a read.</p>
<p><a href="https://wokwi.com/"><strong>Simulating IOT Projects in Your Browser</strong></a><br />
While not directly related to FlowFuse we’ve enjoyed wasting a little too much time looking at the simulated IOT projects on <a href="https://wokwi.com/">Wokwi</a>. The <a href="https://wokwi.com/projects/328451800839488084">Simon Game with Score</a> project is a little too addictive.</p>
<p><a href="https://app.flowfuse.com/account/create"><strong>Try FlowFuse for Free</strong></a><br />
As a thank you for reading our newsletters we’d like to offer you a free, small project for one month on FlowFuse when you create a new team. To get this discount please use the code RELEASE09 when on the payment page after creating a new team.</p>
https://flowfuse.com/blog/2022/09/flowforge-09-released/FlowFuse 0.9 releasedSuspended projects, login with email and Team Types2022-09-01T12:00:00Z<p>Suspend your projects when you don't need them, login with either your username or email, and introducing Team Types</p>
<!--more-->
<p>Keep reading for the details of what's in this release our you can watch our 1 minute roundup video of the new release above.</p>
<p>We're pleased to announce version 0.9 is now available. The next release of the FlowFuse application containing new features, a number of improvements, and bug fixes. Keep reading for a promotion code to get your first month free on FlowFuse Cloud.</p>
<h2 id="features" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/09/flowforge-09-released/#features"># </a> Features</h2>
<p><a href="https://github.com/FlowFuse/flowfuse/issues/893">Suspend Projects</a>
Sometimes you want to put a project to one side for a while, maybe your development has stalled or you're waiting on something external to be ready. Perhaps you don't need it to be running all the time. With the 0.9 release we've added the ability to suspend a project. Once suspended, your flows are safely stored in the platform database, but Node-RED isn't running and the project doesn't consume any resources. In FlowFuse Cloud we do not charge you for suspended projects - you only pay when the project is running.
Your project will be there ready to start back up when you need it with just one click.
Remember that any context data or anything written to the filesystem will not persist through a restart or a suspend of a project.</p>
<p>Alongside this change, we've removed the option to 'stop' a project. That option would only stop Node-RED, but the underlying container would still be running, consuming resources. With Node-RED 3.0 adding the ability to stop the flows, but still be able to edit them, that provides a much better user experience.
You can still restart the Node-RED process from the Forge app as before for example when you have updated a package in your flows.</p>
<p><a href="https://github.com/FlowFuse/flowfuse/issues/733">Team Types</a>
We've introduced another concept into the platform with this release. Team Types will allow us to offer more advanced features to teams on FlowFuse Cloud. You won't see much difference in this release but it allows us to build on in future releases.</p>
<p><a href="https://github.com/FlowFuse/flowfuse/issues/695">PostHog Analytics</a>
We've changed the analytics tooling integrated into the platform. With this release, we've deprecated the use of Plausible Analytics as it didn't quite provide the sort of insight we wanted. We now integrate with <a href="https://posthog.com/">PostHog</a>. They share our ethos and approach to open source and self hosting - something you can take advantage of if you're running your own FlowFuse platform.
For FlowFuse Cloud, the data is sent to our PostHog account so we can better understand how the platform is being used. If you're running your own instance, the information is only captured if you configure it with your own PostHog instance details - it does not send any data back to us.</p>
<p><a href="https://github.com/FlowFuse/flowfuse/issues/856">Login with email</a>
A common problem that we've seen from users is trying to login with their email address instead of their username. As of 0.9 you can now enter either at the login screen.</p>
<p><a href="https://github.com/FlowFuse/flowfuse/issues/774">Custom Dashboard Path</a>
If you are using the Node-RED Dashboard set of nodes, you can now change the path where the dashboard will be served from. The default is still <code>/ui</code> but you can now move that onto <code>/</code> or anything else. This is helpful when migrating existing projects over to FlowFuse.</p>
<h2 id="improvements" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/09/flowforge-09-released/#improvements"># </a> Improvements</h2>
<p>We've made a number of improvements to the overall experience of running FlowFuse.</p>
<ul>
<li>Improvements to the FlowFuse Theme <a href="https://github.com/FlowFuse/flowfuse/pull/883">#883</a>.</li>
<li>Upper-case characters in Project Names <a href="https://github.com/FlowFuse/flowfuse/issues/546">#546</a></li>
<li>Password reset requests are logged<a href="https://github.com/FlowFuse/flowfuse/issues/773">#773</a></li>
<li>Admin can manually verify users email <a href="https://github.com/FlowFuse/flowfuse/issues/692">#902</a></li>
</ul>
<h2 id="bug-fixes" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/09/flowforge-09-released/#bug-fixes"># </a> Bug Fixes</h2>
<p>We've fixed the following bugs in this release.</p>
<ul>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/875">Cannot edit template settings</a><br /></li>
<li><a href="https://github.com/FlowFuse/nr-project-nodes/issues/10">Project Link Nodes Appear in CE Install</a></li>
<li><a href="https://github.com/FlowFuse/nr-project-nodes/issues/14">Project Link Nodes MQTT Connection</a></li>
<li><a href="https://github.com/FlowFuse/flowforge-nr-theme/issues/19">Theme shows white characters on white background</a></li>
<li><a href="https://github.com/FlowFuse/device-agent/issues/27">Changing Project on device doesn't remove old modules</a></li>
<li><a href="https://github.com/FlowFuse/device-agent/issues/30">Device Agent and Node-RED use different time in logs</a></li>
</ul>
<h2 id="contributors" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/09/flowforge-09-released/#contributors"># </a> Contributors</h2>
<p>We'd like the thank the following for their contributions to this release:</p>
<p><a href="https://github.com/bonanitech">Bonantech</a> for his work <a href="https://github.com/FlowFuse/flowforge-nr-theme/commit/30e21a3777dc3438ef206157ee9110728011f59c">cleaning up the theme CSS</a></p>
<p>As an open-source project, we welcome the community involvement in what we're building. If you're interested in contributing, checkout our <a href="https://flowforge.com/docs/contribute/">guide in the docs</a>.</p>
<h3 id="try-it-out" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/09/flowforge-09-released/#try-it-out"># </a> Try it out</h3>
<p><a href="https://app.flowfuse.com/account/create">Sign up for FlowFuse Cloud</a> and at the checkout enter the code <strong>RELEASE09</strong> to get your first project free for a month.</p>
<h3 id="upgrading-flowfuse" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/09/flowforge-09-released/#upgrading-flowfuse"># </a> Upgrading FlowFuse</h3>
<p><a href="https://app.flowfuse.com/">FlowFuse Cloud</a> is already running 0.9 and the stacks updated. Upgrade your project stacks to the latest version and start using the Project Link nodes now.</p>
<p>If you installed a previous version of FlowFuse and want to upgrade, our documentation provides a
guide for <a href="https://flowfuse.com/docs/upgrade/#upgrading-flowfuse">upgrading FlowFuse on a local server</a>.</p>
<h3 id="getting-help" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/09/flowforge-09-released/#getting-help"># </a> Getting help</h3>
<p>If you hit any problems with the platform, or have questions to ask, please do
raise an <a href="https://github.com/FlowFuse/flowfuse/issues">issue on GitHub</a>.
That also includes if you have any feedback or feature requests.</p>
<p>Customers of FlowFuse Cloud can raise a ticket by emailing support@flowfuse.com</p>
<p>We also have a <code>#flowfuse</code> channel on the <a href="https://nodered.org/slack">Node-RED Slack workspace</a>.</p>
https://flowfuse.com/blog/2022/08/community-news-06/Community News July 2022News from the FlowFuse and Node-RED communities2022-08-11T00:00:00Z<p>Welcome to the FlowFuse newsletter, a regular roundup of what`s happening with both FlowFuse and the wider Node-RED community.</p>
<!--more-->
<p>If you've got something that you'd like us to share please email <a href="mailto:contact@flowfuse.com">contact@flowfuse.com</a>.</p>
<p><a href="https://flowfuse.com/blog/2022/08/flowforge-08-released/">FlowFuse 0.8 </a><br />
Version 0.8 was released, notable features include the new Project Link nodes for sharing data between projects, and the ability to stop and start flows within Node-RED.
We've updated the format of our release posts as well to detail all the user facing changes, from new Features through to small improvements and bugs.</p>
<p><a href="https://www.tomshardware.com/how-to/raspberry-pi-pico-w-node-red">Raspberry Pi Pico with Node-RED</a><br />
<a href="https://twitter.com/biglesp">Les Pounder</a> Has published a great tutorial on communicating with the new <a href="https://www.raspberrypi.com/products/raspberry-pi-pico/">Raspberry Pi Pico W</a> and Node-RED. He shows you how to capture data from an environmental sensor then display this on a dashboard.</p>
<p><a href="https://flowfuse.com/blog/2022/07/new-projecttype/">Medium Projects</a><br />
We've added a second size of project to FlowFuse Cloud. A bigger project type with more resources available to it.</p>
<p><a href="https://blog.golioth.io/how-to-use-node-red-to-control-iot-devices-on-golioth/">Using Node-RED to control IoT Devices on Golioth</a><br />
Our friends at <a href="https://golioth.io/">Golioth</a> have published an article on how to use Node-RED to control and process data from IoT Devices connected to their platform.</p>
<p><a href="https://discourse.nodered.org/t/node-red-2-2-3-and-3-0-2-released/66018">Node-RED 3.0.2 and 2.2.3</a><br />
Node-RED 3.0.2 has been released fixing some bugs in the 3.0.0 release, The Node-RED 2.x stream has also had a maintenance release with many of the fixes in 3.0 back-ported. As usual these are already available as stacks on FlowFuse Cloud.</p>
https://flowfuse.com/blog/2022/08/flowforge-08-released/FlowFuse 0.8 releasedInter-Project Communication, Default Teams, and realtime device management.2022-08-04T12:00:00Z<p>Easily pass messages between your projects on the cloud or devices, UX improvements, and more.</p>
<!--more-->
<p>Keep reading for the details of whats in this release our you can watch our 1 minute roundup video of the new release above.</p>
<p>We're pleased to announce version 0.8 is now available. The next release of the FlowFuse application containing new features, a number of improvements, and bug fixes.</p>
<h2 id="features" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/08/flowforge-08-released/#features"># </a> Features</h2>
<p><a href="https://github.com/FlowFuse/flowfuse/issues/662">Project Link Nodes</a>
We've introduced our first custom FlowFuse nodes to the palette of new projects. The Project Link nodes allow you to easily pass data between different projects within the same team.
These projects can be running in the cloud or on devices, with the communication powered by our own internal MQTT broker.
Try these out today on FlowFuse Cloud by creating a new project or updating your existing project's stack. There's more information in the <a href="https://github.com/FlowFuse/nr-project-nodes/blob/main/README.md">README</a> for the nodes.
For local installs of FlowFuse, the nodes are only available with an Enterprise Edition license.
<picture><source type="image/webp" srcset="https://flowfuse.com/img/ProjectLink-3NO4LgATRJ-650.webp 650w, https://flowfuse.com/img/ProjectLink-3NO4LgATRJ-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/gif" srcset="https://flowfuse.com/img/ProjectLink-3NO4LgATRJ-650.gif 650w, https://flowfuse.com/img/ProjectLink-3NO4LgATRJ-1300.gif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="" loading="lazy" decoding="async" src="https://flowfuse.com/img/ProjectLink-3NO4LgATRJ-650.webp" width="1300" height="472" /></picture></p>
<p><a href="https://github.com/FlowFuse/flowfuse/issues/839">Start & Stop Flows</a>
Node-RED 3.0 <a href="https://nodered.org/blog/2022/07/14/version-3-0-released#editing-stopped-flows">introduced a new feature</a> that allows you to stop your flows from processing requests while still being able to work in the editor and deploy changes. We've now enabled this feature within FlowFuse for projects running a Node-RED 3.x stack.</p>
<p><a href="https://github.com/FlowFuse/flowfuse/issues/298">Default Team</a>
If you are a member of multiple teams you can now set your preferred default saving you from having to change teams each time you log in.</p>
<h2 id="improvements" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/08/flowforge-08-released/#improvements"># </a> Improvements</h2>
<p>We've made a number of improvements to the overall experience of running FlowFuse.</p>
<ul>
<li>Devices now communicate to the Forge application over MQTT instead of polling <a href="https://github.com/FlowFuse/flowfuse/issues/754">#754</a>. You'll need to update your Device Agent to the latest version to take advantage of this.</li>
<li>The table views have had a major overhaul allowing you to sort and search items <a href="https://github.com/FlowFuse/forge-ui-components/issues/28">#28</a></li>
<li>If the application receives an error you now see a notification in the UI. <a href="https://github.com/FlowFuse/flowfuse/issues/771">#771</a></li>
<li>The Verification email page has been cleaned up <a href="https://github.com/FlowFuse/flowfuse/issues/718">#718</a></li>
<li>The initial Thank-you page has been cleaned up <a href="https://github.com/FlowFuse/flowfuse/issues/648">#648</a></li>
</ul>
<h2 id="bug-fixes" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/08/flowforge-08-released/#bug-fixes"># </a> Bug Fixes</h2>
<p>We've fixed the following bugs in this release.</p>
<ul>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/793">Logo Distorted in Safari</a><br /></li>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/729">LocalFS Install doesn't check for Build Tools</a><br /></li>
<li><a href="https://github.com/FlowFuse/flowfuse/pull/842">Users with Expired passwords can create teams</a><br /></li>
<li><a href="https://github.com/FlowFuse/flowfuse/pull/790">Click-jacking Vulnerability</a></li>
<li><a href="https://github.com/FlowFuse/flowfuse/pull/824">Users with can create teams without verifying email</a><br /></li>
<li><a href="https://github.com/FlowFuse/flowforge-nr-storage/issues/17">Occasional Timeout when deploying flows</a><br /></li>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/833">Notification of member deletion contains internal ID</a><br /></li>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/334">Pressing Enter in the Team Delete modal triggers cancel</a><br /></li>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/751">Node-Red Isn't ready when Forge app says it is running (Docker)</a><br /></li>
</ul>
<h2 id="contributors" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/08/flowforge-08-released/#contributors"># </a> Contributors</h2>
<p>We'd like the thank the following for their contributions to this release:</p>
<ul>
<li><a href="https://github.com/HaroldPetersInskipp">HaroldPetersInskipp</a> helped <a href="https://github.com/FlowFuse/flowfuse/pull/812">updating our documentation</a></li>
<li><a href="https://github.com/Steveorevo">Steveorevo</a> also <a href="https://github.com/FlowFuse/flowfuse/pull/818">updated our documentation</a></li>
</ul>
<p>As an open-source project, we welcome the community involvement in what we're building. If you're interested in contributing, checkout our <a href="https://flowfuse.com/docs/contribute/">guide in the docs</a>.</p>
<h3 id="upgrading-flowfuse" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/08/flowforge-08-released/#upgrading-flowfuse"># </a> Upgrading FlowFuse</h3>
<p><a href="https://app.flowfuse.com/">FlowFuse Cloud</a> is already running 0.8 and the stacks updated. Upgrade your project stacks to the latest version and start using the Project Link nodes now.</p>
<p>If you installed a previous version of FlowFuse and want to upgrade, our documentation provides a
guide for <a href="https://flowfuse.com/docs/upgrade/#upgrading-flowfuse">upgrading FlowFuse on a local server</a>.</p>
<h3 id="getting-help" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/08/flowforge-08-released/#getting-help"># </a> Getting help</h3>
<p>If you hit any problems with the platform, or have questions to ask, please do
raise an <a href="https://github.com/FlowFuse/flowfuse/issues">issue on GitHub</a>.
That also includes if you have any feedback or feature requests.</p>
<p>Customers of FlowFuse Cloud can raise a ticket by emailing support@flowfuse.com</p>
<p>We also have a <code>#flowfuse</code> channel on the <a href="https://nodered.org/slack">Node-RED Slack workspace</a>.</p>
https://flowfuse.com/blog/2022/07/new-projecttype/Introducing Medium Projects on FlowFuse CloudA bigger project with more resources2022-07-22T12:00:00Z<p>We've added a second size of project to FlowFuse Cloud. A bigger project type with more resources available to it.</p>
<!--more-->
<p>Our <a href="https://flowforge.com/blog/2022/07/flowforge-07-released/">0.7 release</a> introduced the concept of Project Types. This allows platforms to provide different sizes of projects, varying the memory/cpu or features available within a given type.</p>
<p>Today we've put this feature to work on FlowFuse Cloud by introducing the new <strong>Medium Project</strong> type.
<picture><source type="image/avif" srcset="https://flowfuse.com/img/project-type-IyfjtC-GCy-650.avif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/project-type-IyfjtC-GCy-650.webp 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="" loading="lazy" decoding="async" src="https://flowfuse.com/img/project-type-IyfjtC-GCy-650.jpeg" width="650" height="688" /></picture></p>
<p>Medium projects have 3 times the resources of the existing Small type, allowing for more complex flows and larger message objects. This will be useful to business users looking to process complex sets of data.</p>
<p>Our Medium project is priced at $50 a month and we'll be adding new features to this project type in the coming months to further enhance the value of this new tier.</p>
<p>We don't currently support directly upgrading a project between types, but that is in the <a href="https://github.com/FlowFuse/flowfuse/issues/595">plan for the future</a>. In the meantime, you can use the 'Export Project' feature on a project's settings tab to copy it over into a new Medium type project.</p>
https://flowfuse.com/blog/2022/07/community-news-06/Community News June 2022News from the FlowFuse and Node-RED communities2022-07-19T00:00:00Z<p>Welcome to the FlowFuse newsletter, a regular roundup of what`s happening with both FlowFuse and the wider Node-RED community.</p>
<!--more-->
<p>If you've got something that you'd like us to share please email <a href="mailto:contact@flowfuse.com">contact@flowfuse.com</a>.</p>
<p><a href="https://flowfuse.com/blog/2022/07/flowforge-07-released">FlowFuse 0.7 </a><br />
We've shipped the next version of FlowFuse, features in this release include the ability to Rollback a project to a previous snapshot, setting environment variables for a specific device and we've begun to unify the experience between the Forge app and the Node-RED editor with our own Node-RED theme.</p>
<p><a href="https://nodered.org/blog/2022/07/14/version-3-0-released">Node-RED 3.0 Released </a><br />
Node-RED 3.0 Has been officially released, there are a lot of improvements in the user experience of the editor, with new menus and junctions. There's also the ability to stop your flows while you can continue to edit and deploy. Take a look at the blog post for all the details. This is now the default stack on FlowFuse Cloud.</p>
<p><a href="https://discourse.nodered.org/t/node-red-flows-on-esp8266-and-esp32/64345">Node-RED for Microcontrollers</a><br />
<a href="https://twitter.com/phoddie">Peter Hoddie</a> of <a href="https://moddable.com/">Moddable</a> Has released some early <a href="https://github.com/phoddie/node-red-mcu">work</a> on getting the Node-RED runtime to execute a flow on a microcontroller like the ESP32. It's still very early days so don't expect to be building flows directly on the MCU, and the number of nodes that are supported is limited, but this is an interesting development for Node-RED in the IoT space.</p>
<p><a href="https://www.papercall.io/nrcon2022">Node-RED Con CFP</a><br />
A reminder about Node-RED Con and the call for papers, submissions close at the end of July so get your proposals in now.</p>
https://flowfuse.com/blog/2022/07/flowforge-07-released/FlowFuse 0.7 releasedRollbacks, Device Environment Variables and a FlowFuse Theme2022-07-07T12:00:00Z<p>Rollback projects to a previous snapshot, improvements in using Devices, and more.</p>
<!--more-->
<p>Keep reading for the details of whats in this release our you can watch our 1 min roundup video of the new release above.</p>
<p>We're pleased to announce version 0.7 is now available. the next release of the FlowFuse application.</p>
<h2 id="features" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/07/flowforge-07-released/#features"># </a> Features</h2>
<p><a href="https://github.com/FlowFuse/flowfuse/issues/587">Rollback</a>
FlowFuse is about running Node-RED at any scale, part of that scale is having multiple users collaborate on the same project. When you are collaborating with people it's important to be able to go back in time to a known working state. As part of that we are introducing rollbacks, this means that you can now take a snapshot of your project at a point in time and then make changes safe in the knowledge that you can rollback to that previous snapshot if you need to.</p>
<p><a href="https://github.com/FlowFuse/flowfuse/issues/680">Device Environment Variables</a>
In the last release we introduced the concept of devices. We're already learning from how these are used and one feature we've added in 0.7 is Device Environment Variables. You have been able to set Environment Variables at the project level but when deploying a snapshot to multiple devices you may want to override these values for each device, for example to set a site ID. With device specific variable users are enabled to differentiate based on the context in their flows.</p>
<p><a href="https://github.com/FlowFuse/flowforge-nr-theme/">FlowFuse Theme</a>
Now that we have a stronger visual identity in the Forge application we have continued that work through to the Node-RED editor. If you create or upgrade a project with a Node-RED 3.0 stack you will see a different theme in the editor. It's still very much Node-RED but just has some subtle hints to tie it back to the FlowFuse application. We will continue to iterate on this to further integrate the experience between FlowFuse and Node-RED in both directions.
<picture><source type="image/avif" srcset="https://flowfuse.com/img/ff-07-theme-17e1ceCR8s-650.avif 650w, https://flowfuse.com/img/ff-07-theme-17e1ceCR8s-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/ff-07-theme-17e1ceCR8s-650.webp 650w, https://flowfuse.com/img/ff-07-theme-17e1ceCR8s-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/ff-07-theme-17e1ceCR8s-650.jpeg 650w, https://flowfuse.com/img/ff-07-theme-17e1ceCR8s-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="" loading="lazy" decoding="async" src="https://flowfuse.com/img/ff-07-theme-17e1ceCR8s-650.jpeg" width="1300" height="835" /></picture></p>
<p><a href="https://github.com/FlowFuse/flowfuse/issues/380">ProjectTypes</a>
The introduction of ProjectTypes is a way to group Stacks together that share common characteristics - such as memory/cpu limits, or the availability of particular features. In platforms with billing enabled, such as our own FlowFuse Cloud, the ProjectTypes can have different price points set on them. Within FlowFuse Cloud, you'll see we've introduced the Small ProjectType - which applies to all existing projects on the platform.</p>
<p><a href="https://github.com/FlowFuse/flowfuse/issues/694">Stack Versions</a>
This allows an admin to link different stacks together in their lineage. This allows administrators to nudge users to new Node-RED versions or upgrade pre-installed dependencies when running in a container environment. Any users with projects on an old version will be prompted that there is an update available, making it even easier to stay up to date with Node-RED versions when you build your flows on FlowFuse.</p>
<h2 id="improvements" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/07/flowforge-07-released/#improvements"># </a> Improvements</h2>
<p>We've made a number of improvements to the overall experience of running FlowFuse.</p>
<ul>
<li>The Team Switch menu has been moved to a more prominent position in the interface, this also makes it easier to see how to create a new team. <a href="https://github.com/FlowFuse/flowfuse/issues/616">#616</a></li>
<li>Notifications have had an overhaul, you will now see waiting invites on all pages. <a href="https://github.com/FlowFuse/flowfuse/issues/515">#515</a></li>
<li>If you are running your own copy of FlowFuse you can now see the version details in the admin pages <a href="https://github.com/FlowFuse/flowfuse/issues/655">#655</a></li>
<li>Device polling is no longer an INFO level message filling the log on your devices <a href="https://github.com/FlowFuse/device-agent/issues/10">#10</a></li>
</ul>
<h2 id="bug-fixes" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/07/flowforge-07-released/#bug-fixes"># </a> Bug Fixes</h2>
<p>We've fixed the following bugs in this release.</p>
<ul>
<li><a href="https://github.com/FlowFuse/device-agent/issues/7">Devices now listen on all Interfaces allowing you to run local http servers</a><br /></li>
<li><a href="https://github.com/FlowFuse/device-agent/issues/7">Solved an issue where a device gets an error unknown device</a><br /></li>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/507">The Audit Log in the Forge app displays the correct IP when a user logs in to Node-RED</a><br /></li>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/507">Resolved an issue with devices downloading snaphots from legacy stacks</a><br /></li>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/735">Fixed an error where objects in the node-red log would hang the log page</a><br /></li>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/745">Next Billing Date is now shown correctly</a><br /></li>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/689">Fixed a bug where the loading page would flash during polling</a><br /></li>
</ul>
<h3 id="upgrading-flowfuse" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/07/flowforge-07-released/#upgrading-flowfuse"># </a> Upgrading FlowFuse</h3>
<p><a href="https://app.flowfuse.com/">FlowFuse Cloud</a> is already running 0.7 - ready for
you to try out rollbacks and the new theme.</p>
<p>If you installed a previous version of FlowFuse and want to upgrade, our documentation provides a
guide for <a href="https://flowfuse.com/docs/upgrade/#upgrading-flowfuse">upgrading FlowFuse on a local server</a>.</p>
<h3 id="getting-help" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/07/flowforge-07-released/#getting-help"># </a> Getting help</h3>
<p>If you hit any problems with the platform, or have questions to ask, please do
raise an <a href="https://github.com/FlowFuse/flowfuse/issues">issue on GitHub</a>.
That also includes if you have any feedback or feature requests.</p>
<p>Customers of FlowFuse Cloud can raise a ticket by emailing support@flowfuse.com</p>
<p>We also have a <code>#flowfuse</code> channel on the <a href="https://nodered.org/slack">Node-RED Slack workspace</a>.</p>
https://flowfuse.com/blog/2022/06/flowforge-06-released/FlowFuse 0.6 releasedAdding Devices to the platform2022-06-19T12:00:00ZNick O'Leary<p>Node-RED is well known for its role in IoT solutions - which often means running
flows on devices.</p>
<p>This was something we always wanted to support in FlowFuse and with this release
we're taking the next steps in that direction.</p>
<!--more-->
<h3 id="devices" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/06/flowforge-06-released/#devices"># </a> Devices</h3>
<p>This release includes the first alpha release of the <a href="https://github.com/FlowFuse/device-agent">FlowFuse Device Agent</a>. This is a small piece of node.js software that can be
installed on a device, such as a Raspberry Pi. It connects back to the FlowFuse
platform to get the Node-RED flows it should be running.</p>
<p>This builds on the work we added in 0.5 that lets you register the device,
generate credentials for it and pick which Project in your team it should be assigned
to.</p>
<p>It makes it super simple to start developing your flows in FlowFuse and push them
out to a group of devices with a couple clicks.</p>
<p>There's plenty of work still to come on the Devices feature. Under the covers
it uses an HTTP polling approach to check for updates. That was a pragmatic choice
to get something working - but it isn't our long term strategy. We'll be working
towards a more IoT-native MQTT/WebSocket appoach in the coming releases.</p>
<ul>
<li><a href="https://flowfuse.com/docs/user/devices/">Devices documentation</a></li>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/446">Epic #446 - Devices</a></li>
</ul>
<h3 id="snapshots" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/06/flowforge-06-released/#snapshots"># </a> Snapshots</h3>
<p>This release adds the ability to create Snapshots of your projects. These are
point-in-time backups of your project's flows, credentials and settings.</p>
<p>With this release we support <em>creating</em> snapshots and pushing them to devices.</p>
<p>We don't have the ability to revert a project back to a previous snapshot, but
that will come soon.</p>
<ul>
<li><a href="https://flowfuse.com/docs/user/snapshots/">Snapshot documentation</a></li>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/587">Story #587 - Snapshot/Rollback</a></li>
</ul>
<h3 id="other-updates" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/06/flowforge-06-released/#other-updates"># </a> Other updates</h3>
<p>Beyond these headline features, there are a number of smaller, but just as useful
items in this release.</p>
<p>We've continued with the rebranding work started in 0.5 with some more improvements
to the overall UX of the platform. Little touches like placeholder loading graphics
give the UI a more responsive feel.</p>
<p>When you log out of the platform we now also automatically log you out of any
Node-RED editor sessions you have open.</p>
<h3 id="upgrading-flowfuse" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/06/flowforge-06-released/#upgrading-flowfuse"># </a> Upgrading FlowFuse</h3>
<p><a href="https://app.flowfuse.com/">FlowFuse Cloud</a> is already running 0.6 - ready for
you to start creating snapshots and adding devices right now.</p>
<p>If you installed a previous version of FlowFuse and want to upgrade, our documentation provides a
guide for <a href="https://flowfuse.com/docs/upgrade/#upgrading-flowfuse">upgrading FlowFuse on a local server</a>.</p>
<h3 id="getting-help" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/06/flowforge-06-released/#getting-help"># </a> Getting help</h3>
<p>If you hit any problems with the platform, or have questions to ask, please do
raise an <a href="https://github.com/FlowFuse/flowfuse/issues">issue on GitHub</a>.</p>
<p>That also includes if you have any feedback or feature requests.</p>
<p>We also have a <code>#flowfuse</code> channel on the <a href="https://nodered.org/slack">Node-RED Slack workspace</a>.</p>
https://flowfuse.com/blog/2022/06/community-news-05/Community News May 2022News from the FlowFuse and Node-RED communities2022-06-17T00:00:00Z<p>Welcome to the FlowFuse newsletter, a regular roundup of what`s happening with both FlowFuse and the wider Node-RED community.</p>
<!--more-->
<p>If you've got something that you'd like us to share please email <a href="mailto:contact@flowfuse.com">contact@flowfuse.com</a>.</p>
<p><a href="https://flowfuse.com/blog/2022/06/flowforge-06-released/">FlowFuse 0.5 AND 0.6</a><br />
We've had two releases since our last newsletter, there are a lot of related features between them.
We introduced a new design for the forge application which aligns with the branding on our website.
We've added <a href="https://flowfuse.com/docs/user/concepts/#device">Devices</a>, allowing you to run and manage your node-red projects on your own hardware, this is ideal for applications that need to connect to either sensor data or specialist hardware deployed outside the cloud.
We added a new concept as part of this work, <a href="https://flowfuse.com/docs/user/concepts/#instance-snapshot">Snapshots</a> allow you to take a point in time copy of your project, today that can then be deployed to one or more devices but we have plans to expand this concept for things like <a href="https://github.com/FlowFuse/flowfuse/issues/587">rolling back</a> a project to a previous point in time.
<a href="https://flowfuse.com/blog/2022/05/flowforge-05-released/">0.5</a> Introduced the capabilities of copying a project or certain parts of it, allowing for scenarios like having multiple environments for Development and Production.</p>
<p><a href="https://discourse.nodered.org/t/node-red-3-0-0-beta-3-released/64027">Node-RED 3.0.0-beta-3</a><br />
The Node-RED 3.0 beta releases continue as the project is getting very close to the full release in the coming weeks, We'll be making it availble on FlowFuse cloud very soon.</p>
<p><a href="https://kazuhitoyokoi.medium.com/creating-custom-node-from-subflow-in-node-red-ce52cc42bbba">Creating custom node from subflow in Node-RED</a><br />
One of the contributors to Node-RED, Kazuhito Yokoi wrote a nice tutorial on how to turn a subflow into a custom node.</p>
<p><a href="https://www.youtube.com/channel/UCbBzP8NZbv3WDtlt4UouA-g">YouTube Channel</a><br />
Joe has been busy creating short videos to present FlowFuse and our key concepts, these will start to appear on our YouTube channel, so please like and subscribe!</p>
<p><a href="https://www.42flows.tech/blog/why-have-we-decided-to-implement-visa-direct-api-for-node-red/">Visa Direct in Node-RED</a><br />
The folks over at 42flows use Node-RED in a financial and banking context, they've published an article about integrating with the Visa payments APIs</p>
<p><a href="https://www.papercall.io/nrcon2022">Node-RED Con CFP</a><br />
A reminder about Node-RED Con and the call for papers, submissions close at the end of July but don't wait until the last minute to submit your proposal.</p>
https://flowfuse.com/blog/2022/05/sign-up-for-flowforge-cloud/FlowFuse open for everybodySign up and start a new Node-RED project within a minute!2022-05-25T09:00:00ZZJ van de Weg<p>FlowFuse wants to enable everyone to build workflows in Node-RED. Since announcing
<a href="https://flowforge.com/blog/2022/02/announcing-flowforge-cloud/">FlowFuse Cloud</a>
two months ago we've had a waiting list for users to sign up to. That allowed us
to control the pace we were bringing new users onto the platform, learning what
is needed to scale up our platform and continue to improve our first user experience.</p>
<p>Today we have removed the waiting list. Anyone can sign up to FlowFuse and start a
new Node-RED project in under a minute!</p>
<!--more-->
<div class="max-w-md m-auto">
<a class="ff-btn ff-btn--primary" href="https://app.flowfuse.com/account/create">Sign up</a>
</div>
<h2 id="what-we-offer" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/05/sign-up-for-flowforge-cloud/#what-we-offer"># </a> What we offer</h2>
<p>Besides the sub minute time to start a new Node-RED project, there's many more
features our offering includes. Two we'd like to highlight.</p>
<p>To start our blog highlight reel: Collaboration. FlowFuse allows you to work
with a team on your flows. There's the ability to create multiple users, each
with their own credentials that can alter the flows on Node-RED, and it's
execution environment like for example the <a href="https://flowforge.com/docs/user/envvar/">environments variables</a>.</p>
<p>Furthermore, <a href="https://flowforge.com/docs/user/changestack">stacks</a>. These allow
a user to select the execution environment for their Node-RED project. For example; the
Node-RED version being used. Combined with the ability for one to copy a project
to a new stack, this allows FlowFuse users to copy their project to the Node-RED
3.0-beta stack to validate their solutions will continue to work on the new release
without disrupting their main project.</p>
<h2 id="our-roadmap" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/05/sign-up-for-flowforge-cloud/#our-roadmap"># </a> Our roadmap</h2>
<p>Currently we're working towards our 0.6 release. The main feature of this release
will be support for Devices. This will allow you to send a snapshot of a project
to a Node-RED instance running outside of the FlowFuse platform and update the flows
remotely. Remote devices will run our <a href="https://github.com/FlowFuse/device-agent">agent</a>
to communicate with the FlowFuse Cloud project.</p>
<p>While the first iteration will be considered an Alpha release, by shipping early and often, it lets us get
welcome feedback from our users and the wider community - helping to shape the future direction.
It also allows users to start validating the feature for their own proof of concept projects.</p>
<p>Over the next few months we're continuing to drive development of the platform
across a number of areas - including further improvements to the Device feature.
But also looking at new Enterprise-ready features, such as Single-Sign On integration
and more tools to make collaboration even easy.</p>
<p>We intend to grow our offering so that FlowFuse remains the best way to run
Node-RED.</p>
<p>Stay informed by registering for our newsletter!</p>
https://flowfuse.com/blog/2022/05/flowforge-05-released/FlowFuse 0.5 releasedBringing a new look to the platform2022-05-12T12:00:00ZNick O'Leary<p>The cycle continues with our next regularly scheduled release, bringing a fresh
new look to the platform.</p>
<!--more-->
<p>Since joining the team, Joe has been hard at work bringing a more consistent
design language to what we're doing. This release brings a lot of his hardwork
to the platform itself.</p>
<p>There's more to be done on the individual pages of the platform, but this
gives us a solid framework to build on.</p>
<p><picture><source type="image/avif" srcset="https://flowfuse.com/img/ff-05-dashboard-nX3Q-3e2fZ-650.avif 650w, https://flowfuse.com/img/ff-05-dashboard-nX3Q-3e2fZ-1300.avif 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/webp" srcset="https://flowfuse.com/img/ff-05-dashboard-nX3Q-3e2fZ-650.webp 650w, https://flowfuse.com/img/ff-05-dashboard-nX3Q-3e2fZ-1300.webp 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><source type="image/jpeg" srcset="https://flowfuse.com/img/ff-05-dashboard-nX3Q-3e2fZ-650.jpeg 650w, https://flowfuse.com/img/ff-05-dashboard-nX3Q-3e2fZ-1300.jpeg 1300w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img alt="" loading="lazy" decoding="async" src="https://flowfuse.com/img/ff-05-dashboard-nX3Q-3e2fZ-650.jpeg" width="1300" height="827" /></picture></p>
<ul>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/430">Epic #430 - Rebrand Forage App</a></li>
</ul>
<h3 id="copying-projects" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/05/flowforge-05-released/#copying-projects"># </a> Copying Projects</h3>
<p>One of the usage scenarios we want to support is having an easy way to have separate
test and production environments. The previous release added the ability to configure
environment variables on individual projects.</p>
<p>This release unlocks the next piece of the puzzle - making it easy to copy flows
between projects.</p>
<p>The Project settings page has two new options:</p>
<ul>
<li>Copy Project lets you create a complete copy of the project.</li>
<li>Export to existing project lets you copy over selected aspects of the project
over to another project.</li>
</ul>
<p>In both cases, you get to pick what parts of the project should be copied.</p>
<ul>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/268">Epic #268 - Export Project</a></li>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/271">Story #271 - Duplicate Project</a></li>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/272">Story #272 - Export to Existing Project</a></li>
</ul>
<h3 id="improve-billing-information" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/05/flowforge-05-released/#improve-billing-information"># </a> Improve Billing Information</h3>
<p>We've been getting some great feedback from the users of FlowFuse Cloud. One of the
areas we identified as needing some more clarity was around the point users are
asked to setup their billing information.</p>
<ul>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/563">Story #563 - Improve Information on billing</a></li>
</ul>
<h3 id="edge-devices" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/05/flowforge-05-released/#edge-devices"># </a> Edge Devices</h3>
<p>Whilst we always want to deliver new functionality to end users in each release,
sometimes bits of work don't fit naturally into a single four week iteration.</p>
<p>That's the case here with some of the preliminary work we've done to introduce
the idea of Edge Devices to the platform.</p>
<p>The goal here is to provide a way to easily deploy and manage Node-RED projects
on remote devices.</p>
<p>This release introduces a bunch of work to the core app and front-end to begin
introducing the concept of a Device. It includes the basic workflows for registering
a device on the platform and being able to assign it to a team.</p>
<p>The whole feature is hidden behind a feature flag so users on FlowFuse Cloud won't
see any of this quite yet.</p>
<p>The next release will introduce the Edge Agent piece of this - the bit that runs
on devices.</p>
<ul>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/446">Epic #446 - Devices</a></li>
</ul>
<h3 id="upgrading-flowfuse" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/05/flowforge-05-released/#upgrading-flowfuse"># </a> Upgrading FlowFuse</h3>
<p>If you installed a previous version of FlowFuse and want to upgrade, our documentation provides a
guide for <a href="https://flowfuse.com/docs/upgrade/#upgrading-flowfuse">upgrading FlowFuse on a local server</a>.</p>
<h3 id="getting-help" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/05/flowforge-05-released/#getting-help"># </a> Getting help</h3>
<p>If you hit any problems with the platform, or have questions to ask, please do
raise an <a href="https://github.com/FlowFuse/flowfuse/issues">issue on GitHub</a>.</p>
<p>That also includes if you have any feedback or feature requests.</p>
<p>We also have a <code>#flowfuse</code> channel on the <a href="https://nodered.org/slack">Node-RED Slack workspace</a>.</p>
https://flowfuse.com/blog/2022/05/community-news-04/Community News April 2022News from the FlowFuse and Node-RED communities2022-05-06T00:00:00Z<p>Welcome to the FlowFuse newsletter, a regular roundup of what`s happening with both FlowFuse and the wider Node-RED community.</p>
<!--more-->
<p>If you've got something that you'd like us to share please email <a href="mailto:contact@flowfuse.com">contact@flowfuse.com</a>.</p>
<p><a href="https://flowfuse.com/blog/2022/04/flowforge-04-released/">FlowFuse 0.4</a><br />
The next release has enabled us to offer multiple versions of Node-RED along with adding more features to help you configure your Node-RED projects.</p>
<p><a href="https://discourse.nodered.org/t/node-red-3-0-0-beta-1-released/62124">Node-RED 3.0.0-beta-1</a><br />
The first beta for Node-RED 3.0.0 has been published, there's some exciting improvements on UI in the editor to make designing your flows even easier.</p>
<p><a href="https://flowfuse.com/blog/2022/05/node-red-3-beta-stack/">Node-RED Beta on FlowFuse</a><br />
As promised in out 0.4 announcement, we've made the beta available to our users on FlowFuse as a separate stack, this is just one way that we're able to demonstrate the flexibility you get from running Node-RED on FlowFuse.</p>
<p><a href="https://developer.cisco.com/meraki/build/exploring-meraki-and-spark-apis-with-node-red/">Cisco & Node-RED</a><br />
The team at Cisco DevNet published some great guides on using Node-RED to manage both your Meraki Access points and to integrate with WebEx Teams, they've also produced a handy <a href="https://blogs.cisco.com/developer/helloworldlowcodenodered01">starter guide</a> for those that are new to Node-RED</p>
<p><a href="https://nrcon.nodered.org/">Node-RED Con 2022</a><br />
Our friends in the Node-RED Japan User Group have run a number of successful Node-RED conferences over the last few years. This year, we're joining forces with them to bring the event to a wider audience. The <a href="https://www.papercall.io/nrcon2022">Call for Papers</a> is open now and we'd love to see your submissions.</p>
https://flowfuse.com/blog/2022/05/node-red-3-beta-stack/Node-RED 3.0 Beta StackTry out the next major Node-RED release2022-05-04T00:00:00Z<p>The first beta of Node-RED 3.0 is here and FlowFuse is ready for you to try it out.</p>
<!--more-->
<p>When we released <a href="https://flowfuse.com/blog/2022/04/flowforge-04-released/">FlowFuse 0.4</a> last month we talked about allowing users to select the stack their project runs on.
Until now we've only offered one stack which has been the latest Node-RED release (2.2.2).</p>
<p>Yesterday the first beta of Node-RED 3.0 was <a href="https://discourse.nodered.org/t/node-red-3-0-0-beta-1-released/62124">released</a>, so as of today we have added a choice of stacks to FlowFuse Cloud. You can stick with the <em>Default</em> and use Node-RED 2.2.2 or if you want to try out the beta you can select <em>Node-RED-3.0.0-beta-1</em>.</p>
<p><picture><source type="image/gif" srcset="https://flowfuse.com/img/beta_stack-qr0eO95s0v-650.gif 650w" sizes="(min-device-pixel-ratio: 1.25) 1300px, (min-resolution: 120dpi) 1300px, 650px" /><img title="Selecting the beta Stack" alt="Selecting the beta Stack" loading="lazy" decoding="async" src="https://flowfuse.com/img/beta_stack-qr0eO95s0v-650.webp" width="650" height="497" /></picture></p>
<p>FlowFuse is the best way to run multiple Node-RED instances at different versions. Beta releases are exciting to try out, but you don't want to risk your production applications with an early upgrade. FlowFuse makes it easy to create a new project to try things out.</p>
<p>We'll continue to update the stack choice with each beta when they are released.</p>
https://flowfuse.com/blog/2022/04/flowforge-04-released/FlowFuse 0.4 releasedGetting ready for Node-RED 3.02022-04-14T12:00:00Z<p>This release of the FlowFuse adds a seemingly small, but significant new feature.</p>
<!--more-->
<p>With <a href="https://nodered.org/about/releases/">Node-RED 3.0 fast approaching</a> we've been making sure we are ready to support this.</p>
<h3 id="upgrading-node-red" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/04/flowforge-04-released/#upgrading-node-red"># </a> Upgrading Node-RED</h3>
<p>The goal of FlowFuse is to be the best way to run Node-RED at any scale, whether that's many users or many instances. Node-RED is a constantly developing as a platform and therefore part of running Node-RED is also upgrading the version you are running.</p>
<p>With the 0.4 release today we've made that super simple in FlowFuse. Last month we introduced the concept of <a href="https://flowfuse.com/docs/user/concepts/#stack">Project Stacks</a>. One of the key elements of a Stack was the version of Node-RED in use. Initially this may have seemed fairly basic, when you create a new project you usually want to use the latest version of Node-RED. However what happens when a new version is released and you have an existing project?
Now you can change the stack that a project is running on, which in turn will change the version of Node-RED. This is a simple process from the project settings, it only requires a short period of downtime while the project restarts on the new stack, typically around 10-15 seconds.</p>
<p>Our driver to get this feature into the 0.4 release is the approaching release of Node-RED 3.0, now we know that we can be ready to offer our users Node-RED 3.0 as soon as it is released.</p>
<p>We will also be making available the Beta's of Node-RED 3.0 within FlowFuse Cloud, this becomes a great way to test out the new features without having to touch your own environments.</p>
<ul>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/288">Story #288 - Change Stacks</a></li>
<li><a href="https://flowfuse.com/docs/user/changestack/">Docs</a></li>
</ul>
<h3 id="environment-variables" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/04/flowforge-04-released/#environment-variables"># </a> Environment Variables</h3>
<p>Another key new feature we are introducing is the ability to set and manage environment variables within your projects.
Environment Variables are a key tool when building applications as they allow you to to separate the configuration of your system from the logic in the code. Even in Low-Code platforms this is an important design pattern. Environment variables are fully integrated into <a href="https://flowfuse.com/docs/user/concepts/#template">Templates</a> that we introduced last month so they can be set both at the platform level or on an individual project.
Our plans for the next release will make these even more useful as we introduce the ability to <a href="https://github.com/FlowFuse/flowfuse/issues/271">duplicate a project</a> and then modify those variables for the new project.</p>
<ul>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/225">Story #225 - Project Environment Variables</a></li>
<li><a href="https://flowfuse.com/docs/user/envvar/">Docs</a></li>
</ul>
<h3 id="there's-more" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/04/flowforge-04-released/#there's-more"># </a> There's more</h3>
<p>There are many more improvements in this release, such as the ability to <a href="https://github.com/FlowFuse/flowfuse/issues/239">Set the timezone</a> your project is running in, we've also been iterating on our billing experience as we've welcomed the first paying customers to FlowFuse Cloud.</p>
<p>Finally we're very happy that we've had our first external contribution to the code base, as an Open Core company we believe strongly that Open Source lives at the heart of everything we do.
We would like to say a big thank-you to <a href="https://fakocodes.netlify.app/">Fakorede Damilola Idris</a> for his work on fixing a <a href="https://github.com/FlowFuse/flowfuse/issues/424">bug</a> in the UI.</p>
<h3 id="getting-started-with-flowfuse" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/04/flowforge-04-released/#getting-started-with-flowfuse"># </a> Getting started with FlowFuse</h3>
<p>The documentation provides a guide for <a href="https://flowfuse.com/docs/install/">installing FlowFuse on a local server</a>.</p>
<p>If you haven't played with FlowFuse yet, here's a more complete walk-through
of the platform:</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/YYZDx8n17Ys" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
<h3 id="upgrading-flowfuse" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/04/flowforge-04-released/#upgrading-flowfuse"># </a> Upgrading FlowFuse</h3>
<p>If you installed a previous version of FlowFuse and want to upgrade, our documentation provides a
guide for <a href="https://flowfuse.com/docs/upgrade/#upgrading-flowfuse">upgrading FlowFuse on a local server</a>.</p>
<h3 id="getting-help" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/04/flowforge-04-released/#getting-help"># </a> Getting help</h3>
<p>If you hit any problems with the platform, or have questions to ask, please do
raise an <a href="https://github.com/FlowFuse/flowfuse/issues">issue on GitHub</a>.</p>
<p>That also includes if you have any feedback or feature requests.</p>
<p>We also have a <code>#flowfuse</code> channel on the <a href="https://nodered.org/slack">Node-RED Slack workspace</a>.</p>
<h3 id="what's-next%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/04/flowforge-04-released/#what's-next%3F"># </a> What's next?</h3>
<p>Our regular release cycle puts the next release on Thursday 12th May.
We will be building on features in the last few releases around managing your projects and using templates, we're also setting the foundations of our work to <a href="https://github.com/FlowFuse/flowfuse/issues/446">manage Node-RED on your own devices running at the Edge</a>.</p>
<p>For more information, check out the <a href="https://flowfuse.com/blog/announcing-flowforge-cloud/">announcement blog post</a>.</p>
<p>You can also sign up to our general mailing list below if you want to hear more
about the work we're doing.</p>
https://flowfuse.com/blog/2022/04/community-news-03/Community News March 2022News from the FlowFuse and Node-RED communities2022-04-05T00:00:00Z<p>Welcome to the FlowFuse newsletter, a regular roundup of what`s happening with both FlowFuse and the wider Node-RED community.</p>
<!--more-->
<p>If you've got something that you'd like us to share please email <a href="mailto:contact@flowfuse.com">contact@flowfuse.com</a>.</p>
<p><a href="https://flowfuse.com/">New Website</a><br />
Some of you may have noticed the new design on our website, this is the first step in our more refined corporate identity, the same look will be coming to the FlowFuse application <a href="https://github.com/FlowFuse/flowfuse/issues/430">soon.</a>.</p>
<p><a href="https://flowfuse.com/blog/2022/03/flowforge-03-released/">FlowFuse 0.3</a><br />
The latest release introduced 2 new concepts, Templates and Stacks, with these we are starting to show the value of the FlowFuse platform allowing you to easily manage the Node-RED settings and versions used by your projects.</p>
<p><a href="https://www.opto22.com/support/resources-tools/videos/video-introduction-to-json-for-node-red/">Intro to JSON for Node-RED</a><br />
Our friends over at Opto 22 published a handy guide to JSON and how it works in Node-RED, great introduction for new builders and a good refresher for seasoned pros.</p>
https://flowfuse.com/blog/2022/04/flowforge-accepting-customers/FlowFuse is accepting customers nowWe're starting to onboard users from the waitlist2022-04-04T00:00:00ZZJ van de Weg<p>A year ago our CTO, Nick O'Leary, <a href="https://flowfuse.com/blog/2021/04/first-deploy/">introduced FlowFuse</a>.
Since then major milestones have been achieved. As we grow as a company, important
steps are taken. Today we make another very important step; we're accepting our
first customers.</p>
<!--more-->
<p>A few weeks ago our product was nearly in a state where it could support customers,
when that was the case, we <a href="https://flowfuse.com/blog/2022/02/announcing-flowforge-cloud/">opened up our waitlist</a>.
The waitlist has been growing daily and now we're ready to start inviting those
users onto the platform. The first
lucky few users are being added today, and each working day for the foreseeable
future we'll continue onboarding users. New users will receive an email from our
team with their login details and can start creating new workflows with Node-RED
minutes after.</p>
<p>While the source code of FlowFuse is <a href="https://github.com/FlowFuse/flowfuse">available</a>,
there's a chance you're unfamiliar with what has been built around Node-RED.
With FlowFuse, our intent is to build a platform to aid with colaboration of
flows in Node-RED. The first steps to our vision include a managed Node-RED
instance to connect virtually any online service. Multiple users will have
access to the same flows and can collaborate. Further, once Node-RED 3.0 has
been released, the platform will provide a pain-free way to upgrade and keep
your projects up to date. There's many more exciting features right around the
corner on our <a href="https://flowfuse.com/product/roadmap/">roadmap</a></p>
https://flowfuse.com/blog/2022/03/flowforge-03-released/FlowFuse 0.3 releasedMoving towards the launch of FlowFuse Cloud2022-03-17T01:00:00ZNick O'Leary<p>The FlowFuse 0.3 release brings us closer to the launch of FlowFuse Cloud.
Find out more about what's in this new release.</p>
<!--more-->
<p>This release of the FlowFuse platform brings some significant new features that
will underpin more of what is to come.</p>
<h3 id="project-stacks-%26-templates" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/03/flowforge-03-released/#project-stacks-%26-templates"># </a> Project Stacks & Templates</h3>
<p>When we think about what a makes a Project inside FlowFuse, the simple answer
is Node-RED.</p>
<p>The more complete answer is: a version of Node-RED, a version of Node.js, some
memory, some CPU and a bunch of Node-RED settings to customise the instance.</p>
<p>In a platform like FlowFuse, it's important to have the tools to manage all
of these things.</p>
<p>This is where Project Stacks and Template come in.</p>
<p>A Project Stack defines the underlying characteristics of the Node-RED process -
or the container it is running in. For example, with our Local deployment model,
it defines the version of Node-RED to use and how much memory the process should
try to use. In our container based deployment models, the stack identifies the
container to use for the project, along with memory and CPU limits.</p>
<p>In a future release, this will be the way we will support upgrading the version
of Node-RED a project is using - and doing so in a well managed way. An Administrator
will be able to create a new Stack containing the new version of Node-RED.
Project owners will then be able to update their projects to use the new Stack -
at a time that is convenient to them.</p>
<p>A Project Template is more about how the Node-RED instance is configured - exposing
the options a user would traditional modify in their Node-RED settings file.
With this release, we're not exposing a lot of settings as the focus has been
more on the underlying Template concept. But it will be the basis for gradually
exposing more options for customisation in the future.</p>
<ul>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/285">Epic #285 - Project Stacks</a></li>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/141">Epic #141 - Project Templates</a></li>
</ul>
<h3 id="billing-integration" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/03/flowforge-03-released/#billing-integration"># </a> Billing Integration</h3>
<p>With our open core philosophy, the heart of the FlowFuse platform is open source
and available under the Apache 2 license for anyone to use.</p>
<p>But the plan was always to have certain features that were licensed separately.</p>
<p>This release brings the first of those features - Stripe Billing Integration. This
feature brings the ability to require a Team to have a Stripe Billing agreement
in place and to be able to charge on a per-project basis within that Team.</p>
<p>Being able to charge is an important feature for any commercial platform, and
with our own FlowFuse Cloud launching soon, we needed to get this feature in
place today.</p>
<p>We've structured the code in the repository and updated the LICENSE file to make it
very clear what parts of the code base are <em>not</em> covered by the Apache 2 license.</p>
<ul>
<li><a href="https://github.com/FlowFuse/flowfuse/issues/224">Epic #224 - Billing</a></li>
</ul>
<h3 id="getting-started-with-flowfuse" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/03/flowforge-03-released/#getting-started-with-flowfuse"># </a> Getting started with FlowFuse</h3>
<p>The documentation provides a guide for <a href="https://github.com/FlowFuse/flowfuse/tree/main/docs">installing FlowFuse on a local server</a>.</p>
<p>If you haven't played with FlowFuse yet, here's a more complete walk-through
of the platform:</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/YYZDx8n17Ys" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
<h3 id="upgrading-flowfuse" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/03/flowforge-03-released/#upgrading-flowfuse"># </a> Upgrading FlowFuse</h3>
<p>If you installed FlowFuse 0.1 or 0.2 and want to upgrade, our documentation provides a
guide for <a href="https://github.com/FlowFuse/flowfuse/tree/main/docs/install/local#upgrade">upgrading FlowFuse on a local server</a>.</p>
<h3 id="getting-help" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/03/flowforge-03-released/#getting-help"># </a> Getting help</h3>
<p>If you hit any problems with the platform, or have questions to ask, please do
raise an <a href="https://github.com/FlowFuse/flowfuse/issues">issue on GitHub</a>.</p>
<p>That also includes if you have any feedback or feature requests.</p>
<p>We also have a <code>#flowfuse</code> channel on the <a href="https://nodered.org/slack">Node-RED Slack workspace</a>.</p>
<h3 id="what's-next%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/03/flowforge-03-released/#what's-next%3F"># </a> What's next?</h3>
<p>Our regular release cycle puts the next release on Thursday 14th April.</p>
<p>We're still in planning stage for the release, but we'll also be beginning to invite
people from the waiting list to sign-up to FlowFuse Cloud.</p>
<p>For more information, check out the <a href="https://flowfuse.com/blog/announcing-flowforge-cloud/">annoucement blog post</a>.
You can also sign up to our general mailing list below if you want to hear more
about the work we're doing.</p>
https://flowfuse.com/blog/2022/03/community-news-02/Community News February 2022News from the FlowFuse and Node-RED communities2022-03-02T00:00:00Z<p>Welcome to the FlowFuse newsletter, a regular roundup of what`s happening with both FlowFuse and the wider Node-RED community.</p>
<!--more-->
<p>If you've got something that you'd like us to share please email <a href="mailto:contact@flowfuse.com">contact@flowfuse.com</a>.</p>
<p><a href="https://flowfuse.com/blog/announcing-flowforge-cloud/">Announcing FlowFuse Cloud</a><br />
We are excited to announce FlowFuse Cloud, a hosted Node-RED as a service offering and today we are opening the waitlist.</p>
<p><a href="https://flowfuse.com/blog/flowforge-02-released/">FlowFuse 0.2</a><br />
We continue to iterate with our 4 weekly releases of the FlowFuse platform.</p>
<p><a href="https://discourse.nodered.org/t/node-red-2-2-2-released/58606">Node-RED 2.2.2</a><br />
The 2.2 release of Node-RED (last month) has received 2 maintenance releases to fix bugs with duplicate wires in the editor and MQTT.</p>
<p><a href="https://flowfuse.com/blog/welcome-joe/">New Team Members</a><br />
FlowFuse is now up to 6 people, Joe Pavitt has joined the team</p>
<p><a href="https://boards.greenhouse.io/flowfuse/jobs/4312861004">We still are Hiring</a><br />
We're looking for the next member of our team, If you're a Node.JS developer and want to work with us take a look at the link.</p>
https://flowfuse.com/blog/2022/02/announcing-flowforge-cloud/Announcing FlowFuse CloudHosting your Node-RED, so you don't have to.2022-02-23T19:44:00ZZJ van de Weg<p>As an open core company, anyone is free to <a href="https://github.com/FlowFuse/flowfuse/tree/9219e81399eaf52fb0ee5573707a52f5520fbfdd/docs/install">download and install</a>
our platform. In many cases this is a great solution, it
allows for custom setups in your own environment. We know this isn't for everyone
though, some people just want to start building with Node-RED without having to manage their servers.</p>
<p>We are excited to announce FlowFuse Cloud, a hosted
Node-RED as a service offering and today we are opening the waitlist.</p>
<!--more-->
<p>Our waitlist captures your email, and we'll reach out to you on that address once your account is created.</p>
<h3 id="starting-operations" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/02/announcing-flowforge-cloud/#starting-operations"># </a> Starting operations</h3>
<p>After having released v0.2 recently, we're now working on v0.3 that will include
a user flow for <a href="https://github.com/FlowFuse/flowfuse/issues/224">billing</a>.
When that work has been done and deployed people on the waitlist will slowly be invited to the platform.
Currently that's scheduled for April 1st, no joke, although it could happen either sooner
or later.
More details on the exact pricing will be availble nearer the time.</p>
<p>Once you are invited you will be able to;</p>
<ul>
<li>Create multiple Node-RED projects hosted on flowforge.cloud,</li>
<li>Invite team members to collaborate on those projects,</li>
<li>And many more features will automatically become availble with each new release.</li>
</ul>
https://flowfuse.com/blog/2022/02/flowforge-02-released/FlowFuse 0.2 releasedKeeping the releases flowing of our open platform for Node-RED2022-02-17T01:00:00ZNick O'Leary<p>Four weeks have passed since our initial release of FlowFuse, and we're happy
to release v0.2 today as we continue moving forward and evolve the platform.</p>
<!--more-->
<p>There aren't lots of headline features in this release to tell you about as a lot
of the work has been on the internals, as well as responding to some of the early
feedback from the community.</p>
<p>Features like improving the test framework, and building a database migration
framework may not sound too exciting to the end user, but they are critical pieces
when build a platform that needs to be stable and easy to upgrade.</p>
<p>We've also been doing work to get our own instance of the platform running in the
Cloud - and figuring out how to automate as much of that as possible. Aside
from being a key way to test the platform, it helps validate the work we're doing
for when others come to run it in that way. It also lays the ground work for our
own cloud service we'll be sharing more about in the coming days.</p>
<p>The full change-log for the core of the platform is available <a href="https://github.com/FlowFuse/flowfuse/blob/v0.2.0/CHANGELOG.md">on GitHub</a>.
But with a further 15 repositories containing different components, each with its
own change-log, we're still thinking about how best to share a single view of the
updates.</p>
<h3 id="getting-started-with-flowfuse" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/02/flowforge-02-released/#getting-started-with-flowfuse"># </a> Getting started with FlowFuse</h3>
<p>The documentation provides a guide for <a href="https://github.com/FlowFuse/flowfuse/tree/main/docs">installing FlowFuse on a local server</a>.</p>
<p>If you haven't played with FlowFuse 0.1 yet, here's a more complete walk-through
of the platform:</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/YYZDx8n17Ys" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
<h3 id="upgrading-flowfuse" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/02/flowforge-02-released/#upgrading-flowfuse"># </a> Upgrading FlowFuse</h3>
<p>If you installed FlowFuse 0.1 and want to upgrade, our documentation provides a
guide for <a href="https://github.com/FlowFuse/flowfuse/tree/main/docs/install/local#upgrade">upgrading FlowFuse on a local server</a>.</p>
<h3 id="getting-help" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/02/flowforge-02-released/#getting-help"># </a> Getting help</h3>
<p>If you hit any problems with the platform, or have questions to ask, please do
raise an <a href="https://github.com/FlowFuse/flowfuse/issues">issue on GitHub</a>.</p>
<p>That also includes if you have any feedback or feature requests.</p>
<p>We also have a <code>#flowfuse</code> channel on the <a href="https://nodered.org/slack">Node-RED Slack workspace</a>.</p>
<h3 id="what's-next%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/02/flowforge-02-released/#what's-next%3F"># </a> What's next?</h3>
<p>Our regular release cycle puts the next release on Thursday 17th March. We've
got some key features planned in this release around <a href="https://github.com/FlowFuse/flowfuse/issues/141">Project Templates</a> and <a href="https://github.com/FlowFuse/flowfuse/issues/285">Stacks</a> -
which will underpin how you can customise Node-RED within FlowFuse.</p>
<p>We'll also have some exciting news to share about our own hosted service you'll
be able to sign-up for.</p>
<p>Sign up to the mailing list below if you want to hear more about the work we're
doing.</p>
https://flowfuse.com/blog/2022/02/use-case-solar-afloat/Using Node-RED to keep Solar PV afloatHow spb sonne used Node-RED with a renewable energy solution2022-02-09T09:26:00ZZJ van de Weg<p><a href="https://www.linkedin.com/in/krishnanravichandran/">Krisnan Ravichandran</a> works
for <a href="https://www.sbp.solar/">spb sonne</a>, a engineering consultancy for renewable
energy. Within the company he is part of the engineering effort on the
<a href="https://www.sbp.de/en/news/goembhal-sbp-sonnes-pioneering-floating-pv-system/">Gömbhal</a>
project, creating a floatation device for solar panels.</p>
<p>In this post, he shares his experiences of using Node-RED.</p>
<!--more-->
<p>Currently there’s a prototype deployed in Hungary, while the company is located
in Stuttgart: “We’re remotely monitoring the installation. There are over 40
sensors that all connect to an ADAM-6717, Compact Intelligent Gateway. When the
data is acquired we leverage Node-RED flows that maintain the structure, monitor
performance, and provide reporting back to our offices.</p>
<p>Node-RED is embedded in the ADAM 6717, it was very new to me. I was already
experienced in programming, mainly Python, and within a month I felt very
comfortable and productive in Node-RED. Understanding programming is useful,
though not a necessity.</p>
<p>Building and improving flows I did on my own through trial-and-error, as well
as a lot of times through help on the <a href="https://discourse.nodered.org/">Node-RED Forum</a>.
The community is helpful and welcoming to new users. Now I maintain multiple
flows with very different purposes. Some track temperature,
irradiation wind-speed, direction, tilt and wave height; to ensure the floating
PV installation remains floating. Other sensors are connected to actuators
through flows that control pressure.</p>
<p>We do have some challenges; the ADAM 6717 contained an older version of Node-RED.
This raised questions around security and maintenance, as our Node-RED version
isn’t updated to a newer version in an easy manner. It also hampers training a
bit because documentation might reference an API or node for a flow that’s just
not the same on older versions.</p>
<p>However, I’d choose Node-RED again, it’s well known as well as easy to learn.
Furthermore I found it very versatile.”</p>
<hr />
<p>Thanks to Krisnan for sharing his story. If you have a Node-RED story for us
to share, please get in touch via <a href="mailto:contact@flowfuse.com">contact@flowfuse.com</a>.</p>
https://flowfuse.com/blog/2022/02/welcome-joe/Welcome Joe2022-02-08T00:00:00ZNick O'Leary<p>Today we welcome Joe Pavitt (<a href="https://twitter.com/joepavitt3d">@joepavitt3d</a>) as
our new Head of UX & Design. This is a key role that will help deliver the awesome
user experience of the FlowFuse platform.</p>
<!--more-->
<p>Joe has a passion for user experience, data visualisation and creativity in
technology. He joins us having been at IBM for 9 years where he specialised in
building bespoke, first of a kind experiences in IBM's Emerging Technology and
Research teams.</p>
<p>We worked together at IBM and I saw first-hand the range and quality of what he
can do. I was super pleased when he agreed to join us and I look forward to
seeing the real impact he'll have on what we're building.</p>
<p>Welcome aboard Joe!</p>
https://flowfuse.com/blog/2022/01/community-news-01/Community News January 2022News from the FlowFuse and Node-RED communities2022-01-28T00:00:00Z<p>Welcome to the first FlowFuse newsletter, we’re going to publish this as a regular roundup of what`s happening with both FlowFuse and the wider Node-RED community, if you want to receive it via email, sign up for updates at the bottom of the page.</p>
<!--more-->
<p>If you’ve got something that you’d like us to share please email <a href="mailto:contact@flowfuse.com">contact@flowfuse.com</a>.</p>
<p><a href="https://flowfuse.com/blog/flowforge-01-released">FlowFuse 0.1 Released</a><br />
First up we are really pleased to ship the first version of our platform, this is a very early release but hopefully will give you an idea of the direction we’re going in.</p>
<p><a href="https://nodered.org/blog/2022/01/27/version-2-2-released">Node-RED 2.2</a><br />
The next version of Node-RED has been released with new editor features, predefined environment variables and improvements to some of the core nodes. Checkout the blog post and change log for more details.</p>
<p><a href="https://blog.golioth.io/building-iot-dashboards-with-golioth-grafana-and-node-red">Make your IoT data beautiful</a><br />
Ben Mawby wrote a guide on connecting Golioth's WebSocket endpoints to Grafana using Node-RED and InfluxDB</p>
<p><a href="https://www.sammachin.com/posts/alexaweb-reborn">Alexa Voice Service on Node-RED</a><br />
Sam Machin rebuilt an app on Node-RED allowing you to talk to Alexa through the browser. And he has published a new <a href="https://flows.nodered.org/node/@sammachin/node-red-alexa-voice-service">node</a> to use the Alexa Voice Service within your own flows.</p>
<p><a href="https://flowfuse.com/blog">New Team Members</a><br />
We welcomed 2 new members of the FlowFuse team this month <a href="https://flowfuse.com/blog/welcome-zj">ZJ</a> joins as our CEO and <a href="https://flowfuse.com/blog/welcome-steve">Steve</a> has come onboard to work on the Node-RED project</p>
<p><a href="https://boards.greenhouse.io/flowfuse/jobs/4312861004">We are Hiring</a><br />
We're looking for the next member of our team, If you're a Node.JS developer and want to work with us take a look at the link.</p>
https://flowfuse.com/blog/2022/01/flowforge-01-released/FlowFuse 0.1 releasedMaking the first release of the platform and transitioning to open development2022-01-20T01:00:00ZNick O'Leary<p>For an open core company, we haven't been very open with what we're doing. That all
changes today with the release of FlowFuse 0.1 and making all of our repositories
public.</p>
<p>This is a significant step for the company as we look to build a platform around Node-RED.</p>
<!--more-->
<p>The main question we get asked is: 'What is FlowFuse?" - which is a very reasonable
question to ask.</p>
<p>FlowFuse is a platform for managing Node-RED instances at scale. It lets you have
multiple users on the platform, organised into teams to provide proper access control
to individual Node-RED instances, or Projects as we call them.</p>
<p>With the 0.1 release, we have the basic building blocks of the platform in place.</p>
<ul>
<li>Add multiple users to the platform</li>
<li>Create teams for those users</li>
<li>Create Node-RED projects quickly and easily through the platform UI</li>
</ul>
<p>For a more complete walk-through of the platform in this early release, you can
watch this video.</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/YYZDx8n17Ys" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
<h3 id="getting-started-with-flowfuse" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/01/flowforge-01-released/#getting-started-with-flowfuse"># </a> Getting started with FlowFuse</h3>
<p>The documentation provides a guide for <a href="https://github.com/FlowFuse/flowfuse/tree/main/docs">installing FlowFuse on a local server</a>.</p>
<p>We also have drivers for deploying to Docker Compose and Kubernetes based environments
to enable a larger scale of deployment. We'll have more documentation on those options
in the near future.</p>
<h3 id="getting-help" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/01/flowforge-01-released/#getting-help"># </a> Getting help</h3>
<p>If you hit any problems with the platform, or have questions to ask, please do
raise an <a href="https://github.com/FlowFuse/flowfuse/issues">issue on GitHub</a>.</p>
<p>That also includes if you have any feedback or feature requests.</p>
<h3 id="what's-next%3F" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2022/01/flowforge-01-released/#what's-next%3F"># </a> What's next?</h3>
<p>With so much in the plan and lots of exciting features to come, we will have a
regular cycle of releases every four weeks. So you can expect the next release, 0.2,
on Thursday 17th February.</p>
<p>As we're only at 0.1 today, there is a lot still to do. We will be following the
principles of <a href="https://semver.org/">Semantic Versioning</a> with our releases,
but until we reach 1.0, there may be some disruptive changes along the way.</p>
<p>Sign up to the mailing list below if you want to hear more about the work we're
doing.</p>
https://flowfuse.com/blog/2022/01/welcome-steve/Welcome Steve2022-01-20T00:00:00ZNick O'Leary<p>We're continuing to grow the FlowFuse team with our latest hire; Steve McLaughlin
who is joining our development team.</p>
<!--more-->
<p>Steve is a well known face in the Node-RED community. He is a regular contributor
to the community forum, always happy to help users with their questions.</p>
<p>He has published a number of very popular nodes, include <a href="https://flows.nodered.org/node/node-red-contrib-buffer-parser">buffer-parser</a>,
<a href="https://flows.nodered.org/node/node-red-contrib-cron-plus">cron-plus</a> and
<a href="https://flows.nodered.org/node/node-red-contrib-image-tools">image-tools</a>.</p>
<p>He has also made some significant contributions to the core of Node-RED, such as
delivering MQTTv5 support and introducing the Monaco code editor into the heart
of the editor.</p>
<p>Steve joins us from a background in Industrial IoT in the automative manufacturing
space - experience and knowledge that will be invaluable as we look to growing the
FlowFuse platform.</p>
<p>Steve will be focussed on the Node-RED side of our activities - helping to continue
the ongoing development and growth of the open source project at the heart of what
FlowFuse is about.</p>
<p>Welcome aboard Steve!</p>
https://flowfuse.com/blog/2022/01/welcome-zj/Welcome ZJ2022-01-03T00:00:00ZNick O'Leary<p>This year the FlowFuse team will grow further, and I'm excited to announce our
newest addition to the team; Zeger-Jan van de Weg (<a href="https://twitter.com/ZJvandeWeg">@ZJvandeWeg</a>).
Zeger-Jan, also known as ZJ, is joining FlowFuse as CEO.</p>
<!--more-->
<p>ZJ previously worked at GitLab where he helped build a vibrant open source
community and we're thrilled to have him to continue this with the Node-RED
community. Under his supervision the involvement of GitLab in the Git project
grew significantly, allowing Git and GitLab to be successful together. This aligns
well with our vision for FlowFuse:</p>
<blockquote>
<p>We will only be successful if the whole Node-RED community is successful.</p>
</blockquote>
<p>As our first non-engineering hire, ZJ will be focussed on growing the business side
of FlowFuse, working on marketing and ongoing business development.</p>
<p>Welcome aboard ZJ!</p>
https://flowfuse.com/blog/2021/05/welcome-ben/Welcome Ben2021-05-10T00:00:00ZNick O'Leary<p>I'm excited to share the news that Ben Hardill (<a href="https://twitter.com/hardillb">@hardillb</a>) is joining FlowFuse as a Senior Engineer.</p>
<!--more-->
<p>I've known Ben for many years, having worked together at IBM. He's been an active member
of the Node-RED community since the start of the project and he published one of
the very first <a href="https://flows.nodered.org/node/node-red-node-geofence">3rd party nodes</a>.</p>
<p>He is ever-present on Stack Overflow, to the point where I've long since stopped
rushing to respond to questions tagged with <a href="https://stackoverflow.com/questions/tagged/node-red"><code>node-red</code></a>
in the full knowledge that he has usually beaten me to it.</p>
<p>More recently he's been doing some really interesting work exploring <a href="https://www.hardill.me.uk/wordpress/2020/10/01/multi-tenant-node-red/">multi-tenant Node-RED systems</a> - something we'll
be continuing at FlowFuse.</p>
<p>Welcome aboard Ben!</p>
https://flowfuse.com/blog/2021/04/first-deploy/Introducing FlowFuse Inc.Building a new low-code development platform around the Node-RED project2021-04-06T00:00:00ZNick O'Leary<p>When Dave and I first created <a href="https://nodered.org/">Node-RED</a>, it was a tool to solve a
problem - allowing us to do our day job more effectively when building IoT solutions
for clients. That gave us the means and purpose to create a truly useful platform.</p>
<p>When it became an open source project, it quickly found an enthusiastic audience that
has seen the community grow beyond our imagination. From both individual users, to a wide
range of companies integrating it into their own products.</p>
<p>But with that growth, the question in my mind has always been how to take it further
and secure its long term future.</p>
<p>I wrote on the <a href="https://nodered.org/blog/2020/10/13/future-plans">project blog</a>
last year about the future plans of the project. A key piece of that is its sustainability -
how we can increase the commercial adoption of Node-RED and how we can get more people
contributing back.</p>
<p>An opportunity presented itself earlier this year that I believe will bring a
step-change to what the Node-RED project is able to achieve.</p>
<!--more-->
<h3 id="introducing-flowfuse-inc." tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2021/04/first-deploy/#introducing-flowfuse-inc."># </a> Introducing FlowFuse Inc.</h3>
<p>So today, I'm launching FlowFuse Inc - a new company whose mission is to build a low-coding development
platform fit for the enterprise with Node-RED at its heart.</p>
<p>Backed by <a href="https://www.linkedin.com/in/sijbrandij/">Sid Sijbrandij</a>, we have funding
in place to create a fully remote team dedicated to an open core model.</p>
<p>In the short term, this means helping to accelerate the plans already in place for
the Open Source project. Getting the 2.0 release done in the next few weeks, working on
long-standing features such as the Test framework and Flow Debugger.</p>
<p>Alongside that we'll also be building a platform around Node-RED that will make it easier
to adopt at scale and integrate into existing enterprise environments.</p>
<p>Node-RED remains a fully open source project, with its home at the OpenJS Foundation
and an open governance model that allows anyone to have a say in its development.</p>
<p>Our goal is to incorporate as much of our work directly into the core project as possible. Where we do create closed-source components, we will work with the community to ensure the right APIs and extension points are in the core for all to benefit from.</p>
<p>We will only be successful if the whole Node-RED community is successful.</p>
<p>For me personally, this is a really exciting next step. I never expected to turn my little side project into a full-time job and now into a company.</p>
<h3 id="hiring-soon!" tabindex="-1"><a class="header-anchor" href="https://flowfuse.com/blog/2021/04/first-deploy/#hiring-soon!"># </a> Hiring soon!</h3>
<p>We'll be hiring soon - so keep an eye out if you're interesting in getting involved.</p>