flexdash / node-red-flexdash

Node-RED server integration for FlexDash
MIT License
10 stars 3 forks source link
dashboard flexdash iot node-red

node-red-flexdash

Node-RED nodes to interface with FlexDash

FlexDash is a self-contained web dashboard for Node-RED and IoT devices. This package provides Node-RED nodes that form the core of a FlexDash integration. These nodes provide the basis for communicating with FlexDash but they do not make any of the built-in widgets available. For Node-RED nodes corresponding to the built-in widgets use the Node-RED FD CoreWidgets package.

Under the hood the nodes here use Socket.IO and the dashboard(s) can use Node-RED's web server (i.e. the same port) or a different port.

For help, please read the FlexDash Docs and check the Node-RED forum.

Installation

TL;DR: You most likely do not want to explicitly install this package, you want to install the core widgets, which will bring in this package and more and will provide a usable whole.

npm i @flexdash/node-red-fd-corewidgets

If you really want to install node-red-flexdash, e.g., to get a specific version:

npm i @flexdash/node-red-flexdash

You also do not need to install FlexDash, it comes bundled in the node-red-flexdash package.

Pre-release (dev) versions are published on npm using a "dev" tag:

Internals

The main interface with FlexDash is flexdash-dashboard.*, which handles serving up FlexDash and handling messages to/from the dashboard. It also exposes a config node to represent the dashboard connection. There can be multiple dashboards as long as they use different paths or ports.

The Node-RED plugin in flexdash-plugin/* is manages the hierarchy of FlexDash objects, e.g. tabs, grids, panel, widget. It is a Node-RED plugin so node-red widget nodes can call "into FlexDash" without having to figure out how to get a handle onto the appropriate flexdash-dashboard config node first. The plugin is in a subdirectory and forms a separate NPM package due to a bug in Node-RED.

The config nodes in flexdash-tab.* and flexdash-container.* represent containers for widgets in the dashboard. flexdash-container can represent a grid or a panel. A Widget either belongs to a grid or to a panel which itself belongs to a grid. A grid belongs to a tab and there can be multiple tabs per dashboard.

The development server in flexdash-dev-server.* is a node that can be placed anywhere to launch a development server for FlexDash widgets. It runs Vite, which is a web server that automatically pushes source code to the web browser as soon as you save a file (hot module reload). To access the dev server, once launched, point your browser at the dashboard URL plus a -dev suffix, e.g. /flexdash-dev instead of /flexdash for the default set-up. (Note: the dev server feature should be moved into a side-bar eventually.)

The flexdash-in.* and flexdash-out.* nodes are not currently supported. They send/receive raw messages to/from FlexDash which supports advanced usage. However, the current saving of dashboard configuration changes does not really support such advanced usage, so these nodes are not currently exported.

Some relevant Node-RED internals

Flows

This section describes how Node-RED-FlexDash represents dashboards, tabs,. grids, widgets, etc. and integrates with the Node-RED concepts of flows, config nodes, nodes, etc.

Dashboard and Tab config nodes

Grid and Panel config nodes

Widgets and Array widgets

Widget fields

Subflows

Node-RED FlexDash supports one level of subflows, that is, widget nodes can be placed in a subflow and that subflow can be instantiated many times in flows, but it cannot be instantiated/nested in another subflow. In addition, all the widgets in a subflow must be placed into a SubflowPanel, i.e., associated with a SubflowPanel config nodes and they will then appear in a panel in FlexDash.

Subflows are quite complicated because in the flow editor (and the "config" saved and passed into the run-time) there are only the subflow "template" nodes and then a subflow instance node for each instance of a subflow. The run-time then expands each subflow instance into a full copy of the subflow template, so new nodes are created (with new IDs at each deploy!) and those are the ones that exist in the run-time as "nodes" while the template nodes only exist as "config".

At a high level, the relationships in the flow editor are as follows:

In the end, the FlexDash hierarchy is as follows:

In the runtime all this stuff further gets instantiated: each instance of the subflow results in a new set of widgets nodes and a new subflow panel node. The subflow instance node remains as-is and the subflow itself is only present in the config.

The IDs of FlexDash widgets (incl. subflow panels) is w + the Node-RED ID, which means that on every Node-RED deploy the FlexDash widgets are rebuilt from scratch. This is not ideal, but the alternative would add quite a bit of complexity.

Subflow

Subflow instance

Subflow panel

Subflow panel instance

Subflow widget

fd_container / fd_children

A widget config's fd_container refers to the subflow panel config, not to the subflow panel instance node. Similarly, a subflow panel's fd_children contains a list of subflow widget configs.

A subflow panel or a subflow panel instance do not have an fd_container. Instead, the containing grid is found in the subflow instance flexdash_grid env variable. The grid's fd_children contains the subflow instance ID.

Disabled flows

When flows are disabled the nodes simply don't show up in the runtime. This means that fd_children has IDs that are missing and look like they were deleted.

The config coming out of the flow editor needs to ensure that all nodes referenced in the "children" list exist (in the flow editor). Then in the run-time, missing nodes found in the children list are assumed to be disabled and are marked as such, but not removed.

When altering the position of widgets in the dashboard, the missing widgets need to be kept. When the config is pushed back into the flow editor, the missing widgets should be reconnected with the disabled nodes.

Widgets in disabled flows end up with an ID starting with an 'x' to signal to FlexDash that these are to be skipped.

Dirty laundry

Node-red-flexdash uses a bunch of hacks to work around problems in Node-RED. I'm listing them here in case I get asked which specific ones :-) :

License

MIT