From 51319349cdc31ef51613af4991199307b8c61718 Mon Sep 17 00:00:00 2001 From: Sonny Piers Date: Wed, 21 May 2025 09:52:54 +0200 Subject: [PATCH 1/3] Fix device backend service references --- .../community/contribute/tips-and-tricks.md | 18 +- .../software/subsystems/installation.md | 14 +- .../reference/software/subsystems/startup.md | 6 +- .../node-red-dashboard/adafruithat/flows.json | 16878 +++++++--------- .../planktoscopehat/flows.json | 16199 +++++++-------- 5 files changed, 15287 insertions(+), 17828 deletions(-) diff --git a/documentation/docs/community/contribute/tips-and-tricks.md b/documentation/docs/community/contribute/tips-and-tricks.md index 75f4d84a4..c9a8a5c5e 100644 --- a/documentation/docs/community/contribute/tips-and-tricks.md +++ b/documentation/docs/community/contribute/tips-and-tricks.md @@ -1,6 +1,5 @@ # Tips and tricks - This page provides useful snippets and how-tos while developing software for the PlanktoScope. !!! warning @@ -56,6 +55,7 @@ cd ~/PlanktoScope git config --global user.email "you@example.com" git config --global user.name "Your Name" ``` +
@@ -96,7 +96,7 @@ Use `$planktoscope` as the host to connect to and open the "PlanktoScope" direct If you make changes to the backend, you can restart the backend and test your changes with ```sh -sudo systemctl restart planktoscope-org.device-backend.controller-planktoscopehat.service +sudo systemctl restart planktoscope-org.device-backend.controller.service ``` ## Connect to router @@ -116,6 +116,7 @@ nmcli connection up eth0-default # Ethernet nmcli connection down eth0-default ``` +
Your PlanktoScope should be accessible via its hostname which you can retrieve from the PlanktoScope with `hostnamectl` @@ -134,7 +135,6 @@ You will need to plug the SD card into your computer. `/dev/device` refers to the path of the SD card device/disk. You will need to adjust it. Use `diskutil list` on macOS and `fdisk --list` on Linux. - ```sh # backup whole SD card onto an image file on your computer sudo dd bs=1M if=/dev/device status=progress conv=fdatasync | xz > sdcard.img.xz @@ -151,8 +151,8 @@ See also the operating guide [SD Card Cloning](../../operation/clone-sd.md). This is a quick setup guide. See also -* [documentation README](https://github.com/PlanktoScope/PlanktoScope/blob/master/documentation/README.md) -* [Writing Documentation](./documentation.md) +- [documentation README](https://github.com/PlanktoScope/PlanktoScope/blob/master/documentation/README.md) +- [Writing Documentation](./documentation.md) Install dependencies: @@ -162,10 +162,12 @@ Install dependencies: Start by [installing WSL (Ubuntu)](https://learn.microsoft.com/en-us/windows/wsl/install#install-wsl-command) Because of a small incompatibilty between Windows and Linux; we recommend cloning the repo "in WSL" but if you prefer keeping your git clone "in Windows", here are other options: -* [Git line endings](https://learn.microsoft.com/en-us/windows/wsl/tutorials/wsl-git#git-line-endings) -* [Visual Studio Code WSL extension](https://code.visualstudio.com/docs/remote/wsl) + +- [Git line endings](https://learn.microsoft.com/en-us/windows/wsl/tutorials/wsl-git#git-line-endings) +- [Visual Studio Code WSL extension](https://code.visualstudio.com/docs/remote/wsl) Then follow the Ubuntu instructions below. +
@@ -177,6 +179,7 @@ sudo apt install python3-poetry cd documentation poetry install --no-root ``` +
@@ -187,6 +190,7 @@ sudo dnf install python3-poetry cd documentation poetry install --no-root ``` +
Run live previewer: diff --git a/documentation/docs/reference/software/subsystems/installation.md b/documentation/docs/reference/software/subsystems/installation.md index 7daeff18a..45217b334 100644 --- a/documentation/docs/reference/software/subsystems/installation.md +++ b/documentation/docs/reference/software/subsystems/installation.md @@ -2,21 +2,21 @@ This document explains how the [PlanktoScope OS](../architecture/os.md)'s installation process works, as a companion to our [non-standard installation guide](../../../setup/software/nonstandard-install.md) which carries out the process explained below. -The installation process is initiated by booting into an [appropriate](../../../setup/software/nonstandard-install.md#download-a-raspberry-pi-os-sd-card-image) installation of the Raspberry Pi OS and then downloading and [running the *installation bootstrap script*](../../../setup/software/nonstandard-install.md#run-the-installation-script), which in turn downloads and runs the appropriate *distro setup scripts* according to the installation parameters provided to the installation bootstrap script. +The installation process is initiated by booting into an [appropriate](../../../setup/software/nonstandard-install.md#download-a-raspberry-pi-os-sd-card-image) installation of the Raspberry Pi OS and then downloading and [running the _installation bootstrap script_](../../../setup/software/nonstandard-install.md#run-the-installation-script), which in turn downloads and runs the appropriate _distro setup scripts_ according to the installation parameters provided to the installation bootstrap script. ## Installation bootstrap script -The [installation bootstrap script](https://github.com/PlanktoScope/install.planktoscope.community/blob/edge/distro.sh) is provided so that a one-line command can be executed to automatically perform the entire process of installing the PlanktoScope OS on top of the Raspberry Pi OS. [The GitHub repository which contains that script](https://github.com/PlanktoScope/install.planktoscope.community) always publishes the latest version on its `stable` branch to [install.planktoscope.community/distro.sh](https://install.planktoscope.community/distro.sh) via GitHub Pages; other versions can be downloaded from GitHub via the corresponding permalinks for those versions of the file (e.g. for the version from the v2023.9.0 tag in the repository). The installation bootstrap script performs the following steps: +The [installation bootstrap script](https://github.com/PlanktoScope/install.planktoscope.community/blob/edge/distro.sh) is provided so that a one-line command can be executed to automatically perform the entire process of installing the PlanktoScope OS on top of the Raspberry Pi OS. [The GitHub repository which contains that script](https://github.com/PlanktoScope/install.planktoscope.community) always publishes the latest version on its `stable` branch to [install.planktoscope.community/distro.sh](https://install.planktoscope.community/distro.sh) via GitHub Pages; other versions can be downloaded from GitHub via the corresponding permalinks for those versions of the file (e.g. for the version from the v2023.9.0 tag in the repository). The installation bootstrap script performs the following steps: 1. The script loads some [parameters](#script-parameters) (set by environment variables and/or corresponding command-line arguments) which set the behavior of the script. 2. The script installs `git`, if it was not already installed (as is the case on the "Lite" image of the Raspberry Pi OS); if the `yes` parameter was not set and `git` was not already installed, the script will first ask the user to confirm that they wish to install `git` before the script continues. `git` is required to resolve version query parameters provided to the script, so that the script can determine how to download the requested version of the PlanktoScope OS's distro setup scripts. 3. The script clones a minimal ["mirror"](https://git-scm.com/docs/git-clone#Documentation/git-clone.txt---mirror) copy of the specified repository (set by the `repo` parameter) of distro setup scripts to a temporary directory (i.e. a directory created in `/tmp`). This "mirror" copy is used to: - - - Resolve the version query parameters (`version-query`, `query-type`, and - when `query-type` is `tag` - `tag-prefix`) into a specific commit hash for the repository. - - - Determine a [*(pseudo-)version*](https://git-scm.com/docs/git-describe#_examples) string for the resolved commit based on the last release tag (whose name is prefixed with the `tag-prefix` parameter) ancestral to that commit. + + - Resolve the version query parameters (`version-query`, `query-type`, and - when `query-type` is `tag` - `tag-prefix`) into a specific commit hash for the repository. + + - Determine a [_(pseudo-)version_](https://git-scm.com/docs/git-describe#_examples) string for the resolved commit based on the last release tag (whose name is prefixed with the `tag-prefix` parameter) ancestral to that commit. 4. The script clones a copy of the specified repository (set by the `repo` parameter) to a temporary directory and checks out the specific commit which was resolved by the previous step; if the `yes` parameter was not set, the script will first ask the user to confirm that they wish to download the resolved commit of the distro setup scripts before the script continues. Because the repository containing the distro setup scripts may have many large files (e.g. image files for documentation) which are unrelated to the distro setup scripts, this step only downloads files in the specific commit needed for the distro setup scripts. @@ -108,7 +108,7 @@ This phase performs steps which might (in theory) be useful for other projects w This phase performs steps specific to the PlanktoScope's hardware: -- Setup of the PlanktoScope hardware controller: various Python tools (`pip`, `venv`, and `poetry`) are installed using APT, a hard-coded version of a hard-coded Git repository (namely [github.com/PlanktoScope/device-backend](https://github.com/PlanktoScope/device-backend)) is cloned, and various dependencies (both system libraries and Python packages) of the hardware controller are installed. The `planktoscope-org.device-backend.controller-adafruithat.service` and `planktoscope-org.device-backend.controller-planktoscopehat.service` systemd services are created, and the appropriate one is enabled depending on which HAT the PlanktoScope OS is being installed for. The appropriate hardware configuration file will also be copied into the location expected by the hardware controller. (Note: once the PlanktoScope hardware controller is containerized and managed in Forklift, this step will be eliminated.) +- Setup of the PlanktoScope hardware controller: various Python tools (`pip`, `venv`, and `poetry`) are installed using APT, a hard-coded version of a hard-coded Git repository (namely [github.com/PlanktoScope/device-backend](https://github.com/PlanktoScope/device-backend)) is cloned, and various dependencies (both system libraries and Python packages) of the hardware controller are installed. The appropriate hardware configuration file will also be copied into the location expected by the hardware controller. (Note: once the PlanktoScope hardware controller is containerized and managed in Forklift, this step will be eliminated.) - Setup of GPIO stepper initialization at boot: a systemd service is created to release the stepper motors at startup. (Note: this service currently doesn't work and will eventually be fixed, deleted, or replaced.) diff --git a/documentation/docs/reference/software/subsystems/startup.md b/documentation/docs/reference/software/subsystems/startup.md index 412b7eff2..71686060e 100644 --- a/documentation/docs/reference/software/subsystems/startup.md +++ b/documentation/docs/reference/software/subsystems/startup.md @@ -22,7 +22,7 @@ The PlanktoScope OS's setup scripts provide some system services which are not m - `overlay-usr.service` runs after `overlay-sysroot.service` and before `overlay-fs.target`. -- `overlay-etc.service` runs after `overlay-sysroot.service` and `systemd-machine-id-commit.service` , and before `systemd-sysctl.service` and `overlay-fs.target`. +- `overlay-etc.service` runs after `overlay-sysroot.service` and `systemd-machine-id-commit.service` , and before `systemd-sysctl.service` and `overlay-fs.target`. - `start-overlaid-units.service` runs after `overlay-fs.target` and `basic.target`. @@ -54,7 +54,7 @@ For descriptions of the various targets (e.g. `sysinit.target`, `network-pre.tar ### User interface -- `assemble-cockpit-config.service`, `assemble-cockpit-origins.service`, and `assemble-cockpit-origins-templated.service` update Cockpit's configuration file from drop-in config file fragments in `/etc/cockpit/cockpit.conf.d`, `/etc/cockpit/origins.d`, and `/etc/cockpit/origins-templates.d`, respectively. They run after `generate-machine-name.service` and `generate-hostname-templated.service` and before `cockpit.service`. +- `assemble-cockpit-config.service`, `assemble-cockpit-origins.service`, and `assemble-cockpit-origins-templated.service` update Cockpit's configuration file from drop-in config file fragments in `/etc/cockpit/cockpit.conf.d`, `/etc/cockpit/origins.d`, and `/etc/cockpit/origins-templates.d`, respectively. They run after `generate-machine-name.service` and `generate-hostname-templated.service` and before `cockpit.service`. - `ensure-ssh-host-keys.service` regenerates the SSH server's host keys if the keys are missing, and runs before `ssh.service`. @@ -62,4 +62,4 @@ For descriptions of the various targets (e.g. `sysinit.target`, `network-pre.tar ### PlanktoScope-specific hardware abstraction -- The PlanktoScope hardware controller (managed by `planktoscope-org.device-backend.controller-{adafruithat or planktoscopehat}.service`) starts after `forklift-apply.service` (which manages Mosquitto) and `nodered.service` have started, to ensure that the PlanktoScope hardware controller broadcasts the detected camera model name only after the PlanktoScope Node-RED dashboard is ready to receive that broadcast. (In the future the PlanktoScope hardware controller will instead be run as a Docker container and will be managed by `forklift`.) +- The PlanktoScope hardware controller (managed by `planktoscope-org.device-backend.controller.service`) starts after `forklift-apply.service` (which manages Mosquitto) and `nodered.service` have started, to ensure that the PlanktoScope hardware controller broadcasts the detected camera model name only after the PlanktoScope Node-RED dashboard is ready to receive that broadcast. (In the future the PlanktoScope hardware controller will instead be run as a Docker container and will be managed by `forklift`.) diff --git a/software/node-red-dashboard/adafruithat/flows.json b/software/node-red-dashboard/adafruithat/flows.json index 8e03caceb..f7ea326ce 100644 --- a/software/node-red-dashboard/adafruithat/flows.json +++ b/software/node-red-dashboard/adafruithat/flows.json @@ -1,9099 +1,7811 @@ [ - { - "id": "eaae323a.31b3", - "type": "tab", - "label": "Home", - "disabled": false, - "info": "" - }, - { - "id": "b771c342.49603", - "type": "tab", - "label": "Sample", - "disabled": false, - "info": "" - }, - { - "id": "bccd1f23.87219", - "type": "tab", - "label": "Optic Configuration", - "disabled": false, - "info": "" - }, - { - "id": "baa1e3d9.cb29d", - "type": "tab", - "label": "Fluidic Acquisition", - "disabled": false, - "info": "" - }, - { - "id": "cb95299c.2817c8", - "type": "tab", - "label": "Segmentation", - "disabled": false, - "info": "" - }, - { - "id": "c1660bc.e7ff7f8", - "type": "tab", - "label": "Gallery", - "disabled": false, - "info": "" - }, - { - "id": "9daf9e2b.019fc", - "type": "tab", - "label": "Administration", - "disabled": false, - "info": "" - }, - { - "id": "1371dec5.76e671", - "type": "tab", - "label": "System Monitoring", - "disabled": false, - "info": "" - }, - { - "id": "9a22e67a.378818", - "type": "tab", - "label": "MQTT Receive", - "disabled": false, - "info": "" - }, - { - "id": "1eaf21c8.f7a21e", - "type": "tab", - "label": "Hardware Settings", - "disabled": false, - "info": "" - }, - { - "id": "1c24ad9c.bebec2", - "type": "subflow", - "name": "Config", - "info": "An input to this subflow will get the configuration to be saved to disk.\n\nOn startup, this node outputs the loaded configuration", - "category": "", - "in": [ - { - "x": 220, - "y": 160, - "wires": [ - { - "id": "3ad9835.08c937c" - } - ] - } - ], - "out": [ - { - "x": 1040, - "y": 60, - "wires": [ - { - "id": "ad541674.4791c8", - "port": 0 - } - ] - } - ], - "env": [], - "color": "#DDAA99" - }, - { - "id": "4ed26b8b.253504", - "type": "subflow", - "name": "Save hardware config", - "info": "", - "category": "", - "in": [ - { - "x": 40, - "y": 40, - "wires": [ - { - "id": "53d163be.47cf24" - } - ] - } - ], - "out": [], - "env": [], - "meta": {}, - "color": "#DDAA99" - }, - { - "id": "e6665421f66ea4c8", - "type": "subflow", - "name": "Load hardware config", - "info": "", - "category": "", - "in": [ - { - "x": 40, - "y": 40, - "wires": [ - { - "id": "48ceeda454438cb7" - } - ] - } - ], - "out": [ - { - "x": 900, - "y": 40, - "wires": [ - { - "id": "2b1a67ac127f3fe7", - "port": 0 - } - ] - } - ], - "env": [], - "meta": {}, - "color": "#DDAA99" - }, - { - "id": "3a6bb13f.c9703e", - "type": "ui_tab", - "name": "Home", - "icon": "home", - "order": 1, - "disabled": false, - "hidden": false - }, - { - "id": "181bb236.1e94be", - "type": "ui_tab", - "name": "Optic Configuration", - "icon": "fa-eye", - "order": 3, - "disabled": false, - "hidden": false - }, - { - "id": "c9194f02.9d5e9", - "type": "ui_tab", - "name": "Fluidic Acquisition", - "icon": "fa-flask", - "order": 4, - "disabled": false, - "hidden": false - }, - { - "id": "8d16beb8.9b3fb", - "type": "ui_tab", - "name": "Segmentation", - "icon": "fa-crop", - "order": 5, - "disabled": false, - "hidden": false - }, - { - "id": "d9cd733b.ab73d", - "type": "ui_tab", - "name": "System Monitoring", - "icon": "fa-thermometer-full", - "order": 7, - "disabled": false, - "hidden": false - }, - { - "id": "4248342d.e55fac", - "type": "ui_group", - "name": "Optic Characterization", - "tab": "181bb236.1e94be", - "order": 4, - "disp": true, - "width": "6", - "collapse": false - }, - { - "id": "858a0e3c.987fe", - "type": "ui_group", - "name": "Preview", - "tab": "c9194f02.9d5e9", - "order": 1, - "disp": true, - "width": 10, - "collapse": false - }, - { - "id": "64903b47.4034e4", - "type": "ui_group", - "name": "Navigation", - "tab": "8d16beb8.9b3fb", - "order": 3, - "disp": false, - "width": "6", - "collapse": false - }, - { - "id": "3da7da8f.179606", - "type": "ui_group", - "name": "Metrics", - "tab": "d9cd733b.ab73d", - "order": 1, - "disp": true, - "width": "24", - "collapse": true, - "className": "" - }, - { - "id": "cc8bc4eb.651868", - "type": "ui_base", - "theme": { - "name": "theme-dark", - "lightTheme": { - "default": "#0094CE", - "baseColor": "#5900ce", - "baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif", - "edited": false, - "reset": false - }, - "darkTheme": { - "default": "#097479", - "baseColor": "#097479", - "baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif", - "edited": true, - "reset": false - }, - "customTheme": { - "name": "Untitled Theme 1", - "default": "#4B7930", - "baseColor": "#4B7930", - "baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif" - }, - "themeState": { - "base-color": { - "default": "#097479", - "value": "#097479", - "edited": true - }, - "page-titlebar-backgroundColor": { - "value": "#097479", - "edited": false - }, - "page-backgroundColor": { - "value": "#111111", - "edited": false - }, - "page-sidebar-backgroundColor": { - "value": "#333333", - "edited": false - }, - "group-textColor": { - "value": "#0eb8c0", - "edited": false - }, - "group-borderColor": { - "value": "#555555", - "edited": false - }, - "group-backgroundColor": { - "value": "#333333", - "edited": false - }, - "widget-textColor": { - "value": "#eeeeee", - "edited": false - }, - "widget-backgroundColor": { - "value": "#097479", - "edited": false - }, - "widget-borderColor": { - "value": "#333333", - "edited": false - }, - "base-font": { - "value": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif" - } - }, - "angularTheme": { - "primary": "indigo", - "accents": "blue", - "warn": "red", - "background": "grey", - "palette": "light" - } - }, - "site": { - "name": "PlanktoScope", - "hideToolbar": "false", - "allowSwipe": "false", - "lockMenu": "false", - "allowTempTheme": "true", - "dateFormat": "Y-MM-DD", - "sizes": { - "sx": 55, - "sy": 55, - "gx": 4, - "gy": 4, - "cx": 4, - "cy": 4, - "px": 4, - "py": 4 - } - } - }, - { - "id": "36739a35.7cce36", - "type": "ui_tab", - "name": "Gallery", - "icon": "fa-file-image-o", - "order": 6, - "disabled": false, - "hidden": false - }, - { - "id": "c0ebfc57.42527", - "type": "ui_group", - "name": "Group 1", - "tab": "36739a35.7cce36", - "order": 1, - "disp": false, - "width": "24", - "collapse": false - }, - { - "id": "737ec584.2eea2c", - "type": "ui_tab", - "name": "Sample", - "icon": "fa-eyedropper", - "order": 2, - "disabled": false, - "hidden": false - }, - { - "id": "6f97e7ae.270c48", - "type": "ui_group", - "name": "Group 1", - "tab": "3a6bb13f.c9703e", - "order": 1, - "disp": false, - "width": "4", - "collapse": false - }, - { - "id": "3e1ba03d.f01d8", - "type": "ui_group", - "name": "Sample Identification", - "tab": "737ec584.2eea2c", - "order": 1, - "disp": true, - "width": "10", - "collapse": false - }, - { - "id": "4e0cd5ea.17e59c", - "type": "ui_group", - "name": "Group 2", - "tab": "3a6bb13f.c9703e", - "order": 2, - "disp": false, - "width": "4", - "collapse": false - }, - { - "id": "ef590206.24f6", - "type": "ui_group", - "name": "Group 3", - "tab": "3a6bb13f.c9703e", - "order": 3, - "disp": false, - "width": "4", - "collapse": false - }, - { - "id": "ae8f6620.073358", - "type": "ui_group", - "name": "Group 4", - "tab": "3a6bb13f.c9703e", - "order": 4, - "disp": false, - "width": "4", - "collapse": false - }, - { - "id": "196518b2.4d53b7", - "type": "ui_group", - "name": "Group 5", - "tab": "3a6bb13f.c9703e", - "order": 5, - "disp": false, - "width": "4", - "collapse": false - }, - { - "id": "777a7c33.fcd804", - "type": "ui_group", - "name": "Group 6", - "tab": "3a6bb13f.c9703e", - "order": 6, - "disp": false, - "width": "4", - "collapse": false - }, - { - "id": "cef1e703.bcf3c8", - "type": "ui_group", - "name": "Sample Location", - "tab": "737ec584.2eea2c", - "order": 3, - "disp": false, - "width": "10", - "collapse": false - }, - { - "id": "5517c651.b2f668", - "type": "ui_group", - "name": "Validation", - "tab": "737ec584.2eea2c", - "order": 5, - "disp": false, - "width": 10, - "collapse": false - }, - { - "id": "fbd92986.1028c8", - "type": "ui_group", - "name": "Focus Adjustment", - "tab": "181bb236.1e94be", - "order": 2, - "disp": true, - "width": 4, - "collapse": false - }, - { - "id": "707d9797.c8e798", - "type": "ui_group", - "name": "Fluidic Manual Manipulation", - "tab": "181bb236.1e94be", - "order": 5, - "disp": true, - "width": 4, - "collapse": false - }, - { - "id": "7a0b4877.a5d268", - "type": "ui_group", - "name": "Navigation", - "tab": "181bb236.1e94be", - "order": 6, - "disp": false, - "width": 4, - "collapse": false - }, - { - "id": "404c301a.19c4e", - "type": "ui_group", - "name": "Fraction size", - "tab": "c9194f02.9d5e9", - "order": 2, - "disp": true, - "width": "10", - "collapse": false - }, - { - "id": "4322c187.e73e5", - "type": "ui_group", - "name": "Acquisition", - "tab": "c9194f02.9d5e9", - "order": 3, - "disp": true, - "width": 10, - "collapse": false - }, - { - "id": "b7919ae2.c01788", - "type": "ui_group", - "name": "Navigation", - "tab": "c9194f02.9d5e9", - "order": 6, - "disp": false, - "width": "10", - "collapse": false - }, - { - "id": "b5d61bc7.54fe48", - "type": "ui_group", - "name": "Statistics", - "tab": "c9194f02.9d5e9", - "order": 4, - "disp": true, - "width": "10", - "collapse": false - }, - { - "id": "8dc3722c.06efa8", - "type": "mqtt-broker", - "name": "", - "broker": "0.0.0.0", - "port": "1883", - "clientid": "Client_node", - "autoConnect": true, - "usetls": false, - "compatmode": false, - "protocolVersion": "4", - "keepalive": "60", - "cleansession": true, - "birthTopic": "", - "birthQos": "0", - "birthPayload": "", - "birthMsg": {}, - "closeTopic": "", - "closeQos": "0", - "closePayload": "", - "closeMsg": {}, - "willTopic": "", - "willQos": "0", - "willPayload": "", - "willMsg": {}, - "userProps": "", - "sessionExpiry": "" - }, - { - "id": "abeb6dad.635a2", - "type": "ui_group", - "name": "Control", - "tab": "8d16beb8.9b3fb", - "order": 1, - "disp": true, - "width": 10, - "collapse": false - }, - { - "id": "cf5d9f0e.d57e7", - "type": "ui_group", - "name": "Net Metadata", - "tab": "737ec584.2eea2c", - "order": 4, - "disp": false, - "width": "10", - "collapse": false - }, - { - "id": "ce9e278.781eed8", - "type": "ui_group", - "name": "Information", - "tab": "d9cd733b.ab73d", - "order": 5, - "disp": true, - "width": 6, - "collapse": false - }, - { - "id": "70de8209.68416c", - "type": "ui_group", - "name": "Status", - "tab": "c9194f02.9d5e9", - "order": 5, - "disp": true, - "width": 10, - "collapse": false - }, - { - "id": "46be9c86.dea684", - "type": "ui_group", - "name": "Status", - "tab": "8d16beb8.9b3fb", - "order": 2, - "disp": true, - "width": 10, - "collapse": false - }, - { - "id": "8c38a81e.9897a8", - "type": "ui_group", - "name": "Camera Settings", - "tab": "181bb236.1e94be", - "order": 3, - "disp": true, - "width": 6, - "collapse": false - }, - { - "id": "2489e51c.eed77a", - "type": "ui_tab", - "name": "Administration", - "icon": "dashboard", - "order": 9, - "disabled": false, - "hidden": false - }, - { - "id": "b0fb559a.6966a8", - "type": "ui_tab", - "name": "Hardware Settings", - "icon": "fa-cogs", - "disabled": false, - "hidden": false - }, - { - "id": "6be36295.0ab324", - "type": "ui_group", - "name": "Settings", - "tab": "b0fb559a.6966a8", - "order": 1, - "disp": false, - "width": "8", - "collapse": false, - "className": "" - }, - { - "id": "fc5e4e6f.5b1c8", - "type": "ui_group", - "name": "GPS Status", - "tab": "737ec584.2eea2c", - "order": 6, - "disp": true, - "width": 10, - "collapse": false - }, - { - "id": "f3ca28ef.4df0a8", - "type": "ui_group", - "name": "Shutdown", - "tab": "3a6bb13f.c9703e", - "order": 7, - "disp": true, - "width": 4, - "collapse": false - }, - { - "id": "3dfd8a69.69ed56", - "type": "ui_spacer", - "name": "spacer", - "group": "3e1ba03d.f01d8", - "order": 5, - "width": 10, - "height": 1 - }, - { - "id": "72a9216.2ff48e", - "type": "ui_spacer", - "name": "spacer", - "group": "4322c187.e73e5", - "order": 8, - "width": 10, - "height": 1 - }, - { - "id": "1b664927.c91d1f", - "type": "ui_spacer", - "name": "spacer", - "group": "b5d61bc7.54fe48", - "order": 2, - "width": 2, - "height": 1 - }, - { - "id": "1a663b6a.ab5805", - "type": "ui_spacer", - "name": "spacer", - "group": "b5d61bc7.54fe48", - "order": 4, - "width": 2, - "height": 1 - }, - { - "id": "8eeed8d8.ad9098", - "type": "ui_spacer", - "name": "spacer", - "group": "b5d61bc7.54fe48", - "order": 5, - "width": 2, - "height": 1 - }, - { - "id": "be1c5ce7.004e", - "type": "ui_spacer", - "name": "spacer", - "group": "b5d61bc7.54fe48", - "order": 6, - "width": 2, - "height": 1 - }, - { - "id": "c2fe38e9.555e3", - "type": "ui_spacer", - "name": "spacer", - "group": "b5d61bc7.54fe48", - "order": 7, - "width": 2, - "height": 1 - }, - { - "id": "89bd18b7.c779a8", - "type": "ui_spacer", - "name": "spacer", - "group": "b5d61bc7.54fe48", - "order": 8, - "width": 2, - "height": 1 - }, - { - "id": "3cbbfa5d.efa636", - "type": "ui_spacer", - "name": "spacer", - "group": "b7919ae2.c01788", - "order": 2, - "width": 5, - "height": 1 - }, - { - "id": "97148e8d8e298f1a", - "type": "ui_spacer", - "z": "cb95299c.2817c8", - "name": "spacer", - "group": "abeb6dad.635a2", - "order": 7, - "width": 10, - "height": 1 - }, - { - "id": "3b2eccc574e6a9ae", - "type": "ui_spacer", - "z": "cb95299c.2817c8", - "name": "spacer", - "group": "abeb6dad.635a2", - "order": 11, - "width": 1, - "height": 1 - }, - { - "id": "bbd6431d97c86f97", - "type": "ui_spacer", - "z": "cb95299c.2817c8", - "name": "spacer", - "group": "46be9c86.dea684", - "order": 4, - "width": 3, - "height": 1 - }, - { - "id": "5f98f5f140f0ecde", - "type": "ui_spacer", - "z": "cb95299c.2817c8", - "name": "spacer", - "group": "46be9c86.dea684", - "order": 6, - "width": 3, - "height": 1 - }, - { - "id": "7bc0a4c416e4545c", - "type": "ui_group", - "name": "Culture Date and Time", - "tab": "737ec584.2eea2c", - "order": 2, - "disp": true, - "width": "10", - "collapse": false, - "className": "" - }, - { - "id": "6c31ad948a9d62fd", - "type": "ui_spacer", - "name": "spacer", - "group": "4248342d.e55fac", - "order": 2, - "width": 1, - "height": 1 - }, - { - "id": "833bc5bb.217ba8", - "type": "ui_group", - "name": "Preview", - "tab": "181bb236.1e94be", - "order": 1, - "disp": true, - "width": 18, - "collapse": false - }, - { - "id": "a7d64879.38298", - "type": "ui_group", - "name": "Logs", - "tab": "2489e51c.eed77a", - "order": 1, - "disp": true, - "width": "12", - "collapse": true, - "className": "" - }, - { - "id": "6465bdd5.15eb8c", - "type": "file in", - "z": "1c24ad9c.bebec2", - "name": "", - "filename": "/home/pi/PlanktoScope/config.json", - "filenameType": "str", - "format": "utf8", - "chunk": false, - "sendError": false, - "encoding": "none", - "x": 560, - "y": 60, - "wires": [ - [ - "15ceb135.6628bf" - ] - ], - "info": "# PlanktoScope Help\nThis Node will read the content of the file named **config.txt** containing all the input placeholders.\n" - }, - { - "id": "15ceb135.6628bf", - "type": "json", - "z": "1c24ad9c.bebec2", - "name": "config.json", - "property": "payload", - "action": "", - "pretty": false, - "x": 730, - "y": 60, - "wires": [ - [ - "ad541674.4791c8" - ] - ] - }, - { - "id": "7205d267.36adcc", - "type": "file", - "z": "1c24ad9c.bebec2", - "name": "", - "filename": "/home/pi/PlanktoScope/config.json", - "appendNewline": true, - "createDir": true, - "overwriteFile": "true", - "encoding": "none", - "x": 990, - "y": 160, - "wires": [ - [] - ] - }, - { - "id": "2e6ddf51.c0dba", - "type": "json", - "z": "1c24ad9c.bebec2", - "name": "config.json", - "property": "payload", - "action": "str", - "pretty": true, - "x": 730, - "y": 160, - "wires": [ - [ - "7205d267.36adcc" - ] - ] - }, - { - "id": "ad541674.4791c8", - "type": "function", - "z": "1c24ad9c.bebec2", - "name": "Global Set", - "func": "global.set(\"config_keys\", Object.keys(msg.payload));\n\nfor (const key in msg.payload) {\n global.set(key, msg.payload[key]);\n}\n\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 910, - "y": 60, - "wires": [ - [] - ] - }, - { - "id": "3e9a33c.141384c", - "type": "inject", - "z": "1c24ad9c.bebec2", - "name": "Load config", - "props": [ - { - "p": "topic", - "vt": "str" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "", - "payloadType": "str", - "x": 230, - "y": 60, - "wires": [ - [ - "6465bdd5.15eb8c" - ] - ] - }, - { - "id": "3ad9835.08c937c", - "type": "function", - "z": "1c24ad9c.bebec2", - "name": "get config payload", - "func": "keys = global.get(\"config_keys\")\n\nvar payload = {}\n\nkeys.forEach(function(item, index, array) {\n payload[item] = global.get(item);\n})\n\nreturn {\"payload\": payload};", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 410, - "y": 160, - "wires": [ - [ - "2e6ddf51.c0dba" - ] - ] - }, - { - "id": "f439663c.8abd3", - "type": "ui_ui_control", - "z": "1c24ad9c.bebec2", - "name": "Connect Event", - "events": "connect", - "x": 220, - "y": 100, - "wires": [ - [ - "6465bdd5.15eb8c" - ] - ] - }, - { - "id": "82099021.9ceb08", - "type": "file", - "z": "4ed26b8b.253504", - "name": "", - "filename": "/home/pi/PlanktoScope/hardware.json", - "appendNewline": true, - "createDir": true, - "overwriteFile": "true", - "encoding": "none", - "x": 660, - "y": 40, - "wires": [ - [] - ] - }, - { - "id": "bb0a8725.a1849", - "type": "json", - "z": "4ed26b8b.253504", - "name": "Create JSON", - "property": "payload", - "action": "str", - "pretty": true, - "x": 490, - "y": 40, - "wires": [ - [ - "82099021.9ceb08" - ] - ] - }, - { - "id": "53d163be.47cf24", - "type": "function", - "z": "4ed26b8b.253504", - "name": "Update and retrieve hardware_conf", - "func": "// change global\nhardware_conf = global.get(\"hardware_conf\");\n\nif (msg.topic == \"process_pixel_fixed\" && msg.payload == 0){\n delete hardware_conf[msg.topic]\n delete msg.topic\n}\n\nif (msg.topic !== null && msg.topic !== undefined){\n hardware_conf[msg.topic] = msg.payload;\n global.set(\"hardware_conf\", hardware_conf);\n}\n\nreturn {\"payload\": hardware_conf};", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 240, - "y": 40, - "wires": [ - [ - "bb0a8725.a1849" - ] - ] - }, - { - "id": "48ceeda454438cb7", - "type": "file in", - "z": "e6665421f66ea4c8", - "name": "", - "filename": "/home/pi/PlanktoScope/hardware.json", - "filenameType": "str", - "format": "utf8", - "chunk": false, - "sendError": false, - "encoding": "none", - "x": 250, - "y": 40, - "wires": [ - [ - "853c938a270fd85e" - ] - ], - "info": "# PlanktoScope Help\nThis Node will read the content of the file named **config.txt** containing all the input placeholders.\n" - }, - { - "id": "853c938a270fd85e", - "type": "json", - "z": "e6665421f66ea4c8", - "name": "Parse JSON", - "property": "payload", - "action": "", - "pretty": false, - "x": 510, - "y": 40, - "wires": [ - [ - "2b1a67ac127f3fe7" - ] - ] - }, - { - "id": "2b1a67ac127f3fe7", - "type": "change", - "z": "e6665421f66ea4c8", - "name": "", - "rules": [ - { - "t": "set", - "p": "hardware_conf", - "pt": "global", - "to": "payload", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 730, - "y": 40, - "wires": [ - [] - ] - }, - { - "id": "2f30a6ee99587899", - "type": "comment", - "z": "eaae323a.31b3", - "name": "LICENSE", - "info": "Copyright 2022 Thibaut Pollina and Romain Bazile\nLicensed under GPL v3.0", - "x": 140, - "y": 600, - "wires": [] - }, - { - "id": "4e78af2d.90be7", - "type": "ui_ui_control", - "z": "eaae323a.31b3", - "name": "", - "events": "change", - "x": 440, - "y": 160, - "wires": [ - [] - ] - }, - { - "id": "7789839d.69b48c", - "type": "ui_template", - "z": "eaae323a.31b3", - "group": "4e0cd5ea.17e59c", - "name": "Optic Configuration", - "order": 1, - "width": 4, - "height": 4, - "format": "\n \n
Optic Configuration
\n
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "x": 130, - "y": 100, - "wires": [ - [ - "4e78af2d.90be7" - ] - ] - }, - { - "id": "6ea6c306.f9c12c", - "type": "ui_template", - "z": "eaae323a.31b3", - "group": "ef590206.24f6", - "name": "Fluidic Acquisition", - "order": 1, - "width": 4, - "height": 4, - "format": "\n \n
Fluidic Acquisition
\n
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "x": 130, - "y": 140, - "wires": [ - [ - "4e78af2d.90be7" - ] - ] - }, - { - "id": "bb9eb153.9e36c", - "type": "ui_template", - "z": "eaae323a.31b3", - "group": "ae8f6620.073358", - "name": "Segmentation", - "order": 1, - "width": 4, - "height": 4, - "format": "\n \n
Segmentation
\n
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "x": 140, - "y": 180, - "wires": [ - [ - "4e78af2d.90be7" - ] - ] - }, - { - "id": "eaf8ee7f.96f44", - "type": "ui_template", - "z": "eaae323a.31b3", - "group": "196518b2.4d53b7", - "name": "Gallery", - "order": 1, - "width": 4, - "height": 4, - "format": "\n \n
Gallery
\n
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "x": 160, - "y": 220, - "wires": [ - [ - "4e78af2d.90be7" - ] - ] - }, - { - "id": "c1b1469.9650eb8", - "type": "ui_template", - "z": "eaae323a.31b3", - "group": "777a7c33.fcd804", - "name": "System Monitoring", - "order": 1, - "width": 4, - "height": 4, - "format": "\n \n
System Monitoring
\n
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "x": 130, - "y": 260, - "wires": [ - [ - "4e78af2d.90be7" - ] - ] - }, - { - "id": "abafd6e6.04a5f8", - "type": "ui_template", - "z": "eaae323a.31b3", - "group": "6f97e7ae.270c48", - "name": "Sample", - "order": 1, - "width": 4, - "height": 4, - "format": "\n \n
Sample
\n
\n In doubt? Start Here!\n
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "x": 160, - "y": 60, - "wires": [ - [ - "4e78af2d.90be7" - ] - ] - }, - { - "id": "dab82064.26a8d", - "type": "ui_button", - "z": "eaae323a.31b3", - "name": "Unlock button", - "group": "f3ca28ef.4df0a8", - "order": 2, - "width": 0, - "height": 0, - "passthru": false, - "label": "Unlock button", - "tooltip": "", - "color": "", - "bgcolor": "", - "icon": "", - "payload": "shutdown", - "payloadType": "flow", - "topic": "", - "x": 120, - "y": 380, - "wires": [ - [ - "6c3a3b4.78cad44" - ] - ] - }, - { - "id": "1c658761.b852a1", - "type": "ui_toast", - "z": "eaae323a.31b3", - "position": "dialog", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 1, - "ok": "YES PLEASE", - "cancel": "NO!", - "raw": false, - "topic": "Are you sure?", - "name": "Confirmation message", - "x": 800, - "y": 380, - "wires": [ - [ - "8f1b8e23.daafe" - ] - ] - }, - { - "id": "a48ff63f.db5e18", - "type": "inject", - "z": "eaae323a.31b3", - "name": "disabled", - "props": [ - { - "p": "enabled", - "v": "false", - "vt": "bool" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "", - "x": 140, - "y": 420, - "wires": [ - [ - "d58039a9.6e7928" - ] - ] - }, - { - "id": "b67a7147.65fcd8", - "type": "ui_button", - "z": "eaae323a.31b3", - "name": "Shutdown button", - "group": "f3ca28ef.4df0a8", - "order": 4, - "width": 0, - "height": 0, - "passthru": false, - "label": "Shutdown", - "tooltip": "", - "color": "", - "bgcolor": "#AD1625", - "icon": "fa-power-off fa-2x", - "payload": "Do you want to turn the machine off now?", - "payloadType": "str", - "topic": "", - "x": 550, - "y": 380, - "wires": [ - [ - "1c658761.b852a1" - ] - ] - }, - { - "id": "d58039a9.6e7928", - "type": "change", - "z": "eaae323a.31b3", - "name": "", - "rules": [ - { - "t": "set", - "p": "shutdown", - "pt": "flow", - "to": "false", - "tot": "bool" - }, - { - "t": "set", - "p": "enabled", - "pt": "msg", - "to": "shutdown", - "tot": "flow" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 320, - "y": 420, - "wires": [ - [ - "b67a7147.65fcd8" - ] - ] - }, - { - "id": "6c3a3b4.78cad44", - "type": "function", - "z": "eaae323a.31b3", - "name": "Toggle", - "func": "flow.set(\"shutdown\", !flow.get(\"shutdown\"))\nmsg.enabled = flow.get(\"shutdown\")\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 290, - "y": 380, - "wires": [ - [ - "b67a7147.65fcd8" - ] - ] - }, - { - "id": "d1153ad6.40d738", - "type": "ui_template", - "z": "eaae323a.31b3", - "group": "f3ca28ef.4df0a8", - "name": "Shutdown information", - "order": 1, - "width": 0, - "height": 0, - "format": "
To prevent data corruption, please always shutdown the machine before unplugging the unit.\n

\nRemember to first unlock the shutdown button.\n
", - "storeOutMessages": true, - "fwdInMessages": false, - "resendOnRefresh": true, - "templateScope": "local", - "x": 120, - "y": 320, - "wires": [ - [] - ] - }, - { - "id": "e08cfcb8.2a67e8", - "type": "link out", - "z": "eaae323a.31b3", - "name": "Home shutdown button", - "links": [ - "b81b990a.d4dca" - ], - "x": 715, - "y": 500, - "wires": [] - }, - { - "id": "ce7087fc.dcc9e8", - "type": "ui_toast", - "z": "eaae323a.31b3", - "position": "dialog", - "displayTime": "10", - "highlight": "", - "sendall": true, - "outputs": 1, - "ok": "OK", - "cancel": "", - "raw": false, - "topic": "Turning off now!", - "name": "Shutdown message", - "x": 570, - "y": 540, - "wires": [ - [] - ] - }, - { - "id": "7d1626a0.deb85", - "type": "change", - "z": "eaae323a.31b3", - "name": "shutdown!", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "shutdown", - "tot": "str" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 300, - "y": 500, - "wires": [ - [ - "e08cfcb8.2a67e8" - ] - ] - }, - { - "id": "8f1b8e23.daafe", - "type": "switch", - "z": "eaae323a.31b3", - "name": "", - "property": "payload", - "propertyType": "msg", - "rules": [ - { - "t": "eq", - "v": "NO!", - "vt": "str" - }, - { - "t": "else" - } - ], - "checkall": "true", - "repair": false, - "outputs": 2, - "x": 150, - "y": 500, - "wires": [ - [ - "d58039a9.6e7928" - ], - [ - "7d1626a0.deb85", - "281a56c9.ec7902" - ] - ] - }, - { - "id": "281a56c9.ec7902", - "type": "change", - "z": "eaae323a.31b3", - "name": "Shutdown message", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "Please wait a minute before disconnecting the machine from its power supply!", - "tot": "str" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 330, - "y": 540, - "wires": [ - [ - "ce7087fc.dcc9e8" - ] - ] - }, - { - "id": "4557d689.a4fa88", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "sample_ship", - "label": "Name of the ship", - "tooltip": "", - "group": "3e1ba03d.f01d8", - "order": 2, - "width": 0, - "height": 0, - "passthru": true, - "mode": "text", - "delay": "300", - "topic": "sample_ship", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 670, - "y": 80, - "wires": [ - [ - "9f501f49.45645" - ] - ] - }, - { - "id": "fcfc31ae.af3af", - "type": "ui_dropdown", - "z": "b771c342.49603", - "name": "sample_sampling_gear", - "label": "Sampling gear*", - "tooltip": "", - "place": "Choose from list", - "group": "3e1ba03d.f01d8", - "order": 6, - "width": 0, - "height": 0, - "passthru": true, - "multiple": false, - "options": [ - { - "label": "High Speed Net", - "value": "net_hsn", - "type": "str" - }, - { - "label": "Tara Decknet", - "value": "net_decknet", - "type": "str" - }, - { - "label": "Plankton net", - "value": "net", - "type": "str" - }, - { - "label": "Niskin bottle 12L", - "value": "niskin_12L", - "type": "str" - }, - { - "label": "Niskin bottle 24L", - "value": "niskin_24L", - "type": "str" - }, - { - "label": "Pass Hull", - "value": "pass_hull", - "type": "str" - }, - { - "label": "Single location (with net or bucket)", - "value": "single_location", - "type": "str" - }, - { - "label": "Lab culture", - "value": "culture", - "type": "str" - }, - { - "label": "Test", - "value": "test", - "type": "str" - } - ], - "payload": "", - "topic": "sample_sampling_gear", - "topicType": "str", - "className": "", - "x": 630, - "y": 200, - "wires": [ - [ - "9f501f49.45645", - "46eb1bf8.3dc5f4", - "3ac7b631f5d8ef90" - ] - ] - }, - { - "id": "82c5fc77.59c97", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "sample_operator", - "label": "Name of the operator*", - "tooltip": "", - "group": "3e1ba03d.f01d8", - "order": 3, - "width": 0, - "height": 0, - "passthru": true, - "mode": "text", - "delay": "300", - "topic": "sample_operator", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 650, - "y": 160, - "wires": [ - [ - "9f501f49.45645" - ] - ] - }, - { - "id": "9c882b37.fde668", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "sample_project", - "label": "Name of the project*", - "tooltip": "", - "group": "3e1ba03d.f01d8", - "order": 1, - "width": 0, - "height": 0, - "passthru": true, - "mode": "text", - "delay": "300", - "topic": "sample_project", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 660, - "y": 40, - "wires": [ - [ - "9f501f49.45645" - ] - ] - }, - { - "id": "94eb4221.9b92c", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "sample_id", - "label": "Station ID*", - "tooltip": "", - "group": "3e1ba03d.f01d8", - "order": 4, - "width": 0, - "height": 0, - "passthru": true, - "mode": "text", - "delay": "300", - "topic": "sample_id", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 670, - "y": 120, - "wires": [ - [ - "9f501f49.45645" - ] - ] - }, - { - "id": "9f501f49.45645", - "type": "function", - "z": "b771c342.49603", - "name": "set global", - "func": "global.set(msg.topic,msg.payload);", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 1080, - "y": 200, - "wires": [ - [] - ] - }, - { - "id": "222c851d.5d0a3a", - "type": "ui_ui_control", - "z": "b771c342.49603", - "name": "", - "events": "change", - "x": 400, - "y": 880, - "wires": [ - [] - ] - }, - { - "id": "52f6b103.1efb6", - "type": "ui_toast", - "z": "b771c342.49603", - "position": "dialog", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 1, - "ok": "OK", - "cancel": "", - "raw": false, - "topic": "", - "name": "", - "x": 710, - "y": 980, - "wires": [ - [] - ] - }, - { - "id": "986d960a.c75908", - "type": "function", - "z": "b771c342.49603", - "name": "Check form", - "func": "var sample_project= global.get(\"sample_project\");\nvar sample_id= global.get(\"sample_id\");\nvar sample_operator= global.get(\"sample_operator\");\nvar sample_sampling_gear= global.get(\"sample_sampling_gear\");\nvar object_lat= global.get(\"object_lat\");\nvar object_lon= global.get(\"object_lon\");\nvar object_date= global.get(\"object_date\");\nvar object_time= global.get(\"object_time\");\nif (sample_project === undefined || sample_project === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Sample project\"\n return [null, msg];\n}\n\nelse if (sample_id === undefined || sample_id === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Sample ID\"\n return [null, msg];\n}\n\nelse if (sample_operator === undefined || sample_operator === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Sample operator\"\n return [null, msg];\n}\n\nelse if (sample_sampling_gear === undefined || sample_sampling_gear === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Sample sampling gear\"\n return [null, msg];\n}\n\nelse if (object_lat === undefined || object_lat === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Latitude of sample\"\n return [null, msg];\n}\n\nelse if (object_lon === undefined || object_lon === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Longitude of sample\"\n return [null, msg];\n}\n\nelse if (object_date === undefined || object_date === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Date of sample\"\n return [null, msg];\n}\n\nelse if (object_time === undefined || object_time === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Time of sample\"\n return [null, msg];\n}\nelse if (sample_sampling_gear.startsWith(\"net\")){\n var object_lat_end = global.get(\"object_lat_end\");\n var object_lon_end = global.get(\"object_lon_end\");\n var object_date_end = global.get(\"object_date_end\");\n var object_time_end = global.get(\"object_time_end\");\n var sample_gear_net_opening = global.get(\"sample_gear_net_opening\");\n\n if (object_lat_end === undefined || object_lat_end === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Latitude of retrieval\"\n return [null, msg];\n }\n \n else if (object_lon_end === undefined || object_lon_end === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Longitude of retrieval\"\n return [null, msg];\n }\n \n else if (object_date_end === undefined || object_date_end === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Date of retrieval\"\n return [null, msg];\n }\n \n else if (object_time_end === undefined || object_time_end === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Time of retrieval\"\n return [null, msg];\n }\n \n else if (sample_gear_net_opening === undefined || sample_gear_net_opening === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Net opening dimension\"\n return [null, msg];\n }\n \n if (sample_sampling_gear == \"net_decknet\"){\n var sample_total_volume = global.get(\"sample_total_volume\");\n if (sample_total_volume === undefined || sample_total_volume === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Decknet flowmeter readings\"\n return [null, msg];\n }\n }\n}\nmsg.topic = \"config_save\"\nmsg.payload={\"tab\":\"Optic Configuration\"};\n\nreturn [msg, null];", - "outputs": 2, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 470, - "y": 940, - "wires": [ - [ - "726a7822.cd6298", - "e2b277c1.07283" - ], - [ - "52f6b103.1efb6" - ] - ], - "outputLabels": [ - "message", - "error" - ] - }, - { - "id": "18f44504.cac66b", - "type": "gpsd", - "z": "b771c342.49603", - "name": "", - "hostname": "localhost", - "port": "2947", - "tpv": true, - "sky": false, - "info": false, - "device": false, - "gst": false, - "att": false, - "x": 250, - "y": 1240, - "wires": [ - [ - "258b4562.9f778a", - "54e37580.fdc31c", - "cc21ca16.b92928", - "4a4de52c.cf2884", - "73c4a14a.9b93c8" - ] - ] - }, - { - "id": "726a7822.cd6298", - "type": "ui_ui_control", - "z": "b771c342.49603", - "name": "", - "events": "change", - "x": 700, - "y": 900, - "wires": [ - [] - ] - }, - { - "id": "16de754c.cc969b", - "type": "ui_button", - "z": "b771c342.49603", - "name": "", - "group": "5517c651.b2f668", - "order": 1, - "width": 5, - "height": 1, - "passthru": false, - "label": "Previous", - "tooltip": "", - "color": "#097479", - "bgcolor": "white", - "icon": "keyboard_return", - "payload": "{\"tab\":\"Home\"}", - "payloadType": "json", - "topic": "", - "x": 240, - "y": 880, - "wires": [ - [ - "222c851d.5d0a3a" - ] - ] - }, - { - "id": "84f3d040.5f7ea", - "type": "ui_button", - "z": "b771c342.49603", - "name": "", - "group": "5517c651.b2f668", - "order": 2, - "width": 5, - "height": 1, - "passthru": false, - "label": "Continue", - "tooltip": "", - "color": "#097479", - "bgcolor": "white", - "icon": "keyboard_tab", - "payload": "{\"tab\":\"Home\"}", - "payloadType": "json", - "topic": "", - "x": 240, - "y": 940, - "wires": [ - [ - "986d960a.c75908" - ] - ] - }, - { - "id": "d027a6bf.7049e8", - "type": "function", - "z": "b771c342.49603", - "name": "get sample_projet", - "func": "msg.payload = msg.payload.sample_project;\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 310, - "y": 40, - "wires": [ - [ - "9c882b37.fde668" - ] - ] - }, - { - "id": "5a811caf.0f3144", - "type": "function", - "z": "b771c342.49603", - "name": "get sample_ship", - "func": "msg.payload = msg.payload.sample_ship;\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 300, - "y": 80, - "wires": [ - [ - "4557d689.a4fa88" - ] - ] - }, - { - "id": "45911c98.2bd83c", - "type": "function", - "z": "b771c342.49603", - "name": "get sample_id", - "func": "msg.payload = msg.payload.sample_id;\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 300, - "y": 120, - "wires": [ - [ - "94eb4221.9b92c" - ] - ] - }, - { - "id": "1e09a4ab.72996b", - "type": "function", - "z": "b771c342.49603", - "name": "get sample_operator", - "func": "msg.payload = msg.payload.sample_operator;\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 320, - "y": 160, - "wires": [ - [ - "82c5fc77.59c97" - ] - ] - }, - { - "id": "a3272681.f271c8", - "type": "function", - "z": "b771c342.49603", - "name": "get sample_sampling_gear", - "func": "msg.topic = \"sample_sampling_gear\"\nif (msg.payload.sample_sampling_gear === undefined){\n msg.payload = \"net\";\n}\nelse\n{\n msg.payload = msg.payload.sample_sampling_gear;\n}\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 340, - "y": 200, - "wires": [ - [ - "fcfc31ae.af3af" - ] - ] - }, - { - "id": "a6907a38.f6611", - "type": "subflow:1c24ad9c.bebec2", - "z": "b771c342.49603", - "name": "", - "env": [], - "x": 70, - "y": 220, - "wires": [ - [ - "d027a6bf.7049e8", - "5a811caf.0f3144", - "45911c98.2bd83c", - "1e09a4ab.72996b", - "8dff1648.82e42", - "9f04c5ec.75f3d8", - "f408a273.4fb538", - "e73fd87d.d24e4", - "489c8e06.cc7d6", - "a3272681.f271c8" - ] - ] - }, - { - "id": "e2b277c1.07283", - "type": "subflow:1c24ad9c.bebec2", - "z": "b771c342.49603", - "name": "", - "env": [], - "x": 690, - "y": 940, - "wires": [ - [] - ] - }, - { - "id": "7116e906.9f50f", - "type": "ui_text", - "z": "b771c342.49603", - "group": "fc5e4e6f.5b1c8", - "order": 1, - "width": 10, - "height": 1, - "name": "GPS Status Display", - "label": "GPS Status:", - "format": "{{msg.payload}}", - "layout": "row-center", - "x": 730, - "y": 1080, - "wires": [] - }, - { - "id": "9c7f7fc9.c8d3a", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "object_depth_max", - "label": "Max sampling depth (m)", - "tooltip": "in m", - "group": "3e1ba03d.f01d8", - "order": 10, - "width": 5, - "height": 1, - "passthru": true, - "mode": "number", - "delay": "300", - "topic": "object_depth_max", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 650, - "y": 240, - "wires": [ - [ - "9f501f49.45645" - ] - ] - }, - { - "id": "317eeeb7.8d3042", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "object_depth_min", - "label": "Min sampling depth (m)", - "tooltip": "in m", - "group": "3e1ba03d.f01d8", - "order": 9, - "width": 5, - "height": 1, - "passthru": true, - "mode": "number", - "delay": "300", - "topic": "object_depth_min", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 650, - "y": 280, - "wires": [ - [ - "9f501f49.45645" - ] - ] - }, - { - "id": "cbb123ab.fd3428", - "type": "ui_ui_control", - "z": "b771c342.49603", - "name": "show/hide net groups", - "events": "change", - "x": 1320, - "y": 300, - "wires": [ - [] - ] - }, - { - "id": "642ff403.1ed91c", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "sample_concentrated_sample_volume", - "label": "Concentrated sample volume (mL)", - "tooltip": "Volume extracted from the net codend (in mL)", - "group": "3e1ba03d.f01d8", - "order": 12, - "width": 10, - "height": 1, - "passthru": true, - "mode": "number", - "delay": "300", - "topic": "sample_concentrated_sample_volume", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 590, - "y": 440, - "wires": [ - [ - "9f501f49.45645" - ] - ] - }, - { - "id": "e967b844.46aa48", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "sample_gear_net_opening", - "label": "Net opening dimension (mm)", - "tooltip": "Size of the net mouth opening (in mm)", - "group": "cf5d9f0e.d57e7", - "order": 1, - "width": 10, - "height": 1, - "passthru": true, - "mode": "number", - "delay": "300", - "topic": "sample_gear_net_opening", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 620, - "y": 320, - "wires": [ - [ - "9f501f49.45645" - ] - ] - }, - { - "id": "c0ce5626.b6c5", - "type": "ui_toast", - "z": "b771c342.49603", - "position": "dialog", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 1, - "ok": "OK", - "cancel": "", - "raw": false, - "topic": "", - "name": "", - "x": 1230, - "y": 620, - "wires": [ - [] - ] - }, - { - "id": "c33f1124.af6688", - "type": "ui_form", - "z": "b771c342.49603", - "name": "sample_location", - "label": "Sample Location", - "group": "cef1e703.bcf3c8", - "order": 1, - "width": 0, - "height": 0, - "options": [ - { - "label": "Latitude (36.574439°N or 36°57.4439'N)", - "value": "object_lat", - "type": "text", - "required": true, - "rows": null - }, - { - "label": "Longitude (110.42100°W or 110°4.2100'W)", - "value": "object_lon", - "type": "text", - "required": true, - "rows": null - }, - { - "label": "Date (YYYY-MM-DD, UTC)", - "value": "object_date", - "type": "text", - "required": true, - "rows": null - }, - { - "label": "Time (HH:MM(:SS), UTC 24h)", - "value": "object_time", - "type": "text", - "required": true, - "rows": null - } - ], - "formValue": { - "object_lat": "", - "object_lon": "", - "object_date": "", - "object_time": "" - }, - "payload": "", - "submit": "Validate", - "cancel": "Reset", - "topic": "sample_location", - "x": 660, - "y": 580, - "wires": [ - [ - "14658615.47c862", - "3318a1aaa70fc2ee" - ] - ] - }, - { - "id": "358908cd.416ab", - "type": "ui_form", - "z": "b771c342.49603", - "name": "net_throw_location", - "label": "Net Throw Location", - "group": "cf5d9f0e.d57e7", - "order": 3, - "width": 0, - "height": 0, - "options": [ - { - "label": "Latitude (36.574439°N or 36°57.4439'N)", - "value": "object_lat", - "type": "text", - "required": true, - "rows": null - }, - { - "label": "Longitude (110.42100°W or 110°4.2100'W)", - "value": "object_lon", - "type": "text", - "required": true, - "rows": null - }, - { - "label": "Date (YYYY-MM-DD UTC)", - "value": "object_date", - "type": "text", - "required": true, - "rows": null - }, - { - "label": "Time (HH:MM, UTC 24h)", - "value": "object_time", - "type": "text", - "required": true, - "rows": null - } - ], - "formValue": { - "object_lat": "", - "object_lon": "", - "object_date": "", - "object_time": "" - }, - "payload": "", - "submit": "Validate", - "cancel": "", - "topic": "net_throw_location", - "topicType": "str", - "splitLayout": false, - "className": "", - "x": 650, - "y": 620, - "wires": [ - [ - "14658615.47c862", - "cc67c97f55a340d3" - ] - ] - }, - { - "id": "56d40584.eff4e4", - "type": "ui_form", - "z": "b771c342.49603", - "name": "net_retrieval_location", - "label": "Net Retrieval Location", - "group": "cf5d9f0e.d57e7", - "order": 4, - "width": 0, - "height": 0, - "options": [ - { - "label": "Latitude (36.574439°N or 36°57.4439'N)", - "value": "object_lat_end", - "type": "text", - "required": true, - "rows": null - }, - { - "label": "Longitude (110.42100°W or 110°4.2100'W)", - "value": "object_lon_end", - "type": "text", - "required": true, - "rows": null - }, - { - "label": "Date (YYYY-MM-DD UTC)", - "value": "object_date_end", - "type": "text", - "required": true, - "rows": null - }, - { - "label": "Time (HH:MM, UTC 24h)", - "value": "object_time_end", - "type": "text", - "required": true, - "rows": null - } - ], - "formValue": { - "object_lat_end": "", - "object_lon_end": "", - "object_date_end": "", - "object_time_end": "" - }, - "payload": "", - "submit": "Validate", - "cancel": "", - "topic": "net_retrieval_location", - "topicType": "str", - "splitLayout": false, - "x": 640, - "y": 660, - "wires": [ - [ - "14658615.47c862", - "9c8f370d124a55e4" - ] - ] - }, - { - "id": "14658615.47c862", - "type": "function", - "z": "b771c342.49603", - "name": "Validate Location / Timestamp", - "func": "// Code added here will be run once\n// whenever the node is started.\nfunction ConvertDDMMToDD(input) {\n // Input Format 36°57.4439'N, 110°4.2100'W\n // From https://stackoverflow.com/questions/1140189/converting-latitude-and-longitude-to-decimal-values\n if (!input.match(/\\d+°\\d+\\.*\\d*\\'[NSEW]/)){\n \treturn \"parsing error\"\n }\n var parts = input.split(/[^\\d.\\w]+/)\n if (parts.length != 3){\n \treturn \"parsing error\"\n }\n var dd = Number(parts[0]) + Number(parts[1])/60\n return dd.toFixed(6) + parts[2]\n}\n\nfunction ValidateCoordinates(input, lat){\n // Input Format 36.574439°N, 110.42100°W\n // Or 36°57.4439'N, 110°4.2100'W\n if (input.match(\"'\")){\n input = ConvertDDMMToDD(input)\n }\n \n var error = {}\n\n if (input.startsWith(\"parsing error\")){\n error.topic = \"Error with the \"\n error.payload = \"You need to respect the format example, 36.574439°N or 36°57.4439'N\"\n return [null, error]\n }\n \n var direction = input.match(/[NSEW]/)\n var position = input.match(/[\\+\\-\\d\\.]+/)\n \n if (direction === null){\n error.topic = \"Error with the \"\n error.payload = \"You need to explicitely enter N/S/E/W\"\n return [null, error]\n }\n \n // Test that position is only made of digits!\n if(/^[\\+\\-]/.test(position)){\n error.topic = \"Error with the \"\n error.payload = \"Use of +/- sign is inconsistent with N/S/E/W letter! Please only use N/S/E/W!\"\n return [null, error]\n }\n \n var dd = Number(position)\n if (lat){\n // Check latitude\n if (direction == \"S\" || direction == \"N\") {\n if (dd>90.0){\n error.topic = \"Error with the \"\n error.payload = \"Latitude is more than 90°\"\n return [null, error]\n }\n }\n if (direction == \"W\" || direction == \"E\") {\n error.topic = \"Error with the \"\n error.payload = \"This is not a Latitude!\"\n return [null, error]\n }\n }\n else{\n // Check longitude\n if (direction == \"W\" || direction == \"E\") {\n if (dd>180.0){\n error.topic = \"Error with the \"\n error.payload = \"Longitude is more than 180°\"\n return [null, error]\n }\n }\n if (direction == \"N\" || direction == \"S\") {\n error.topic = \"Error with the \"\n error.payload = \"This is not a Longitude!\"\n return [null, error]\n }\n }\n \n if (direction == \"S\" || direction == \"W\") {\n dd = dd * -1\n } // Don't do anything for N or E\n return [dd.toFixed(4), null]\n \n}\n\nfunction ValidateDate(input){\n // Input Format 2020-12-25\n var error = {};\n \n if (! /20\\d{2}-[0-1]\\d-[0-3]\\d/.test(input)){\n error.topic = \"Error with the date\";\n error.payload = \"The date should respect the ISO format YYYY-MM-DD\";\n return [null, error];\n }\n else {\n var date = input.match(/\\d+/g);\n if (!((2000 < date[0]) && (date[0] < 2100))){\n error.topic = \"Error with the date\"\n error.payload = \"The year should be between 2000 and 2100\"\n return [null, error]\n }\n else if (!((0 < date[1]) && (date[1] <= 12))){\n error.topic = \"Error with the date\"\n error.payload = \"The month should be between 01 and 12\"\n return [null, error]\n }\n else if (!((0 < date[2]) && (date[2] <= 31))){\n error.topic = \"Error with the date\"\n error.payload = \"The day should be between 01 and 31\"\n return [null, error]\n }\n }\n return [input.replace(/-/g, ''), null]\n}\n\nfunction ValidateTime(input){\n // Input Format 12:00\n var error = {}\n \n if (! /[0-2]?\\d:[0-5]\\d/.test(input)){\n error.topic = \"Error with the time\"\n error.payload = \"The date should respect the ISO format HH:MM\"\n return [null, error]\n }\n else {\n var time = input.match(/\\d+/g)\n \n if (!((0 <= time[0]) && (time[0] < 24))){\n error.topic = \"Error with the time\"\n error.payload = \"The hours should be 0 and 23.\"\n return [null, error]\n }\n else if (!((0 <= time[1]) && (time[1] < 60))){\n error.topic = \"Error with the time\"\n error.payload = \"The minutes should be between 0 and 59\"\n return [null, error]\n }\n }\n return [input.replace(/:/g, ''), null]\n}\n\n\nvar ret\nvar payload_for_form = {payload:{}}\nmsg.valid = false\n\nif (msg.topic == \"culture_timestamp\"){\n ret = ValidateDate(msg.payload.object_date)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_date\", ret[0])\n \n ret = ValidateTime(msg.payload.object_time)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_time\", ret[0])\n return [{topic: \"Date and time format valid!\", payload: \"All good!\", valid: true}, payload_for_form]\n}\nelse if (msg.topic == \"net_retrieval_location\"){\n ret = ValidateCoordinates(msg.payload.object_lat_end, true);\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" Latitude\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_lat_end\", ret[0])\n ret = ValidateCoordinates(msg.payload.object_lon_end, false)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" Longitude\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_lon_end\", ret[0]);\n \n ret = ValidateDate(msg.payload.object_date_end)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample retrieval\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_date_end\", ret[0])\n \n ret = ValidateTime(msg.payload.object_time_end)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample retrieval\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_time_end\", ret[0])\n}\nelse{\n ret = ValidateCoordinates(msg.payload.object_lat, true);\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" Latitude\";\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_lat\", ret[0]);\n payload_for_form.payload[\"object_lat_end\"] = msg.payload.object_lat;\n \n ret = ValidateCoordinates(msg.payload.object_lon, false);\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" Longitude\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_lon\", ret[0])\n payload_for_form.payload[\"object_lon_end\"] = msg.payload.object_lon;\n\n ret = ValidateDate(msg.payload.object_date)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_date\", ret[0])\n payload_for_form.payload[\"object_date_end\"] = msg.payload.object_date;\n \n ret = ValidateTime(msg.payload.object_time)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_time\", ret[0])\n payload_for_form.payload[\"object_time_end\"] = msg.payload.object_time;\n}\nreturn [{topic: \"Coordinates valid!\", payload: \"All good!\", valid: true}, payload_for_form]\n", - "outputs": 2, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 930, - "y": 620, - "wires": [ - [ - "c0ce5626.b6c5", - "9a18a4b4.178448" - ], - [ - "56d40584.eff4e4" - ] - ], - "inputLabels": [ - "Location form data" - ], - "outputLabels": [ - "Message", - "Location validated" - ] - }, - { - "id": "46eb1bf8.3dc5f4", - "type": "function", - "z": "b771c342.49603", - "name": "Net check", - "func": "var decknet = {}\nvar activation_msg = {}\n\nif (msg.payload.startsWith(\"net_decknet\")){\n decknet.enabled = true;\n}\nelse {\n decknet.enabled = false;\n}\n\nif (msg.payload.startsWith(\"net\")){\n activation_msg.payload = {\"group\":{\"show\":[\"Sample_Net_Metadata\"],\"hide\":[\"Sample_Sample_Location\",\"Sample_Culture_Date_and_Time\"]}};\n}\nelse if (msg.payload != \"culture\" && msg.payload != \"test\"){\n activation_msg.payload = {\"group\":{\"show\":[\"Sample_Sample_Location\"], \"hide\":[\"Sample_Net_Metadata\",\"Sample_Culture_Date_and_Time\"]}};\n}\n\n\nreturn [decknet, activation_msg];", - "outputs": 2, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 1080, - "y": 240, - "wires": [ - [ - "516375fd.2ed61c", - "470e382a.25691", - "fbe32ac8.ff6a38" - ], - [ - "cbb123ab.fd3428" - ] - ], - "outputLabels": [ - "decknet activation", - "group display control" - ] - }, - { - "id": "516375fd.2ed61c", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "sample_total_flowmeter_start", - "label": "Decknet flowmeter start", - "tooltip": "in L", - "group": "cf5d9f0e.d57e7", - "order": 6, - "width": 5, - "height": 1, - "passthru": false, - "mode": "text", - "delay": "300", - "topic": "sample_total_flowmeter_start", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 1340, - "y": 220, - "wires": [ - [ - "e9bc112c.eb75f8" - ] - ] - }, - { - "id": "470e382a.25691", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "sample_total_flowmeter_end", - "label": "Decknet flowmeter end", - "tooltip": "in L", - "group": "cf5d9f0e.d57e7", - "order": 7, - "width": 5, - "height": 1, - "passthru": false, - "mode": "text", - "delay": "300", - "topic": "sample_total_flowmeter_end", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 1340, - "y": 260, - "wires": [ - [ - "e9bc112c.eb75f8" - ] - ] - }, - { - "id": "fbe32ac8.ff6a38", - "type": "ui_template", - "z": "b771c342.49603", - "group": "cf5d9f0e.d57e7", - "name": "Decknet flowmeter read", - "order": 5, - "width": 10, - "height": 1, - "format": "
\n

Decknet flowmeter readings

\n

Those values are used to calculate sample_total_volume. Values are in L.

\n
\n", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": true, - "templateScope": "local", - "x": 1330, - "y": 180, - "wires": [ - [] - ] - }, - { - "id": "f408a273.4fb538", - "type": "function", - "z": "b771c342.49603", - "name": "get sample_gear_net_opening", - "func": "if (msg.payload.sample_gear_net_opening === null){\n msg.payload = 0;\n global.set(\"sample_gear_net_opening\",msg.payload);\n}\nelse\n{\n msg.payload = msg.payload.sample_gear_net_opening;\n}\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 350, - "y": 320, - "wires": [ - [ - "e967b844.46aa48" - ] - ] - }, - { - "id": "8dff1648.82e42", - "type": "function", - "z": "b771c342.49603", - "name": "get object_depth_max", - "func": "if (msg.payload.object_depth_max === null){\n msg.payload = 0;\n global.set(\"object_depth_max\",msg.payload);\n}\nelse\n{\n msg.payload = msg.payload.object_depth_max;\n}\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 320, - "y": 240, - "wires": [ - [ - "9c7f7fc9.c8d3a" - ] - ] - }, - { - "id": "9f04c5ec.75f3d8", - "type": "function", - "z": "b771c342.49603", - "name": "get object_depth_min", - "func": "if (msg.payload.object_depth_min === null){\n msg.payload = 0;\n global.set(\"object_depth_min\",msg.payload);\n}\nelse\n{\n msg.payload = msg.payload.object_depth_min;\n}\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 320, - "y": 280, - "wires": [ - [ - "317eeeb7.8d3042" - ] - ] - }, - { - "id": "9a18a4b4.178448", - "type": "function", - "z": "b771c342.49603", - "name": "calculate sample_total_volume", - "func": "\n/*object_lat = 33.95 \nobject_lon = 118.4 \nobject_lat_end = 40.6333 \nobject_lon_end = 73.78333\nsample_gear_net_opening = 40*/\n\n// Copyright 1997 Ed Williams. All rights reserved\n// Adapted by Romain Bazile - Ocean Trotter - 01-2021\n\ndecpl=4 // Dec places of minutes output\n\nellipse = {\"name\":\"WSG84\", \"a\":6378.137/1.852, \"invf\":298.257223563}\n\nfunction ComputeDistance(lat1, lon1, lat2, lon2){\n var d,crs12,crs21\n var argacos\n var a,invf\n \n // lat and lon in radian\n lat1=(Math.PI/180)*lat1\n lat2=(Math.PI/180)*lat2\n lon1=(Math.PI/180)*lon1\n lon2=(Math.PI/180)*lon2\n \n //alert(\"lat1=\" + lat1 + \"lon1=\" + lon1 +\"\\nlat2=\" +lat2+ \"lon2=\"+lon2)\n \n /* get distance conversion factor */\n dc=1.852 //km\n //alert(\"dc=\" +dc)\n \n //showProps(ellipse,\"ellipse\")\n \n // elliptic code\n d=crsdist_ell(lat1,-lon1,lat2,-lon2,ellipse) // ellipse uses East negative\n d=d*dc // go to physical units\n \n //alert(\"d=\"+d+\" crs12=\"+crs12+\" crs21=\"+crs21)\n return d\n}\n\nfunction crsdist(lat1,lon1,lat2,lon2){ // radian args\n /* compute course and distance (spherical) */\n if ((lat1+lat2===0) && (Math.abs(lon1-lon2)==Math.PI) && \n (Math.abs(lat1) != (Math.PI/180)*90)){\t\n \talert(\"Course between antipodal points is undefined\")\n }\n \n d = Math.acos(Math.sin(lat1)*Math.sin(lat2)+Math.cos(lat1)*Math.cos(lat2)*Math.cos(lon1-lon2))\n return d\n}\n\nfunction crsdist_ell(glat1,glon1,glat2,glon2,ellipse){\n // glat1 initial geodetic latitude in radians N positive \n // glon1 initial geodetic longitude in radians E positive \n // glat2 final geodetic latitude in radians N positive \n // glon2 final geodetic longitude in radians E positive \n a=ellipse.a\n f=1/ellipse.invf\n //alert(\"a=\"+a+\" f=\"+f)\n var r, tu1, tu2, cu1, su1, cu2, s1, b1, f1\n var x, sx, cx, sy, cy,y, sa, c2a, cz, e, c, d\n var EPS= 0.00000000005\n var faz, baz, s\n var iter=1\n var MAXITER=100\n if ((glat1+glat2===0) && (Math.abs(glon1-glon2)==Math.PI)){\n alert(\"Course and distance between antipodal points is undefined\")\n glat1=glat1+0.00001 // allow algorithm to complete\n }\n if (glat1==glat2 && (glon1==glon2 || Math.abs(Math.abs(glon1-glon2)-2*Math.PI) < EPS)){\n alert(\"Points 1 and 2 are identical- course undefined\")\n out=new MakeArray(0)\n out.d=0\n out.crs12=0\n out.crs21=Math.PI\n return out\n }\n r = 1 - f\n tu1 = r * Math.tan (glat1)\n tu2 = r * Math.tan (glat2)\n cu1 = 1 / Math.sqrt (1 + tu1 * tu1)\n su1 = cu1 * tu1\n cu2 = 1 / Math.sqrt (1 + tu2 * tu2)\n s1 = cu1 * cu2\n b1 = s1 * tu2\n f1 = b1 * tu1\n x = glon2 - glon1\n d = x + 1 // force one pass\n while ((Math.abs(d - x) > EPS) && (iter < MAXITER))\n {\n iter=iter+1\n sx = Math.sin (x)\n // alert(\"sx=\"+sx)\n cx = Math.cos (x)\n tu1 = cu2 * sx\n tu2 = b1 - su1 * cu2 * cx\n sy = Math.sqrt(tu1 * tu1 + tu2 * tu2)\n cy = s1 * cx + f1\n y = atan2 (sy, cy)\n sa = s1 * sx / sy\n c2a = 1 - sa * sa\n cz = f1 + f1\n if (c2a > 0)\n cz = cy - cz / c2a\n e = cz * cz * 2 - 1\n c = ((-3 * c2a + 4) * f + 4) * c2a * f / 16\n d = x\n x = ((e * cy * c + cz) * sy * c + y) * sa\n x = (1 - c) * x * f + glon2 - glon1\n }\n x = Math.sqrt ((1 / (r * r) - 1) * c2a + 1)\n x +=1\n x = (x - 2) / x\n c = 1 - x\n c = (x * x / 4 + 1) / c\n d = (0.375 * x * x - 1) * x\n x = e * cy\n d = ((((sy*sy*4-3)*(1-e-e)*cz*d/6-x)*d/4+cz)*sy*d+y)*c*a*r\n if (Math.abs(iter-MAXITER)0) && (y>=0)){ out= Math.atan(y/x)}\n if ((x >0) && (y<0)) { out= Math.atan(y/x)+2*Math.PI}\n if ((x===0) && (y>0)) { out= Math.PI/2}\n if ((x===0) && (y<0)) { out= 3*Math.PI/2} \n if ((x===0) && (y===0)) {\n alert(\"atan2(0,0) undefined\")\n out= 0\n } \n return out\n}\n\nfunction showProps(obj,objName){\n var result=\"\"\n for (var i in obj){\n result +=objName + \".\" + i + \" = \" + obj[i] + \"\\n\"\n }\n alert(result)\n}\n\n\nif (msg.valid){\n msg.topic=\"sample_total_volume\"\n \n var object_lat_end = global.get(\"object_lat_end\")\n var object_lon_end = global.get(\"object_lon_end\")\n var sample_sampling_gear = global.get(\"sample_sampling_gear\")\n \n if (sample_sampling_gear.startsWith(\"net\") && sample_sampling_gear != \"net_decknet\") {\n if (!(isNaN(object_lat_end) && isNaN(object_lon_end))){\n var object_lat = global.get(\"object_lat\")\n var object_lon = global.get(\"object_lon\")\n var sample_gear_net_opening = global.get(\"sample_gear_net_opening\");\n\n distance_km = ComputeDistance(object_lat, object_lon, object_lat_end, object_lon_end)\n\n sample_total_volume = distance_km*(Math.PI*(sample_gear_net_opening/2)*(sample_gear_net_opening/2)) // liters\n sample_total_volume = Math.round(sample_total_volume + Number.EPSILON)\n msg.payload = sample_total_volume\n return msg\n }\n }\n}", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 930, - "y": 760, - "wires": [ - [ - "4f6afc5a.81e454" - ] - ] - }, - { - "id": "4fb4e0ad.c417c", - "type": "ui_text", - "z": "b771c342.49603", - "group": "fc5e4e6f.5b1c8", - "order": 6, - "width": 5, - "height": 1, - "name": "Latitude", - "label": "Latitude", - "format": "{{msg.payload.lat.deg}}°{{msg.payload.lat.min}}'{{msg.payload.lat.sec}}{{msg.payload.lat.dir}}", - "layout": "col-center", - "x": 700, - "y": 1120, - "wires": [] - }, - { - "id": "8d2b5026.13e6e8", - "type": "ui_text", - "z": "b771c342.49603", - "group": "fc5e4e6f.5b1c8", - "order": 7, - "width": 5, - "height": 1, - "name": "Longitude", - "label": "Longitude", - "format": "{{msg.payload.lon.deg}}°{{msg.payload.lon.min}}'{{msg.payload.lon.sec}}{{msg.payload.lon.dir}}", - "layout": "col-center", - "x": 700, - "y": 1160, - "wires": [] - }, - { - "id": "258b4562.9f778a", - "type": "function", - "z": "b771c342.49603", - "name": "Convert DD to DMS", - "func": "function ConvertDDToDMS(D, lng){\n // from https://stackoverflow.com/a/5786281/2108279\n return {\n dir : D<0?lng?'W':'S':lng?'E':'N',\n deg : 0|(D<0?D=-D:D),\n min : 0|D%1*60,\n sec :(0|D*60%1*6000)/100\n };\n}\n\nmsg.payload = {\n \"lat\":ConvertDDToDMS(msg.payload.lat, false),\n \"lon\":ConvertDDToDMS(msg.payload.lon, true)\n};\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 490, - "y": 1140, - "wires": [ - [ - "4fb4e0ad.c417c", - "8d2b5026.13e6e8" - ] - ] - }, - { - "id": "7c4ce5f3.62dd5c", - "type": "ui_text", - "z": "b771c342.49603", - "group": "fc5e4e6f.5b1c8", - "order": 4, - "width": 2, - "height": 1, - "name": "Speed", - "label": "Speed", - "format": "{{msg.payload}} kts", - "layout": "col-center", - "x": 690, - "y": 1200, - "wires": [] - }, - { - "id": "54e37580.fdc31c", - "type": "ui_text", - "z": "b771c342.49603", - "group": "fc5e4e6f.5b1c8", - "order": 5, - "width": 2, - "height": 1, - "name": "Direction", - "label": "Direction", - "format": "{{msg.payload.track}} °", - "layout": "col-center", - "x": 700, - "y": 1240, - "wires": [] - }, - { - "id": "cc21ca16.b92928", - "type": "function", - "z": "b771c342.49603", - "name": "GPS Mode", - "func": "switch (msg.payload.mode){\n case 1:msg.payload = \"No Fix\"; break\n case 2:msg.payload = \"2D Fix\"; break\n case 3:msg.payload = \"3D Fix\"; break\n default: msg.payload = \"No info\"\n}\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 470, - "y": 1080, - "wires": [ - [ - "7116e906.9f50f" - ] - ] - }, - { - "id": "4a4de52c.cf2884", - "type": "function", - "z": "b771c342.49603", - "name": "Speed conversion", - "func": "msg.payload = (0|msg.payload.speed) * 1.9438\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 490, - "y": 1200, - "wires": [ - [ - "7c4ce5f3.62dd5c" - ] - ] - }, - { - "id": "35ad311f.344c76", - "type": "ui_text", - "z": "b771c342.49603", - "group": "fc5e4e6f.5b1c8", - "order": 2, - "width": 5, - "height": 1, - "name": "Time", - "label": "Time", - "format": "{{msg.payload.time}}", - "layout": "col-center", - "x": 690, - "y": 1280, - "wires": [] - }, - { - "id": "e73fd87d.d24e4", - "type": "function", - "z": "b771c342.49603", - "name": "get acq_minimum_mesh", - "func": "msg.payload = msg.payload.acq_minimum_mesh;\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 330, - "y": 360, - "wires": [ - [ - "1aad56b31b5647ce" - ] - ] - }, - { - "id": "489c8e06.cc7d6", - "type": "function", - "z": "b771c342.49603", - "name": "get acq_maximum_mesh", - "func": "msg.payload = msg.payload.acq_maximum_mesh;\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 330, - "y": 400, - "wires": [ - [ - "10eb31a2d7a6590c" - ] - ] - }, - { - "id": "73c4a14a.9b93c8", - "type": "function", - "z": "b771c342.49603", - "name": "Convert time", - "func": "msg.payload.time = msg.payload.time.replace('T', ' ');\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 470, - "y": 1280, - "wires": [ - [ - "35ad311f.344c76" - ] - ] - }, - { - "id": "58de1340.3cc354", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "sample_dilution_factor", - "label": "Concentration Factor", - "tooltip": "0.5 if diluted by two; 2 if concentrated by a factor 2", - "group": "3e1ba03d.f01d8", - "order": 13, - "width": 10, - "height": 1, - "passthru": true, - "mode": "number", - "delay": "300", - "topic": "sample_dilution_factor", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 640, - "y": 480, - "wires": [ - [ - "9f501f49.45645" - ] - ] - }, - { - "id": "4f6afc5a.81e454", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "sample_total_volume", - "label": "Filtered volume (in L)", - "tooltip": "Calculated or hand filled", - "group": "3e1ba03d.f01d8", - "order": 11, - "width": 0, - "height": 0, - "passthru": true, - "mode": "text", - "delay": "300", - "topic": "sample_total_volume", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 1220, - "y": 760, - "wires": [ - [ - "e1f2f6eb.fe1dd" - ] - ] - }, - { - "id": "e1f2f6eb.fe1dd", - "type": "function", - "z": "b771c342.49603", - "name": "set global", - "func": "global.set(msg.topic,msg.payload);", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 1420, - "y": 760, - "wires": [ - [] - ] - }, - { - "id": "e9bc112c.eb75f8", - "type": "function", - "z": "b771c342.49603", - "name": "Calculate volume", - "func": "if (msg.topic == \"sample_total_flowmeter_start\"){\n context.set(\"sample_total_flowmeter_start\", msg.payload);\n}\nif (msg.topic == \"sample_total_flowmeter_end\"){\n context.set(\"sample_total_flowmeter_end\", msg.payload);\n}\n\nif (context.keys().length == 2){\n sample_total_volume = context.get(\"sample_total_flowmeter_end\") - context.get(\"sample_total_flowmeter_start\");\n msg.topic=\"sample_total_volume\"\n msg.payload=sample_total_volume\n return msg\n}\n", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 1610, - "y": 240, - "wires": [ - [ - "4f6afc5a.81e454" - ] - ] - }, - { - "id": "cdd4181922eecf11", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "sample_speed_through_water", - "label": "Speed Through Water (kts)", - "tooltip": "in knots", - "group": "cf5d9f0e.d57e7", - "order": 2, - "width": 10, - "height": 1, - "passthru": true, - "mode": "number", - "delay": "300", - "topic": "sample_speed_through_water", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 610, - "y": 520, - "wires": [ - [ - "9f501f49.45645" - ] - ] - }, - { - "id": "1aad56b31b5647ce", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "acq_minimum_mesh", - "label": "Minimal fraction size (μm)", - "tooltip": "Net mesh pore size or minimal filtration mesh pore size", - "group": "3e1ba03d.f01d8", - "order": 7, - "width": 5, - "height": 1, - "passthru": true, - "mode": "number", - "delay": "300", - "topic": "acq_minimum_mesh", - "topicType": "str", - "x": 640, - "y": 360, - "wires": [ - [ - "9f501f49.45645" - ] - ] - }, - { - "id": "10eb31a2d7a6590c", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "acq_maximum_mesh", - "label": "Maximal fraction size (μm)", - "tooltip": "Maximal filtration mesh pore size", - "group": "3e1ba03d.f01d8", - "order": 8, - "width": 5, - "height": 1, - "passthru": true, - "mode": "number", - "delay": "300", - "topic": "acq_maximum_mesh", - "topicType": "str", - "x": 640, - "y": 400, - "wires": [ - [ - "9f501f49.45645" - ] - ] - }, - { - "id": "3ac7b631f5d8ef90", - "type": "function", - "z": "b771c342.49603", - "name": "Culture check", - "func": "var activation_msg = {}\nvar date_msg = {}\nvar timestamp=new Date().toISOString();\n\nif (msg.payload === \"culture\"){\n activation_msg.payload = {\"group\":{\"show\":[\"Sample_Culture_Date_and_Time\"],\"hide\":[\"Sample_Sample_Location\", \"Sample_Net_Metadata\"]}};\n global.set(\"object_lat\", \"-90.0000\")\n global.set(\"object_lon\", \"0.0000\")\n date_msg.payload = {\"object_date\": timestamp.split('T')[0],\n \"object_time\": timestamp.split('T')[1].split('.')[0]}\n return [activation_msg, date_msg];\n}\nelse if (msg.payload === \"test\"){\n activation_msg.payload = {\"group\":{\"hide\":[\"Sample_Culture_Date_and_Time\", \"Sample_Sample_Location\", \"Sample_Net_Metadata\"]}};\n global.set(\"object_lat\", \"-90.0000\")\n global.set(\"object_lon\", \"0.0000\")\n global.set(\"object_date\", timestamp.split('T')[0])\n global.set(\"object_time\", timestamp.split('T')[1].split('.')[0])\n return [activation_msg, null];\n}\nelse{\n return [null, null]\n}\n\n", - "outputs": 2, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 1100, - "y": 320, - "wires": [ - [ - "cbb123ab.fd3428" - ], - [ - "05c6aff2afbd69cf" - ] - ], - "outputLabels": [ - "decknet activation", - "" - ] - }, - { - "id": "05c6aff2afbd69cf", - "type": "ui_form", - "z": "b771c342.49603", - "name": "culture_timestamp", - "label": "Culture timestamp", - "group": "7bc0a4c416e4545c", - "order": 1, - "width": 0, - "height": 0, - "options": [ - { - "label": "Date (YYYY-MM-DD, UTC)", - "value": "object_date", - "type": "text", - "required": true, - "rows": null - }, - { - "label": "Time (HH:MM(:SS), UTC 24h)", - "value": "object_time", - "type": "text", - "required": true, - "rows": null - } - ], - "formValue": { - "object_date": "", - "object_time": "" - }, - "payload": "", - "submit": "Validate", - "cancel": "Reset", - "topic": "culture_timestamp", - "topicType": "str", - "splitLayout": false, - "className": "", - "x": 650, - "y": 700, - "wires": [ - [ - "14658615.47c862", - "38616e738f4f615b" - ] - ] - }, - { - "id": "3318a1aaa70fc2ee", - "type": "change", - "z": "b771c342.49603", - "name": "Repopulate input fields", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 400, - "y": 580, - "wires": [ - [ - "c33f1124.af6688" - ] - ] - }, - { - "id": "cc67c97f55a340d3", - "type": "change", - "z": "b771c342.49603", - "name": "Repopulate input fields", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 400, - "y": 620, - "wires": [ - [ - "358908cd.416ab" - ] - ] - }, - { - "id": "9c8f370d124a55e4", - "type": "change", - "z": "b771c342.49603", - "name": "Repopulate input fields", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 400, - "y": 660, - "wires": [ - [ - "56d40584.eff4e4" - ] - ] - }, - { - "id": "38616e738f4f615b", - "type": "change", - "z": "b771c342.49603", - "name": "Repopulate input fields", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 400, - "y": 700, - "wires": [ - [ - "05c6aff2afbd69cf" - ] - ] - }, - { - "id": "577be9c22c739ca0", - "type": "inject", - "z": "b771c342.49603", - "name": "", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "", - "payload": "1", - "payloadType": "num", - "x": 270, - "y": 480, - "wires": [ - [ - "58de1340.3cc354" - ] - ] - }, - { - "id": "6a84252a.d52a0c", - "type": "ui_template", - "z": "bccd1f23.87219", - "group": "833bc5bb.217ba8", - "name": "Stream Pi Camera", - "order": 1, - "width": 18, - "height": 14, - "format": "
\n \"If\n
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "className": "", - "x": 610, - "y": 40, - "wires": [ - [] - ] - }, - { - "id": "dc48dc42.98d18", - "type": "function", - "z": "bccd1f23.87219", - "name": "set global", - "func": "global.set(msg.topic,msg.payload);", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 880, - "y": 440, - "wires": [ - [] - ] - }, - { - "id": "811cd88c.daf528", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "down", - "group": "fbd92986.1028c8", - "order": 6, - "width": 4, - "height": 1, - "passthru": true, - "label": "", - "tooltip": "", - "color": "", - "bgcolor": "", - "icon": "fa-angle-double-down fa-3x", - "payload": "DOWN", - "payloadType": "str", - "topic": "actuator/focus", - "x": 550, - "y": 800, - "wires": [ - [ - "65ad39d.b6d4d48" - ] - ] - }, - { - "id": "edda4df4.76de2", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "up", - "group": "fbd92986.1028c8", - "order": 3, - "width": 4, - "height": 1, - "passthru": false, - "label": "", - "tooltip": "", - "color": "", - "bgcolor": "", - "icon": "fa-angle-double-up fa-3x", - "payload": "UP", - "payloadType": "str", - "topic": "actuator/focus", - "x": 550, - "y": 760, - "wires": [ - [ - "65ad39d.b6d4d48" - ] - ] - }, - { - "id": "68962547.34a67c", - "type": "ui_text_input", - "z": "bccd1f23.87219", - "name": "pump_manual_volume", - "label": "Volume to pass (ml)", - "tooltip": "Tiny values are accepted down to 0.001mL", - "group": "707d9797.c8e798", - "order": 3, - "width": 2, - "height": 1, - "passthru": true, - "mode": "text", - "delay": "300", - "topic": "pump_manual_volume", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 600, - "y": 420, - "wires": [ - [ - "dc48dc42.98d18" - ] - ] - }, - { - "id": "6c792043.b6ff9", - "type": "ui_ui_control", - "z": "bccd1f23.87219", - "name": "", - "events": "change", - "x": 560, - "y": 1140, - "wires": [ - [] - ] - }, - { - "id": "902429eb.ceacb8", - "type": "ui_toast", - "z": "bccd1f23.87219", - "position": "dialog", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 1, - "ok": "OK", - "cancel": "", - "raw": false, - "topic": "", - "name": "", - "x": 570, - "y": 1220, - "wires": [ - [] - ] - }, - { - "id": "fe840e05.b46f3", - "type": "function", - "z": "bccd1f23.87219", - "name": "Check form", - "func": "var acq_fnumber_objective= global.get(\"acq_fnumber_objective\");\n\nif (acq_fnumber_objective === undefined || acq_fnumber_objective === \"\") {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Focal Length of the objective\";\n return [null, msg];\n}\n\nmsg.topic = \"Change Tab\";\nmsg.payload={\"tab\":\"Fluidic Acquisition\"};\nreturn [msg, null];", - "outputs": 2, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 330, - "y": 1180, - "wires": [ - [ - "6c792043.b6ff9", - "326a1d95.ca21aa" - ], - [ - "902429eb.ceacb8" - ] - ], - "outputLabels": [ - "message", - "error" - ] - }, - { - "id": "5846b1d4.7971b", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "Backward", - "group": "707d9797.c8e798", - "order": 2, - "width": 1, - "height": 1, - "passthru": false, - "label": "", - "tooltip": "", - "color": "", - "bgcolor": "", - "icon": "fa-rotate-left fa-2x", - "payload": "BACKWARD", - "payloadType": "str", - "topic": "actuator/pump", - "x": 560, - "y": 280, - "wires": [ - [ - "3cb96380.e575ec" - ] - ] - }, - { - "id": "2cab680b.baf888", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "Forward", - "group": "707d9797.c8e798", - "order": 4, - "width": 1, - "height": 1, - "passthru": true, - "label": "", - "tooltip": "", - "color": "", - "bgcolor": "", - "icon": "fa-rotate-right fa-2x", - "payload": "FORWARD", - "payloadType": "str", - "topic": "actuator/pump", - "x": 560, - "y": 320, - "wires": [ - [ - "3cb96380.e575ec" - ] - ] - }, - { - "id": "8038414a.34461", - "type": "function", - "z": "bccd1f23.87219", - "name": "Calculate optics", - "func": "var acq_fnumber_objective = String(global.get(\"acq_fnumber_objective\"));\nvar acq_camera = global.get(\"acq_camera\")\n\n// Those values needs to be recalculated, they are not good!\nif (acq_camera == \"HQ Camera\"){\n switch(acq_fnumber_objective) {\n case \"25\":\n acq_magnification= 0.6;\n process_pixel= 1.56;\n sug_min= 60;\n sug_max= 670;\n sug_flowrate= 3;\n break;\n case \"16\":\n acq_magnification= 1.6;\n process_pixel= 1.01;\n sug_min= 40;\n sug_max= 430;\n sug_flowrate= 2.4;\n break;\n case \"12\":\n acq_magnification= 1.20;\n process_pixel= 0.79;\n sug_min= 30;\n sug_max= 340;\n sug_flowrate= 1.25;\n break;\n case \"8\":\n acq_magnification= 1.78;\n process_pixel= 0.53;\n sug_min= 20;\n sug_max= 230;\n sug_flowrate= 0.42;\n break;\n case \"6\":\n acq_magnification= 2.36;\n process_pixel= 0.41;\n sug_min= 15;\n sug_max= 170;\n sug_flowrate= 0.32;\n break;\n }\n}\nelse if (acq_camera == \"Camera v2.1\"){\n switch(acq_fnumber_objective) {\n case \"25\":\n acq_magnification= 0.6;\n process_pixel= 1.86;\n sug_min= 60;\n sug_max= 670;\n sug_flowrate= 3;\n break;\n case \"16\":\n acq_magnification= 1.6;\n process_pixel= 0.7;\n sug_min= 40;\n sug_max= 430;\n sug_flowrate= 2.4;\n break;\n case \"12\":\n acq_magnification= 1.20;\n process_pixel= 0.94;\n sug_min= 30;\n sug_max= 340;\n sug_flowrate= 1.25;\n break;\n case \"8\":\n acq_magnification= 1.78;\n process_pixel= 0.63;\n sug_min= 20;\n sug_max= 230;\n sug_flowrate= 0.42;\n break;\n case \"6\":\n acq_magnification= 2.36;\n process_pixel= 0.48;\n sug_min= 15;\n sug_max= 170;\n sug_flowrate= 0.32;\n break;\n }\n}else {\n acq_magnification= \"ERROR\";\n process_pixel= \"ERROR\";\n sug_min= \"ERROR\";\n sug_max= \"ERROR\";\n sug_flowrate= \"ERROR\";\n}\n\nvar process_pixel_fixed = global.get(\"process_pixel_fixed\")\n\nif (process_pixel_fixed !== undefined && process_pixel_fixed !== \"\") {\n process_pixel = process_pixel_fixed\n}\n\nglobal.set(\"process_pixel\",process_pixel);\n\nglobal.set(\"acq_magnification\",acq_magnification);\n\n\nreturn [{payload: acq_fnumber_objective}, {payload: acq_magnification}, {payload: process_pixel}, {payload: sug_min}, {payload: sug_max}];", - "outputs": 5, - "timeout": "", - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 1080, - "y": 120, - "wires": [ - [], - [], - [], - [], - [] - ], - "inputLabels": [ - "acq_fnumber_objective" - ], - "outputLabels": [ - "acq_magnification", - "process_pixel", - "sug_min", - "sug_max", - "" - ] - }, - { - "id": "f61aaed5.1e64", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "", - "group": "7a0b4877.a5d268", - "order": 1, - "width": 2, - "height": 1, - "passthru": false, - "label": "Previous", - "tooltip": "", - "color": "#097479", - "bgcolor": "white", - "icon": "keyboard_return", - "payload": "{\"tab\":\"Sample\"}", - "payloadType": "json", - "topic": "", - "x": 140, - "y": 1140, - "wires": [ - [ - "6c792043.b6ff9" - ] - ] - }, - { - "id": "9ba6ec0a.22c96", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "", - "group": "7a0b4877.a5d268", - "order": 2, - "width": 2, - "height": 1, - "passthru": false, - "label": "Continue", - "tooltip": "", - "color": "#097479", - "bgcolor": "white", - "icon": "keyboard_tab", - "payload": "{\"tab\":\"Home\"}", - "payloadType": "json", - "topic": "", - "x": 140, - "y": 1180, - "wires": [ - [ - "fe840e05.b46f3" - ] - ] - }, - { - "id": "cbb8afed.0a026", - "type": "rpi-gpio out", - "z": "bccd1f23.87219", - "name": "LED Output", - "pin": "21", - "set": true, - "level": "0", - "freq": "", - "out": "out", - "bcm": true, - "x": 550, - "y": 120, - "wires": [] - }, - { - "id": "3cb96380.e575ec", - "type": "function", - "z": "bccd1f23.87219", - "name": "pump", - "func": "var manual_volume= global.get(\"pump_manual_volume\");\nvar flowrate= global.get(\"pump_flowrate\");\n\nif (manual_volume === undefined || manual_volume === \"\" || manual_volume === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Volume to pass\";\n return [null, msg];\n}\nelse if (flowrate === undefined || flowrate === \"\" || flowrate === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Flowrate\";\n return [null, msg];\n}\nelse {\n msg.topic = \"actuator/pump\";\n // msg.payload is FORWARD or BACKWARD here\n msg.payload={\"action\":\"move\", \n \"direction\":msg.payload,\n \"volume\":manual_volume,\n \"flowrate\":flowrate};\n}\nreturn [msg, null];", - "outputs": 2, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 750, - "y": 300, - "wires": [ - [ - "bdc8ce57.de1f08" - ], - [ - "8bcce348.efc1a" - ] - ], - "inputLabels": [ - "direction" - ], - "outputLabels": [ - "message", - "error" - ] - }, - { - "id": "8bcce348.efc1a", - "type": "ui_toast", - "z": "bccd1f23.87219", - "position": "dialog", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 1, - "ok": "OK", - "cancel": "", - "raw": false, - "topic": "", - "name": "", - "x": 1090, - "y": 300, - "wires": [ - [] - ] - }, - { - "id": "bdc8ce57.de1f08", - "type": "mqtt out", - "z": "bccd1f23.87219", - "name": "", - "topic": "", - "qos": "", - "retain": "", - "broker": "8dc3722c.06efa8", - "x": 1210, - "y": 260, - "wires": [] - }, - { - "id": "d71d224f.0585d8", - "type": "ui_toast", - "z": "bccd1f23.87219", - "position": "dialog", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 1, - "ok": "OK", - "cancel": "", - "raw": false, - "topic": "", - "name": "", - "x": 1090, - "y": 800, - "wires": [ - [] - ] - }, - { - "id": "65ad39d.b6d4d48", - "type": "function", - "z": "bccd1f23.87219", - "name": "focus", - "func": "var distance = global.get(\"focus_distance\");\n\nif (distance === undefined || distance === \"\" || distance === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Distance\";\n return [null, msg]\n}else {\n distance = global.get(\"focus_distance\");\n // msg.payload is UP or DOWN here\n msg.payload={\"action\":\"move\", \n \"direction\":msg.payload,\n \"distance\":(distance/1000)};\n}\nreturn [msg, null];", - "outputs": 2, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 850, - "y": 780, - "wires": [ - [ - "62030521.88317c" - ], - [ - "d71d224f.0585d8" - ] - ], - "inputLabels": [ - "direction" - ], - "outputLabels": [ - "message", - "error" - ] - }, - { - "id": "1962d999.4a97e6", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "stop focus", - "group": "fbd92986.1028c8", - "order": 9, - "width": 0, - "height": 0, - "passthru": true, - "label": " STOP FOCUS", - "tooltip": "", - "color": "", - "bgcolor": "#AD1625", - "icon": "fa-pause fa-2x", - "payload": "{\"action\":\"stop\"}", - "payloadType": "json", - "topic": "actuator/focus", - "x": 570, - "y": 560, - "wires": [ - [ - "62030521.88317c" - ] - ] - }, - { - "id": "62030521.88317c", - "type": "mqtt out", - "z": "bccd1f23.87219", - "name": "", - "topic": "", - "qos": "", - "retain": "", - "broker": "8dc3722c.06efa8", - "x": 1210, - "y": 720, - "wires": [] - }, - { - "id": "3bd43039.bc5fb8", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "", - "group": "fbd92986.1028c8", - "order": 1, - "width": 4, - "height": 1, - "passthru": false, - "label": "UP 1mm", - "tooltip": "", - "color": "", - "bgcolor": "", - "icon": "fa-angle-up fa-3x", - "payload": "{\"action\":\"move\",\"direction\":\"UP\",\"distance\":1}", - "payloadType": "json", - "topic": "actuator/focus", - "topicType": "str", - "x": 560, - "y": 600, - "wires": [ - [ - "62030521.88317c" - ] - ] - }, - { - "id": "c0663029.2d03b", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "", - "group": "fbd92986.1028c8", - "order": 8, - "width": 4, - "height": 1, - "passthru": false, - "label": "DOWN 1mm", - "tooltip": "", - "color": "", - "bgcolor": "", - "icon": "fa-angle-down fa-3x", - "payload": "{\"action\":\"move\",\"direction\":\"DOWN\",\"distance\":1}", - "payloadType": "json", - "topic": "actuator/focus", - "topicType": "str", - "x": 570, - "y": 720, - "wires": [ - [ - "62030521.88317c" - ] - ] - }, - { - "id": "71f55a58.d7eaf4", - "type": "inject", - "z": "bccd1f23.87219", - "name": "Default: 500µm", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": "0.5", - "topic": "", - "payload": "500", - "payloadType": "num", - "x": 120, - "y": 460, - "wires": [ - [ - "be33e564.029358" - ] - ] - }, - { - "id": "9a1d0e7c.2d5a1", - "type": "inject", - "z": "bccd1f23.87219", - "name": "Default: OFF", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "", - "payload": "off", - "payloadType": "str", - "x": 130, - "y": 120, - "wires": [ - [ - "f0775525.cf806" - ] - ] - }, - { - "id": "f782a471.447748", - "type": "inject", - "z": "bccd1f23.87219", - "name": "Default: 2mL/min", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": "0.5", - "topic": "", - "payload": "2", - "payloadType": "num", - "x": 130, - "y": 380, - "wires": [ - [ - "cb2d5174.cfe9f" - ] - ] - }, - { - "id": "73b8252a.5ca754", - "type": "inject", - "z": "bccd1f23.87219", - "name": "Default: 2mL", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": "0.5", - "topic": "", - "payload": "2", - "payloadType": "num", - "x": 110, - "y": 420, - "wires": [ - [ - "68962547.34a67c" - ] - ] - }, - { - "id": "6451f991.aaac1", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "stop pump", - "group": "707d9797.c8e798", - "order": 5, - "width": 4, - "height": 1, - "passthru": true, - "label": " STOP PUMP", - "tooltip": "", - "color": "", - "bgcolor": "#AD1625", - "icon": "fa-pause fa-2x", - "payload": "{\"action\":\"stop\"}", - "payloadType": "json", - "topic": "actuator/pump", - "x": 570, - "y": 240, - "wires": [ - [ - "bdc8ce57.de1f08" - ] - ] - }, - { - "id": "cfc783d7.d6ceb", - "type": "link in", - "z": "bccd1f23.87219", - "name": "Optics recalculation", - "links": [ - "559a8085.1d6b9", - "5d5ad36d2c50dcc2" - ], - "x": 915, - "y": 120, - "wires": [ - [ - "8038414a.34461" - ] - ] - }, - { - "id": "326a1d95.ca21aa", - "type": "subflow:1c24ad9c.bebec2", - "z": "bccd1f23.87219", - "name": "", - "x": 550, - "y": 1180, - "wires": [ - [] - ] - }, - { - "id": "2d371e59.b0e50a", - "type": "inject", - "z": "bccd1f23.87219", - "name": "Default: 1000µm/s", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": "0.5", - "topic": "", - "payload": "1000", - "payloadType": "num", - "x": 130, - "y": 500, - "wires": [ - [ - "3a86de51.765b9a" - ] - ] - }, - { - "id": "167cda35.c9b6ae", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "", - "group": "fbd92986.1028c8", - "order": 2, - "width": 4, - "height": 1, - "passthru": false, - "label": "UP 100um", - "tooltip": "", - "color": "", - "bgcolor": "", - "icon": "fa-angle-up fa-3x", - "payload": "{\"action\":\"move\",\"direction\":\"UP\",\"distance\":0.1}", - "payloadType": "json", - "topic": "actuator/focus", - "topicType": "str", - "x": 570, - "y": 640, - "wires": [ - [ - "62030521.88317c" - ] - ] - }, - { - "id": "72a7c597.9374fc", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "", - "group": "fbd92986.1028c8", - "order": 7, - "width": 4, - "height": 1, - "passthru": false, - "label": "DOWN 100um", - "tooltip": "", - "color": "", - "bgcolor": "", - "icon": "fa-angle-down fa-3x", - "payload": "{\"action\":\"move\",\"direction\":\"DOWN\",\"distance\":0.1}", - "payloadType": "json", - "topic": "actuator/focus", - "topicType": "str", - "x": 580, - "y": 680, - "wires": [ - [ - "62030521.88317c" - ] - ] - }, - { - "id": "f0775525.cf806", - "type": "ui_multistate_switch", - "z": "bccd1f23.87219", - "name": "light_control", - "group": "4248342d.e55fac", - "order": 1, - "width": 5, - "height": 1, - "label": "Light ", - "stateField": "payload", - "enableField": "enable", - "rounded": true, - "useThemeColors": true, - "hideSelectedLabel": false, - "options": [ - { - "label": "Off", - "value": "0", - "valueType": "num", - "color": "#009933" - }, - { - "label": "On", - "value": "1", - "valueType": "num", - "color": "#999999" - } - ], - "x": 350, - "y": 120, - "wires": [ - [ - "cbb8afed.0a026" - ] - ] - }, - { - "id": "8ea9dc9a.c7d87", - "type": "function", - "z": "bccd1f23.87219", - "name": "Encapsulate settings", - "func": "msg.payload = {\n \"action\":\"settings\", \n \"settings\":{[msg.topic]:msg.payload}\n}\n\nmsg.topic = \"imager/image\"\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 1120, - "y": 940, - "wires": [ - [ - "845e06e1.0d812" - ] - ] - }, - { - "id": "5765a825.a595c8", - "type": "ui_slider", - "z": "bccd1f23.87219", - "name": "Shutter speed slider", - "label": "Shutter Speed", - "tooltip": "In microseconds, up to 1000µs, 125µs by default", - "group": "8c38a81e.9897a8", - "order": 4, - "width": 0, - "height": 0, - "passthru": true, - "outs": "end", - "topic": "shutter_speed", - "topicType": "str", - "min": "125", - "max": "1000", - "step": "1", - "className": "", - "x": 600, - "y": 880, - "wires": [ - [ - "8ea9dc9a.c7d87" - ] - ] - }, - { - "id": "845e06e1.0d812", - "type": "mqtt out", - "z": "bccd1f23.87219", - "name": "", - "topic": "", - "qos": "", - "retain": "", - "broker": "8dc3722c.06efa8", - "x": 1390, - "y": 980, - "wires": [] - }, - { - "id": "2350e507.d4e302", - "type": "inject", - "z": "bccd1f23.87219", - "name": "Default: 125µs", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": "1", - "topic": "", - "payload": "125", - "payloadType": "num", - "x": 120, - "y": 880, - "wires": [ - [ - "5765a825.a595c8" - ] - ] - }, - { - "id": "5e147425.7666ec", - "type": "function", - "z": "bccd1f23.87219", - "name": "Encapsulate wb gain settings", - "func": "msg.payload = {\n \"action\":\"settings\", \n \"settings\":{\"white_balance_gain\":{\n [msg.topic]:Math.round(msg.payload*100)\n }\n }\n}\nmsg.topic = \"imager/image\"\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 1100, - "y": 1060, - "wires": [ - [ - "845e06e1.0d812" - ] - ] - }, - { - "id": "82722a3c.846b3", - "type": "inject", - "z": "bccd1f23.87219", - "name": "Default: OFF", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": "1", - "topic": "", - "payload": "false", - "payloadType": "bool", - "x": 110, - "y": 920, - "wires": [ - [ - "60e44330.50bdec" - ] - ] - }, - { - "id": "60e44330.50bdec", - "type": "ui_switch", - "z": "bccd1f23.87219", - "name": "AWB", - "label": "Auto White Balance", - "tooltip": "", - "group": "8c38a81e.9897a8", - "order": 5, - "width": 2, - "height": 2, - "passthru": true, - "decouple": "false", - "topic": "white_balance", - "topicType": "str", - "style": "", - "onvalue": "auto", - "onvalueType": "str", - "onicon": "", - "oncolor": "", - "offvalue": "off", - "offvalueType": "str", - "officon": "", - "offcolor": "", - "animate": true, - "className": "", - "x": 550, - "y": 920, - "wires": [ - [ - "8ea9dc9a.c7d87" - ] - ] - }, - { - "id": "6be64480.7e7e24", - "type": "change", - "z": "bccd1f23.87219", - "name": "Get red_gain", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.red_gain", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 370, - "y": 1040, - "wires": [ - [ - "d5415af6.e06cc" - ] - ] - }, - { - "id": "6d49d161.13628", - "type": "change", - "z": "bccd1f23.87219", - "name": "Get blue_gain", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.blue_gain", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 380, - "y": 1080, - "wires": [ - [ - "dba68c1f.e3144" - ] - ] - }, - { - "id": "56835fa1.2fe538", - "type": "subflow:4ed26b8b.253504", - "z": "bccd1f23.87219", - "name": "", - "env": [], - "x": 1160, - "y": 1020, - "wires": [] - }, - { - "id": "8ef294ba.12213", - "type": "change", - "z": "bccd1f23.87219", - "name": "Get analog_gain", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "1", - "tot": "num" - }, - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.analog_gain", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 380, - "y": 960, - "wires": [ - [ - "a6c7eec4.f7a918" - ] - ] - }, - { - "id": "8e336e58.14722", - "type": "change", - "z": "bccd1f23.87219", - "name": "Get digital_gain", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "1", - "tot": "num" - }, - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.digital_gain", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 380, - "y": 1000, - "wires": [ - [ - "66b37eef.f3f9e" - ] - ] - }, - { - "id": "a6c7eec4.f7a918", - "type": "ui_text_input", - "z": "bccd1f23.87219", - "d": true, - "name": "Analog gain field", - "label": "Analog Gain", - "tooltip": "From 1.0 to 12.0", - "group": "8c38a81e.9897a8", - "order": 2, - "width": 0, - "height": 0, - "passthru": true, - "mode": "number", - "delay": 300, - "topic": "analog", - "topicType": "str", - "x": 580, - "y": 960, - "wires": [ - [ - "44e02933.a66688", - "d361a2c4.0990f8" - ] - ] - }, - { - "id": "66b37eef.f3f9e", - "type": "ui_text_input", - "z": "bccd1f23.87219", - "d": true, - "name": "Digital gain field", - "label": "Digital Gain", - "tooltip": "From 1.0 to 64.0. Overexpose starting at 4.0", - "group": "8c38a81e.9897a8", - "order": 3, - "width": 0, - "height": 0, - "passthru": true, - "mode": "number", - "delay": 300, - "topic": "digital", - "topicType": "str", - "x": 580, - "y": 1000, - "wires": [ - [ - "44e02933.a66688", - "d361a2c4.0990f8" - ] - ] - }, - { - "id": "44e02933.a66688", - "type": "function", - "z": "bccd1f23.87219", - "name": "Encapsulate image gain settings", - "func": "msg.payload = {\n \"action\":\"settings\", \n \"settings\":{\"image_gain\":{\n [msg.topic]:Math.round(msg.payload*100)\n }\n }\n}\nmsg.topic = \"imager/image\"\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 1090, - "y": 980, - "wires": [ - [ - "845e06e1.0d812" - ] - ] - }, - { - "id": "d361a2c4.0990f8", - "type": "change", - "z": "bccd1f23.87219", - "name": "topic *_gain", - "rules": [ - { - "t": "set", - "p": "topic", - "pt": "msg", - "to": "topic&'_gain'", - "tot": "jsonata" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 970, - "y": 1020, - "wires": [ - [ - "56835fa1.2fe538" - ] - ] - }, - { - "id": "d8d006bf.2947f", - "type": "inject", - "z": "bccd1f23.87219", - "name": "Default: ISO 150", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": "1", - "topic": "", - "payload": "150", - "payloadType": "num", - "x": 130, - "y": 840, - "wires": [ - [ - "37f412d1454deb64" - ] - ] - }, - { - "id": "eb9966de.cf13c8", - "type": "change", - "z": "bccd1f23.87219", - "name": "", - "rules": [ - { - "t": "set", - "p": "topic", - "pt": "msg", - "to": "iso", - "tot": "str" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 740, - "y": 840, - "wires": [ - [ - "8ea9dc9a.c7d87" - ] - ] - }, - { - "id": "be33e564.029358", - "type": "ui_text_input", - "z": "bccd1f23.87219", - "name": "focus_distance", - "label": "Focus Distance (in µm)", - "tooltip": "in µm, 25µm resolution", - "group": "fbd92986.1028c8", - "order": 4, - "width": 0, - "height": 0, - "passthru": true, - "mode": "number", - "delay": 300, - "topic": "focus_distance", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 580, - "y": 460, - "wires": [ - [ - "dc48dc42.98d18" - ] - ] - }, - { - "id": "3a86de51.765b9a", - "type": "ui_text_input", - "z": "bccd1f23.87219", - "name": "focus_speed", - "label": "Focus Speed (in µm/sec)", - "tooltip": "in µm/sec", - "group": "fbd92986.1028c8", - "order": 5, - "width": 0, - "height": 0, - "passthru": true, - "mode": "number", - "delay": 300, - "topic": "focus_speed", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 570, - "y": 500, - "wires": [ - [ - "dc48dc42.98d18" - ] - ] - }, - { - "id": "cb2d5174.cfe9f", - "type": "ui_text_input", - "z": "bccd1f23.87219", - "name": "pump_flowrate", - "label": "Flowrate (ml/min)*", - "tooltip": "", - "group": "707d9797.c8e798", - "order": 1, - "width": 0, - "height": 0, - "passthru": true, - "mode": "text", - "delay": 300, - "topic": "pump_flowrate", - "topicType": "str", - "x": 580, - "y": 380, - "wires": [ - [ - "dc48dc42.98d18" - ] - ] - }, - { - "id": "d5415af6.e06cc", - "type": "ui_text_input", - "z": "bccd1f23.87219", - "name": "WB Red input", - "label": "WB: Red", - "tooltip": "From 0.0 to 32.0", - "group": "8c38a81e.9897a8", - "order": 6, - "width": 4, - "height": 1, - "passthru": true, - "mode": "number", - "delay": "0", - "topic": "red", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 580, - "y": 1040, - "wires": [ - [ - "f7a7398fd6ce4a4f" - ] - ] - }, - { - "id": "dba68c1f.e3144", - "type": "ui_text_input", - "z": "bccd1f23.87219", - "name": "WB Blue input", - "label": "WB: Blue", - "tooltip": "From 0.0 to 64.0", - "group": "8c38a81e.9897a8", - "order": 7, - "width": 4, - "height": 1, - "passthru": true, - "mode": "number", - "delay": "0", - "topic": "blue", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 580, - "y": 1080, - "wires": [ - [ - "df8a7667c9d133b1" - ] - ] - }, - { - "id": "d91550e8b15ed3b8", - "type": "subflow:e6665421f66ea4c8", - "z": "bccd1f23.87219", - "name": "", - "x": 160, - "y": 1020, - "wires": [ - [ - "8ef294ba.12213", - "8e336e58.14722", - "6be64480.7e7e24", - "6d49d161.13628" - ] - ] - }, - { - "id": "04920f50bbbf6a2a", - "type": "link in", - "z": "bccd1f23.87219", - "name": "Load hardware config", - "links": [ - "e4ead350b3d07578", - "4a1f303f0b6f7f42" - ], - "x": 25, - "y": 1000, - "wires": [ - [ - "d91550e8b15ed3b8" - ] - ] - }, - { - "id": "7386eaf7ca9d8bfa", - "type": "inject", - "z": "bccd1f23.87219", - "name": "Once", - "props": [], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "", - "x": 50, - "y": 1080, - "wires": [ - [ - "d91550e8b15ed3b8" - ] - ] - }, - { - "id": "f7a7398fd6ce4a4f", - "type": "switch", - "z": "bccd1f23.87219", - "name": "Validate", - "property": "payload", - "propertyType": "msg", - "rules": [ - { - "t": "btwn", - "v": "0.0", - "vt": "num", - "v2": "32.0", - "v2t": "num" - }, - { - "t": "else" - } - ], - "checkall": "false", - "repair": false, - "outputs": 2, - "x": 740, - "y": 1040, - "wires": [ - [ - "d361a2c4.0990f8", - "5e147425.7666ec" - ], - [ - "64b05eea4c5469be", - "4a1f303f0b6f7f42" - ] - ] - }, - { - "id": "df8a7667c9d133b1", - "type": "switch", - "z": "bccd1f23.87219", - "name": "Validate", - "property": "payload", - "propertyType": "msg", - "rules": [ - { - "t": "btwn", - "v": "0.0", - "vt": "num", - "v2": "32.0", - "v2t": "num" - }, - { - "t": "else" - } - ], - "checkall": "false", - "repair": false, - "outputs": 2, - "x": 740, - "y": 1080, - "wires": [ - [ - "d361a2c4.0990f8", - "5e147425.7666ec" - ], - [ - "64b05eea4c5469be", - "4a1f303f0b6f7f42" - ] - ] - }, - { - "id": "64b05eea4c5469be", - "type": "ui_toast", - "z": "bccd1f23.87219", - "position": "top right", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 0, - "ok": "OK", - "cancel": "", - "raw": false, - "className": "", - "topic": "Invalid white balance value", - "name": "", - "x": 990, - "y": 1100, - "wires": [] - }, - { - "id": "4a1f303f0b6f7f42", - "type": "link out", - "z": "bccd1f23.87219", - "name": "Reload hardware config", - "mode": "link", - "links": [ - "04920f50bbbf6a2a" - ], - "x": 915, - "y": 1140, - "wires": [] - }, - { - "id": "37f412d1454deb64", - "type": "ui_slider", - "z": "bccd1f23.87219", - "name": "ISO selector", - "label": "ISO", - "tooltip": "", - "group": "8c38a81e.9897a8", - "order": 1, - "width": 0, - "height": 0, - "passthru": true, - "outs": "end", - "topic": "topic", - "topicType": "msg", - "min": "50", - "max": "800", - "step": "50", - "className": "", - "x": 570, - "y": 840, - "wires": [ - [ - "eb9966de.cf13c8" - ] - ] - }, - { - "id": "f59a2f0d.5e9af", - "type": "ui_numeric", - "z": "baa1e3d9.cb29d", - "name": "acq_minimum_mesh", - "label": "Min fraction size (μm)", - "tooltip": "", - "group": "404c301a.19c4e", - "order": 1, - "width": 5, - "height": 1, - "wrap": false, - "passthru": true, - "topic": "acq_minimum_mesh", - "format": "{{value}}", - "min": 0, - "max": "300", - "step": "10", - "x": 640, - "y": 160, - "wires": [ - [ - "fb887036.12429" - ] - ] - }, - { - "id": "6008a8bb.259f08", - "type": "ui_numeric", - "z": "baa1e3d9.cb29d", - "name": "acq_maximum_mesh", - "label": "Max fraction size (μm)", - "tooltip": "", - "group": "404c301a.19c4e", - "order": 2, - "width": 5, - "height": 1, - "wrap": false, - "passthru": true, - "topic": "acq_maximum_mesh", - "format": "{{value}}", - "min": "200", - "max": "2000", - "step": "100", - "x": 640, - "y": 200, - "wires": [ - [ - "fb887036.12429" - ] - ] - }, - { - "id": "6b34c456.83178c", - "type": "ui_text_input", - "z": "baa1e3d9.cb29d", - "name": "acq_id", - "label": "Acquisition unique ID*", - "tooltip": "", - "group": "4322c187.e73e5", - "order": 1, - "width": 5, - "height": 1, - "passthru": true, - "mode": "text", - "delay": 300, - "topic": "acq_id", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 690, - "y": 240, - "wires": [ - [ - "fb887036.12429" - ] - ] - }, - { - "id": "cc0ca68b.4263a8", - "type": "ui_dropdown", - "z": "baa1e3d9.cb29d", - "name": "acq_celltype", - "label": "Flowcell thickness*", - "tooltip": "", - "place": "Select option", - "group": "4322c187.e73e5", - "order": 6, - "width": 5, - "height": 1, - "passthru": true, - "multiple": false, - "options": [ - { - "label": "200 μm µ-Slide I Luer", - "value": 200, - "type": "num" - }, - { - "label": "300 µm capillary", - "value": 300, - "type": "num" - }, - { - "label": "400 μm µ-Slide I Luer", - "value": 400, - "type": "num" - }, - { - "label": "600 μm µ-Slide I Luer", - "value": 600, - "type": "num" - }, - { - "label": "800 μm µ-Slide I Luer", - "value": 800, - "type": "num" - } - ], - "payload": "", - "topic": "acq_celltype", - "topicType": "str", - "className": "", - "x": 670, - "y": 80, - "wires": [ - [ - "fb887036.12429", - "99b11fe4.2795d" - ] - ] - }, - { - "id": "fb887036.12429", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "set global", - "func": "global.set(msg.topic, msg.payload);\nreturn msg", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 920, - "y": 220, - "wires": [ - [ - "52ea7d01.711034" - ] - ] - }, - { - "id": "bb2bb7ce.1d1458", - "type": "ui_template", - "z": "baa1e3d9.cb29d", - "group": "858a0e3c.987fe", - "name": "Stream Pi Camera", - "order": 1, - "width": 10, - "height": 8, - "format": "
\n \"If\n
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "className": "", - "x": 650, - "y": 20, - "wires": [ - [] - ] - }, - { - "id": "d0c5b57d.590818", - "type": "ui_ui_control", - "z": "baa1e3d9.cb29d", - "name": "", - "events": "change", - "x": 1280, - "y": 660, - "wires": [ - [] - ] - }, - { - "id": "c72f8fae.23bd4", - "type": "ui_button", - "z": "baa1e3d9.cb29d", - "name": "", - "group": "b7919ae2.c01788", - "order": 1, - "width": 5, - "height": 1, - "passthru": false, - "label": "Previous", - "tooltip": "", - "color": "#097479", - "bgcolor": "white", - "icon": "keyboard_return", - "payload": "{\"tab\":\"Optic Configuration\"}", - "payloadType": "json", - "topic": "", - "x": 1140, - "y": 660, - "wires": [ - [ - "d0c5b57d.590818" - ] - ] - }, - { - "id": "29be525e.0c87fe", - "type": "ui_template", - "z": "baa1e3d9.cb29d", - "group": "b5d61bc7.54fe48", - "name": "Show Metadata", - "order": 9, - "width": 0, - "height": 0, - "format": "
\n \n \n \n \n \n \n \n \n \n
\n

Sample

\n

id:

\n

project:\n

\n

ship:

\n

operator:\n

\n

sampling gear:\n

\n

concentrated volume:\n

\n

gear net opening:\n

\n

total volume filtered:\n

\n
\n

Acquisition

\n

id:

\n

instrument:\n

\n

instrument id:\n

\n

camera:

\n

celltype: \n

\n

minimum mesh:\n

\n

maximum mesh:\n

\n

min esd: \n

\n

max esd: \n

\n

volume:

\n

magnification:\n

\n

fnumber objective:\n

\n

software: \n

\n
\n

Object

\n

latitude: \n

\n

longitude: \n

\n

latitude end:\n

\n

longitude end:\n

\n

date:

\n

time:

\n

date end:\n

\n

time end:\n

\n

depth min:\n

\n

depth max:\n

\n
\n

Process

\n

pixel: \n

\n

id:

\n
\n
", - "storeOutMessages": false, - "fwdInMessages": false, - "resendOnRefresh": false, - "templateScope": "local", - "className": "", - "x": 1180, - "y": 380, - "wires": [ - [] - ] - }, - { - "id": "c9f510c0.7d1328", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "Image control", - "func": "// Reset the number of images taken\nflow.set('img_counter', 0);\n\nvar acq_celltype = global.get(\"acq_celltype\");\nvar acq_minimum_mesh = global.get(\"acq_minimum_mesh\");\nvar acq_maximum_mesh = global.get(\"acq_maximum_mesh\");\nvar imaging_pump_volume = global.get(\"imaging_pump_volume\");\nvar acq_id = global.get(\"acq_id\");\nvar nb_frame = global.get(\"nb_frame\");\nvar pump_direction = global.get(\"pump_direction\");\nvar sleep_before = global.get(\"sleep_before\");\nvar object_date = global.get(\"object_date\");\n\nif (acq_celltype === undefined || acq_celltype === \"\") {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Type of the flowcell\";\n return [null, msg];\n} else if (acq_minimum_mesh === undefined || acq_minimum_mesh === \"\") {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Lower fraction size\";\n return [null, msg];\n} else if (acq_maximum_mesh === undefined || acq_maximum_mesh === \"\") {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Upper fraction size\";\n return [null, msg];\n} else if (imaging_pump_volume === undefined || imaging_pump_volume === \"\" || imaging_pump_volume === null) {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Volume inbetween images\";\n return [null, msg];\n} else if (acq_id === undefined || acq_id === \"\") {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Acquisition ID\";\n return [null, msg];\n} else if (nb_frame === undefined || nb_frame === \"\" || nb_frame === null) {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Number of image to save\";\n return [null, msg];\n} else if (pump_direction === undefined || pump_direction === \"\" || pump_direction === null) {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Pump direction\";\n return [null, msg];\n} else if (sleep_before === undefined || sleep_before === \"\" || sleep_before === null) {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Delay before image\";\n return [null, msg];\n}else if (object_date === undefined || object_date === \"\" || object_date === null) {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Object date\";\n return [null, msg];\n}\n\nmsg.payload = {\n \"action\": \"image\",\n \"sleep\": sleep_before,\n \"pump_direction\": pump_direction,\n \"volume\": imaging_pump_volume,\n \"nb_frame\": nb_frame,\n}\nmsg.send = true\n\nreturn [msg, null];", - "outputs": 2, - "timeout": "", - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 680, - "y": 480, - "wires": [ - [ - "52ea7d01.711034", - "40c12463.a1f84c", - "a4abb1ae.2ae418" - ], - [ - "20e0a8c8.edbeb" - ] - ] - }, - { - "id": "20e0a8c8.edbeb", - "type": "ui_toast", - "z": "baa1e3d9.cb29d", - "position": "dialog", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 1, - "ok": "OK", - "cancel": "", - "raw": false, - "className": "", - "topic": "", - "name": "", - "x": 950, - "y": 560, - "wires": [ - [] - ] - }, - { - "id": "c3e50240.82aa58", - "type": "mqtt out", - "z": "baa1e3d9.cb29d", - "name": "", - "topic": "", - "qos": "", - "retain": "", - "respTopic": "", - "contentType": "", - "userProps": "", - "correl": "", - "expiry": "", - "broker": "8dc3722c.06efa8", - "x": 1150, - "y": 440, - "wires": [] - }, - { - "id": "3a4450b1.4459a8", - "type": "ui_button", - "z": "baa1e3d9.cb29d", - "name": "Stop Acquisition", - "group": "4322c187.e73e5", - "order": 11, - "width": 5, - "height": 1, - "passthru": true, - "label": "STOP ACQUISITION", - "tooltip": "", - "color": "", - "bgcolor": "#AD1625", - "className": "", - "icon": "cancel", - "payload": "{\"action\":\"stop\"}", - "payloadType": "json", - "topic": "imager/image", - "topicType": "str", - "x": 460, - "y": 520, - "wires": [ - [ - "d74210ef.edc15" - ] - ] - }, - { - "id": "d74210ef.edc15", - "type": "mqtt out", - "z": "baa1e3d9.cb29d", - "name": "", - "topic": "", - "qos": "", - "retain": "", - "broker": "8dc3722c.06efa8", - "x": 650, - "y": 520, - "wires": [] - }, - { - "id": "bb62da8a.ebc328", - "type": "ui_switch", - "z": "baa1e3d9.cb29d", - "name": "Pump direction", - "label": "Pump direction", - "tooltip": "BACKWARD / FORWARD", - "group": "4322c187.e73e5", - "order": 9, - "width": 5, - "height": 1, - "passthru": true, - "decouple": "false", - "topic": "pump_direction", - "style": "", - "onvalue": "FORWARD", - "onvalueType": "str", - "onicon": "", - "oncolor": "", - "offvalue": "BACKWARD", - "offvalueType": "str", - "officon": "", - "offcolor": "", - "x": 460, - "y": 560, - "wires": [ - [ - "6b2239f3.41fa3" - ] - ] - }, - { - "id": "52ea7d01.711034", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "Encapsulate config", - "func": "msg.payload = {\n\t\"action\": \"update_config\",\n\t\"config\": {\n \t\"description\": {\n \t\t\"sample_project\": \"Project's name\",\n \t\t\"sample_id\": \"Sample ID\",\n \t\t\"sample_uuid\": \"Sample UUID (Autogenerated)\",\n \t\t\"sample_ship\": \"Ship's name\",\n \t\t\"sample_operator\": \"Operator's name\",\n \t\t\"sample_sampling_gear\": \"Sampling gear used\",\n \t\t\"sample_concentrated_sample_volume\": \"Volume of concentrated sample, in mL\",\n \t\t\"sample_total_volume\": \"Total volume filtered by the net used, in L\",\n \t\t\"sample_dilution_factor\": \"Dilution factor of the sample, 0.5 if diluted by 2, 2 if concentrated by 2\",\n \t\t\"sample_speed_through_water\": \"Speed of the boat through water when sampling, in kts\",\n \t\t\"acq_id\": \"Acquisition ID\",\n \t\t\"acq_uuid\": \"Acquisition UUID (Autogenerated)\",\n \t\t\"acq_instrument\": \"Instrument type\",\n \t\t\"acq_instrument_id\": \"Instrument ID\",\n \t\t\"acq_celltype\": \"Flow cell dimension thickness, in µm\",\n \t\t\"acq_minimum_mesh\": \"Minimum filtration mesh size, in µm\",\n \t\t\"acq_maximum_mesh\": \"Maximum filtration mesh size, in µm\",\n \t\t\"acq_min_esd\": \"\",\n \t\t\"acq_max_esd\": \"\",\n \t\t\"acq_volume\": \"Pumped volume, in mL\",\n\t\t \"acq_imaged_volume\": \"Total imaged volume, in mL\",\n \t\t\"acq_magnification\": \"Optical magnification\",\n \t\t\"acq_fnumber_objective\": \"Focal length of the objective, in mm\",\n \t\t\"acq_camera_name\": \"Name of the camera used\",\n \t\t\"acq_nb_frame\": \"Number of picture taken\",\n \"acq_local_datetime\": \"Instrument local datetime\",\n \"acq_camera_resolution\": \"Resolution of the images\",\n \"acq_camera_iso\": \"ISO Number of the images\",\n \"acq_camera_shutter_speed\": \"Shutter speed of the images, in µs\",\n \"acq_software\": \"Software version number\",\n \t\t\"object_date\": \"Sample collection date (or beginning if using a net)\",\n \t\t\"object_time\": \"Sample collection time (or beginning if using a net)\",\n \t\t\"object_lat\": \"Sample collection latitude (or beginning if using a net)\",\n \t\t\"object_lon\": \"Sample collection longitude (or beginning if using a net)\",\n \t\t\"object_depth_min\": \"Sample collection minimal depth, in m\",\n \t\t\"object_depth_max\": \"Sample collection maximum depth, in m\",\n \t\t\"process_pixel\": \"Pixel imaging resolution, in µm/pixel\",\n \t\t\"process_datetime\": \"Segmentation timestamp\",\n \t\t\"process_id\": \"Segmentation ID\",\n \t\t\"process_uuid\": \"Segmentation UUID (Autogenerated)\",\n \t\t\"process_source\": \"Code source link of the executed code\",\n \t\t\"process_commit\": \"Version reference of the executed code\",\n \t\t\"sample_gear_net_opening\": \"Sample mouth opening dimension, in mm\",\n \t\t\"object_date_end\": \"Sample end collection date when using a net\",\n \t\t\"object_time_end\": \"Sample end collection time when using a net\",\n \t\t\"object_lat_end\": \"Sample end collection latitude when using a net\",\n \t\t\"object_lon_end\": \"Sample end collection longitude when using a net\",\n \t},\n\t\t\"sample_project\": global.get(\"sample_project\"),\n\t\t\"sample_id\": global.get(\"sample_project\") + \"_\" + global.get(\"sample_id\"),\n\t\t\"sample_ship\": global.get(\"sample_ship\"),\n\t\t\"sample_operator\": global.get(\"sample_operator\"),\n\t\t\"sample_sampling_gear\": global.get(\"sample_sampling_gear\"),\n\t\t\"sample_concentrated_sample_volume\": global.get(\"sample_concentrated_sample_volume\"),\n\t\t\"sample_total_volume\": global.get(\"sample_total_volume\"),\n\t\t\"sample_dilution_factor\": global.get(\"sample_dilution_factor\"),\n\t\t\"sample_speed_through_water\": global.get(\"sample_speed_through_water\"),\n\n\t\t\"acq_id\": global.get(\"sample_project\") + \"_\" + global.get(\"sample_id\")+ \"_\" + global.get(\"acq_id\"),\n\t\t\"acq_instrument\": global.get(\"acq_instrument\"),\n\t\t\"acq_instrument_id\": global.get(\"acq_instrument_id\"),\n\t\t\"acq_celltype\": global.get(\"acq_celltype\"),\n\t\t\"acq_minimum_mesh\": global.get(\"acq_minimum_mesh\"),\n\t\t\"acq_maximum_mesh\": global.get(\"acq_maximum_mesh\"),\n\t\t\"acq_min_esd\": global.get(\"acq_min_esd\"),\n\t\t\"acq_max_esd\": global.get(\"acq_max_esd\"),\n\t\t\"acq_volume\": global.get(\"acq_volume\"),\n\t\t\"acq_imaged_volume\": global.get(\"acq_imaged_volume\"),\n\t\t\"acq_magnification\": global.get(\"acq_magnification\"),\n\t\t\"acq_fnumber_objective\": global.get(\"acq_fnumber_objective\"),\n\t\t\"acq_camera\": global.get(\"acq_camera\"),\n\t\t\"acq_nb_frame\": global.get(\"nb_frame\"),\n\t\t\"acq_software\": global.get(\"acq_software\"),\n\n\t\t\"object_date\": global.get(\"object_date\"),\n\t\t\"object_time\": global.get(\"object_time\"),\n\t\t\"object_lat\": global.get(\"object_lat\"),\n\t\t\"object_lon\": global.get(\"object_lon\"),\n\t\t\"object_depth_min\": global.get(\"object_depth_min\"),\n\t\t\"object_depth_max\": global.get(\"object_depth_max\"),\n\n\t\t\"process_pixel\": global.get(\"process_pixel\"),\n\t\t\"process_source\": global.get(\"process_source\"),\n\t\t\"process_commit\": global.get(\"process_commit\")\n\t}\n};\n\nif (msg.payload.config.sample_sampling_gear.startsWith(\"net\")) {\n\tmsg.payload.config[\"sample_gear_net_opening\"] = global.get(\"sample_gear_net_opening\")\n\tmsg.payload.config[\"object_date_end\"] = global.get(\"object_date_end\")\n\tmsg.payload.config[\"object_time_end\"] = global.get(\"object_time_end\")\n\tmsg.payload.config[\"object_lat_end\"] = global.get(\"object_lat_end\")\n\tmsg.payload.config[\"object_lon_end\"] = global.get(\"object_lon_end\")\n}\n\nif ( msg.send == true){\n\treturn [msg, msg]\n}\nelse{\n\treturn [msg, null]\n}", - "outputs": 2, - "timeout": "", - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 910, - "y": 440, - "wires": [ - [ - "29be525e.0c87fe" - ], - [ - "c3e50240.82aa58" - ] - ] - }, - { - "id": "40c12463.a1f84c", - "type": "delay", - "z": "baa1e3d9.cb29d", - "name": "", - "pauseType": "delay", - "timeout": "1", - "timeoutUnits": "seconds", - "rate": "1", - "nbRateUnits": "1", - "rateUnits": "second", - "randomFirst": "1", - "randomLast": "5", - "randomUnits": "seconds", - "drop": false, - "outputs": 1, - "x": 940, - "y": 480, - "wires": [ - [ - "c3e50240.82aa58" - ] - ] - }, - { - "id": "4d1b02cb.83b51c", - "type": "ui_button", - "z": "baa1e3d9.cb29d", - "name": "", - "group": "4322c187.e73e5", - "order": 10, - "width": 5, - "height": 1, - "passthru": false, - "label": "Update config", - "tooltip": "", - "color": "", - "bgcolor": "", - "className": "", - "icon": "save", - "payload": "", - "payloadType": "str", - "topic": "imager/image", - "topicType": "str", - "x": 680, - "y": 440, - "wires": [ - [ - "52ea7d01.711034" - ] - ] - }, - { - "id": "5921d0d0.a3d568", - "type": "subflow:1c24ad9c.bebec2", - "z": "baa1e3d9.cb29d", - "name": "", - "env": [], - "x": 110, - "y": 220, - "wires": [ - [ - "f3658d30.b8448", - "de2c90cf.b73b08", - "4be09c97f86897d9", - "f573206abefa9518", - "f948151ab4031df4", - "5e3dec55.881074", - "d3ca8847.4d1ae" - ] - ] - }, - { - "id": "f3658d30.b8448", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "get acq_id", - "func": "msg.payload = msg.payload.acq_id;\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 330, - "y": 240, - "wires": [ - [ - "6b34c456.83178c" - ] - ] - }, - { - "id": "de2c90cf.b73b08", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "get acq_celltype", - "func": "msg.topic = 'acq_celltype';\nmsg.payload = msg.payload.acq_celltype;\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 340, - "y": 80, - "wires": [ - [ - "cc0ca68b.4263a8" - ] - ] - }, - { - "id": "5e3dec55.881074", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "get acq_minimum_mesh", - "func": "msg.payload = msg.payload.acq_minimum_mesh;\nreturn msg;", - "outputs": 1, - "noerr": 0, - "x": 370, - "y": 160, - "wires": [ - [ - "f59a2f0d.5e9af" - ] - ] - }, - { - "id": "d3ca8847.4d1ae", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "get acq_maximum_mesh", - "func": "msg.payload = msg.payload.acq_maximum_mesh;\nreturn msg;", - "outputs": 1, - "noerr": 0, - "x": 370, - "y": 200, - "wires": [ - [ - "6008a8bb.259f08" - ] - ] - }, - { - "id": "b402f719.55bc98", - "type": "inject", - "z": "baa1e3d9.cb29d", - "name": "Default: FORWARD", - "props": [ - { - "p": "payload" - }, - { - "p": "topic", - "vt": "str" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "pump_direction", - "payload": "FORWARD", - "payloadType": "str", - "x": 220, - "y": 560, - "wires": [ - [ - "bb62da8a.ebc328" - ] - ] - }, - { - "id": "6b2239f3.41fa3", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "set global", - "func": "global.set(msg.topic, msg.payload);", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 660, - "y": 560, - "wires": [ - [] - ] - }, - { - "id": "51b4d0df.d70a88", - "type": "ui_text_input", - "z": "baa1e3d9.cb29d", - "name": "nb_frame", - "label": "Number of images to acquire", - "tooltip": "", - "group": "4322c187.e73e5", - "order": 2, - "width": 5, - "height": 1, - "passthru": true, - "mode": "number", - "delay": 300, - "topic": "nb_frame", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 680, - "y": 280, - "wires": [ - [ - "fb887036.12429", - "67091ac0.8f9f6c", - "99b11fe4.2795d" - ] - ] - }, - { - "id": "999065ca.27edb8", - "type": "switch", - "z": "baa1e3d9.cb29d", - "name": "topic filter", - "property": "topic", - "propertyType": "msg", - "rules": [ - { - "t": "eq", - "v": "status/pump", - "vt": "str" - }, - { - "t": "eq", - "v": "status/focus", - "vt": "str" - }, - { - "t": "eq", - "v": "status/imager", - "vt": "str" - } - ], - "checkall": "true", - "repair": false, - "outputs": 3, - "x": 320, - "y": 800, - "wires": [ - [ - "a46a1e7f.88a92", - "6742014e.1bb238" - ], - [ - "c516d9ea.f7f6e", - "6742014e.1bb238" - ], - [ - "307c851e.fb0f7a", - "2b9d6988.d84836" - ] - ] - }, - { - "id": "2b009bd7.c07004", - "type": "ui_text", - "z": "baa1e3d9.cb29d", - "group": "70de8209.68416c", - "order": 3, - "width": 10, - "height": 2, - "name": "imager", - "label": "Imager status:", - "format": "{{msg.payload.status}}", - "layout": "col-center", - "x": 770, - "y": 740, - "wires": [] - }, - { - "id": "c516d9ea.f7f6e", - "type": "ui_text", - "z": "baa1e3d9.cb29d", - "group": "70de8209.68416c", - "order": 1, - "width": 5, - "height": 1, - "name": "focus", - "label": "Focus status:", - "format": "{{msg.payload.status}}", - "layout": "col-center", - "x": 770, - "y": 700, - "wires": [] - }, - { - "id": "a46a1e7f.88a92", - "type": "ui_text", - "z": "baa1e3d9.cb29d", - "group": "70de8209.68416c", - "order": 2, - "width": 5, - "height": 1, - "name": "pump", - "label": "Pump status:", - "format": "{{msg.payload.status}}", - "layout": "col-center", - "x": 770, - "y": 660, - "wires": [] - }, - { - "id": "bb628f8d.98f108", - "type": "link in", - "z": "baa1e3d9.cb29d", - "name": "Status for fluidic module", - "links": [ - "58f2e0f.4e8b12" - ], - "x": 175, - "y": 800, - "wires": [ - [ - "999065ca.27edb8" - ] - ] - }, - { - "id": "307c851e.fb0f7a", - "type": "switch", - "z": "baa1e3d9.cb29d", - "name": "Imaging state", - "property": "payload", - "propertyType": "msg", - "rules": [ - { - "t": "jsonata_exp", - "v": "$contains(msg.payload.status, \"jpg\")\t", - "vt": "jsonata" - }, - { - "t": "else" - } - ], - "checkall": "false", - "repair": false, - "outputs": 2, - "x": 540, - "y": 880, - "wires": [ - [ - "db8e3dde.44efb8" - ], - [ - "6742014e.1bb238" - ] - ] - }, - { - "id": "db8e3dde.44efb8", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "img_counter", - "func": "img_counter=flow.get('img_counter')\nif (img_counter === undefined || img_counter === \"\"){\n img_counter = 0\n}\nimg_counter=img_counter+1\nflow.set('img_counter',img_counter)\nmsg.payload = img_counter\nmsg.payload = (100 * img_counter/global.get('nb_frame')).toFixed(2)\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 770, - "y": 860, - "wires": [ - [ - "1a2e721a.f5e876" - ] - ] - }, - { - "id": "59164d65.e7993c", - "type": "ui_toast", - "z": "baa1e3d9.cb29d", - "position": "top right", - "displayTime": "5", - "highlight": "", - "sendall": true, - "outputs": 0, - "ok": "OK", - "cancel": "", - "raw": false, - "topic": "", - "name": "", - "x": 1260, - "y": 900, - "wires": [] - }, - { - "id": "8c7348aa.1962e8", - "type": "template", - "z": "baa1e3d9.cb29d", - "name": "Create sentence", - "field": "payload", - "fieldType": "msg", - "format": "handlebars", - "syntax": "mustache", - "template": "The {{topic}} is {{payload.status}}", - "output": "str", - "x": 1050, - "y": 900, - "wires": [ - [ - "59164d65.e7993c" - ] - ] - }, - { - "id": "6742014e.1bb238", - "type": "change", - "z": "baa1e3d9.cb29d", - "name": "Remove high-level topic", - "rules": [ - { - "t": "change", - "p": "topic", - "pt": "msg", - "from": "status/", - "fromt": "str", - "to": "", - "tot": "str" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 810, - "y": 900, - "wires": [ - [ - "8c7348aa.1962e8" - ] - ] - }, - { - "id": "1a2e721a.f5e876", - "type": "ui_gauge", - "z": "baa1e3d9.cb29d", - "name": "progress donut", - "group": "b5d61bc7.54fe48", - "order": 3, - "width": 6, - "height": 3, - "gtype": "donut", - "title": "", - "label": "%", - "format": "{{value}}", - "min": 0, - "max": "100", - "colors": [ - "#ffa83f", - "#e6ff02", - "#00dfe9" - ], - "seg1": "50", - "seg2": "75", - "x": 1260, - "y": 860, - "wires": [] - }, - { - "id": "9bd72495.a8a098", - "type": "ui_text", - "z": "baa1e3d9.cb29d", - "group": "4322c187.e73e5", - "order": 5, - "width": 5, - "height": 1, - "name": "Total imaged volume", - "label": "Total imaged volume", - "format": "{{msg.payload}}", - "layout": "col-center", - "x": 1200, - "y": 140, - "wires": [] - }, - { - "id": "99b11fe4.2795d", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "imaged volume calc", - "func": "camera = global.get(\"acq_camera\");\ncell = global.get(\"acq_celltype\");\nnb_frame = global.get(\"nb_frame\");\nprocess_pixel = global.get(\"process_pixel\");\n\nvar volume = 0\nif (camera == \"HQ Camera\"){\n volume = nb_frame * (process_pixel*4056*process_pixel*3040*cell/1000000000) / 1000;\n}\nelse if (camera == \"Camera v2.1\"){\n volume = nb_frame * (process_pixel*3280*process_pixel*2464*cell/1000000000) / 1000;\n}\nelse{\n msg.payload = \"The camera is not known to this system\";\n return msg;\n}\n\nglobal.set(\"acq_imaged_volume\", volume.toFixed(4))\n\nmsg.payload = volume.toFixed(2) + \" mL\"\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 960, - "y": 140, - "wires": [ - [ - "9bd72495.a8a098" - ] - ], - "info": "### Focusing\n##### focus.py `nb_step` `orientation`\n\n- `nb_step` : **integer** (from 1 to 100000) - number of step to perform by the stage (about 31um/step)\n- `orientation` : **string** - orientation of the focus either `up` or `down`\n\nExample:\n\n python3.7 $HOME/PlanktoScope/scripts/focus.py 650 up\n" - }, - { - "id": "8e16aa2f.e40398", - "type": "ui_text", - "z": "baa1e3d9.cb29d", - "group": "4322c187.e73e5", - "order": 7, - "width": 5, - "height": 1, - "name": "Total pumped volume", - "label": "Total pumped volume", - "format": "{{msg.payload}} mL", - "layout": "col-center", - "x": 1200, - "y": 300, - "wires": [] - }, - { - "id": "67091ac0.8f9f6c", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "acq_volume calc", - "func": "var imaging_pump_volume = global.get(\"imaging_pump_volume\");\nvar nb_frame = global.get(\"nb_frame\");\nvar acq_volume = 0\n\nacq_volume = (Number(nb_frame)*Number(imaging_pump_volume)).toFixed(2)\nglobal.set(\"acq_volume\", acq_volume)\n\nmsg.payload = acq_volume\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 950, - "y": 300, - "wires": [ - [ - "8e16aa2f.e40398" - ] - ], - "info": "### Focusing\n##### focus.py `nb_step` `orientation`\n\n- `nb_step` : **integer** (from 1 to 100000) - number of step to perform by the stage (about 31um/step)\n- `orientation` : **string** - orientation of the focus either `up` or `down`\n\nExample:\n\n python3.7 $HOME/PlanktoScope/scripts/focus.py 650 up\n" - }, - { - "id": "2b9d6988.d84836", - "type": "switch", - "z": "baa1e3d9.cb29d", - "name": "", - "property": "payload", - "propertyType": "msg", - "rules": [ - { - "t": "hask", - "v": "status", - "vt": "str" - }, - { - "t": "hask", - "v": "camera_name", - "vt": "str" - } - ], - "checkall": "true", - "repair": false, - "outputs": 2, - "x": 650, - "y": 760, - "wires": [ - [ - "2b009bd7.c07004" - ], - [ - "3bbb756a.84190a" - ] - ] - }, - { - "id": "3bbb756a.84190a", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "set camera name", - "func": "global.set(\"acq_camera\", msg.payload.camera_name);\n\nmsg.payload = msg.payload.camera_name;\n\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 810, - "y": 780, - "wires": [ - [ - "559a8085.1d6b9" - ] - ] - }, - { - "id": "559a8085.1d6b9", - "type": "link out", - "z": "baa1e3d9.cb29d", - "name": "Camera Name", - "links": [ - "30067f35.532f2", - "572a6daa.6004c4" - ], - "x": 965, - "y": 780, - "wires": [] - }, - { - "id": "49ea1123.ee1768", - "type": "ui_numeric", - "z": "baa1e3d9.cb29d", - "name": "sleep_before", - "label": "Delay to stabilize image (s)", - "tooltip": "Happens before every capture", - "group": "4322c187.e73e5", - "order": 4, - "width": 5, - "height": 1, - "wrap": false, - "passthru": true, - "topic": "sleep_before", - "topicType": "str", - "format": "{{value}}", - "min": "0.1", - "max": "5", - "step": "0.1", - "className": "", - "x": 670, - "y": 120, - "wires": [ - [ - "fb887036.12429" - ] - ] - }, - { - "id": "572a6daa.6004c4", - "type": "link in", - "z": "baa1e3d9.cb29d", - "name": "", - "links": [ - "559a8085.1d6b9" - ], - "x": 795, - "y": 140, - "wires": [ - [ - "99b11fe4.2795d" - ] - ] - }, - { - "id": "8032ea50.1b57f", - "type": "ui_template", - "z": "baa1e3d9.cb29d", - "group": "b5d61bc7.54fe48", - "name": "progress header", - "order": 1, - "width": 0, - "height": 0, - "format": "

Capture progress

", - "storeOutMessages": false, - "fwdInMessages": false, - "resendOnRefresh": false, - "templateScope": "local", - "x": 1260, - "y": 820, - "wires": [ - [] - ] - }, - { - "id": "a4abb1ae.2ae418", - "type": "subflow:1c24ad9c.bebec2", - "z": "baa1e3d9.cb29d", - "name": "", - "env": [], - "x": 930, - "y": 520, - "wires": [ - [] - ] - }, - { - "id": "4be09c97f86897d9", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "get nb_frame", - "func": "msg.payload = msg.payload.nb_frame;\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 330, - "y": 280, - "wires": [ - [ - "51b4d0df.d70a88" - ] - ] - }, - { - "id": "f573206abefa9518", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "get imaging_pump_volume", - "func": "msg.payload = msg.payload.imaging_pump_volume;\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 380, - "y": 320, - "wires": [ - [ - "e1acc6c599033114" - ] - ] - }, - { - "id": "f948151ab4031df4", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "get sleep_before", - "func": "msg.payload = msg.payload.sleep_before;\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 340, - "y": 120, - "wires": [ - [ - "49ea1123.ee1768" - ] - ] - }, - { - "id": "ad153212312f0347", - "type": "ui_ui_control", - "z": "baa1e3d9.cb29d", - "name": "onTab", - "events": "all", - "x": 330, - "y": 380, - "wires": [ - [ - "9b69ea945b587192" - ] - ] - }, - { - "id": "9b69ea945b587192", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "check tab", - "func": "if (msg.name == \"Fluidic Acquisition\"){\n return { \"topic\": \"imager/ image\" }\n}", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 480, - "y": 380, - "wires": [ - [ - "52ea7d01.711034" - ] - ], - "outputLabels": [ - "interface" - ] - }, - { - "id": "e1acc6c599033114", - "type": "ui_text_input", - "z": "baa1e3d9.cb29d", - "name": "imaging_pump_volume", - "label": "Pumped volume (mL)", - "tooltip": "between frames", - "group": "4322c187.e73e5", - "order": 3, - "width": 0, - "height": 0, - "passthru": true, - "mode": "text", - "delay": 300, - "topic": "imaging_pump_volume", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 630, - "y": 320, - "wires": [ - [ - "fb887036.12429", - "67091ac0.8f9f6c" - ] - ] - }, - { - "id": "f4caa15e2bbfd6e7", - "type": "ui_template", - "z": "baa1e3d9.cb29d", - "group": "4322c187.e73e5", - "name": "Start Acquisition", - "order": 13, - "width": "5", - "height": "1", - "format": "\n\n", - "storeOutMessages": false, - "fwdInMessages": false, - "resendOnRefresh": false, - "templateScope": "local", - "className": "", - "x": 460, - "y": 480, - "wires": [ - [ - "c9f510c0.7d1328" - ] - ] - }, - { - "id": "9d6abe67.6bb3d", - "type": "ui_button", - "z": "cb95299c.2817c8", - "name": "", - "group": "64903b47.4034e4", - "order": 1, - "width": 0, - "height": 0, - "passthru": false, - "label": "Home", - "tooltip": "", - "color": "", - "bgcolor": "", - "icon": "home", - "payload": "{\"tab\":\"Home\"}", - "payloadType": "json", - "topic": "", - "x": 430, - "y": 600, - "wires": [ - [ - "f0fb77cf.8f1c28" - ] - ] - }, - { - "id": "f0fb77cf.8f1c28", - "type": "ui_ui_control", - "z": "cb95299c.2817c8", - "name": "", - "events": "change", - "x": 740, - "y": 600, - "wires": [ - [] - ] - }, - { - "id": "8ec68b82.17e3d8", - "type": "ui_button", - "z": "cb95299c.2817c8", - "name": "Start segmentation", - "group": "abeb6dad.635a2", - "order": 10, - "width": 5, - "height": 1, - "passthru": false, - "label": "Start segmentation", - "tooltip": "", - "color": "", - "bgcolor": "", - "icon": "", - "payload": "{\"action\":\"segment\"}", - "payloadType": "json", - "topic": "segmenter/segment", - "x": 370, - "y": 460, - "wires": [ - [ - "33c28dc1.238002", - "c72a1064.1ec388" - ] - ] - }, - { - "id": "27be7971.b3fbce", - "type": "ui_button", - "z": "cb95299c.2817c8", - "d": true, - "name": "Stop segmentation", - "group": "abeb6dad.635a2", - "order": 12, - "width": 4, - "height": 1, - "passthru": true, - "label": "Stop segmentation", - "tooltip": "", - "color": "", - "bgcolor": "#AD1625", - "icon": "", - "payload": "{\"action\":\"stop\"}", - "payloadType": "json", - "topic": "segmenter/segment", - "x": 370, - "y": 520, - "wires": [ - [ - "16f3cef4.0acac9" - ] - ] - }, - { - "id": "16f3cef4.0acac9", - "type": "mqtt out", - "z": "cb95299c.2817c8", - "name": "", - "topic": "", - "qos": "", - "retain": "", - "broker": "8dc3722c.06efa8", - "x": 850, - "y": 520, - "wires": [] - }, - { - "id": "8f3788f6.ddcf98", - "type": "function", - "z": "cb95299c.2817c8", - "name": "obj_counter", - "func": "obj_counter = flow.get('obj_counter')\nobj_counter = obj_counter + 1\nflow.set('obj_counter', obj_counter)\nmsg.payload = obj_counter\nmsg.topic = \"object count\"\nreturn msg", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 810, - "y": 800, - "wires": [ - [ - "fa3b7929.ac7da8", - "9d53dbe2.dbffe8" - ] - ] - }, - { - "id": "aa38dbbc.cf0a9", - "type": "switch", - "z": "cb95299c.2817c8", - "name": "Segmenter", - "property": "topic", - "propertyType": "msg", - "rules": [ - { - "t": "eq", - "v": "status/segmenter", - "vt": "str" - }, - { - "t": "eq", - "v": "status/segmenter/name", - "vt": "str" - }, - { - "t": "eq", - "v": "status/segmenter/object_id", - "vt": "str" - }, - { - "t": "eq", - "v": "status/segmenter/metric", - "vt": "str" - } - ], - "checkall": "true", - "repair": false, - "outputs": 4, - "x": 490, - "y": 740, - "wires": [ - [ - "b9a23b91.93638", - "6919465f.332e5" - ], - [ - "49af3d24.1799e4" - ], - [ - "8f3788f6.ddcf98" - ], - [] - ] - }, - { - "id": "9d53dbe2.dbffe8", - "type": "ui_chart", - "z": "cb95299c.2817c8", - "name": "counter graph", - "group": "46be9c86.dea684", - "order": 7, - "width": 10, - "height": 2, - "label": "", - "chartType": "horizontalBar", - "legend": "false", - "xformat": "HH:mm:ss", - "interpolate": "linear", - "nodata": "Objects count will be shown here once the segmentation is started", - "dot": false, - "ymin": "", - "ymax": "", - "removeOlder": 1, - "removeOlderPoints": "", - "removeOlderUnit": "3600", - "cutout": 0, - "useOneColor": true, - "useUTC": false, - "colors": [ - "#1f77b4", - "#aec7e8", - "#ff7f0e", - "#2ca02c", - "#98df8a", - "#d62728", - "#ff9896", - "#9467bd", - "#c5b0d5" - ], - "outputs": 1, - "x": 1340, - "y": 840, - "wires": [ - [] - ] - }, - { - "id": "a4f0f0d1.3aca88", - "type": "ui_toast", - "z": "cb95299c.2817c8", - "position": "top right", - "displayTime": "5", - "highlight": "", - "sendall": true, - "outputs": 0, - "ok": "OK", - "cancel": "", - "raw": false, - "topic": "", - "name": "", - "x": 1340, - "y": 680, - "wires": [] - }, - { - "id": "49af3d24.1799e4", - "type": "debug", - "z": "cb95299c.2817c8", - "name": "segmentation name", - "active": true, - "tosidebar": true, - "console": false, - "tostatus": false, - "complete": "true", - "targetType": "full", - "statusVal": "", - "statusType": "auto", - "x": 830, - "y": 760, - "wires": [] - }, - { - "id": "7088a5be.0c79a4", - "type": "template", - "z": "cb95299c.2817c8", - "name": "Create sentence", - "field": "payload", - "fieldType": "msg", - "format": "handlebars", - "syntax": "mustache", - "template": "The {{topic}} is {{payload.status}}", - "output": "str", - "x": 1100, - "y": 680, - "wires": [ - [ - "a4f0f0d1.3aca88" - ] - ] - }, - { - "id": "b9a23b91.93638", - "type": "change", - "z": "cb95299c.2817c8", - "name": "Remove high-level topic", - "rules": [ - { - "t": "change", - "p": "topic", - "pt": "msg", - "from": "status/", - "fromt": "str", - "to": "", - "tot": "str" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 850, - "y": 680, - "wires": [ - [ - "7088a5be.0c79a4" - ] - ] - }, - { - "id": "6919465f.332e5", - "type": "ui_text", - "z": "cb95299c.2817c8", - "group": "46be9c86.dea684", - "order": 1, - "width": 10, - "height": 1, - "name": "segmenter", - "label": "Segmenter status:", - "format": "{{msg.payload.status}}", - "layout": "row-spread", - "x": 810, - "y": 720, - "wires": [] - }, - { - "id": "fa3b7929.ac7da8", - "type": "ui_text", - "z": "cb95299c.2817c8", - "group": "46be9c86.dea684", - "order": 5, - "width": 4, - "height": 1, - "name": "counter", - "label": "", - "format": "{{msg.payload}}", - "layout": "col-center", - "x": 1320, - "y": 800, - "wires": [] - }, - { - "id": "640ece83.88cab", - "type": "inject", - "z": "cb95299c.2817c8", - "name": "Init graphs", - "props": [ - { - "p": "payload" - }, - { - "p": "topic", - "vt": "str" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "object count", - "payload": "0", - "payloadType": "num", - "x": 810, - "y": 880, - "wires": [ - [ - "4f3f7c4a.cb21c4" - ] - ] - }, - { - "id": "25867454.a8e334", - "type": "link in", - "z": "cb95299c.2817c8", - "name": "Segmenter module status", - "links": [ - "dcf5bd45.16a8d" - ], - "x": 295, - "y": 740, - "wires": [ - [ - "aa38dbbc.cf0a9" - ] - ] - }, - { - "id": "c8749cbb.55254", - "type": "function", - "z": "cb95299c.2817c8", - "name": "set global", - "func": "global.set(msg.topic, msg.payload);", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 960, - "y": 380, - "wires": [ - [] - ] - }, - { - "id": "d43c3ed9.e6cb1", - "type": "ui_template", - "z": "cb95299c.2817c8", - "group": "46be9c86.dea684", - "name": "Object counts", - "order": 3, - "width": 0, - "height": 0, - "format": "

Object counts

", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": true, - "templateScope": "local", - "className": "", - "x": 1340, - "y": 760, - "wires": [ - [] - ] - }, - { - "id": "33c28dc1.238002", - "type": "function", - "z": "cb95299c.2817c8", - "name": "prepare segmentation", - "func": "global.set('obj_counter', 0);\n\nvar segmentation_list = flow.get('segmentation_list')\nif (segmentation_list !== undefined && segmentation_list !== \"\") {\n msg.payload['path'] = segmentation_list\n}\n\n\nvar force = flow.get('force')\nif (force !== undefined && force !== \"\") {\n msg.payload['settings'] = {\"force\":Boolean(force)}\n}\n\n\nvar recursive = flow.get('recursive')\nif (recursive !== undefined && recursive !== \"\") {\n if (\"settings\" in msg.payload){\n msg.payload.settings[\"recursive\"] = Boolean(recursive)\n }\n else{\n msg.payload['settings'] = {\"recursive\": Boolean(recursive)}\n }\n}\n\nvar ecotaxa = flow.get('ecotaxa')\nif (ecotaxa !== undefined && ecotaxa !== \"\") {\n if (\"settings\" in msg.payload){\n msg.payload.settings[\"ecotaxa\"] = Boolean(ecotaxa)\n }\n else{\n msg.payload['settings'] = {\"ecotaxa\": Boolean(ecotaxa)}\n }\n}\n\nvar keep = flow.get('keep')\nif (keep !== undefined && keep !== \"\") {\n if (\"settings\" in msg.payload){\n msg.payload.settings[\"keep\"] = Boolean(keep)\n }\n else{\n msg.payload['settings'] = {\"keep\": Boolean(keep)}\n }\n}\n\nvar process_id = global.get('process_id')\nif (process_id !== undefined && process_id !== \"\") {\n if (\"settings\" in msg.payload){\n msg.payload.settings[\"process_id\"] = process_id\n }\n else{\n msg.payload['settings'] = {\"process_id\": process_id}\n }\n}\n\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 620, - "y": 460, - "wires": [ - [ - "16f3cef4.0acac9" - ] - ] - }, - { - "id": "fa12f9f8.00cfa8", - "type": "subflow:1c24ad9c.bebec2", - "z": "cb95299c.2817c8", - "name": "", - "env": [], - "x": 430, - "y": 380, - "wires": [ - [ - "3b72d11c.86e9e6" - ] - ] - }, - { - "id": "3b72d11c.86e9e6", - "type": "function", - "z": "cb95299c.2817c8", - "name": "get process_id", - "func": "msg.payload = msg.payload.process_id;\nmsg.topic = \"process_id\";\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 600, - "y": 380, - "wires": [ - [ - "56971109c8be3b54" - ] - ] - }, - { - "id": "3ea12061.ce62c", - "type": "ui_list", - "z": "cb95299c.2817c8", - "group": "abeb6dad.635a2", - "name": "", - "order": 9, - "width": 10, - "height": 11, - "lineType": "one", - "actionType": "check", - "allowHTML": false, - "outputs": 1, - "topic": "", - "x": 790, - "y": 140, - "wires": [ - [ - "cb3b87b5.63c4" - ] - ] - }, - { - "id": "8bd8fb2c.53fa4", - "type": "dir2files", - "z": "cb95299c.2817c8", - "name": "", - "dirname": "/home/pi/data/img/", - "pathRegex": "", - "isRecursive": true, - "findDir": true, - "isArray": true, - "x": 460, - "y": 140, - "wires": [ - [ - "ba2947.c854deb8" - ] - ] - }, - { - "id": "127d4ee.f8ad1b1", - "type": "ui_button", - "z": "cb95299c.2817c8", - "name": "Refresh", - "group": "abeb6dad.635a2", - "order": 8, - "width": 0, - "height": 0, - "passthru": false, - "label": "Update acquisition's folder list", - "tooltip": "Refresh the list of previous acquisitions", - "color": "", - "bgcolor": "", - "icon": "mi-find_replace", - "payload": "", - "payloadType": "date", - "topic": "update", - "x": 260, - "y": 140, - "wires": [ - [ - "8bd8fb2c.53fa4", - "56f845f5.e7c054" - ] - ] - }, - { - "id": "946ce9ee.092cf", - "type": "inject", - "z": "cb95299c.2817c8", - "name": "Init", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "", - "payload": "", - "payloadType": "date", - "x": 270, - "y": 100, - "wires": [ - [ - "8bd8fb2c.53fa4", - "56f845f5.e7c054" - ] - ] - }, - { - "id": "cb3b87b5.63c4", - "type": "function", - "z": "cb95299c.2817c8", - "name": "update segmentation_list", - "func": "var segmentation_list = flow.get('segmentation_list');\n\nif (segmentation_list === undefined || segmentation_list === \"\") {\n segmentation_list = []\n console.log(\"error\")\n}\n\npath = \"/home/pi/data/img/\" + msg.payload.title\n\nif (msg.payload.isChecked){\n if (segmentation_list.includes(path) === false){\n segmentation_list.push(path)\n }\n // Element already in list, don't push it more than once\n //segmentation_list.push(msg.payload[\"title\"])\n}\nelse {\n var pos = segmentation_list.indexOf(path)\n segmentation_list.splice(pos, 1)\n}\n\nflow.set('segmentation_list', segmentation_list)", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 990, - "y": 140, - "wires": [ - [] - ] - }, - { - "id": "56f845f5.e7c054", - "type": "change", - "z": "cb95299c.2817c8", - "name": "Reset segmentation_list", - "rules": [ - { - "t": "set", - "p": "segmentation_list", - "pt": "flow", - "to": "[]", - "tot": "json" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 510, - "y": 100, - "wires": [ - [] - ] - }, - { - "id": "7fc72364.8f038c", - "type": "ui_template", - "z": "cb95299c.2817c8", - "group": "abeb6dad.635a2", - "name": "Update message", - "order": 1, - "width": 10, - "height": 3, - "format": "
You can choose here in which folder(s) you want the segmentation script to run. A few details though:\n
The segmentation is run recursively in all folders. So if you select a top level folder, the segmentation will be run in all subfolders.\n
Also, you will be able to chose wether for force the segmentation for folders in which it has run already.
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": true, - "templateScope": "local", - "x": 270, - "y": 40, - "wires": [ - [] - ] - }, - { - "id": "ba2947.c854deb8", - "type": "function", - "z": "cb95299c.2817c8", - "name": "remove common", - "func": "function remove_path(item, index, array) {\n array[index] = item.replace(\"/home/pi/data/img/\", \"\")\n} \n\nmsg.payload.forEach(remove_path)\n\nreturn msg", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 630, - "y": 140, - "wires": [ - [ - "3ea12061.ce62c" - ] - ] - }, - { - "id": "21af0db1.c2c182", - "type": "ui_multistate_switch", - "z": "cb95299c.2817c8", - "name": "recursive toggle", - "group": "abeb6dad.635a2", - "order": 4, - "width": 5, - "height": 1, - "label": "Recursive folder", - "stateField": "payload", - "enableField": "enable", - "rounded": true, - "useThemeColors": true, - "hideSelectedLabel": false, - "options": [ - { - "label": "No", - "value": "0", - "valueType": "num", - "color": "#009933" - }, - { - "label": "Yes", - "value": "1", - "valueType": "num", - "color": "#999999" - } - ], - "x": 480, - "y": 220, - "wires": [ - [ - "880b192a.88e2d" - ] - ] - }, - { - "id": "dffb9881.feef8", - "type": "ui_multistate_switch", - "z": "cb95299c.2817c8", - "name": "force toggle", - "group": "abeb6dad.635a2", - "order": 3, - "width": 5, - "height": 1, - "label": "Force rework", - "stateField": "payload", - "enableField": "enable", - "rounded": true, - "useThemeColors": true, - "hideSelectedLabel": false, - "options": [ - { - "label": "No", - "value": "0", - "valueType": "num", - "color": "#009933" - }, - { - "label": "Yes", - "value": "1", - "valueType": "num", - "color": "#999999" - } - ], - "x": 470, - "y": 300, - "wires": [ - [ - "a4f68fa6.5d77f8" - ] - ] - }, - { - "id": "880b192a.88e2d", - "type": "change", - "z": "cb95299c.2817c8", - "name": "", - "rules": [ - { - "t": "set", - "p": "recursive", - "pt": "flow", - "to": "payload", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 690, - "y": 240, - "wires": [ - [] - ] - }, - { - "id": "a4f68fa6.5d77f8", - "type": "change", - "z": "cb95299c.2817c8", - "name": "", - "rules": [ - { - "t": "set", - "p": "force", - "pt": "flow", - "to": "payload", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 670, - "y": 280, - "wires": [ - [] - ] - }, - { - "id": "1ef1b43b.b0f064", - "type": "inject", - "z": "cb95299c.2817c8", - "name": "0", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "", - "payload": "0", - "payloadType": "num", - "x": 270, - "y": 280, - "wires": [ - [ - "dffb9881.feef8", - "a4f68fa6.5d77f8" - ] - ] - }, - { - "id": "f078c068.eacf58", - "type": "ui_template", - "z": "cb95299c.2817c8", - "group": "46be9c86.dea684", - "name": "Stream Segmented object", - "order": 2, - "width": 10, - "height": 8, - "format": "
\n Latest object segmented:
\n \"If\n
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "className": "", - "x": 1370, - "y": 600, - "wires": [ - [] - ] - }, - { - "id": "43f97b93.b76294", - "type": "inject", - "z": "cb95299c.2817c8", - "name": "1", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "", - "payload": "1", - "payloadType": "num", - "x": 270, - "y": 240, - "wires": [ - [ - "21af0db1.c2c182", - "880b192a.88e2d" - ] - ] - }, - { - "id": "4f3f7c4a.cb21c4", - "type": "change", - "z": "cb95299c.2817c8", - "name": "", - "rules": [ - { - "t": "set", - "p": "obj_counter", - "pt": "flow", - "to": "0", - "tot": "num" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 1010, - "y": 840, - "wires": [ - [ - "fa3b7929.ac7da8", - "9d53dbe2.dbffe8" - ] - ] - }, - { - "id": "6bce0f60.f48998", - "type": "link in", - "z": "cb95299c.2817c8", - "name": "", - "links": [ - "596fc9d4.46c75" - ], - "x": 855, - "y": 840, - "wires": [ - [ - "4f3f7c4a.cb21c4" - ] - ] - }, - { - "id": "596fc9d4.46c75", - "type": "link out", - "z": "cb95299c.2817c8", - "name": "", - "links": [ - "6bce0f60.f48998" - ], - "x": 715, - "y": 500, - "wires": [] - }, - { - "id": "c72a1064.1ec388", - "type": "change", - "z": "cb95299c.2817c8", - "name": "Reset counters", - "rules": [ - { - "t": "set", - "p": "topic", - "pt": "msg", - "to": "object count", - "tot": "str" - }, - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "0", - "tot": "num" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 600, - "y": 500, - "wires": [ - [ - "596fc9d4.46c75" - ] - ] - }, - { - "id": "9367534a.fb8568", - "type": "ui_multistate_switch", - "z": "cb95299c.2817c8", - "name": "Ecotaxa archive", - "group": "abeb6dad.635a2", - "order": 6, - "width": 5, - "height": 1, - "label": "Ecotaxa archive", - "stateField": "payload", - "enableField": "enable", - "rounded": true, - "useThemeColors": true, - "hideSelectedLabel": false, - "options": [ - { - "label": "No", - "value": "0", - "valueType": "num", - "color": "#009933" - }, - { - "label": "Yes", - "value": "1", - "valueType": "num", - "color": "#999999" - } - ], - "x": 1080, - "y": 220, - "wires": [ - [ - "25ac4f9a.5b05c8" - ] - ] - }, - { - "id": "25ac4f9a.5b05c8", - "type": "change", - "z": "cb95299c.2817c8", - "name": "", - "rules": [ - { - "t": "set", - "p": "ecotaxa", - "pt": "flow", - "to": "payload", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 1280, - "y": 240, - "wires": [ - [] - ] - }, - { - "id": "bef78886.8f0b98", - "type": "inject", - "z": "cb95299c.2817c8", - "name": "1", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "", - "payload": "1", - "payloadType": "num", - "x": 910, - "y": 240, - "wires": [ - [ - "9367534a.fb8568", - "25ac4f9a.5b05c8" - ] - ] - }, - { - "id": "32465a4e.8fcac6", - "type": "ui_multistate_switch", - "z": "cb95299c.2817c8", - "name": "Keep objects", - "group": "abeb6dad.635a2", - "order": 5, - "width": 5, - "height": 1, - "label": "Keep objects", - "stateField": "payload", - "enableField": "enable", - "rounded": true, - "useThemeColors": true, - "hideSelectedLabel": false, - "options": [ - { - "label": "No", - "value": "0", - "valueType": "num", - "color": "#009933" - }, - { - "label": "Yes", - "value": "1", - "valueType": "num", - "color": "#999999" - } - ], - "x": 1070, - "y": 300, - "wires": [ - [ - "8dd6f57f.b77f98" - ] - ] - }, - { - "id": "8dd6f57f.b77f98", - "type": "change", - "z": "cb95299c.2817c8", - "name": "", - "rules": [ - { - "t": "set", - "p": "keep", - "pt": "flow", - "to": "payload", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 1270, - "y": 280, - "wires": [ - [] - ] - }, - { - "id": "8090df89.c029e", - "type": "inject", - "z": "cb95299c.2817c8", - "name": "1", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "", - "payload": "1", - "payloadType": "num", - "x": 910, - "y": 280, - "wires": [ - [ - "32465a4e.8fcac6", - "8dd6f57f.b77f98" - ] - ] - }, - { - "id": "56971109c8be3b54", - "type": "ui_text_input", - "z": "cb95299c.2817c8", - "name": "process_id", - "label": "Process unique ID*", - "tooltip": "", - "group": "abeb6dad.635a2", - "order": 2, - "width": 10, - "height": 1, - "passthru": true, - "mode": "text", - "delay": 300, - "topic": "process_id", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 790, - "y": 380, - "wires": [ - [ - "c8749cbb.55254" - ] - ] - }, - { - "id": "2911fbc6.d28c24", - "type": "ui_template", - "z": "c1660bc.e7ff7f8", - "group": "c0ebfc57.42527", - "name": "Image browser", - "order": 1, - "width": "0", - "height": "0", - "format": "
\n\n
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "className": "", - "x": 400, - "y": 100, - "wires": [ - [] - ] - }, - { - "id": "4f02c726.de69b8", - "type": "ui_button", - "z": "9daf9e2b.019fc", - "name": "", - "group": "a7d64879.38298", - "order": 4, - "width": 6, - "height": 1, - "passthru": false, - "label": "Reboot", - "tooltip": "", - "color": "", - "bgcolor": "#AD1625", - "className": "", - "icon": "fa-repeat fa-2x", - "payload": "reboot", - "payloadType": "str", - "topic": "reboot", - "topicType": "str", - "x": 160, - "y": 240, - "wires": [ - [ - "4af9112d.87767" - ] - ] - }, - { - "id": "611a8b1c.a829b4", - "type": "exec", - "z": "9daf9e2b.019fc", - "command": "sudo", - "addpay": "payload", - "append": "now", - "useSpawn": "false", - "timer": "2", - "winHide": false, - "oldrc": false, - "name": "sudo cmd now", - "x": 480, - "y": 280, - "wires": [ - [], - [], - [] - ] - }, - { - "id": "bc76c4d6.a7ad28", - "type": "ui_button", - "z": "9daf9e2b.019fc", - "name": "", - "group": "a7d64879.38298", - "order": 5, - "width": 6, - "height": 1, - "passthru": false, - "label": "Shutdown", - "tooltip": "", - "color": "", - "bgcolor": "#AD1625", - "className": "", - "icon": "fa-power-off fa-2x", - "payload": "shutdown", - "payloadType": "str", - "topic": "shutdown", - "topicType": "str", - "x": 160, - "y": 320, - "wires": [ - [ - "4af9112d.87767" - ] - ] - }, - { - "id": "4af9112d.87767", - "type": "python3-function", - "z": "9daf9e2b.019fc", - "name": "action", - "func": "#!/usr/bin/python3\nimport smbus2 as smbus\n\nbus = smbus.SMBus(1)\n#turn off LED\nbus.write_byte_data(0x0d, 0x07, 0x00)\n#turn off Fan\nbus.write_byte_data(0x0d, 0x08, 0x00)\n\n#msg[\"payload\"] = str(msg[\"topic\"])+' now'\nreturn msg", - "outputs": 1, - "x": 330, - "y": 280, - "wires": [ - [ - "611a8b1c.a829b4" - ] - ] - }, - { - "id": "466eb611.4da048", - "type": "ui_button", - "z": "9daf9e2b.019fc", - "name": "", - "group": "a7d64879.38298", - "order": 2, - "width": 6, - "height": 1, - "passthru": true, - "label": "Restart Hardware Controller", - "tooltip": "", - "color": "", - "bgcolor": "#AD1625", - "className": "", - "icon": "fa-refresh fa-2x", - "payload": "Restarting hardware controller...", - "payloadType": "str", - "topic": "", - "topicType": "str", - "x": 460, - "y": 420, - "wires": [ - [ - "bd5cceef.b17ad", - "414353cde6a62346" - ] - ] - }, - { - "id": "bd5cceef.b17ad", - "type": "exec", - "z": "9daf9e2b.019fc", - "command": "sudo systemctl restart planktoscope-org.device-backend.controller.service", - "addpay": false, - "append": "", - "useSpawn": "false", - "timer": "", - "winHide": false, - "oldrc": false, - "name": "Restart hardware controller", - "x": 800, - "y": 420, - "wires": [ - [], - [], - [] - ] - }, - { - "id": "43cf8ff7.75231", - "type": "rpi-gpio out", - "z": "9daf9e2b.019fc", - "name": "Pump Enable", - "pin": "4", - "set": true, - "level": "1", - "freq": "", - "out": "out", - "bcm": true, - "x": 420, - "y": 80, - "wires": [] - }, - { - "id": "4bca8a25.15be3c", - "type": "rpi-gpio out", - "z": "9daf9e2b.019fc", - "name": "Focus Enable", - "pin": "12", - "set": true, - "level": "1", - "freq": "", - "out": "out", - "bcm": true, - "x": 420, - "y": 120, - "wires": [] - }, - { - "id": "50f9b5b.a84bccc", - "type": "inject", - "z": "9daf9e2b.019fc", - "name": "Default: ON", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": "0.01", - "topic": "", - "payload": "true", - "payloadType": "bool", - "x": 150, - "y": 100, - "wires": [ - [ - "43cf8ff7.75231", - "4bca8a25.15be3c", - "6db0fcf5.f0effc", - "5fc4ede4.72516c" - ] - ] - }, - { - "id": "45a7b5aa.2ed20c", - "type": "link in", - "z": "9daf9e2b.019fc", - "name": "Restart Hardware Controller", - "links": [ - "e41870d7.300eb8", - "e4ead350b3d07578" - ], - "x": 195, - "y": 420, - "wires": [ - [ - "466eb611.4da048" - ] - ] - }, - { - "id": "b81b990a.d4dca", - "type": "link in", - "z": "9daf9e2b.019fc", - "name": "Shutdown", - "links": [ - "e08cfcb8.2a67e8" - ], - "x": 195, - "y": 280, - "wires": [ - [ - "4af9112d.87767" - ] - ] - }, - { - "id": "5fc4ede4.72516c", - "type": "rpi-gpio out", - "z": "9daf9e2b.019fc", - "name": "HAT Pump Enable", - "pin": "23", - "set": true, - "level": "1", - "freq": "", - "out": "out", - "bcm": true, - "x": 430, - "y": 40, - "wires": [] - }, - { - "id": "6db0fcf5.f0effc", - "type": "rpi-gpio out", - "z": "9daf9e2b.019fc", - "name": "HAT Focus Enable", - "pin": "5", - "set": true, - "level": "1", - "freq": "", - "out": "out", - "bcm": true, - "x": 430, - "y": 160, - "wires": [] - }, - { - "id": "38c05fcb891c82bf", - "type": "exec", - "z": "9daf9e2b.019fc", - "command": "docker restart apps_ps_backend_proc-segmenter-server-1", - "addpay": false, - "append": "", - "useSpawn": "false", - "timer": "", - "winHide": false, - "oldrc": false, - "name": "Restart segmenter", - "x": 770, - "y": 500, - "wires": [ - [], - [], - [] - ] - }, - { - "id": "631b8626185addfc", - "type": "ui_button", - "z": "9daf9e2b.019fc", - "name": "", - "group": "a7d64879.38298", - "order": 3, - "width": 6, - "height": 1, - "passthru": true, - "label": "Restart Segmenter", - "tooltip": "", - "color": "", - "bgcolor": "#AD1625", - "className": "", - "icon": "fa-refresh fa-2x", - "payload": "Restarting segmenter...", - "payloadType": "str", - "topic": "", - "topicType": "str", - "x": 430, - "y": 500, - "wires": [ - [ - "38c05fcb891c82bf", - "e036d07cf78fde85" - ] - ] - }, - { - "id": "cec5bd6f962f6903", - "type": "ui_template", - "z": "9daf9e2b.019fc", - "group": "a7d64879.38298", - "name": "Logs", - "order": 1, - "width": 0, - "height": 0, - "format": "

\n The PlanktoScope software application consists of three components: a Node-RED dashboard which provides the user interface you're using; a Hardware Controller\n which executes commands sent from the Node-RED dashboard for hardware control and image acquisition; and a Segmenter which processes an acquired dataset of\n images and isolates objects from those images. Each component has its own independent log of messages, managed separately from the logs for the other components.\n

\n

\n All three components have live-updating logs which you can monitor. Additionally, the Hardware Controller and the Segmenter also save all of their log messages\n to files which you can browse and download. Those software components create a new log file each time they start, and the name of the log file includes the time\n in the PlanktoScope's clock when the software component started. However, if your PlanktoScope's clock is usually wrong, it makes the log files difficult to navigate.\n This will be fixed in a future version of the software.\n

\n

\n If you need to share your logs with other people (e.g. on Slack or GitHub), you should open the \"Downloadable Logs\" links, and then you can select one file or multiple\n log files for downloading as a zip archive.\n

\n", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": true, - "templateScope": "local", - "className": "", - "x": 650, - "y": 180, - "wires": [ - [] - ] - }, - { - "id": "414353cde6a62346", - "type": "ui_toast", - "z": "9daf9e2b.019fc", - "position": "top right", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 0, - "ok": "OK", - "cancel": "", - "raw": false, - "className": "", - "topic": "", - "name": "", - "x": 770, - "y": 380, - "wires": [] - }, - { - "id": "e036d07cf78fde85", - "type": "ui_toast", - "z": "9daf9e2b.019fc", - "position": "top right", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 0, - "ok": "OK", - "cancel": "", - "raw": false, - "className": "", - "topic": "", - "name": "", - "x": 770, - "y": 460, - "wires": [] - }, - { - "id": "ddcbbfa5.cd158", - "type": "exec", - "z": "1371dec5.76e671", - "command": "vcgencmd measure_temp | tr -d \"temp=\" | tr -d \"'C\" | tr -d \"\\n\"", - "addpay": false, - "append": "", - "useSpawn": "", - "timer": "", - "name": "RPi Temp.", - "x": 330, - "y": 40, - "wires": [ - [ - "bc503fa5.f46dd" - ], - [], - [] - ] - }, - { - "id": "3910d662.fa1f7a", - "type": "exec", - "z": "1371dec5.76e671", - "command": "df -h | grep /dev/root | awk -F ' ' '{print $5}' | tr -d % | tr \"\\n$\" \"\\ \" | sed 's/,/./' | tr -d \" \"", - "addpay": false, - "append": "", - "useSpawn": "", - "timer": "", - "name": "Disk Usage", - "x": 330, - "y": 120, - "wires": [ - [ - "eaf74a43.fa27d" - ], - [], - [] - ] - }, - { - "id": "1cd5b4c0.46af9b", - "type": "inject", - "z": "1371dec5.76e671", - "name": "update: 5s", - "props": [ - { - "p": "payload" - }, - { - "p": "topic", - "vt": "str" - } - ], - "repeat": "5", - "crontab": "", - "once": false, - "onceDelay": "", - "topic": "", - "payload": "", - "payloadType": "date", - "x": 110, + { + "id": "eaae323a.31b3", + "type": "tab", + "label": "Home", + "disabled": false, + "info": "" + }, + { + "id": "b771c342.49603", + "type": "tab", + "label": "Sample", + "disabled": false, + "info": "" + }, + { + "id": "bccd1f23.87219", + "type": "tab", + "label": "Optic Configuration", + "disabled": false, + "info": "" + }, + { + "id": "baa1e3d9.cb29d", + "type": "tab", + "label": "Fluidic Acquisition", + "disabled": false, + "info": "" + }, + { + "id": "cb95299c.2817c8", + "type": "tab", + "label": "Segmentation", + "disabled": false, + "info": "" + }, + { + "id": "c1660bc.e7ff7f8", + "type": "tab", + "label": "Gallery", + "disabled": false, + "info": "" + }, + { + "id": "9daf9e2b.019fc", + "type": "tab", + "label": "Administration", + "disabled": false, + "info": "" + }, + { + "id": "1371dec5.76e671", + "type": "tab", + "label": "System Monitoring", + "disabled": false, + "info": "" + }, + { + "id": "9a22e67a.378818", + "type": "tab", + "label": "MQTT Receive", + "disabled": false, + "info": "" + }, + { + "id": "1eaf21c8.f7a21e", + "type": "tab", + "label": "Hardware Settings", + "disabled": false, + "info": "" + }, + { + "id": "1c24ad9c.bebec2", + "type": "subflow", + "name": "Config", + "info": "An input to this subflow will get the configuration to be saved to disk.\n\nOn startup, this node outputs the loaded configuration", + "category": "", + "in": [ + { + "x": 220, "y": 160, "wires": [ - [ - "3910d662.fa1f7a", - "ddcbbfa5.cd158", - "23a84a3856fb68bd", - "4ed64bd91fa9fbdf", - "ed5f2d963d85478b" - ] - ] - }, - { - "id": "2549f778.4eb828", - "type": "python3-function", - "z": "1371dec5.76e671", - "name": "fan control", - "func": "import smbus2 as smbus\n\nstate = msg[\"payload\"]\nbus = smbus.SMBus(1)\n\nDEVICE_ADDRESS = 0x0d\n# command happens twice, for reasons\nif state == \"off\":\n with smbus.SMBus(1) as bus:\n bus.write_byte_data(DEVICE_ADDRESS, 0x08, 0x00)\n bus.write_byte_data(DEVICE_ADDRESS, 0x08, 0x00)\n return msg\nif state == \"on\":\n with smbus.SMBus(1) as bus:\n bus.write_byte_data(DEVICE_ADDRESS, 0x08, 0x01)\n bus.write_byte_data(DEVICE_ADDRESS, 0x08, 0x01)\n return msg\n", - "outputs": 1, - "x": 1150, - "y": 40, - "wires": [ - [ - "e640ebb5c397f424" - ] - ] - }, - { - "id": "b7ab1ada.1f4158", - "type": "exec", - "z": "1371dec5.76e671", - "command": "i2cdetect -y 1", - "addpay": false, - "append": "", - "useSpawn": "false", - "timer": "1", - "winHide": false, - "oldrc": false, - "name": "i2c update", - "x": 1440, - "y": 40, - "wires": [ - [], - [], - [] - ] - }, - { - "id": "bc503fa5.f46dd", - "type": "switch", - "z": "1371dec5.76e671", - "name": "", - "property": "payload", - "propertyType": "msg", - "rules": [ - { - "t": "gt", - "v": "40", - "vt": "num" - }, - { - "t": "lte", - "v": "35", - "vt": "num" - } - ], - "checkall": "true", - "repair": false, - "outputs": 2, - "x": 570, - "y": 40, - "wires": [ - [ - "a25d6486.e1ce28" - ], - [ - "5d4f3e71.1bad4" - ] + { + "id": "3ad9835.08c937c" + } ] - }, - { - "id": "5d4f3e71.1bad4", - "type": "change", - "z": "1371dec5.76e671", - "name": "Set OFF", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "off", - "tot": "str" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 720, + } + ], + "out": [ + { + "x": 1040, "y": 60, "wires": [ - [ - "7fb13a4a53b612a0" - ] - ] - }, - { - "id": "a25d6486.e1ce28", - "type": "change", - "z": "1371dec5.76e671", - "name": "Set ON", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "on", - "tot": "str" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 720, - "y": 20, - "wires": [ - [ - "7fb13a4a53b612a0" - ] - ] - }, - { - "id": "569154a.b53182c", - "type": "inject", - "z": "1371dec5.76e671", - "name": "once", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": "", - "topic": "", - "payload": "start", - "payloadType": "str", - "x": 170, - "y": 680, - "wires": [ - [ - "ccb5172d10c1ccaf" - ] - ] - }, - { - "id": "4828d2f4.7c712c", - "type": "function", - "z": "1371dec5.76e671", - "name": "set global", - "func": "global.set(\"acq_instrument_id\",msg.payload);\n", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 580, - "y": 700, - "wires": [ - [] - ] - }, - { - "id": "e2f39a35.f57298", - "type": "subflow:1c24ad9c.bebec2", - "z": "1371dec5.76e671", - "name": "", - "env": [], - "x": 170, - "y": 620, - "wires": [ - [ - "950b773ad4c0fdfe" - ] - ] - }, - { - "id": "3e64877a.9684b", - "type": "function", - "z": "1371dec5.76e671", - "name": "set global", - "func": "global.set(\"acq_software\", \"PlanktoScope \" + msg.payload);\n", - "outputs": 1, - "timeout": "", - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 820, - "y": 500, - "wires": [ - [] - ] - }, - { - "id": "bdc6718a.dd5d48", - "type": "ui_text", - "z": "1371dec5.76e671", - "group": "ce9e278.781eed8", - "order": 2, - "width": 0, - "height": 0, - "name": "", - "label": "Instrument Type", - "format": "{{msg.payload}}", - "layout": "row-spread", - "className": "", - "style": false, - "font": "", - "fontSize": "", - "color": "#000000", - "x": 600, - "y": 620, - "wires": [] - }, - { - "id": "a400a97e.e333a8", - "type": "ui_text", - "z": "1371dec5.76e671", - "group": "ce9e278.781eed8", - "order": 1, - "width": 0, - "height": 0, - "name": "", - "label": "Instrument Name", - "format": "{{msg.payload}}", - "layout": "row-spread", - "className": "", - "style": false, - "font": "", - "fontSize": "", - "color": "#000000", - "x": 610, - "y": 660, - "wires": [] - }, - { - "id": "8343fa69.49339", - "type": "ui_text", - "z": "1371dec5.76e671", - "group": "ce9e278.781eed8", - "order": 3, - "width": 0, - "height": 0, - "name": "", - "label": "Software Version", - "format": "{{msg.payload}}", - "layout": "row-spread", - "className": "", - "style": false, - "font": "", - "fontSize": "", - "color": "#000000", - "x": 850, - "y": 540, - "wires": [] - }, - { - "id": "f783aefd.c3bfd8", - "type": "ui_text", - "z": "1371dec5.76e671", - "group": "ce9e278.781eed8", - "order": 4, - "width": 0, - "height": 0, - "name": "", - "label": "Camera Name", - "format": "{{msg.payload}}", - "layout": "row-spread", - "x": 600, - "y": 740, - "wires": [] - }, - { - "id": "30067f35.532f2", - "type": "link in", - "z": "1371dec5.76e671", - "name": "Camera Name", - "links": [ - "559a8085.1d6b9" - ], - "x": 205, - "y": 740, - "wires": [ - [ - "f783aefd.c3bfd8" - ] - ] - }, - { - "id": "11b51f8f.acd308", - "type": "python3-function", - "z": "1371dec5.76e671", - "d": true, - "name": "fan temperature", - "func": "import smbus\nbus = smbus.SMBus(1)\n\naddr = 0x0d\nfan_reg = 0x08\n\ntemp = float( msg[\"payload\"])\n\n# 0x01 full speed, 0x02: 20% speed, ..., 0x09: 90% speed\n\nif temp < 38:\n bus.write_byte_data(addr, fan_reg, 0x00)\nelif temp < 43:\n bus.write_byte_data(addr, fan_reg, 0x02)\nelif temp < 46:\n bus.write_byte_data(addr, fan_reg, 0x04)\nelif temp < 48:\n bus.write_byte_data(addr, fan_reg, 0x06)\nelif temp < 52:\n bus.write_byte_data(addr, fan_reg, 0x08)\nelse:\n bus.write_byte_data(addr, fan_reg, 0x01)\n\nreturn msg", - "outputs": 1, - "x": 1440, - "y": 120, - "wires": [ - [] - ] - }, - { - "id": "eaf74a43.fa27d", - "type": "switch", - "z": "1371dec5.76e671", - "name": "if disk > 90%", - "property": "payload", - "propertyType": "msg", - "rules": [ - { - "t": "gte", - "v": "90", - "vt": "num" - } - ], - "checkall": "true", - "repair": false, - "outputs": 1, - "x": 590, - "y": 120, - "wires": [ - [ - "6d09f428.930bcc" - ] - ] - }, - { - "id": "46d5e78b.15f998", - "type": "ui_toast", - "z": "1371dec5.76e671", - "position": "dialog", - "displayTime": "10", - "highlight": "", - "sendall": true, - "outputs": 1, - "ok": "OK", - "cancel": "", - "raw": false, - "className": "", - "topic": "", - "name": "", - "x": 1090, - "y": 120, - "wires": [ - [] - ] - }, - { - "id": "24df077a.cb252", - "type": "change", - "z": "1371dec5.76e671", - "name": "full disk msg", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "\"Your drive has reached 90% capacity, you should do a backup to an external drive and a purge.\"", - "tot": "str" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 930, - "y": 120, - "wires": [ - [ - "46d5e78b.15f998" - ] - ] - }, - { - "id": "6d09f428.930bcc", - "type": "delay", - "z": "1371dec5.76e671", - "name": "", - "pauseType": "rate", - "timeout": "5", - "timeoutUnits": "seconds", - "rate": "1", - "nbRateUnits": "5", - "rateUnits": "minute", - "randomFirst": "1", - "randomLast": "5", - "randomUnits": "seconds", - "drop": true, - "allowrate": false, - "outputs": 1, - "x": 760, - "y": 120, - "wires": [ - [ - "24df077a.cb252" - ] - ] - }, - { - "id": "e640ebb5c397f424", - "type": "delay", - "z": "1371dec5.76e671", - "name": "", - "pauseType": "delay", - "timeout": "1", - "timeoutUnits": "seconds", - "rate": "1", - "nbRateUnits": "1", - "rateUnits": "second", - "randomFirst": "1", - "randomLast": "5", - "randomUnits": "seconds", - "drop": false, - "allowrate": false, - "outputs": 1, - "x": 1300, + { + "id": "ad541674.4791c8", + "port": 0 + } + ] + } + ], + "env": [], + "color": "#DDAA99" + }, + { + "id": "4ed26b8b.253504", + "type": "subflow", + "name": "Save hardware config", + "info": "", + "category": "", + "in": [ + { + "x": 40, "y": 40, "wires": [ - [ - "b7ab1ada.1f4158" - ] - ] - }, - { - "id": "7fb13a4a53b612a0", - "type": "rbe", - "z": "1371dec5.76e671", - "name": "", - "func": "rbe", - "gap": "", - "start": "", - "inout": "out", - "septopics": true, - "property": "payload", - "topi": "topic", - "x": 1010, + { + "id": "53d163be.47cf24" + } + ] + } + ], + "out": [], + "env": [], + "meta": {}, + "color": "#DDAA99" + }, + { + "id": "e6665421f66ea4c8", + "type": "subflow", + "name": "Load hardware config", + "info": "", + "category": "", + "in": [ + { + "x": 40, "y": 40, "wires": [ - [ - "2549f778.4eb828" - ] - ] - }, - { - "id": "ccb5172d10c1ccaf", - "type": "file in", - "z": "1371dec5.76e671", - "name": "Get machine name", - "filename": "/run/machine-name", - "filenameType": "str", - "format": "utf8", - "chunk": false, - "sendError": false, - "encoding": "none", - "allProps": false, - "x": 350, - "y": 680, - "wires": [ - [ - "a400a97e.e333a8", - "4828d2f4.7c712c" - ] - ] - }, - { - "id": "950b773ad4c0fdfe", - "type": "change", - "z": "1371dec5.76e671", - "name": "Get acq_instrument", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.acq_instrument", - "tot": "msg" - }, - { - "t": "set", - "p": "topic", - "pt": "msg", - "to": "acq_instrument", - "tot": "str" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 350, - "y": 620, - "wires": [ - [ - "bdc6718a.dd5d48" - ] - ] - }, - { - "id": "24de7407445d2087", - "type": "inject", - "z": "1371dec5.76e671", - "name": "once", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": "", - "topic": "", - "payload": "start", - "payloadType": "str", - "x": 90, - "y": 520, - "wires": [ - [ - "e4f9ed2b337c2fa6" - ] - ] - }, - { - "id": "e4f9ed2b337c2fa6", - "type": "file in", - "z": "1371dec5.76e671", - "name": "Versioning File", - "filename": "/usr/share/planktoscope/installer-versioning.yml", - "filenameType": "str", - "format": "utf8", - "chunk": false, - "sendError": false, - "encoding": "none", - "allProps": false, - "x": 240, - "y": 520, - "wires": [ - [ - "db79aae8a7fe3512" - ] - ] - }, - { - "id": "db79aae8a7fe3512", - "type": "yaml", - "z": "1371dec5.76e671", - "property": "payload", - "name": "", - "x": 390, - "y": 520, - "wires": [ - [ - "04c313e8d9aac122", - "ef1970121e57c5e8", - "574361abfe75b3b3" - ] - ] - }, - { - "id": "04c313e8d9aac122", - "type": "change", - "z": "1371dec5.76e671", - "name": "Get repo", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.repo", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 580, - "y": 480, - "wires": [ - [ - "57b3b083a2455e09" - ] - ] - }, - { - "id": "ef1970121e57c5e8", - "type": "change", - "z": "1371dec5.76e671", - "name": "Get version", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.version", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 590, - "y": 520, - "wires": [ - [ - "3e64877a.9684b", - "8343fa69.49339" - ] - ] - }, - { - "id": "57b3b083a2455e09", - "type": "function", - "z": "1371dec5.76e671", - "name": "set global", - "func": "global.set(\"process_source\", msg.payload);\n", - "outputs": 1, - "timeout": "", - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 820, - "y": 460, - "wires": [ - [] - ] - }, - { - "id": "574361abfe75b3b3", - "type": "change", - "z": "1371dec5.76e671", - "name": "Get commit", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.commit", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 590, - "y": 560, - "wires": [ - [ - "016d1d2a2f19f1a6" - ] - ] - }, - { - "id": "016d1d2a2f19f1a6", - "type": "function", - "z": "1371dec5.76e671", - "name": "set global", - "func": "global.set(\"process_commit\", msg.payload);\n", - "outputs": 1, - "timeout": "", - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 820, - "y": 580, - "wires": [ - [] - ] - }, - { - "id": "4ed64bd91fa9fbdf", - "type": "ui_template", - "z": "1371dec5.76e671", - "group": "3da7da8f.179606", - "name": "Metrics panel", - "order": 1, - "width": "0", - "height": "0", - "format": "
\n

\n The instrument's system time is different from your web browser's time by {{drift}}.\n As a result, timestamps in your datasets will be incorrect.\n Additionally, system metrics will not be recorded or shown correctly.\n Additionally, you will see incorrectly-aligned graphs in the metrics below.\n

\n

Please change the instrument's system time or your web browser's time to accurate values.

\n

\n \n

\n
\n\n
\n

Loading system metrics, please wait...

\n
\n\n
\n \n
\n\n\n", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "className": "", - "x": 330, - "y": 280, - "wires": [ - [] - ] - }, - { - "id": "38bad1e220cd5d87", - "type": "ui_text", - "z": "1371dec5.76e671", - "group": "ce9e278.781eed8", - "order": 5, - "width": 0, - "height": 0, - "name": "", - "label": "System Time", - "format": "{{msg.payload}}", - "layout": "row-spread", - "className": "", - "style": false, - "font": "", - "fontSize": 16, - "color": "#000000", - "x": 590, - "y": 240, - "wires": [] - }, - { - "id": "ed5f2d963d85478b", - "type": "function", - "z": "1371dec5.76e671", - "name": "Get system time", - "func": "var date = new Date();\ndate.setSeconds(0, 0);\nmsg.payload = (\n date.toISOString().replace('T', ' ').replace(/:\\d+\\.\\d+Z/,' UTC')\n);\nreturn msg", - "outputs": 1, - "timeout": 0, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 340, - "y": 240, - "wires": [ - [ - "38bad1e220cd5d87" - ] - ] - }, - { - "id": "23a84a3856fb68bd", - "type": "ui_template", - "z": "1371dec5.76e671", - "group": "ce9e278.781eed8", - "name": "Browser time", - "order": 6, - "width": "6", - "height": "1", - "format": "
\n

Browser Time

\n

{{time}}

\n
\n\n", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "className": "", - "x": 330, - "y": 200, - "wires": [ - [] - ] - }, - { - "id": "19a45f972be2b0f1", - "type": "function", - "z": "1371dec5.76e671", - "name": "Get system time", - "func": "var date = new Date(msg.payload.timestamp);\nmsg.payload = (\n date.toISOString().replace('T', ' ').replace(/:\\d+\\.\\d+Z/,' UTC')\n);\nreturn msg", - "outputs": 1, - "timeout": 0, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 340, - "y": 340, - "wires": [ - [ - "ee2c5e7c29eb4760" - ] - ] - }, - { - "id": "8ba3e2774987fd58", - "type": "http in", - "z": "1371dec5.76e671", - "name": "POST /api/system-time", - "url": "/api/system-time", - "method": "post", - "upload": false, - "swaggerDoc": "", - "x": 120, - "y": 360, - "wires": [ - [ - "19a45f972be2b0f1", - "07bbdca8d6153210", - "595df18543c8328e" - ] - ] - }, - { - "id": "ee2c5e7c29eb4760", - "type": "ui_toast", - "z": "1371dec5.76e671", - "position": "top right", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 0, - "ok": "OK", - "cancel": "", - "raw": false, - "className": "", - "topic": "Setting system time", - "name": "", - "x": 610, - "y": 340, - "wires": [] - }, - { - "id": "07bbdca8d6153210", - "type": "function", - "z": "1371dec5.76e671", - "name": "Prepare timestamp", - "func": "msg.payload = ('@' + msg.payload.timestamp).slice(0, -3);\nreturn msg;", - "outputs": 1, - "timeout": 0, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 350, - "y": 380, - "wires": [ - [ - "7558e8f302d5b944" - ] + { + "id": "48ceeda454438cb7" + } ] - }, - { - "id": "7558e8f302d5b944", - "type": "exec", - "z": "1371dec5.76e671", - "command": "sudo date -s", - "addpay": "payload", - "append": "", - "useSpawn": "", - "timer": "", - "winHide": false, - "name": "Set system time", - "x": 600, - "y": 380, - "wires": [ - [], - [], - [] - ] - }, - { - "id": "c8be8dad272e1fa5", - "type": "http in", - "z": "1371dec5.76e671", - "name": "GET /api/system-time", - "url": "/api/system-time", - "method": "get", - "upload": false, - "swaggerDoc": "", - "x": 120, - "y": 420, - "wires": [ - [ - "0f4ce59587fa14e1" - ] - ] - }, - { - "id": "0f4ce59587fa14e1", - "type": "function", - "z": "1371dec5.76e671", - "name": "Get system time", - "func": "var date = new Date();\nmsg.payload = {'timestamp': date.getTime()};\nreturn msg", - "outputs": 1, - "timeout": 0, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 340, - "y": 420, + } + ], + "out": [ + { + "x": 900, + "y": 40, "wires": [ - [ - "433d48a4b1bc0b27" - ] - ] - }, - { - "id": "433d48a4b1bc0b27", - "type": "http response", - "z": "1371dec5.76e671", - "name": "Send GET response", - "statusCode": "", - "headers": { - "Content-Type": "application/json; charset=UTF-8" + { + "id": "2b1a67ac127f3fe7", + "port": 0 + } + ] + } + ], + "env": [], + "meta": {}, + "color": "#DDAA99" + }, + { + "id": "3a6bb13f.c9703e", + "type": "ui_tab", + "name": "Home", + "icon": "home", + "order": 1, + "disabled": false, + "hidden": false + }, + { + "id": "181bb236.1e94be", + "type": "ui_tab", + "name": "Optic Configuration", + "icon": "fa-eye", + "order": 3, + "disabled": false, + "hidden": false + }, + { + "id": "c9194f02.9d5e9", + "type": "ui_tab", + "name": "Fluidic Acquisition", + "icon": "fa-flask", + "order": 4, + "disabled": false, + "hidden": false + }, + { + "id": "8d16beb8.9b3fb", + "type": "ui_tab", + "name": "Segmentation", + "icon": "fa-crop", + "order": 5, + "disabled": false, + "hidden": false + }, + { + "id": "d9cd733b.ab73d", + "type": "ui_tab", + "name": "System Monitoring", + "icon": "fa-thermometer-full", + "order": 7, + "disabled": false, + "hidden": false + }, + { + "id": "4248342d.e55fac", + "type": "ui_group", + "name": "Optic Characterization", + "tab": "181bb236.1e94be", + "order": 4, + "disp": true, + "width": "6", + "collapse": false + }, + { + "id": "858a0e3c.987fe", + "type": "ui_group", + "name": "Preview", + "tab": "c9194f02.9d5e9", + "order": 1, + "disp": true, + "width": 10, + "collapse": false + }, + { + "id": "64903b47.4034e4", + "type": "ui_group", + "name": "Navigation", + "tab": "8d16beb8.9b3fb", + "order": 3, + "disp": false, + "width": "6", + "collapse": false + }, + { + "id": "3da7da8f.179606", + "type": "ui_group", + "name": "Metrics", + "tab": "d9cd733b.ab73d", + "order": 1, + "disp": true, + "width": "24", + "collapse": true, + "className": "" + }, + { + "id": "cc8bc4eb.651868", + "type": "ui_base", + "theme": { + "name": "theme-dark", + "lightTheme": { + "default": "#0094CE", + "baseColor": "#5900ce", + "baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif", + "edited": false, + "reset": false + }, + "darkTheme": { + "default": "#097479", + "baseColor": "#097479", + "baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif", + "edited": true, + "reset": false + }, + "customTheme": { + "name": "Untitled Theme 1", + "default": "#4B7930", + "baseColor": "#4B7930", + "baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif" + }, + "themeState": { + "base-color": { + "default": "#097479", + "value": "#097479", + "edited": true }, - "x": 620, - "y": 420, - "wires": [] - }, - { - "id": "595df18543c8328e", - "type": "http response", - "z": "1371dec5.76e671", - "name": "Send POST response", - "statusCode": "", - "headers": {}, - "x": 620, - "y": 300, - "wires": [] - }, - { - "id": "1fdf77b5.24e4e", - "type": "mqtt in", - "z": "9a22e67a.378818", - "name": "", - "topic": "status/#", - "qos": "0", - "datatype": "json", - "broker": "8dc3722c.06efa8", - "inputs": 0, - "x": 290, - "y": 340, - "wires": [ - [ - "fa73983d.318188" - ] - ] - }, - { - "id": "4a1e9e3e.27506", - "type": "switch", - "z": "9a22e67a.378818", - "name": "Filter segmenter out", - "property": "topic", - "propertyType": "msg", - "rules": [ - { - "t": "else" - }, - { - "t": "cont", - "v": "status/segmenter", - "vt": "str" - } - ], - "checkall": "true", - "repair": false, - "outputs": 2, - "x": 620, - "y": 340, - "wires": [ - [ - "58f2e0f.4e8b12" - ], - [ - "dcf5bd45.16a8d" - ] - ] - }, - { - "id": "fa73983d.318188", - "type": "json", - "z": "9a22e67a.378818", - "name": "", - "property": "payload", - "action": "obj", - "pretty": true, - "x": 430, - "y": 340, - "wires": [ - [ - "4a1e9e3e.27506" - ] - ] - }, - { - "id": "58f2e0f.4e8b12", - "type": "link out", - "z": "9a22e67a.378818", - "name": "Fluidic module status", - "links": [ - "bb628f8d.98f108" - ], - "x": 795, - "y": 320, - "wires": [] - }, - { - "id": "dcf5bd45.16a8d", - "type": "link out", - "z": "9a22e67a.378818", - "name": "Segmenter module status", - "links": [ - "25867454.a8e334" - ], - "x": 795, - "y": 360, - "wires": [] - }, - { - "id": "e41870d7.300eb8", - "type": "link out", - "z": "1eaf21c8.f7a21e", - "name": "Stepper config change", - "links": [ - "45a7b5aa.2ed20c" - ], - "x": 1475, - "y": 380, - "wires": [] - }, - { - "id": "2068e7f.f4efb18", - "type": "delay", - "z": "1eaf21c8.f7a21e", - "name": "", - "pauseType": "delay", - "timeout": "1", - "timeoutUnits": "seconds", - "rate": "1", - "nbRateUnits": "1", - "rateUnits": "second", - "randomFirst": "1", - "randomLast": "5", - "randomUnits": "seconds", - "drop": false, - "outputs": 1, - "x": 1160, - "y": 380, - "wires": [ - [ - "e41870d7.300eb8" - ] - ] - }, - { - "id": "8e3b3d3c.955148", - "type": "subflow:4ed26b8b.253504", - "z": "1eaf21c8.f7a21e", - "name": "", - "env": [], - "x": 1200, - "y": 420, - "wires": [] - }, - { - "id": "c534fd26.13741", - "type": "change", - "z": "1eaf21c8.f7a21e", - "name": "Get stepper_reverse", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.stepper_reverse", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 640, - "y": 440, - "wires": [ - [ - "cd1987c7.027f58" - ] - ] - }, - { - "id": "cd1987c7.027f58", - "type": "ui_switch", - "z": "1eaf21c8.f7a21e", - "name": "stepper_reverse", - "label": "Invert stepper output", - "tooltip": "Stepper 1 is controlled by output 1 or the other way around", - "group": "6be36295.0ab324", - "order": 5, - "width": 0, - "height": 0, - "passthru": false, - "decouple": "false", - "topic": "stepper_reverse", - "style": "", - "onvalue": "true", - "onvalueType": "bool", - "onicon": "", - "oncolor": "", - "offvalue": "false", - "offvalueType": "bool", - "officon": "", - "offcolor": "", - "x": 940, - "y": 440, - "wires": [ - [ - "8e3b3d3c.955148", - "2068e7f.f4efb18" - ] - ] - }, - { - "id": "54ba7f16.709ad8", - "type": "change", - "z": "1eaf21c8.f7a21e", - "name": "Get pump_steps_per_ml", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.pump_steps_per_ml", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 650, - "y": 400, - "wires": [ - [ - "ee58b91c.396108" - ] - ] - }, - { - "id": "ee58b91c.396108", - "type": "ui_text_input", - "z": "1eaf21c8.f7a21e", - "name": "pump_steps_per_ml", - "label": "Pump: steps per mL", - "tooltip": "", - "group": "6be36295.0ab324", - "order": 6, - "width": 0, - "height": 0, - "passthru": false, - "mode": "number", - "delay": "2000", - "topic": "pump_steps_per_ml", - "topicType": "str", - "x": 920, - "y": 400, - "wires": [ - [ - "2068e7f.f4efb18", - "8e3b3d3c.955148" - ] - ] - }, - { - "id": "7534dfd9.8cf3e8", - "type": "ui_template", - "z": "1eaf21c8.f7a21e", - "group": "6be36295.0ab324", - "name": "Information", - "order": 1, - "width": "8", - "height": 3, - "format": "
\n

\n Changing one of these values will cause the Python hardware controller to restart, to reload the new hardware configuration.\n

\n

\n Warning: selecting a hardware version from the dropdown menu below will also overwrite all of your hardware settings, including your camera white balance settings.\n

\n

\n If you are not sure, you probably should not be touching anything here!\n

\n
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": true, - "templateScope": "local", - "className": "", - "x": 590, - "y": 60, - "wires": [ - [] - ] - }, - { - "id": "a7e5c7f4.644678", - "type": "ui_dropdown", - "z": "1eaf21c8.f7a21e", - "name": "", - "label": "Hardware version", - "tooltip": "", - "place": "Select option", - "group": "6be36295.0ab324", - "order": 2, - "width": 0, - "height": 0, - "passthru": false, - "multiple": false, - "options": [ - { - "label": "", - "value": "PlanktoScope v2.1", - "type": "str" - }, - { - "label": "", - "value": "PlanktoScope v2.3", - "type": "str" - }, - { - "label": "", - "value": "PlanktoScope v2.5", - "type": "str" - }, - { - "label": "", - "value": "PlanktoScope v2.6", - "type": "str" - } - ], - "payload": "", - "topic": "acq_instrument", - "topicType": "str", - "className": "", - "x": 580, - "y": 160, - "wires": [ - [ - "3e2c5c1c.4c57b4", - "932a1ef8c2e81979", - "025ad3cdaa557843" - ] - ] - }, - { - "id": "1cfadc66.3cde8c", - "type": "subflow:1c24ad9c.bebec2", - "z": "1eaf21c8.f7a21e", - "name": "", - "env": [], - "x": 970, - "y": 160, - "wires": [ - [] - ] - }, - { - "id": "3e2c5c1c.4c57b4", - "type": "function", - "z": "1eaf21c8.f7a21e", - "name": "Save global", - "func": "global.set(msg.topic,msg.payload);\nreturn msg;", - "outputs": 1, - "timeout": "", - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 810, - "y": 160, - "wires": [ - [ - "1cfadc66.3cde8c" - ] - ] - }, - { - "id": "427c312.fc5e65", - "type": "subflow:1c24ad9c.bebec2", - "z": "1eaf21c8.f7a21e", - "name": "", - "env": [], - "x": 130, - "y": 160, - "wires": [ - [ - "2716aa5b3d027f95" - ] - ] - }, - { - "id": "c67c305004f87e39", - "type": "change", - "z": "1eaf21c8.f7a21e", - "name": "Get process_pixel_fixed", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.process_pixel_fixed", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 650, - "y": 480, - "wires": [ - [ - "244ca5dd62df2bcd" - ] - ] - }, - { - "id": "244ca5dd62df2bcd", - "type": "ui_text_input", - "z": "1eaf21c8.f7a21e", - "name": "process_pixel_fixed", - "label": "Pixel size calibration: um per pixel", - "tooltip": "Object size in µm / pixel. 0 will remove this calibration.", - "group": "6be36295.0ab324", - "order": 8, - "width": 0, - "height": 0, - "passthru": true, - "mode": "number", - "delay": "1000", - "topic": "process_pixel_fixed", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 930, - "y": 480, - "wires": [ - [ - "8e3b3d3c.955148", - "f9b47f4b1da15778" - ] - ] - }, - { - "id": "f9b47f4b1da15778", - "type": "function", - "z": "1eaf21c8.f7a21e", - "name": "Set or remove if null", - "func": "if (msg.payload == 0){\n global.set(msg.topic,undefined)\n}\nelse {\n global.set(msg.topic,msg.payload);\n}\n\nreturn msg", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 1200, - "y": 480, - "wires": [ - [ - "5d5ad36d2c50dcc2" - ] - ] - }, - { - "id": "5d5ad36d2c50dcc2", - "type": "link out", - "z": "1eaf21c8.f7a21e", - "name": "Process_pixel calibration", - "links": [], - "x": 1475, - "y": 500, - "wires": [] - }, - { - "id": "6146ba22df928516", - "type": "ui_dropdown", - "z": "1eaf21c8.f7a21e", - "name": "acq_fnumber_objective", - "label": "M12 Lens", - "tooltip": "", - "place": "Select option", - "group": "6be36295.0ab324", - "order": 7, - "width": 0, - "height": 0, - "passthru": true, - "multiple": false, - "options": [ - { - "label": "f 25mm 1/2\" 5MP IR", - "value": 25, - "type": "num" - }, - { - "label": "f 16mm 1/2.5\" 5MP IR", - "value": 16, - "type": "num" - }, - { - "label": "f 12mm 1/2.5\" 5MP IR", - "value": 12, - "type": "num" - }, - { - "label": "f 8mm 1/2.5\" 5MP IR", - "value": 8, - "type": "num" - }, - { - "label": "f 6mm 1/2.5\" 5MP IR", - "value": 6, - "type": "num" - } - ], - "payload": "", - "topic": "acq_fnumber_objective", - "topicType": "str", - "x": 910, - "y": 520, - "wires": [ - [ - "a6983d3232b570a7", - "8e3b3d3c.955148" - ] - ] - }, - { - "id": "a6983d3232b570a7", - "type": "change", - "z": "1eaf21c8.f7a21e", - "name": "", - "rules": [ - { - "t": "set", - "p": "acq_fnumber_objective", - "pt": "global", - "to": "payload", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 1240, - "y": 520, - "wires": [ - [ - "5d5ad36d2c50dcc2" - ] - ] - }, - { - "id": "11955bbeefc29ab4", - "type": "change", - "z": "1eaf21c8.f7a21e", - "name": "Get acq_fnumber_objective", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.acq_fnumber_objective", - "tot": "msg" - }, - { - "t": "set", - "p": "topic", - "pt": "msg", - "to": "acq_fnumber_objective", - "tot": "str" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 660, - "y": 520, - "wires": [ - [ - "6146ba22df928516" - ] - ] - }, - { - "id": "da3d4a90384d62a8", - "type": "subflow:e6665421f66ea4c8", - "z": "1eaf21c8.f7a21e", - "name": "", - "x": 360, - "y": 440, - "wires": [ - [ - "c534fd26.13741", - "54ba7f16.709ad8", - "c67c305004f87e39", - "11955bbeefc29ab4" - ] - ] - }, - { - "id": "f83560053c609914", - "type": "inject", - "z": "1eaf21c8.f7a21e", - "name": "Once", - "props": [], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "", - "x": 130, - "y": 440, - "wires": [ - [ - "da3d4a90384d62a8" - ] - ] - }, - { - "id": "e4ead350b3d07578", - "type": "link out", - "z": "1eaf21c8.f7a21e", - "name": "Reload hardware config", - "mode": "link", - "links": [ - "04920f50bbbf6a2a", - "45a7b5aa.2ed20c" - ], - "x": 875, - "y": 240, - "wires": [] - }, - { - "id": "025ad3cdaa557843", - "type": "ui_toast", - "z": "1eaf21c8.f7a21e", - "position": "top right", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 0, - "ok": "OK", - "cancel": "", - "raw": false, - "className": "", - "topic": "Resetting hardware configuration to version-specific default", - "name": "", - "x": 830, - "y": 120, - "wires": [] - }, - { - "id": "932a1ef8c2e81979", - "type": "change", - "z": "1eaf21c8.f7a21e", - "name": "Choose default hardware config", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "$join([\"/home/pi/PlanktoScope/device-backend/default-configs/\", $substringAfter(msg.payload, \"PlanktoScope \"), \".hardware.json\"])", - "tot": "jsonata" - } - ], - "action": "", - "property": "", - "from": "", + "page-titlebar-backgroundColor": { + "value": "#097479", + "edited": false + }, + "page-backgroundColor": { + "value": "#111111", + "edited": false + }, + "page-sidebar-backgroundColor": { + "value": "#333333", + "edited": false + }, + "group-textColor": { + "value": "#0eb8c0", + "edited": false + }, + "group-borderColor": { + "value": "#555555", + "edited": false + }, + "group-backgroundColor": { + "value": "#333333", + "edited": false + }, + "widget-textColor": { + "value": "#eeeeee", + "edited": false + }, + "widget-backgroundColor": { + "value": "#097479", + "edited": false + }, + "widget-borderColor": { + "value": "#333333", + "edited": false + }, + "base-font": { + "value": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif" + } + }, + "angularTheme": { + "primary": "indigo", + "accents": "blue", + "warn": "red", + "background": "grey", + "palette": "light" + } + }, + "site": { + "name": "PlanktoScope", + "hideToolbar": "false", + "allowSwipe": "false", + "lockMenu": "false", + "allowTempTheme": "true", + "dateFormat": "Y-MM-DD", + "sizes": { + "sx": 55, + "sy": 55, + "gx": 4, + "gy": 4, + "cx": 4, + "cy": 4, + "px": 4, + "py": 4 + } + } + }, + { + "id": "36739a35.7cce36", + "type": "ui_tab", + "name": "Gallery", + "icon": "fa-file-image-o", + "order": 6, + "disabled": false, + "hidden": false + }, + { + "id": "c0ebfc57.42527", + "type": "ui_group", + "name": "Group 1", + "tab": "36739a35.7cce36", + "order": 1, + "disp": false, + "width": "24", + "collapse": false + }, + { + "id": "737ec584.2eea2c", + "type": "ui_tab", + "name": "Sample", + "icon": "fa-eyedropper", + "order": 2, + "disabled": false, + "hidden": false + }, + { + "id": "6f97e7ae.270c48", + "type": "ui_group", + "name": "Group 1", + "tab": "3a6bb13f.c9703e", + "order": 1, + "disp": false, + "width": "4", + "collapse": false + }, + { + "id": "3e1ba03d.f01d8", + "type": "ui_group", + "name": "Sample Identification", + "tab": "737ec584.2eea2c", + "order": 1, + "disp": true, + "width": "10", + "collapse": false + }, + { + "id": "4e0cd5ea.17e59c", + "type": "ui_group", + "name": "Group 2", + "tab": "3a6bb13f.c9703e", + "order": 2, + "disp": false, + "width": "4", + "collapse": false + }, + { + "id": "ef590206.24f6", + "type": "ui_group", + "name": "Group 3", + "tab": "3a6bb13f.c9703e", + "order": 3, + "disp": false, + "width": "4", + "collapse": false + }, + { + "id": "ae8f6620.073358", + "type": "ui_group", + "name": "Group 4", + "tab": "3a6bb13f.c9703e", + "order": 4, + "disp": false, + "width": "4", + "collapse": false + }, + { + "id": "196518b2.4d53b7", + "type": "ui_group", + "name": "Group 5", + "tab": "3a6bb13f.c9703e", + "order": 5, + "disp": false, + "width": "4", + "collapse": false + }, + { + "id": "777a7c33.fcd804", + "type": "ui_group", + "name": "Group 6", + "tab": "3a6bb13f.c9703e", + "order": 6, + "disp": false, + "width": "4", + "collapse": false + }, + { + "id": "cef1e703.bcf3c8", + "type": "ui_group", + "name": "Sample Location", + "tab": "737ec584.2eea2c", + "order": 3, + "disp": false, + "width": "10", + "collapse": false + }, + { + "id": "5517c651.b2f668", + "type": "ui_group", + "name": "Validation", + "tab": "737ec584.2eea2c", + "order": 5, + "disp": false, + "width": 10, + "collapse": false + }, + { + "id": "fbd92986.1028c8", + "type": "ui_group", + "name": "Focus Adjustment", + "tab": "181bb236.1e94be", + "order": 2, + "disp": true, + "width": 4, + "collapse": false + }, + { + "id": "707d9797.c8e798", + "type": "ui_group", + "name": "Fluidic Manual Manipulation", + "tab": "181bb236.1e94be", + "order": 5, + "disp": true, + "width": 4, + "collapse": false + }, + { + "id": "7a0b4877.a5d268", + "type": "ui_group", + "name": "Navigation", + "tab": "181bb236.1e94be", + "order": 6, + "disp": false, + "width": 4, + "collapse": false + }, + { + "id": "404c301a.19c4e", + "type": "ui_group", + "name": "Fraction size", + "tab": "c9194f02.9d5e9", + "order": 2, + "disp": true, + "width": "10", + "collapse": false + }, + { + "id": "4322c187.e73e5", + "type": "ui_group", + "name": "Acquisition", + "tab": "c9194f02.9d5e9", + "order": 3, + "disp": true, + "width": 10, + "collapse": false + }, + { + "id": "b7919ae2.c01788", + "type": "ui_group", + "name": "Navigation", + "tab": "c9194f02.9d5e9", + "order": 6, + "disp": false, + "width": "10", + "collapse": false + }, + { + "id": "b5d61bc7.54fe48", + "type": "ui_group", + "name": "Statistics", + "tab": "c9194f02.9d5e9", + "order": 4, + "disp": true, + "width": "10", + "collapse": false + }, + { + "id": "8dc3722c.06efa8", + "type": "mqtt-broker", + "name": "", + "broker": "0.0.0.0", + "port": "1883", + "clientid": "Client_node", + "autoConnect": true, + "usetls": false, + "compatmode": false, + "protocolVersion": "4", + "keepalive": "60", + "cleansession": true, + "birthTopic": "", + "birthQos": "0", + "birthPayload": "", + "birthMsg": {}, + "closeTopic": "", + "closeQos": "0", + "closePayload": "", + "closeMsg": {}, + "willTopic": "", + "willQos": "0", + "willPayload": "", + "willMsg": {}, + "userProps": "", + "sessionExpiry": "" + }, + { + "id": "abeb6dad.635a2", + "type": "ui_group", + "name": "Control", + "tab": "8d16beb8.9b3fb", + "order": 1, + "disp": true, + "width": 10, + "collapse": false + }, + { + "id": "cf5d9f0e.d57e7", + "type": "ui_group", + "name": "Net Metadata", + "tab": "737ec584.2eea2c", + "order": 4, + "disp": false, + "width": "10", + "collapse": false + }, + { + "id": "ce9e278.781eed8", + "type": "ui_group", + "name": "Information", + "tab": "d9cd733b.ab73d", + "order": 5, + "disp": true, + "width": 6, + "collapse": false + }, + { + "id": "70de8209.68416c", + "type": "ui_group", + "name": "Status", + "tab": "c9194f02.9d5e9", + "order": 5, + "disp": true, + "width": 10, + "collapse": false + }, + { + "id": "46be9c86.dea684", + "type": "ui_group", + "name": "Status", + "tab": "8d16beb8.9b3fb", + "order": 2, + "disp": true, + "width": 10, + "collapse": false + }, + { + "id": "8c38a81e.9897a8", + "type": "ui_group", + "name": "Camera Settings", + "tab": "181bb236.1e94be", + "order": 3, + "disp": true, + "width": 6, + "collapse": false + }, + { + "id": "2489e51c.eed77a", + "type": "ui_tab", + "name": "Administration", + "icon": "dashboard", + "order": 9, + "disabled": false, + "hidden": false + }, + { + "id": "b0fb559a.6966a8", + "type": "ui_tab", + "name": "Hardware Settings", + "icon": "fa-cogs", + "disabled": false, + "hidden": false + }, + { + "id": "6be36295.0ab324", + "type": "ui_group", + "name": "Settings", + "tab": "b0fb559a.6966a8", + "order": 1, + "disp": false, + "width": "8", + "collapse": false, + "className": "" + }, + { + "id": "fc5e4e6f.5b1c8", + "type": "ui_group", + "name": "GPS Status", + "tab": "737ec584.2eea2c", + "order": 6, + "disp": true, + "width": 10, + "collapse": false + }, + { + "id": "f3ca28ef.4df0a8", + "type": "ui_group", + "name": "Shutdown", + "tab": "3a6bb13f.c9703e", + "order": 7, + "disp": true, + "width": 4, + "collapse": false + }, + { + "id": "3dfd8a69.69ed56", + "type": "ui_spacer", + "name": "spacer", + "group": "3e1ba03d.f01d8", + "order": 5, + "width": 10, + "height": 1 + }, + { + "id": "72a9216.2ff48e", + "type": "ui_spacer", + "name": "spacer", + "group": "4322c187.e73e5", + "order": 8, + "width": 10, + "height": 1 + }, + { + "id": "1b664927.c91d1f", + "type": "ui_spacer", + "name": "spacer", + "group": "b5d61bc7.54fe48", + "order": 2, + "width": 2, + "height": 1 + }, + { + "id": "1a663b6a.ab5805", + "type": "ui_spacer", + "name": "spacer", + "group": "b5d61bc7.54fe48", + "order": 4, + "width": 2, + "height": 1 + }, + { + "id": "8eeed8d8.ad9098", + "type": "ui_spacer", + "name": "spacer", + "group": "b5d61bc7.54fe48", + "order": 5, + "width": 2, + "height": 1 + }, + { + "id": "be1c5ce7.004e", + "type": "ui_spacer", + "name": "spacer", + "group": "b5d61bc7.54fe48", + "order": 6, + "width": 2, + "height": 1 + }, + { + "id": "c2fe38e9.555e3", + "type": "ui_spacer", + "name": "spacer", + "group": "b5d61bc7.54fe48", + "order": 7, + "width": 2, + "height": 1 + }, + { + "id": "89bd18b7.c779a8", + "type": "ui_spacer", + "name": "spacer", + "group": "b5d61bc7.54fe48", + "order": 8, + "width": 2, + "height": 1 + }, + { + "id": "3cbbfa5d.efa636", + "type": "ui_spacer", + "name": "spacer", + "group": "b7919ae2.c01788", + "order": 2, + "width": 5, + "height": 1 + }, + { + "id": "97148e8d8e298f1a", + "type": "ui_spacer", + "z": "cb95299c.2817c8", + "name": "spacer", + "group": "abeb6dad.635a2", + "order": 7, + "width": 10, + "height": 1 + }, + { + "id": "3b2eccc574e6a9ae", + "type": "ui_spacer", + "z": "cb95299c.2817c8", + "name": "spacer", + "group": "abeb6dad.635a2", + "order": 11, + "width": 1, + "height": 1 + }, + { + "id": "bbd6431d97c86f97", + "type": "ui_spacer", + "z": "cb95299c.2817c8", + "name": "spacer", + "group": "46be9c86.dea684", + "order": 4, + "width": 3, + "height": 1 + }, + { + "id": "5f98f5f140f0ecde", + "type": "ui_spacer", + "z": "cb95299c.2817c8", + "name": "spacer", + "group": "46be9c86.dea684", + "order": 6, + "width": 3, + "height": 1 + }, + { + "id": "7bc0a4c416e4545c", + "type": "ui_group", + "name": "Culture Date and Time", + "tab": "737ec584.2eea2c", + "order": 2, + "disp": true, + "width": "10", + "collapse": false, + "className": "" + }, + { + "id": "6c31ad948a9d62fd", + "type": "ui_spacer", + "name": "spacer", + "group": "4248342d.e55fac", + "order": 2, + "width": 1, + "height": 1 + }, + { + "id": "833bc5bb.217ba8", + "type": "ui_group", + "name": "Preview", + "tab": "181bb236.1e94be", + "order": 1, + "disp": true, + "width": 18, + "collapse": false + }, + { + "id": "a7d64879.38298", + "type": "ui_group", + "name": "Logs", + "tab": "2489e51c.eed77a", + "order": 1, + "disp": true, + "width": "12", + "collapse": true, + "className": "" + }, + { + "id": "6465bdd5.15eb8c", + "type": "file in", + "z": "1c24ad9c.bebec2", + "name": "", + "filename": "/home/pi/PlanktoScope/config.json", + "filenameType": "str", + "format": "utf8", + "chunk": false, + "sendError": false, + "encoding": "none", + "x": 560, + "y": 60, + "wires": [["15ceb135.6628bf"]], + "info": "# PlanktoScope Help\nThis Node will read the content of the file named **config.txt** containing all the input placeholders.\n" + }, + { + "id": "15ceb135.6628bf", + "type": "json", + "z": "1c24ad9c.bebec2", + "name": "config.json", + "property": "payload", + "action": "", + "pretty": false, + "x": 730, + "y": 60, + "wires": [["ad541674.4791c8"]] + }, + { + "id": "7205d267.36adcc", + "type": "file", + "z": "1c24ad9c.bebec2", + "name": "", + "filename": "/home/pi/PlanktoScope/config.json", + "appendNewline": true, + "createDir": true, + "overwriteFile": "true", + "encoding": "none", + "x": 990, + "y": 160, + "wires": [[]] + }, + { + "id": "2e6ddf51.c0dba", + "type": "json", + "z": "1c24ad9c.bebec2", + "name": "config.json", + "property": "payload", + "action": "str", + "pretty": true, + "x": 730, + "y": 160, + "wires": [["7205d267.36adcc"]] + }, + { + "id": "ad541674.4791c8", + "type": "function", + "z": "1c24ad9c.bebec2", + "name": "Global Set", + "func": "global.set(\"config_keys\", Object.keys(msg.payload));\n\nfor (const key in msg.payload) {\n global.set(key, msg.payload[key]);\n}\n\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 910, + "y": 60, + "wires": [[]] + }, + { + "id": "3e9a33c.141384c", + "type": "inject", + "z": "1c24ad9c.bebec2", + "name": "Load config", + "props": [ + { + "p": "topic", + "vt": "str" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "payloadType": "str", + "x": 230, + "y": 60, + "wires": [["6465bdd5.15eb8c"]] + }, + { + "id": "3ad9835.08c937c", + "type": "function", + "z": "1c24ad9c.bebec2", + "name": "get config payload", + "func": "keys = global.get(\"config_keys\")\n\nvar payload = {}\n\nkeys.forEach(function(item, index, array) {\n payload[item] = global.get(item);\n})\n\nreturn {\"payload\": payload};", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 410, + "y": 160, + "wires": [["2e6ddf51.c0dba"]] + }, + { + "id": "f439663c.8abd3", + "type": "ui_ui_control", + "z": "1c24ad9c.bebec2", + "name": "Connect Event", + "events": "connect", + "x": 220, + "y": 100, + "wires": [["6465bdd5.15eb8c"]] + }, + { + "id": "82099021.9ceb08", + "type": "file", + "z": "4ed26b8b.253504", + "name": "", + "filename": "/home/pi/PlanktoScope/hardware.json", + "appendNewline": true, + "createDir": true, + "overwriteFile": "true", + "encoding": "none", + "x": 660, + "y": 40, + "wires": [[]] + }, + { + "id": "bb0a8725.a1849", + "type": "json", + "z": "4ed26b8b.253504", + "name": "Create JSON", + "property": "payload", + "action": "str", + "pretty": true, + "x": 490, + "y": 40, + "wires": [["82099021.9ceb08"]] + }, + { + "id": "53d163be.47cf24", + "type": "function", + "z": "4ed26b8b.253504", + "name": "Update and retrieve hardware_conf", + "func": "// change global\nhardware_conf = global.get(\"hardware_conf\");\n\nif (msg.topic == \"process_pixel_fixed\" && msg.payload == 0){\n delete hardware_conf[msg.topic]\n delete msg.topic\n}\n\nif (msg.topic !== null && msg.topic !== undefined){\n hardware_conf[msg.topic] = msg.payload;\n global.set(\"hardware_conf\", hardware_conf);\n}\n\nreturn {\"payload\": hardware_conf};", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 240, + "y": 40, + "wires": [["bb0a8725.a1849"]] + }, + { + "id": "48ceeda454438cb7", + "type": "file in", + "z": "e6665421f66ea4c8", + "name": "", + "filename": "/home/pi/PlanktoScope/hardware.json", + "filenameType": "str", + "format": "utf8", + "chunk": false, + "sendError": false, + "encoding": "none", + "x": 250, + "y": 40, + "wires": [["853c938a270fd85e"]], + "info": "# PlanktoScope Help\nThis Node will read the content of the file named **config.txt** containing all the input placeholders.\n" + }, + { + "id": "853c938a270fd85e", + "type": "json", + "z": "e6665421f66ea4c8", + "name": "Parse JSON", + "property": "payload", + "action": "", + "pretty": false, + "x": 510, + "y": 40, + "wires": [["2b1a67ac127f3fe7"]] + }, + { + "id": "2b1a67ac127f3fe7", + "type": "change", + "z": "e6665421f66ea4c8", + "name": "", + "rules": [ + { + "t": "set", + "p": "hardware_conf", + "pt": "global", + "to": "payload", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 730, + "y": 40, + "wires": [[]] + }, + { + "id": "2f30a6ee99587899", + "type": "comment", + "z": "eaae323a.31b3", + "name": "LICENSE", + "info": "Copyright 2022 Thibaut Pollina and Romain Bazile\nLicensed under GPL v3.0", + "x": 140, + "y": 600, + "wires": [] + }, + { + "id": "4e78af2d.90be7", + "type": "ui_ui_control", + "z": "eaae323a.31b3", + "name": "", + "events": "change", + "x": 440, + "y": 160, + "wires": [[]] + }, + { + "id": "7789839d.69b48c", + "type": "ui_template", + "z": "eaae323a.31b3", + "group": "4e0cd5ea.17e59c", + "name": "Optic Configuration", + "order": 1, + "width": 4, + "height": 4, + "format": "\n \n
Optic Configuration
\n
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "x": 130, + "y": 100, + "wires": [["4e78af2d.90be7"]] + }, + { + "id": "6ea6c306.f9c12c", + "type": "ui_template", + "z": "eaae323a.31b3", + "group": "ef590206.24f6", + "name": "Fluidic Acquisition", + "order": 1, + "width": 4, + "height": 4, + "format": "\n \n
Fluidic Acquisition
\n
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "x": 130, + "y": 140, + "wires": [["4e78af2d.90be7"]] + }, + { + "id": "bb9eb153.9e36c", + "type": "ui_template", + "z": "eaae323a.31b3", + "group": "ae8f6620.073358", + "name": "Segmentation", + "order": 1, + "width": 4, + "height": 4, + "format": "\n \n
Segmentation
\n
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "x": 140, + "y": 180, + "wires": [["4e78af2d.90be7"]] + }, + { + "id": "eaf8ee7f.96f44", + "type": "ui_template", + "z": "eaae323a.31b3", + "group": "196518b2.4d53b7", + "name": "Gallery", + "order": 1, + "width": 4, + "height": 4, + "format": "\n \n
Gallery
\n
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "x": 160, + "y": 220, + "wires": [["4e78af2d.90be7"]] + }, + { + "id": "c1b1469.9650eb8", + "type": "ui_template", + "z": "eaae323a.31b3", + "group": "777a7c33.fcd804", + "name": "System Monitoring", + "order": 1, + "width": 4, + "height": 4, + "format": "\n \n
System Monitoring
\n
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "x": 130, + "y": 260, + "wires": [["4e78af2d.90be7"]] + }, + { + "id": "abafd6e6.04a5f8", + "type": "ui_template", + "z": "eaae323a.31b3", + "group": "6f97e7ae.270c48", + "name": "Sample", + "order": 1, + "width": 4, + "height": 4, + "format": "\n \n
Sample
\n
\n In doubt? Start Here!\n
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "x": 160, + "y": 60, + "wires": [["4e78af2d.90be7"]] + }, + { + "id": "dab82064.26a8d", + "type": "ui_button", + "z": "eaae323a.31b3", + "name": "Unlock button", + "group": "f3ca28ef.4df0a8", + "order": 2, + "width": 0, + "height": 0, + "passthru": false, + "label": "Unlock button", + "tooltip": "", + "color": "", + "bgcolor": "", + "icon": "", + "payload": "shutdown", + "payloadType": "flow", + "topic": "", + "x": 120, + "y": 380, + "wires": [["6c3a3b4.78cad44"]] + }, + { + "id": "1c658761.b852a1", + "type": "ui_toast", + "z": "eaae323a.31b3", + "position": "dialog", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 1, + "ok": "YES PLEASE", + "cancel": "NO!", + "raw": false, + "topic": "Are you sure?", + "name": "Confirmation message", + "x": 800, + "y": 380, + "wires": [["8f1b8e23.daafe"]] + }, + { + "id": "a48ff63f.db5e18", + "type": "inject", + "z": "eaae323a.31b3", + "name": "disabled", + "props": [ + { + "p": "enabled", + "v": "false", + "vt": "bool" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "x": 140, + "y": 420, + "wires": [["d58039a9.6e7928"]] + }, + { + "id": "b67a7147.65fcd8", + "type": "ui_button", + "z": "eaae323a.31b3", + "name": "Shutdown button", + "group": "f3ca28ef.4df0a8", + "order": 4, + "width": 0, + "height": 0, + "passthru": false, + "label": "Shutdown", + "tooltip": "", + "color": "", + "bgcolor": "#AD1625", + "icon": "fa-power-off fa-2x", + "payload": "Do you want to turn the machine off now?", + "payloadType": "str", + "topic": "", + "x": 550, + "y": 380, + "wires": [["1c658761.b852a1"]] + }, + { + "id": "d58039a9.6e7928", + "type": "change", + "z": "eaae323a.31b3", + "name": "", + "rules": [ + { + "t": "set", + "p": "shutdown", + "pt": "flow", + "to": "false", + "tot": "bool" + }, + { + "t": "set", + "p": "enabled", + "pt": "msg", + "to": "shutdown", + "tot": "flow" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 320, + "y": 420, + "wires": [["b67a7147.65fcd8"]] + }, + { + "id": "6c3a3b4.78cad44", + "type": "function", + "z": "eaae323a.31b3", + "name": "Toggle", + "func": "flow.set(\"shutdown\", !flow.get(\"shutdown\"))\nmsg.enabled = flow.get(\"shutdown\")\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 290, + "y": 380, + "wires": [["b67a7147.65fcd8"]] + }, + { + "id": "d1153ad6.40d738", + "type": "ui_template", + "z": "eaae323a.31b3", + "group": "f3ca28ef.4df0a8", + "name": "Shutdown information", + "order": 1, + "width": 0, + "height": 0, + "format": "
To prevent data corruption, please always shutdown the machine before unplugging the unit.\n

\nRemember to first unlock the shutdown button.\n
", + "storeOutMessages": true, + "fwdInMessages": false, + "resendOnRefresh": true, + "templateScope": "local", + "x": 120, + "y": 320, + "wires": [[]] + }, + { + "id": "e08cfcb8.2a67e8", + "type": "link out", + "z": "eaae323a.31b3", + "name": "Home shutdown button", + "links": ["b81b990a.d4dca"], + "x": 715, + "y": 500, + "wires": [] + }, + { + "id": "ce7087fc.dcc9e8", + "type": "ui_toast", + "z": "eaae323a.31b3", + "position": "dialog", + "displayTime": "10", + "highlight": "", + "sendall": true, + "outputs": 1, + "ok": "OK", + "cancel": "", + "raw": false, + "topic": "Turning off now!", + "name": "Shutdown message", + "x": 570, + "y": 540, + "wires": [[]] + }, + { + "id": "7d1626a0.deb85", + "type": "change", + "z": "eaae323a.31b3", + "name": "shutdown!", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "shutdown", + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 300, + "y": 500, + "wires": [["e08cfcb8.2a67e8"]] + }, + { + "id": "8f1b8e23.daafe", + "type": "switch", + "z": "eaae323a.31b3", + "name": "", + "property": "payload", + "propertyType": "msg", + "rules": [ + { + "t": "eq", + "v": "NO!", + "vt": "str" + }, + { + "t": "else" + } + ], + "checkall": "true", + "repair": false, + "outputs": 2, + "x": 150, + "y": 500, + "wires": [["d58039a9.6e7928"], ["7d1626a0.deb85", "281a56c9.ec7902"]] + }, + { + "id": "281a56c9.ec7902", + "type": "change", + "z": "eaae323a.31b3", + "name": "Shutdown message", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "Please wait a minute before disconnecting the machine from its power supply!", + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 330, + "y": 540, + "wires": [["ce7087fc.dcc9e8"]] + }, + { + "id": "4557d689.a4fa88", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "sample_ship", + "label": "Name of the ship", + "tooltip": "", + "group": "3e1ba03d.f01d8", + "order": 2, + "width": 0, + "height": 0, + "passthru": true, + "mode": "text", + "delay": "300", + "topic": "sample_ship", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 670, + "y": 80, + "wires": [["9f501f49.45645"]] + }, + { + "id": "fcfc31ae.af3af", + "type": "ui_dropdown", + "z": "b771c342.49603", + "name": "sample_sampling_gear", + "label": "Sampling gear*", + "tooltip": "", + "place": "Choose from list", + "group": "3e1ba03d.f01d8", + "order": 6, + "width": 0, + "height": 0, + "passthru": true, + "multiple": false, + "options": [ + { + "label": "High Speed Net", + "value": "net_hsn", + "type": "str" + }, + { + "label": "Tara Decknet", + "value": "net_decknet", + "type": "str" + }, + { + "label": "Plankton net", + "value": "net", + "type": "str" + }, + { + "label": "Niskin bottle 12L", + "value": "niskin_12L", + "type": "str" + }, + { + "label": "Niskin bottle 24L", + "value": "niskin_24L", + "type": "str" + }, + { + "label": "Pass Hull", + "value": "pass_hull", + "type": "str" + }, + { + "label": "Single location (with net or bucket)", + "value": "single_location", + "type": "str" + }, + { + "label": "Lab culture", + "value": "culture", + "type": "str" + }, + { + "label": "Test", + "value": "test", + "type": "str" + } + ], + "payload": "", + "topic": "sample_sampling_gear", + "topicType": "str", + "className": "", + "x": 630, + "y": 200, + "wires": [["9f501f49.45645", "46eb1bf8.3dc5f4", "3ac7b631f5d8ef90"]] + }, + { + "id": "82c5fc77.59c97", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "sample_operator", + "label": "Name of the operator*", + "tooltip": "", + "group": "3e1ba03d.f01d8", + "order": 3, + "width": 0, + "height": 0, + "passthru": true, + "mode": "text", + "delay": "300", + "topic": "sample_operator", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 650, + "y": 160, + "wires": [["9f501f49.45645"]] + }, + { + "id": "9c882b37.fde668", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "sample_project", + "label": "Name of the project*", + "tooltip": "", + "group": "3e1ba03d.f01d8", + "order": 1, + "width": 0, + "height": 0, + "passthru": true, + "mode": "text", + "delay": "300", + "topic": "sample_project", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 660, + "y": 40, + "wires": [["9f501f49.45645"]] + }, + { + "id": "94eb4221.9b92c", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "sample_id", + "label": "Station ID*", + "tooltip": "", + "group": "3e1ba03d.f01d8", + "order": 4, + "width": 0, + "height": 0, + "passthru": true, + "mode": "text", + "delay": "300", + "topic": "sample_id", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 670, + "y": 120, + "wires": [["9f501f49.45645"]] + }, + { + "id": "9f501f49.45645", + "type": "function", + "z": "b771c342.49603", + "name": "set global", + "func": "global.set(msg.topic,msg.payload);", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 1080, + "y": 200, + "wires": [[]] + }, + { + "id": "222c851d.5d0a3a", + "type": "ui_ui_control", + "z": "b771c342.49603", + "name": "", + "events": "change", + "x": 400, + "y": 880, + "wires": [[]] + }, + { + "id": "52f6b103.1efb6", + "type": "ui_toast", + "z": "b771c342.49603", + "position": "dialog", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 1, + "ok": "OK", + "cancel": "", + "raw": false, + "topic": "", + "name": "", + "x": 710, + "y": 980, + "wires": [[]] + }, + { + "id": "986d960a.c75908", + "type": "function", + "z": "b771c342.49603", + "name": "Check form", + "func": "var sample_project= global.get(\"sample_project\");\nvar sample_id= global.get(\"sample_id\");\nvar sample_operator= global.get(\"sample_operator\");\nvar sample_sampling_gear= global.get(\"sample_sampling_gear\");\nvar object_lat= global.get(\"object_lat\");\nvar object_lon= global.get(\"object_lon\");\nvar object_date= global.get(\"object_date\");\nvar object_time= global.get(\"object_time\");\nif (sample_project === undefined || sample_project === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Sample project\"\n return [null, msg];\n}\n\nelse if (sample_id === undefined || sample_id === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Sample ID\"\n return [null, msg];\n}\n\nelse if (sample_operator === undefined || sample_operator === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Sample operator\"\n return [null, msg];\n}\n\nelse if (sample_sampling_gear === undefined || sample_sampling_gear === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Sample sampling gear\"\n return [null, msg];\n}\n\nelse if (object_lat === undefined || object_lat === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Latitude of sample\"\n return [null, msg];\n}\n\nelse if (object_lon === undefined || object_lon === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Longitude of sample\"\n return [null, msg];\n}\n\nelse if (object_date === undefined || object_date === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Date of sample\"\n return [null, msg];\n}\n\nelse if (object_time === undefined || object_time === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Time of sample\"\n return [null, msg];\n}\nelse if (sample_sampling_gear.startsWith(\"net\")){\n var object_lat_end = global.get(\"object_lat_end\");\n var object_lon_end = global.get(\"object_lon_end\");\n var object_date_end = global.get(\"object_date_end\");\n var object_time_end = global.get(\"object_time_end\");\n var sample_gear_net_opening = global.get(\"sample_gear_net_opening\");\n\n if (object_lat_end === undefined || object_lat_end === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Latitude of retrieval\"\n return [null, msg];\n }\n \n else if (object_lon_end === undefined || object_lon_end === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Longitude of retrieval\"\n return [null, msg];\n }\n \n else if (object_date_end === undefined || object_date_end === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Date of retrieval\"\n return [null, msg];\n }\n \n else if (object_time_end === undefined || object_time_end === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Time of retrieval\"\n return [null, msg];\n }\n \n else if (sample_gear_net_opening === undefined || sample_gear_net_opening === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Net opening dimension\"\n return [null, msg];\n }\n \n if (sample_sampling_gear == \"net_decknet\"){\n var sample_total_volume = global.get(\"sample_total_volume\");\n if (sample_total_volume === undefined || sample_total_volume === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Decknet flowmeter readings\"\n return [null, msg];\n }\n }\n}\nmsg.topic = \"config_save\"\nmsg.payload={\"tab\":\"Optic Configuration\"};\n\nreturn [msg, null];", + "outputs": 2, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 470, + "y": 940, + "wires": [["726a7822.cd6298", "e2b277c1.07283"], ["52f6b103.1efb6"]], + "outputLabels": ["message", "error"] + }, + { + "id": "18f44504.cac66b", + "type": "gpsd", + "z": "b771c342.49603", + "name": "", + "hostname": "localhost", + "port": "2947", + "tpv": true, + "sky": false, + "info": false, + "device": false, + "gst": false, + "att": false, + "x": 250, + "y": 1240, + "wires": [ + [ + "258b4562.9f778a", + "54e37580.fdc31c", + "cc21ca16.b92928", + "4a4de52c.cf2884", + "73c4a14a.9b93c8" + ] + ] + }, + { + "id": "726a7822.cd6298", + "type": "ui_ui_control", + "z": "b771c342.49603", + "name": "", + "events": "change", + "x": 700, + "y": 900, + "wires": [[]] + }, + { + "id": "16de754c.cc969b", + "type": "ui_button", + "z": "b771c342.49603", + "name": "", + "group": "5517c651.b2f668", + "order": 1, + "width": 5, + "height": 1, + "passthru": false, + "label": "Previous", + "tooltip": "", + "color": "#097479", + "bgcolor": "white", + "icon": "keyboard_return", + "payload": "{\"tab\":\"Home\"}", + "payloadType": "json", + "topic": "", + "x": 240, + "y": 880, + "wires": [["222c851d.5d0a3a"]] + }, + { + "id": "84f3d040.5f7ea", + "type": "ui_button", + "z": "b771c342.49603", + "name": "", + "group": "5517c651.b2f668", + "order": 2, + "width": 5, + "height": 1, + "passthru": false, + "label": "Continue", + "tooltip": "", + "color": "#097479", + "bgcolor": "white", + "icon": "keyboard_tab", + "payload": "{\"tab\":\"Home\"}", + "payloadType": "json", + "topic": "", + "x": 240, + "y": 940, + "wires": [["986d960a.c75908"]] + }, + { + "id": "d027a6bf.7049e8", + "type": "function", + "z": "b771c342.49603", + "name": "get sample_projet", + "func": "msg.payload = msg.payload.sample_project;\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 310, + "y": 40, + "wires": [["9c882b37.fde668"]] + }, + { + "id": "5a811caf.0f3144", + "type": "function", + "z": "b771c342.49603", + "name": "get sample_ship", + "func": "msg.payload = msg.payload.sample_ship;\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 300, + "y": 80, + "wires": [["4557d689.a4fa88"]] + }, + { + "id": "45911c98.2bd83c", + "type": "function", + "z": "b771c342.49603", + "name": "get sample_id", + "func": "msg.payload = msg.payload.sample_id;\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 300, + "y": 120, + "wires": [["94eb4221.9b92c"]] + }, + { + "id": "1e09a4ab.72996b", + "type": "function", + "z": "b771c342.49603", + "name": "get sample_operator", + "func": "msg.payload = msg.payload.sample_operator;\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 320, + "y": 160, + "wires": [["82c5fc77.59c97"]] + }, + { + "id": "a3272681.f271c8", + "type": "function", + "z": "b771c342.49603", + "name": "get sample_sampling_gear", + "func": "msg.topic = \"sample_sampling_gear\"\nif (msg.payload.sample_sampling_gear === undefined){\n msg.payload = \"net\";\n}\nelse\n{\n msg.payload = msg.payload.sample_sampling_gear;\n}\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 340, + "y": 200, + "wires": [["fcfc31ae.af3af"]] + }, + { + "id": "a6907a38.f6611", + "type": "subflow:1c24ad9c.bebec2", + "z": "b771c342.49603", + "name": "", + "env": [], + "x": 70, + "y": 220, + "wires": [ + [ + "d027a6bf.7049e8", + "5a811caf.0f3144", + "45911c98.2bd83c", + "1e09a4ab.72996b", + "8dff1648.82e42", + "9f04c5ec.75f3d8", + "f408a273.4fb538", + "e73fd87d.d24e4", + "489c8e06.cc7d6", + "a3272681.f271c8" + ] + ] + }, + { + "id": "e2b277c1.07283", + "type": "subflow:1c24ad9c.bebec2", + "z": "b771c342.49603", + "name": "", + "env": [], + "x": 690, + "y": 940, + "wires": [[]] + }, + { + "id": "7116e906.9f50f", + "type": "ui_text", + "z": "b771c342.49603", + "group": "fc5e4e6f.5b1c8", + "order": 1, + "width": 10, + "height": 1, + "name": "GPS Status Display", + "label": "GPS Status:", + "format": "{{msg.payload}}", + "layout": "row-center", + "x": 730, + "y": 1080, + "wires": [] + }, + { + "id": "9c7f7fc9.c8d3a", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "object_depth_max", + "label": "Max sampling depth (m)", + "tooltip": "in m", + "group": "3e1ba03d.f01d8", + "order": 10, + "width": 5, + "height": 1, + "passthru": true, + "mode": "number", + "delay": "300", + "topic": "object_depth_max", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 650, + "y": 240, + "wires": [["9f501f49.45645"]] + }, + { + "id": "317eeeb7.8d3042", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "object_depth_min", + "label": "Min sampling depth (m)", + "tooltip": "in m", + "group": "3e1ba03d.f01d8", + "order": 9, + "width": 5, + "height": 1, + "passthru": true, + "mode": "number", + "delay": "300", + "topic": "object_depth_min", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 650, + "y": 280, + "wires": [["9f501f49.45645"]] + }, + { + "id": "cbb123ab.fd3428", + "type": "ui_ui_control", + "z": "b771c342.49603", + "name": "show/hide net groups", + "events": "change", + "x": 1320, + "y": 300, + "wires": [[]] + }, + { + "id": "642ff403.1ed91c", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "sample_concentrated_sample_volume", + "label": "Concentrated sample volume (mL)", + "tooltip": "Volume extracted from the net codend (in mL)", + "group": "3e1ba03d.f01d8", + "order": 12, + "width": 10, + "height": 1, + "passthru": true, + "mode": "number", + "delay": "300", + "topic": "sample_concentrated_sample_volume", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 590, + "y": 440, + "wires": [["9f501f49.45645"]] + }, + { + "id": "e967b844.46aa48", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "sample_gear_net_opening", + "label": "Net opening dimension (mm)", + "tooltip": "Size of the net mouth opening (in mm)", + "group": "cf5d9f0e.d57e7", + "order": 1, + "width": 10, + "height": 1, + "passthru": true, + "mode": "number", + "delay": "300", + "topic": "sample_gear_net_opening", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 620, + "y": 320, + "wires": [["9f501f49.45645"]] + }, + { + "id": "c0ce5626.b6c5", + "type": "ui_toast", + "z": "b771c342.49603", + "position": "dialog", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 1, + "ok": "OK", + "cancel": "", + "raw": false, + "topic": "", + "name": "", + "x": 1230, + "y": 620, + "wires": [[]] + }, + { + "id": "c33f1124.af6688", + "type": "ui_form", + "z": "b771c342.49603", + "name": "sample_location", + "label": "Sample Location", + "group": "cef1e703.bcf3c8", + "order": 1, + "width": 0, + "height": 0, + "options": [ + { + "label": "Latitude (36.574439°N or 36°57.4439'N)", + "value": "object_lat", + "type": "text", + "required": true, + "rows": null + }, + { + "label": "Longitude (110.42100°W or 110°4.2100'W)", + "value": "object_lon", + "type": "text", + "required": true, + "rows": null + }, + { + "label": "Date (YYYY-MM-DD, UTC)", + "value": "object_date", + "type": "text", + "required": true, + "rows": null + }, + { + "label": "Time (HH:MM(:SS), UTC 24h)", + "value": "object_time", + "type": "text", + "required": true, + "rows": null + } + ], + "formValue": { + "object_lat": "", + "object_lon": "", + "object_date": "", + "object_time": "" + }, + "payload": "", + "submit": "Validate", + "cancel": "Reset", + "topic": "sample_location", + "x": 660, + "y": 580, + "wires": [["14658615.47c862", "3318a1aaa70fc2ee"]] + }, + { + "id": "358908cd.416ab", + "type": "ui_form", + "z": "b771c342.49603", + "name": "net_throw_location", + "label": "Net Throw Location", + "group": "cf5d9f0e.d57e7", + "order": 3, + "width": 0, + "height": 0, + "options": [ + { + "label": "Latitude (36.574439°N or 36°57.4439'N)", + "value": "object_lat", + "type": "text", + "required": true, + "rows": null + }, + { + "label": "Longitude (110.42100°W or 110°4.2100'W)", + "value": "object_lon", + "type": "text", + "required": true, + "rows": null + }, + { + "label": "Date (YYYY-MM-DD UTC)", + "value": "object_date", + "type": "text", + "required": true, + "rows": null + }, + { + "label": "Time (HH:MM, UTC 24h)", + "value": "object_time", + "type": "text", + "required": true, + "rows": null + } + ], + "formValue": { + "object_lat": "", + "object_lon": "", + "object_date": "", + "object_time": "" + }, + "payload": "", + "submit": "Validate", + "cancel": "", + "topic": "net_throw_location", + "topicType": "str", + "splitLayout": false, + "className": "", + "x": 650, + "y": 620, + "wires": [["14658615.47c862", "cc67c97f55a340d3"]] + }, + { + "id": "56d40584.eff4e4", + "type": "ui_form", + "z": "b771c342.49603", + "name": "net_retrieval_location", + "label": "Net Retrieval Location", + "group": "cf5d9f0e.d57e7", + "order": 4, + "width": 0, + "height": 0, + "options": [ + { + "label": "Latitude (36.574439°N or 36°57.4439'N)", + "value": "object_lat_end", + "type": "text", + "required": true, + "rows": null + }, + { + "label": "Longitude (110.42100°W or 110°4.2100'W)", + "value": "object_lon_end", + "type": "text", + "required": true, + "rows": null + }, + { + "label": "Date (YYYY-MM-DD UTC)", + "value": "object_date_end", + "type": "text", + "required": true, + "rows": null + }, + { + "label": "Time (HH:MM, UTC 24h)", + "value": "object_time_end", + "type": "text", + "required": true, + "rows": null + } + ], + "formValue": { + "object_lat_end": "", + "object_lon_end": "", + "object_date_end": "", + "object_time_end": "" + }, + "payload": "", + "submit": "Validate", + "cancel": "", + "topic": "net_retrieval_location", + "topicType": "str", + "splitLayout": false, + "x": 640, + "y": 660, + "wires": [["14658615.47c862", "9c8f370d124a55e4"]] + }, + { + "id": "14658615.47c862", + "type": "function", + "z": "b771c342.49603", + "name": "Validate Location / Timestamp", + "func": "// Code added here will be run once\n// whenever the node is started.\nfunction ConvertDDMMToDD(input) {\n // Input Format 36°57.4439'N, 110°4.2100'W\n // From https://stackoverflow.com/questions/1140189/converting-latitude-and-longitude-to-decimal-values\n if (!input.match(/\\d+°\\d+\\.*\\d*\\'[NSEW]/)){\n \treturn \"parsing error\"\n }\n var parts = input.split(/[^\\d.\\w]+/)\n if (parts.length != 3){\n \treturn \"parsing error\"\n }\n var dd = Number(parts[0]) + Number(parts[1])/60\n return dd.toFixed(6) + parts[2]\n}\n\nfunction ValidateCoordinates(input, lat){\n // Input Format 36.574439°N, 110.42100°W\n // Or 36°57.4439'N, 110°4.2100'W\n if (input.match(\"'\")){\n input = ConvertDDMMToDD(input)\n }\n \n var error = {}\n\n if (input.startsWith(\"parsing error\")){\n error.topic = \"Error with the \"\n error.payload = \"You need to respect the format example, 36.574439°N or 36°57.4439'N\"\n return [null, error]\n }\n \n var direction = input.match(/[NSEW]/)\n var position = input.match(/[\\+\\-\\d\\.]+/)\n \n if (direction === null){\n error.topic = \"Error with the \"\n error.payload = \"You need to explicitely enter N/S/E/W\"\n return [null, error]\n }\n \n // Test that position is only made of digits!\n if(/^[\\+\\-]/.test(position)){\n error.topic = \"Error with the \"\n error.payload = \"Use of +/- sign is inconsistent with N/S/E/W letter! Please only use N/S/E/W!\"\n return [null, error]\n }\n \n var dd = Number(position)\n if (lat){\n // Check latitude\n if (direction == \"S\" || direction == \"N\") {\n if (dd>90.0){\n error.topic = \"Error with the \"\n error.payload = \"Latitude is more than 90°\"\n return [null, error]\n }\n }\n if (direction == \"W\" || direction == \"E\") {\n error.topic = \"Error with the \"\n error.payload = \"This is not a Latitude!\"\n return [null, error]\n }\n }\n else{\n // Check longitude\n if (direction == \"W\" || direction == \"E\") {\n if (dd>180.0){\n error.topic = \"Error with the \"\n error.payload = \"Longitude is more than 180°\"\n return [null, error]\n }\n }\n if (direction == \"N\" || direction == \"S\") {\n error.topic = \"Error with the \"\n error.payload = \"This is not a Longitude!\"\n return [null, error]\n }\n }\n \n if (direction == \"S\" || direction == \"W\") {\n dd = dd * -1\n } // Don't do anything for N or E\n return [dd.toFixed(4), null]\n \n}\n\nfunction ValidateDate(input){\n // Input Format 2020-12-25\n var error = {};\n \n if (! /20\\d{2}-[0-1]\\d-[0-3]\\d/.test(input)){\n error.topic = \"Error with the date\";\n error.payload = \"The date should respect the ISO format YYYY-MM-DD\";\n return [null, error];\n }\n else {\n var date = input.match(/\\d+/g);\n if (!((2000 < date[0]) && (date[0] < 2100))){\n error.topic = \"Error with the date\"\n error.payload = \"The year should be between 2000 and 2100\"\n return [null, error]\n }\n else if (!((0 < date[1]) && (date[1] <= 12))){\n error.topic = \"Error with the date\"\n error.payload = \"The month should be between 01 and 12\"\n return [null, error]\n }\n else if (!((0 < date[2]) && (date[2] <= 31))){\n error.topic = \"Error with the date\"\n error.payload = \"The day should be between 01 and 31\"\n return [null, error]\n }\n }\n return [input.replace(/-/g, ''), null]\n}\n\nfunction ValidateTime(input){\n // Input Format 12:00\n var error = {}\n \n if (! /[0-2]?\\d:[0-5]\\d/.test(input)){\n error.topic = \"Error with the time\"\n error.payload = \"The date should respect the ISO format HH:MM\"\n return [null, error]\n }\n else {\n var time = input.match(/\\d+/g)\n \n if (!((0 <= time[0]) && (time[0] < 24))){\n error.topic = \"Error with the time\"\n error.payload = \"The hours should be 0 and 23.\"\n return [null, error]\n }\n else if (!((0 <= time[1]) && (time[1] < 60))){\n error.topic = \"Error with the time\"\n error.payload = \"The minutes should be between 0 and 59\"\n return [null, error]\n }\n }\n return [input.replace(/:/g, ''), null]\n}\n\n\nvar ret\nvar payload_for_form = {payload:{}}\nmsg.valid = false\n\nif (msg.topic == \"culture_timestamp\"){\n ret = ValidateDate(msg.payload.object_date)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_date\", ret[0])\n \n ret = ValidateTime(msg.payload.object_time)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_time\", ret[0])\n return [{topic: \"Date and time format valid!\", payload: \"All good!\", valid: true}, payload_for_form]\n}\nelse if (msg.topic == \"net_retrieval_location\"){\n ret = ValidateCoordinates(msg.payload.object_lat_end, true);\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" Latitude\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_lat_end\", ret[0])\n ret = ValidateCoordinates(msg.payload.object_lon_end, false)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" Longitude\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_lon_end\", ret[0]);\n \n ret = ValidateDate(msg.payload.object_date_end)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample retrieval\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_date_end\", ret[0])\n \n ret = ValidateTime(msg.payload.object_time_end)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample retrieval\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_time_end\", ret[0])\n}\nelse{\n ret = ValidateCoordinates(msg.payload.object_lat, true);\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" Latitude\";\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_lat\", ret[0]);\n payload_for_form.payload[\"object_lat_end\"] = msg.payload.object_lat;\n \n ret = ValidateCoordinates(msg.payload.object_lon, false);\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" Longitude\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_lon\", ret[0])\n payload_for_form.payload[\"object_lon_end\"] = msg.payload.object_lon;\n\n ret = ValidateDate(msg.payload.object_date)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_date\", ret[0])\n payload_for_form.payload[\"object_date_end\"] = msg.payload.object_date;\n \n ret = ValidateTime(msg.payload.object_time)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_time\", ret[0])\n payload_for_form.payload[\"object_time_end\"] = msg.payload.object_time;\n}\nreturn [{topic: \"Coordinates valid!\", payload: \"All good!\", valid: true}, payload_for_form]\n", + "outputs": 2, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 930, + "y": 620, + "wires": [["c0ce5626.b6c5", "9a18a4b4.178448"], ["56d40584.eff4e4"]], + "inputLabels": ["Location form data"], + "outputLabels": ["Message", "Location validated"] + }, + { + "id": "46eb1bf8.3dc5f4", + "type": "function", + "z": "b771c342.49603", + "name": "Net check", + "func": "var decknet = {}\nvar activation_msg = {}\n\nif (msg.payload.startsWith(\"net_decknet\")){\n decknet.enabled = true;\n}\nelse {\n decknet.enabled = false;\n}\n\nif (msg.payload.startsWith(\"net\")){\n activation_msg.payload = {\"group\":{\"show\":[\"Sample_Net_Metadata\"],\"hide\":[\"Sample_Sample_Location\",\"Sample_Culture_Date_and_Time\"]}};\n}\nelse if (msg.payload != \"culture\" && msg.payload != \"test\"){\n activation_msg.payload = {\"group\":{\"show\":[\"Sample_Sample_Location\"], \"hide\":[\"Sample_Net_Metadata\",\"Sample_Culture_Date_and_Time\"]}};\n}\n\n\nreturn [decknet, activation_msg];", + "outputs": 2, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 1080, + "y": 240, + "wires": [ + ["516375fd.2ed61c", "470e382a.25691", "fbe32ac8.ff6a38"], + ["cbb123ab.fd3428"] + ], + "outputLabels": ["decknet activation", "group display control"] + }, + { + "id": "516375fd.2ed61c", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "sample_total_flowmeter_start", + "label": "Decknet flowmeter start", + "tooltip": "in L", + "group": "cf5d9f0e.d57e7", + "order": 6, + "width": 5, + "height": 1, + "passthru": false, + "mode": "text", + "delay": "300", + "topic": "sample_total_flowmeter_start", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 1340, + "y": 220, + "wires": [["e9bc112c.eb75f8"]] + }, + { + "id": "470e382a.25691", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "sample_total_flowmeter_end", + "label": "Decknet flowmeter end", + "tooltip": "in L", + "group": "cf5d9f0e.d57e7", + "order": 7, + "width": 5, + "height": 1, + "passthru": false, + "mode": "text", + "delay": "300", + "topic": "sample_total_flowmeter_end", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 1340, + "y": 260, + "wires": [["e9bc112c.eb75f8"]] + }, + { + "id": "fbe32ac8.ff6a38", + "type": "ui_template", + "z": "b771c342.49603", + "group": "cf5d9f0e.d57e7", + "name": "Decknet flowmeter read", + "order": 5, + "width": 10, + "height": 1, + "format": "
\n

Decknet flowmeter readings

\n

Those values are used to calculate sample_total_volume. Values are in L.

\n
\n", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": true, + "templateScope": "local", + "x": 1330, + "y": 180, + "wires": [[]] + }, + { + "id": "f408a273.4fb538", + "type": "function", + "z": "b771c342.49603", + "name": "get sample_gear_net_opening", + "func": "if (msg.payload.sample_gear_net_opening === null){\n msg.payload = 0;\n global.set(\"sample_gear_net_opening\",msg.payload);\n}\nelse\n{\n msg.payload = msg.payload.sample_gear_net_opening;\n}\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 350, + "y": 320, + "wires": [["e967b844.46aa48"]] + }, + { + "id": "8dff1648.82e42", + "type": "function", + "z": "b771c342.49603", + "name": "get object_depth_max", + "func": "if (msg.payload.object_depth_max === null){\n msg.payload = 0;\n global.set(\"object_depth_max\",msg.payload);\n}\nelse\n{\n msg.payload = msg.payload.object_depth_max;\n}\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 320, + "y": 240, + "wires": [["9c7f7fc9.c8d3a"]] + }, + { + "id": "9f04c5ec.75f3d8", + "type": "function", + "z": "b771c342.49603", + "name": "get object_depth_min", + "func": "if (msg.payload.object_depth_min === null){\n msg.payload = 0;\n global.set(\"object_depth_min\",msg.payload);\n}\nelse\n{\n msg.payload = msg.payload.object_depth_min;\n}\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 320, + "y": 280, + "wires": [["317eeeb7.8d3042"]] + }, + { + "id": "9a18a4b4.178448", + "type": "function", + "z": "b771c342.49603", + "name": "calculate sample_total_volume", + "func": "\n/*object_lat = 33.95 \nobject_lon = 118.4 \nobject_lat_end = 40.6333 \nobject_lon_end = 73.78333\nsample_gear_net_opening = 40*/\n\n// Copyright 1997 Ed Williams. All rights reserved\n// Adapted by Romain Bazile - Ocean Trotter - 01-2021\n\ndecpl=4 // Dec places of minutes output\n\nellipse = {\"name\":\"WSG84\", \"a\":6378.137/1.852, \"invf\":298.257223563}\n\nfunction ComputeDistance(lat1, lon1, lat2, lon2){\n var d,crs12,crs21\n var argacos\n var a,invf\n \n // lat and lon in radian\n lat1=(Math.PI/180)*lat1\n lat2=(Math.PI/180)*lat2\n lon1=(Math.PI/180)*lon1\n lon2=(Math.PI/180)*lon2\n \n //alert(\"lat1=\" + lat1 + \"lon1=\" + lon1 +\"\\nlat2=\" +lat2+ \"lon2=\"+lon2)\n \n /* get distance conversion factor */\n dc=1.852 //km\n //alert(\"dc=\" +dc)\n \n //showProps(ellipse,\"ellipse\")\n \n // elliptic code\n d=crsdist_ell(lat1,-lon1,lat2,-lon2,ellipse) // ellipse uses East negative\n d=d*dc // go to physical units\n \n //alert(\"d=\"+d+\" crs12=\"+crs12+\" crs21=\"+crs21)\n return d\n}\n\nfunction crsdist(lat1,lon1,lat2,lon2){ // radian args\n /* compute course and distance (spherical) */\n if ((lat1+lat2===0) && (Math.abs(lon1-lon2)==Math.PI) && \n (Math.abs(lat1) != (Math.PI/180)*90)){\t\n \talert(\"Course between antipodal points is undefined\")\n }\n \n d = Math.acos(Math.sin(lat1)*Math.sin(lat2)+Math.cos(lat1)*Math.cos(lat2)*Math.cos(lon1-lon2))\n return d\n}\n\nfunction crsdist_ell(glat1,glon1,glat2,glon2,ellipse){\n // glat1 initial geodetic latitude in radians N positive \n // glon1 initial geodetic longitude in radians E positive \n // glat2 final geodetic latitude in radians N positive \n // glon2 final geodetic longitude in radians E positive \n a=ellipse.a\n f=1/ellipse.invf\n //alert(\"a=\"+a+\" f=\"+f)\n var r, tu1, tu2, cu1, su1, cu2, s1, b1, f1\n var x, sx, cx, sy, cy,y, sa, c2a, cz, e, c, d\n var EPS= 0.00000000005\n var faz, baz, s\n var iter=1\n var MAXITER=100\n if ((glat1+glat2===0) && (Math.abs(glon1-glon2)==Math.PI)){\n alert(\"Course and distance between antipodal points is undefined\")\n glat1=glat1+0.00001 // allow algorithm to complete\n }\n if (glat1==glat2 && (glon1==glon2 || Math.abs(Math.abs(glon1-glon2)-2*Math.PI) < EPS)){\n alert(\"Points 1 and 2 are identical- course undefined\")\n out=new MakeArray(0)\n out.d=0\n out.crs12=0\n out.crs21=Math.PI\n return out\n }\n r = 1 - f\n tu1 = r * Math.tan (glat1)\n tu2 = r * Math.tan (glat2)\n cu1 = 1 / Math.sqrt (1 + tu1 * tu1)\n su1 = cu1 * tu1\n cu2 = 1 / Math.sqrt (1 + tu2 * tu2)\n s1 = cu1 * cu2\n b1 = s1 * tu2\n f1 = b1 * tu1\n x = glon2 - glon1\n d = x + 1 // force one pass\n while ((Math.abs(d - x) > EPS) && (iter < MAXITER))\n {\n iter=iter+1\n sx = Math.sin (x)\n // alert(\"sx=\"+sx)\n cx = Math.cos (x)\n tu1 = cu2 * sx\n tu2 = b1 - su1 * cu2 * cx\n sy = Math.sqrt(tu1 * tu1 + tu2 * tu2)\n cy = s1 * cx + f1\n y = atan2 (sy, cy)\n sa = s1 * sx / sy\n c2a = 1 - sa * sa\n cz = f1 + f1\n if (c2a > 0)\n cz = cy - cz / c2a\n e = cz * cz * 2 - 1\n c = ((-3 * c2a + 4) * f + 4) * c2a * f / 16\n d = x\n x = ((e * cy * c + cz) * sy * c + y) * sa\n x = (1 - c) * x * f + glon2 - glon1\n }\n x = Math.sqrt ((1 / (r * r) - 1) * c2a + 1)\n x +=1\n x = (x - 2) / x\n c = 1 - x\n c = (x * x / 4 + 1) / c\n d = (0.375 * x * x - 1) * x\n x = e * cy\n d = ((((sy*sy*4-3)*(1-e-e)*cz*d/6-x)*d/4+cz)*sy*d+y)*c*a*r\n if (Math.abs(iter-MAXITER)0) && (y>=0)){ out= Math.atan(y/x)}\n if ((x >0) && (y<0)) { out= Math.atan(y/x)+2*Math.PI}\n if ((x===0) && (y>0)) { out= Math.PI/2}\n if ((x===0) && (y<0)) { out= 3*Math.PI/2} \n if ((x===0) && (y===0)) {\n alert(\"atan2(0,0) undefined\")\n out= 0\n } \n return out\n}\n\nfunction showProps(obj,objName){\n var result=\"\"\n for (var i in obj){\n result +=objName + \".\" + i + \" = \" + obj[i] + \"\\n\"\n }\n alert(result)\n}\n\n\nif (msg.valid){\n msg.topic=\"sample_total_volume\"\n \n var object_lat_end = global.get(\"object_lat_end\")\n var object_lon_end = global.get(\"object_lon_end\")\n var sample_sampling_gear = global.get(\"sample_sampling_gear\")\n \n if (sample_sampling_gear.startsWith(\"net\") && sample_sampling_gear != \"net_decknet\") {\n if (!(isNaN(object_lat_end) && isNaN(object_lon_end))){\n var object_lat = global.get(\"object_lat\")\n var object_lon = global.get(\"object_lon\")\n var sample_gear_net_opening = global.get(\"sample_gear_net_opening\");\n\n distance_km = ComputeDistance(object_lat, object_lon, object_lat_end, object_lon_end)\n\n sample_total_volume = distance_km*(Math.PI*(sample_gear_net_opening/2)*(sample_gear_net_opening/2)) // liters\n sample_total_volume = Math.round(sample_total_volume + Number.EPSILON)\n msg.payload = sample_total_volume\n return msg\n }\n }\n}", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 930, + "y": 760, + "wires": [["4f6afc5a.81e454"]] + }, + { + "id": "4fb4e0ad.c417c", + "type": "ui_text", + "z": "b771c342.49603", + "group": "fc5e4e6f.5b1c8", + "order": 6, + "width": 5, + "height": 1, + "name": "Latitude", + "label": "Latitude", + "format": "{{msg.payload.lat.deg}}°{{msg.payload.lat.min}}'{{msg.payload.lat.sec}}{{msg.payload.lat.dir}}", + "layout": "col-center", + "x": 700, + "y": 1120, + "wires": [] + }, + { + "id": "8d2b5026.13e6e8", + "type": "ui_text", + "z": "b771c342.49603", + "group": "fc5e4e6f.5b1c8", + "order": 7, + "width": 5, + "height": 1, + "name": "Longitude", + "label": "Longitude", + "format": "{{msg.payload.lon.deg}}°{{msg.payload.lon.min}}'{{msg.payload.lon.sec}}{{msg.payload.lon.dir}}", + "layout": "col-center", + "x": 700, + "y": 1160, + "wires": [] + }, + { + "id": "258b4562.9f778a", + "type": "function", + "z": "b771c342.49603", + "name": "Convert DD to DMS", + "func": "function ConvertDDToDMS(D, lng){\n // from https://stackoverflow.com/a/5786281/2108279\n return {\n dir : D<0?lng?'W':'S':lng?'E':'N',\n deg : 0|(D<0?D=-D:D),\n min : 0|D%1*60,\n sec :(0|D*60%1*6000)/100\n };\n}\n\nmsg.payload = {\n \"lat\":ConvertDDToDMS(msg.payload.lat, false),\n \"lon\":ConvertDDToDMS(msg.payload.lon, true)\n};\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 490, + "y": 1140, + "wires": [["4fb4e0ad.c417c", "8d2b5026.13e6e8"]] + }, + { + "id": "7c4ce5f3.62dd5c", + "type": "ui_text", + "z": "b771c342.49603", + "group": "fc5e4e6f.5b1c8", + "order": 4, + "width": 2, + "height": 1, + "name": "Speed", + "label": "Speed", + "format": "{{msg.payload}} kts", + "layout": "col-center", + "x": 690, + "y": 1200, + "wires": [] + }, + { + "id": "54e37580.fdc31c", + "type": "ui_text", + "z": "b771c342.49603", + "group": "fc5e4e6f.5b1c8", + "order": 5, + "width": 2, + "height": 1, + "name": "Direction", + "label": "Direction", + "format": "{{msg.payload.track}} °", + "layout": "col-center", + "x": 700, + "y": 1240, + "wires": [] + }, + { + "id": "cc21ca16.b92928", + "type": "function", + "z": "b771c342.49603", + "name": "GPS Mode", + "func": "switch (msg.payload.mode){\n case 1:msg.payload = \"No Fix\"; break\n case 2:msg.payload = \"2D Fix\"; break\n case 3:msg.payload = \"3D Fix\"; break\n default: msg.payload = \"No info\"\n}\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 470, + "y": 1080, + "wires": [["7116e906.9f50f"]] + }, + { + "id": "4a4de52c.cf2884", + "type": "function", + "z": "b771c342.49603", + "name": "Speed conversion", + "func": "msg.payload = (0|msg.payload.speed) * 1.9438\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 490, + "y": 1200, + "wires": [["7c4ce5f3.62dd5c"]] + }, + { + "id": "35ad311f.344c76", + "type": "ui_text", + "z": "b771c342.49603", + "group": "fc5e4e6f.5b1c8", + "order": 2, + "width": 5, + "height": 1, + "name": "Time", + "label": "Time", + "format": "{{msg.payload.time}}", + "layout": "col-center", + "x": 690, + "y": 1280, + "wires": [] + }, + { + "id": "e73fd87d.d24e4", + "type": "function", + "z": "b771c342.49603", + "name": "get acq_minimum_mesh", + "func": "msg.payload = msg.payload.acq_minimum_mesh;\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 330, + "y": 360, + "wires": [["1aad56b31b5647ce"]] + }, + { + "id": "489c8e06.cc7d6", + "type": "function", + "z": "b771c342.49603", + "name": "get acq_maximum_mesh", + "func": "msg.payload = msg.payload.acq_maximum_mesh;\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 330, + "y": 400, + "wires": [["10eb31a2d7a6590c"]] + }, + { + "id": "73c4a14a.9b93c8", + "type": "function", + "z": "b771c342.49603", + "name": "Convert time", + "func": "msg.payload.time = msg.payload.time.replace('T', ' ');\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 470, + "y": 1280, + "wires": [["35ad311f.344c76"]] + }, + { + "id": "58de1340.3cc354", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "sample_dilution_factor", + "label": "Concentration Factor", + "tooltip": "0.5 if diluted by two; 2 if concentrated by a factor 2", + "group": "3e1ba03d.f01d8", + "order": 13, + "width": 10, + "height": 1, + "passthru": true, + "mode": "number", + "delay": "300", + "topic": "sample_dilution_factor", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 640, + "y": 480, + "wires": [["9f501f49.45645"]] + }, + { + "id": "4f6afc5a.81e454", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "sample_total_volume", + "label": "Filtered volume (in L)", + "tooltip": "Calculated or hand filled", + "group": "3e1ba03d.f01d8", + "order": 11, + "width": 0, + "height": 0, + "passthru": true, + "mode": "text", + "delay": "300", + "topic": "sample_total_volume", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 1220, + "y": 760, + "wires": [["e1f2f6eb.fe1dd"]] + }, + { + "id": "e1f2f6eb.fe1dd", + "type": "function", + "z": "b771c342.49603", + "name": "set global", + "func": "global.set(msg.topic,msg.payload);", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 1420, + "y": 760, + "wires": [[]] + }, + { + "id": "e9bc112c.eb75f8", + "type": "function", + "z": "b771c342.49603", + "name": "Calculate volume", + "func": "if (msg.topic == \"sample_total_flowmeter_start\"){\n context.set(\"sample_total_flowmeter_start\", msg.payload);\n}\nif (msg.topic == \"sample_total_flowmeter_end\"){\n context.set(\"sample_total_flowmeter_end\", msg.payload);\n}\n\nif (context.keys().length == 2){\n sample_total_volume = context.get(\"sample_total_flowmeter_end\") - context.get(\"sample_total_flowmeter_start\");\n msg.topic=\"sample_total_volume\"\n msg.payload=sample_total_volume\n return msg\n}\n", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 1610, + "y": 240, + "wires": [["4f6afc5a.81e454"]] + }, + { + "id": "cdd4181922eecf11", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "sample_speed_through_water", + "label": "Speed Through Water (kts)", + "tooltip": "in knots", + "group": "cf5d9f0e.d57e7", + "order": 2, + "width": 10, + "height": 1, + "passthru": true, + "mode": "number", + "delay": "300", + "topic": "sample_speed_through_water", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 610, + "y": 520, + "wires": [["9f501f49.45645"]] + }, + { + "id": "1aad56b31b5647ce", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "acq_minimum_mesh", + "label": "Minimal fraction size (μm)", + "tooltip": "Net mesh pore size or minimal filtration mesh pore size", + "group": "3e1ba03d.f01d8", + "order": 7, + "width": 5, + "height": 1, + "passthru": true, + "mode": "number", + "delay": "300", + "topic": "acq_minimum_mesh", + "topicType": "str", + "x": 640, + "y": 360, + "wires": [["9f501f49.45645"]] + }, + { + "id": "10eb31a2d7a6590c", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "acq_maximum_mesh", + "label": "Maximal fraction size (μm)", + "tooltip": "Maximal filtration mesh pore size", + "group": "3e1ba03d.f01d8", + "order": 8, + "width": 5, + "height": 1, + "passthru": true, + "mode": "number", + "delay": "300", + "topic": "acq_maximum_mesh", + "topicType": "str", + "x": 640, + "y": 400, + "wires": [["9f501f49.45645"]] + }, + { + "id": "3ac7b631f5d8ef90", + "type": "function", + "z": "b771c342.49603", + "name": "Culture check", + "func": "var activation_msg = {}\nvar date_msg = {}\nvar timestamp=new Date().toISOString();\n\nif (msg.payload === \"culture\"){\n activation_msg.payload = {\"group\":{\"show\":[\"Sample_Culture_Date_and_Time\"],\"hide\":[\"Sample_Sample_Location\", \"Sample_Net_Metadata\"]}};\n global.set(\"object_lat\", \"-90.0000\")\n global.set(\"object_lon\", \"0.0000\")\n date_msg.payload = {\"object_date\": timestamp.split('T')[0],\n \"object_time\": timestamp.split('T')[1].split('.')[0]}\n return [activation_msg, date_msg];\n}\nelse if (msg.payload === \"test\"){\n activation_msg.payload = {\"group\":{\"hide\":[\"Sample_Culture_Date_and_Time\", \"Sample_Sample_Location\", \"Sample_Net_Metadata\"]}};\n global.set(\"object_lat\", \"-90.0000\")\n global.set(\"object_lon\", \"0.0000\")\n global.set(\"object_date\", timestamp.split('T')[0])\n global.set(\"object_time\", timestamp.split('T')[1].split('.')[0])\n return [activation_msg, null];\n}\nelse{\n return [null, null]\n}\n\n", + "outputs": 2, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 1100, + "y": 320, + "wires": [["cbb123ab.fd3428"], ["05c6aff2afbd69cf"]], + "outputLabels": ["decknet activation", ""] + }, + { + "id": "05c6aff2afbd69cf", + "type": "ui_form", + "z": "b771c342.49603", + "name": "culture_timestamp", + "label": "Culture timestamp", + "group": "7bc0a4c416e4545c", + "order": 1, + "width": 0, + "height": 0, + "options": [ + { + "label": "Date (YYYY-MM-DD, UTC)", + "value": "object_date", + "type": "text", + "required": true, + "rows": null + }, + { + "label": "Time (HH:MM(:SS), UTC 24h)", + "value": "object_time", + "type": "text", + "required": true, + "rows": null + } + ], + "formValue": { + "object_date": "", + "object_time": "" + }, + "payload": "", + "submit": "Validate", + "cancel": "Reset", + "topic": "culture_timestamp", + "topicType": "str", + "splitLayout": false, + "className": "", + "x": 650, + "y": 700, + "wires": [["14658615.47c862", "38616e738f4f615b"]] + }, + { + "id": "3318a1aaa70fc2ee", + "type": "change", + "z": "b771c342.49603", + "name": "Repopulate input fields", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 400, + "y": 580, + "wires": [["c33f1124.af6688"]] + }, + { + "id": "cc67c97f55a340d3", + "type": "change", + "z": "b771c342.49603", + "name": "Repopulate input fields", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 400, + "y": 620, + "wires": [["358908cd.416ab"]] + }, + { + "id": "9c8f370d124a55e4", + "type": "change", + "z": "b771c342.49603", + "name": "Repopulate input fields", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 400, + "y": 660, + "wires": [["56d40584.eff4e4"]] + }, + { + "id": "38616e738f4f615b", + "type": "change", + "z": "b771c342.49603", + "name": "Repopulate input fields", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 400, + "y": 700, + "wires": [["05c6aff2afbd69cf"]] + }, + { + "id": "577be9c22c739ca0", + "type": "inject", + "z": "b771c342.49603", + "name": "", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "payload": "1", + "payloadType": "num", + "x": 270, + "y": 480, + "wires": [["58de1340.3cc354"]] + }, + { + "id": "6a84252a.d52a0c", + "type": "ui_template", + "z": "bccd1f23.87219", + "group": "833bc5bb.217ba8", + "name": "Stream Pi Camera", + "order": 1, + "width": 18, + "height": 14, + "format": "
\n \"If\n
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "className": "", + "x": 610, + "y": 40, + "wires": [[]] + }, + { + "id": "dc48dc42.98d18", + "type": "function", + "z": "bccd1f23.87219", + "name": "set global", + "func": "global.set(msg.topic,msg.payload);", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 880, + "y": 440, + "wires": [[]] + }, + { + "id": "811cd88c.daf528", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "down", + "group": "fbd92986.1028c8", + "order": 6, + "width": 4, + "height": 1, + "passthru": true, + "label": "", + "tooltip": "", + "color": "", + "bgcolor": "", + "icon": "fa-angle-double-down fa-3x", + "payload": "DOWN", + "payloadType": "str", + "topic": "actuator/focus", + "x": 550, + "y": 800, + "wires": [["65ad39d.b6d4d48"]] + }, + { + "id": "edda4df4.76de2", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "up", + "group": "fbd92986.1028c8", + "order": 3, + "width": 4, + "height": 1, + "passthru": false, + "label": "", + "tooltip": "", + "color": "", + "bgcolor": "", + "icon": "fa-angle-double-up fa-3x", + "payload": "UP", + "payloadType": "str", + "topic": "actuator/focus", + "x": 550, + "y": 760, + "wires": [["65ad39d.b6d4d48"]] + }, + { + "id": "68962547.34a67c", + "type": "ui_text_input", + "z": "bccd1f23.87219", + "name": "pump_manual_volume", + "label": "Volume to pass (ml)", + "tooltip": "Tiny values are accepted down to 0.001mL", + "group": "707d9797.c8e798", + "order": 3, + "width": 2, + "height": 1, + "passthru": true, + "mode": "text", + "delay": "300", + "topic": "pump_manual_volume", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 600, + "y": 420, + "wires": [["dc48dc42.98d18"]] + }, + { + "id": "6c792043.b6ff9", + "type": "ui_ui_control", + "z": "bccd1f23.87219", + "name": "", + "events": "change", + "x": 560, + "y": 1140, + "wires": [[]] + }, + { + "id": "902429eb.ceacb8", + "type": "ui_toast", + "z": "bccd1f23.87219", + "position": "dialog", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 1, + "ok": "OK", + "cancel": "", + "raw": false, + "topic": "", + "name": "", + "x": 570, + "y": 1220, + "wires": [[]] + }, + { + "id": "fe840e05.b46f3", + "type": "function", + "z": "bccd1f23.87219", + "name": "Check form", + "func": "var acq_fnumber_objective= global.get(\"acq_fnumber_objective\");\n\nif (acq_fnumber_objective === undefined || acq_fnumber_objective === \"\") {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Focal Length of the objective\";\n return [null, msg];\n}\n\nmsg.topic = \"Change Tab\";\nmsg.payload={\"tab\":\"Fluidic Acquisition\"};\nreturn [msg, null];", + "outputs": 2, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 330, + "y": 1180, + "wires": [["6c792043.b6ff9", "326a1d95.ca21aa"], ["902429eb.ceacb8"]], + "outputLabels": ["message", "error"] + }, + { + "id": "5846b1d4.7971b", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "Backward", + "group": "707d9797.c8e798", + "order": 2, + "width": 1, + "height": 1, + "passthru": false, + "label": "", + "tooltip": "", + "color": "", + "bgcolor": "", + "icon": "fa-rotate-left fa-2x", + "payload": "BACKWARD", + "payloadType": "str", + "topic": "actuator/pump", + "x": 560, + "y": 280, + "wires": [["3cb96380.e575ec"]] + }, + { + "id": "2cab680b.baf888", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "Forward", + "group": "707d9797.c8e798", + "order": 4, + "width": 1, + "height": 1, + "passthru": true, + "label": "", + "tooltip": "", + "color": "", + "bgcolor": "", + "icon": "fa-rotate-right fa-2x", + "payload": "FORWARD", + "payloadType": "str", + "topic": "actuator/pump", + "x": 560, + "y": 320, + "wires": [["3cb96380.e575ec"]] + }, + { + "id": "8038414a.34461", + "type": "function", + "z": "bccd1f23.87219", + "name": "Calculate optics", + "func": "var acq_fnumber_objective = String(global.get(\"acq_fnumber_objective\"));\nvar acq_camera = global.get(\"acq_camera\")\n\n// Those values needs to be recalculated, they are not good!\nif (acq_camera == \"HQ Camera\"){\n switch(acq_fnumber_objective) {\n case \"25\":\n acq_magnification= 0.6;\n process_pixel= 1.56;\n sug_min= 60;\n sug_max= 670;\n sug_flowrate= 3;\n break;\n case \"16\":\n acq_magnification= 1.6;\n process_pixel= 1.01;\n sug_min= 40;\n sug_max= 430;\n sug_flowrate= 2.4;\n break;\n case \"12\":\n acq_magnification= 1.20;\n process_pixel= 0.79;\n sug_min= 30;\n sug_max= 340;\n sug_flowrate= 1.25;\n break;\n case \"8\":\n acq_magnification= 1.78;\n process_pixel= 0.53;\n sug_min= 20;\n sug_max= 230;\n sug_flowrate= 0.42;\n break;\n case \"6\":\n acq_magnification= 2.36;\n process_pixel= 0.41;\n sug_min= 15;\n sug_max= 170;\n sug_flowrate= 0.32;\n break;\n }\n}\nelse if (acq_camera == \"Camera v2.1\"){\n switch(acq_fnumber_objective) {\n case \"25\":\n acq_magnification= 0.6;\n process_pixel= 1.86;\n sug_min= 60;\n sug_max= 670;\n sug_flowrate= 3;\n break;\n case \"16\":\n acq_magnification= 1.6;\n process_pixel= 0.7;\n sug_min= 40;\n sug_max= 430;\n sug_flowrate= 2.4;\n break;\n case \"12\":\n acq_magnification= 1.20;\n process_pixel= 0.94;\n sug_min= 30;\n sug_max= 340;\n sug_flowrate= 1.25;\n break;\n case \"8\":\n acq_magnification= 1.78;\n process_pixel= 0.63;\n sug_min= 20;\n sug_max= 230;\n sug_flowrate= 0.42;\n break;\n case \"6\":\n acq_magnification= 2.36;\n process_pixel= 0.48;\n sug_min= 15;\n sug_max= 170;\n sug_flowrate= 0.32;\n break;\n }\n}else {\n acq_magnification= \"ERROR\";\n process_pixel= \"ERROR\";\n sug_min= \"ERROR\";\n sug_max= \"ERROR\";\n sug_flowrate= \"ERROR\";\n}\n\nvar process_pixel_fixed = global.get(\"process_pixel_fixed\")\n\nif (process_pixel_fixed !== undefined && process_pixel_fixed !== \"\") {\n process_pixel = process_pixel_fixed\n}\n\nglobal.set(\"process_pixel\",process_pixel);\n\nglobal.set(\"acq_magnification\",acq_magnification);\n\n\nreturn [{payload: acq_fnumber_objective}, {payload: acq_magnification}, {payload: process_pixel}, {payload: sug_min}, {payload: sug_max}];", + "outputs": 5, + "timeout": "", + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 1080, + "y": 120, + "wires": [[], [], [], [], []], + "inputLabels": ["acq_fnumber_objective"], + "outputLabels": [ + "acq_magnification", + "process_pixel", + "sug_min", + "sug_max", + "" + ] + }, + { + "id": "f61aaed5.1e64", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "", + "group": "7a0b4877.a5d268", + "order": 1, + "width": 2, + "height": 1, + "passthru": false, + "label": "Previous", + "tooltip": "", + "color": "#097479", + "bgcolor": "white", + "icon": "keyboard_return", + "payload": "{\"tab\":\"Sample\"}", + "payloadType": "json", + "topic": "", + "x": 140, + "y": 1140, + "wires": [["6c792043.b6ff9"]] + }, + { + "id": "9ba6ec0a.22c96", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "", + "group": "7a0b4877.a5d268", + "order": 2, + "width": 2, + "height": 1, + "passthru": false, + "label": "Continue", + "tooltip": "", + "color": "#097479", + "bgcolor": "white", + "icon": "keyboard_tab", + "payload": "{\"tab\":\"Home\"}", + "payloadType": "json", + "topic": "", + "x": 140, + "y": 1180, + "wires": [["fe840e05.b46f3"]] + }, + { + "id": "cbb8afed.0a026", + "type": "rpi-gpio out", + "z": "bccd1f23.87219", + "name": "LED Output", + "pin": "21", + "set": true, + "level": "0", + "freq": "", + "out": "out", + "bcm": true, + "x": 550, + "y": 120, + "wires": [] + }, + { + "id": "3cb96380.e575ec", + "type": "function", + "z": "bccd1f23.87219", + "name": "pump", + "func": "var manual_volume= global.get(\"pump_manual_volume\");\nvar flowrate= global.get(\"pump_flowrate\");\n\nif (manual_volume === undefined || manual_volume === \"\" || manual_volume === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Volume to pass\";\n return [null, msg];\n}\nelse if (flowrate === undefined || flowrate === \"\" || flowrate === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Flowrate\";\n return [null, msg];\n}\nelse {\n msg.topic = \"actuator/pump\";\n // msg.payload is FORWARD or BACKWARD here\n msg.payload={\"action\":\"move\", \n \"direction\":msg.payload,\n \"volume\":manual_volume,\n \"flowrate\":flowrate};\n}\nreturn [msg, null];", + "outputs": 2, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 750, + "y": 300, + "wires": [["bdc8ce57.de1f08"], ["8bcce348.efc1a"]], + "inputLabels": ["direction"], + "outputLabels": ["message", "error"] + }, + { + "id": "8bcce348.efc1a", + "type": "ui_toast", + "z": "bccd1f23.87219", + "position": "dialog", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 1, + "ok": "OK", + "cancel": "", + "raw": false, + "topic": "", + "name": "", + "x": 1090, + "y": 300, + "wires": [[]] + }, + { + "id": "bdc8ce57.de1f08", + "type": "mqtt out", + "z": "bccd1f23.87219", + "name": "", + "topic": "", + "qos": "", + "retain": "", + "broker": "8dc3722c.06efa8", + "x": 1210, + "y": 260, + "wires": [] + }, + { + "id": "d71d224f.0585d8", + "type": "ui_toast", + "z": "bccd1f23.87219", + "position": "dialog", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 1, + "ok": "OK", + "cancel": "", + "raw": false, + "topic": "", + "name": "", + "x": 1090, + "y": 800, + "wires": [[]] + }, + { + "id": "65ad39d.b6d4d48", + "type": "function", + "z": "bccd1f23.87219", + "name": "focus", + "func": "var distance = global.get(\"focus_distance\");\n\nif (distance === undefined || distance === \"\" || distance === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Distance\";\n return [null, msg]\n}else {\n distance = global.get(\"focus_distance\");\n // msg.payload is UP or DOWN here\n msg.payload={\"action\":\"move\", \n \"direction\":msg.payload,\n \"distance\":(distance/1000)};\n}\nreturn [msg, null];", + "outputs": 2, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 850, + "y": 780, + "wires": [["62030521.88317c"], ["d71d224f.0585d8"]], + "inputLabels": ["direction"], + "outputLabels": ["message", "error"] + }, + { + "id": "1962d999.4a97e6", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "stop focus", + "group": "fbd92986.1028c8", + "order": 9, + "width": 0, + "height": 0, + "passthru": true, + "label": " STOP FOCUS", + "tooltip": "", + "color": "", + "bgcolor": "#AD1625", + "icon": "fa-pause fa-2x", + "payload": "{\"action\":\"stop\"}", + "payloadType": "json", + "topic": "actuator/focus", + "x": 570, + "y": 560, + "wires": [["62030521.88317c"]] + }, + { + "id": "62030521.88317c", + "type": "mqtt out", + "z": "bccd1f23.87219", + "name": "", + "topic": "", + "qos": "", + "retain": "", + "broker": "8dc3722c.06efa8", + "x": 1210, + "y": 720, + "wires": [] + }, + { + "id": "3bd43039.bc5fb8", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "", + "group": "fbd92986.1028c8", + "order": 1, + "width": 4, + "height": 1, + "passthru": false, + "label": "UP 1mm", + "tooltip": "", + "color": "", + "bgcolor": "", + "icon": "fa-angle-up fa-3x", + "payload": "{\"action\":\"move\",\"direction\":\"UP\",\"distance\":1}", + "payloadType": "json", + "topic": "actuator/focus", + "topicType": "str", + "x": 560, + "y": 600, + "wires": [["62030521.88317c"]] + }, + { + "id": "c0663029.2d03b", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "", + "group": "fbd92986.1028c8", + "order": 8, + "width": 4, + "height": 1, + "passthru": false, + "label": "DOWN 1mm", + "tooltip": "", + "color": "", + "bgcolor": "", + "icon": "fa-angle-down fa-3x", + "payload": "{\"action\":\"move\",\"direction\":\"DOWN\",\"distance\":1}", + "payloadType": "json", + "topic": "actuator/focus", + "topicType": "str", + "x": 570, + "y": 720, + "wires": [["62030521.88317c"]] + }, + { + "id": "71f55a58.d7eaf4", + "type": "inject", + "z": "bccd1f23.87219", + "name": "Default: 500µm", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": "0.5", + "topic": "", + "payload": "500", + "payloadType": "num", + "x": 120, + "y": 460, + "wires": [["be33e564.029358"]] + }, + { + "id": "9a1d0e7c.2d5a1", + "type": "inject", + "z": "bccd1f23.87219", + "name": "Default: OFF", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "payload": "off", + "payloadType": "str", + "x": 130, + "y": 120, + "wires": [["f0775525.cf806"]] + }, + { + "id": "f782a471.447748", + "type": "inject", + "z": "bccd1f23.87219", + "name": "Default: 2mL/min", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": "0.5", + "topic": "", + "payload": "2", + "payloadType": "num", + "x": 130, + "y": 380, + "wires": [["cb2d5174.cfe9f"]] + }, + { + "id": "73b8252a.5ca754", + "type": "inject", + "z": "bccd1f23.87219", + "name": "Default: 2mL", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": "0.5", + "topic": "", + "payload": "2", + "payloadType": "num", + "x": 110, + "y": 420, + "wires": [["68962547.34a67c"]] + }, + { + "id": "6451f991.aaac1", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "stop pump", + "group": "707d9797.c8e798", + "order": 5, + "width": 4, + "height": 1, + "passthru": true, + "label": " STOP PUMP", + "tooltip": "", + "color": "", + "bgcolor": "#AD1625", + "icon": "fa-pause fa-2x", + "payload": "{\"action\":\"stop\"}", + "payloadType": "json", + "topic": "actuator/pump", + "x": 570, + "y": 240, + "wires": [["bdc8ce57.de1f08"]] + }, + { + "id": "cfc783d7.d6ceb", + "type": "link in", + "z": "bccd1f23.87219", + "name": "Optics recalculation", + "links": ["559a8085.1d6b9", "5d5ad36d2c50dcc2"], + "x": 915, + "y": 120, + "wires": [["8038414a.34461"]] + }, + { + "id": "326a1d95.ca21aa", + "type": "subflow:1c24ad9c.bebec2", + "z": "bccd1f23.87219", + "name": "", + "x": 550, + "y": 1180, + "wires": [[]] + }, + { + "id": "2d371e59.b0e50a", + "type": "inject", + "z": "bccd1f23.87219", + "name": "Default: 1000µm/s", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": "0.5", + "topic": "", + "payload": "1000", + "payloadType": "num", + "x": 130, + "y": 500, + "wires": [["3a86de51.765b9a"]] + }, + { + "id": "167cda35.c9b6ae", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "", + "group": "fbd92986.1028c8", + "order": 2, + "width": 4, + "height": 1, + "passthru": false, + "label": "UP 100um", + "tooltip": "", + "color": "", + "bgcolor": "", + "icon": "fa-angle-up fa-3x", + "payload": "{\"action\":\"move\",\"direction\":\"UP\",\"distance\":0.1}", + "payloadType": "json", + "topic": "actuator/focus", + "topicType": "str", + "x": 570, + "y": 640, + "wires": [["62030521.88317c"]] + }, + { + "id": "72a7c597.9374fc", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "", + "group": "fbd92986.1028c8", + "order": 7, + "width": 4, + "height": 1, + "passthru": false, + "label": "DOWN 100um", + "tooltip": "", + "color": "", + "bgcolor": "", + "icon": "fa-angle-down fa-3x", + "payload": "{\"action\":\"move\",\"direction\":\"DOWN\",\"distance\":0.1}", + "payloadType": "json", + "topic": "actuator/focus", + "topicType": "str", + "x": 580, + "y": 680, + "wires": [["62030521.88317c"]] + }, + { + "id": "f0775525.cf806", + "type": "ui_multistate_switch", + "z": "bccd1f23.87219", + "name": "light_control", + "group": "4248342d.e55fac", + "order": 1, + "width": 5, + "height": 1, + "label": "Light ", + "stateField": "payload", + "enableField": "enable", + "rounded": true, + "useThemeColors": true, + "hideSelectedLabel": false, + "options": [ + { + "label": "Off", + "value": "0", + "valueType": "num", + "color": "#009933" + }, + { + "label": "On", + "value": "1", + "valueType": "num", + "color": "#999999" + } + ], + "x": 350, + "y": 120, + "wires": [["cbb8afed.0a026"]] + }, + { + "id": "8ea9dc9a.c7d87", + "type": "function", + "z": "bccd1f23.87219", + "name": "Encapsulate settings", + "func": "msg.payload = {\n \"action\":\"settings\", \n \"settings\":{[msg.topic]:msg.payload}\n}\n\nmsg.topic = \"imager/image\"\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 1120, + "y": 940, + "wires": [["845e06e1.0d812"]] + }, + { + "id": "5765a825.a595c8", + "type": "ui_slider", + "z": "bccd1f23.87219", + "name": "Shutter speed slider", + "label": "Shutter Speed", + "tooltip": "In microseconds, up to 1000µs, 125µs by default", + "group": "8c38a81e.9897a8", + "order": 4, + "width": 0, + "height": 0, + "passthru": true, + "outs": "end", + "topic": "shutter_speed", + "topicType": "str", + "min": "125", + "max": "1000", + "step": "1", + "className": "", + "x": 600, + "y": 880, + "wires": [["8ea9dc9a.c7d87"]] + }, + { + "id": "845e06e1.0d812", + "type": "mqtt out", + "z": "bccd1f23.87219", + "name": "", + "topic": "", + "qos": "", + "retain": "", + "broker": "8dc3722c.06efa8", + "x": 1390, + "y": 980, + "wires": [] + }, + { + "id": "2350e507.d4e302", + "type": "inject", + "z": "bccd1f23.87219", + "name": "Default: 125µs", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": "1", + "topic": "", + "payload": "125", + "payloadType": "num", + "x": 120, + "y": 880, + "wires": [["5765a825.a595c8"]] + }, + { + "id": "5e147425.7666ec", + "type": "function", + "z": "bccd1f23.87219", + "name": "Encapsulate wb gain settings", + "func": "msg.payload = {\n \"action\":\"settings\", \n \"settings\":{\"white_balance_gain\":{\n [msg.topic]:Math.round(msg.payload*100)\n }\n }\n}\nmsg.topic = \"imager/image\"\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 1100, + "y": 1060, + "wires": [["845e06e1.0d812"]] + }, + { + "id": "82722a3c.846b3", + "type": "inject", + "z": "bccd1f23.87219", + "name": "Default: OFF", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": "1", + "topic": "", + "payload": "false", + "payloadType": "bool", + "x": 110, + "y": 920, + "wires": [["60e44330.50bdec"]] + }, + { + "id": "60e44330.50bdec", + "type": "ui_switch", + "z": "bccd1f23.87219", + "name": "AWB", + "label": "Auto White Balance", + "tooltip": "", + "group": "8c38a81e.9897a8", + "order": 5, + "width": 2, + "height": 2, + "passthru": true, + "decouple": "false", + "topic": "white_balance", + "topicType": "str", + "style": "", + "onvalue": "auto", + "onvalueType": "str", + "onicon": "", + "oncolor": "", + "offvalue": "off", + "offvalueType": "str", + "officon": "", + "offcolor": "", + "animate": true, + "className": "", + "x": 550, + "y": 920, + "wires": [["8ea9dc9a.c7d87"]] + }, + { + "id": "6be64480.7e7e24", + "type": "change", + "z": "bccd1f23.87219", + "name": "Get red_gain", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.red_gain", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 370, + "y": 1040, + "wires": [["d5415af6.e06cc"]] + }, + { + "id": "6d49d161.13628", + "type": "change", + "z": "bccd1f23.87219", + "name": "Get blue_gain", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.blue_gain", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 380, + "y": 1080, + "wires": [["dba68c1f.e3144"]] + }, + { + "id": "56835fa1.2fe538", + "type": "subflow:4ed26b8b.253504", + "z": "bccd1f23.87219", + "name": "", + "env": [], + "x": 1160, + "y": 1020, + "wires": [] + }, + { + "id": "8ef294ba.12213", + "type": "change", + "z": "bccd1f23.87219", + "name": "Get analog_gain", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "1", + "tot": "num" + }, + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.analog_gain", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 380, + "y": 960, + "wires": [["a6c7eec4.f7a918"]] + }, + { + "id": "8e336e58.14722", + "type": "change", + "z": "bccd1f23.87219", + "name": "Get digital_gain", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "1", + "tot": "num" + }, + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.digital_gain", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 380, + "y": 1000, + "wires": [["66b37eef.f3f9e"]] + }, + { + "id": "a6c7eec4.f7a918", + "type": "ui_text_input", + "z": "bccd1f23.87219", + "d": true, + "name": "Analog gain field", + "label": "Analog Gain", + "tooltip": "From 1.0 to 12.0", + "group": "8c38a81e.9897a8", + "order": 2, + "width": 0, + "height": 0, + "passthru": true, + "mode": "number", + "delay": 300, + "topic": "analog", + "topicType": "str", + "x": 580, + "y": 960, + "wires": [["44e02933.a66688", "d361a2c4.0990f8"]] + }, + { + "id": "66b37eef.f3f9e", + "type": "ui_text_input", + "z": "bccd1f23.87219", + "d": true, + "name": "Digital gain field", + "label": "Digital Gain", + "tooltip": "From 1.0 to 64.0. Overexpose starting at 4.0", + "group": "8c38a81e.9897a8", + "order": 3, + "width": 0, + "height": 0, + "passthru": true, + "mode": "number", + "delay": 300, + "topic": "digital", + "topicType": "str", + "x": 580, + "y": 1000, + "wires": [["44e02933.a66688", "d361a2c4.0990f8"]] + }, + { + "id": "44e02933.a66688", + "type": "function", + "z": "bccd1f23.87219", + "name": "Encapsulate image gain settings", + "func": "msg.payload = {\n \"action\":\"settings\", \n \"settings\":{\"image_gain\":{\n [msg.topic]:Math.round(msg.payload*100)\n }\n }\n}\nmsg.topic = \"imager/image\"\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 1090, + "y": 980, + "wires": [["845e06e1.0d812"]] + }, + { + "id": "d361a2c4.0990f8", + "type": "change", + "z": "bccd1f23.87219", + "name": "topic *_gain", + "rules": [ + { + "t": "set", + "p": "topic", + "pt": "msg", + "to": "topic&'_gain'", + "tot": "jsonata" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 970, + "y": 1020, + "wires": [["56835fa1.2fe538"]] + }, + { + "id": "d8d006bf.2947f", + "type": "inject", + "z": "bccd1f23.87219", + "name": "Default: ISO 150", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": "1", + "topic": "", + "payload": "150", + "payloadType": "num", + "x": 130, + "y": 840, + "wires": [["37f412d1454deb64"]] + }, + { + "id": "eb9966de.cf13c8", + "type": "change", + "z": "bccd1f23.87219", + "name": "", + "rules": [ + { + "t": "set", + "p": "topic", + "pt": "msg", + "to": "iso", + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 740, + "y": 840, + "wires": [["8ea9dc9a.c7d87"]] + }, + { + "id": "be33e564.029358", + "type": "ui_text_input", + "z": "bccd1f23.87219", + "name": "focus_distance", + "label": "Focus Distance (in µm)", + "tooltip": "in µm, 25µm resolution", + "group": "fbd92986.1028c8", + "order": 4, + "width": 0, + "height": 0, + "passthru": true, + "mode": "number", + "delay": 300, + "topic": "focus_distance", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 580, + "y": 460, + "wires": [["dc48dc42.98d18"]] + }, + { + "id": "3a86de51.765b9a", + "type": "ui_text_input", + "z": "bccd1f23.87219", + "name": "focus_speed", + "label": "Focus Speed (in µm/sec)", + "tooltip": "in µm/sec", + "group": "fbd92986.1028c8", + "order": 5, + "width": 0, + "height": 0, + "passthru": true, + "mode": "number", + "delay": 300, + "topic": "focus_speed", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 570, + "y": 500, + "wires": [["dc48dc42.98d18"]] + }, + { + "id": "cb2d5174.cfe9f", + "type": "ui_text_input", + "z": "bccd1f23.87219", + "name": "pump_flowrate", + "label": "Flowrate (ml/min)*", + "tooltip": "", + "group": "707d9797.c8e798", + "order": 1, + "width": 0, + "height": 0, + "passthru": true, + "mode": "text", + "delay": 300, + "topic": "pump_flowrate", + "topicType": "str", + "x": 580, + "y": 380, + "wires": [["dc48dc42.98d18"]] + }, + { + "id": "d5415af6.e06cc", + "type": "ui_text_input", + "z": "bccd1f23.87219", + "name": "WB Red input", + "label": "WB: Red", + "tooltip": "From 0.0 to 32.0", + "group": "8c38a81e.9897a8", + "order": 6, + "width": 4, + "height": 1, + "passthru": true, + "mode": "number", + "delay": "0", + "topic": "red", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 580, + "y": 1040, + "wires": [["f7a7398fd6ce4a4f"]] + }, + { + "id": "dba68c1f.e3144", + "type": "ui_text_input", + "z": "bccd1f23.87219", + "name": "WB Blue input", + "label": "WB: Blue", + "tooltip": "From 0.0 to 64.0", + "group": "8c38a81e.9897a8", + "order": 7, + "width": 4, + "height": 1, + "passthru": true, + "mode": "number", + "delay": "0", + "topic": "blue", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 580, + "y": 1080, + "wires": [["df8a7667c9d133b1"]] + }, + { + "id": "d91550e8b15ed3b8", + "type": "subflow:e6665421f66ea4c8", + "z": "bccd1f23.87219", + "name": "", + "x": 160, + "y": 1020, + "wires": [ + ["8ef294ba.12213", "8e336e58.14722", "6be64480.7e7e24", "6d49d161.13628"] + ] + }, + { + "id": "04920f50bbbf6a2a", + "type": "link in", + "z": "bccd1f23.87219", + "name": "Load hardware config", + "links": ["e4ead350b3d07578", "4a1f303f0b6f7f42"], + "x": 25, + "y": 1000, + "wires": [["d91550e8b15ed3b8"]] + }, + { + "id": "7386eaf7ca9d8bfa", + "type": "inject", + "z": "bccd1f23.87219", + "name": "Once", + "props": [], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "x": 50, + "y": 1080, + "wires": [["d91550e8b15ed3b8"]] + }, + { + "id": "f7a7398fd6ce4a4f", + "type": "switch", + "z": "bccd1f23.87219", + "name": "Validate", + "property": "payload", + "propertyType": "msg", + "rules": [ + { + "t": "btwn", + "v": "0.0", + "vt": "num", + "v2": "32.0", + "v2t": "num" + }, + { + "t": "else" + } + ], + "checkall": "false", + "repair": false, + "outputs": 2, + "x": 740, + "y": 1040, + "wires": [ + ["d361a2c4.0990f8", "5e147425.7666ec"], + ["64b05eea4c5469be", "4a1f303f0b6f7f42"] + ] + }, + { + "id": "df8a7667c9d133b1", + "type": "switch", + "z": "bccd1f23.87219", + "name": "Validate", + "property": "payload", + "propertyType": "msg", + "rules": [ + { + "t": "btwn", + "v": "0.0", + "vt": "num", + "v2": "32.0", + "v2t": "num" + }, + { + "t": "else" + } + ], + "checkall": "false", + "repair": false, + "outputs": 2, + "x": 740, + "y": 1080, + "wires": [ + ["d361a2c4.0990f8", "5e147425.7666ec"], + ["64b05eea4c5469be", "4a1f303f0b6f7f42"] + ] + }, + { + "id": "64b05eea4c5469be", + "type": "ui_toast", + "z": "bccd1f23.87219", + "position": "top right", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 0, + "ok": "OK", + "cancel": "", + "raw": false, + "className": "", + "topic": "Invalid white balance value", + "name": "", + "x": 990, + "y": 1100, + "wires": [] + }, + { + "id": "4a1f303f0b6f7f42", + "type": "link out", + "z": "bccd1f23.87219", + "name": "Reload hardware config", + "mode": "link", + "links": ["04920f50bbbf6a2a"], + "x": 915, + "y": 1140, + "wires": [] + }, + { + "id": "37f412d1454deb64", + "type": "ui_slider", + "z": "bccd1f23.87219", + "name": "ISO selector", + "label": "ISO", + "tooltip": "", + "group": "8c38a81e.9897a8", + "order": 1, + "width": 0, + "height": 0, + "passthru": true, + "outs": "end", + "topic": "topic", + "topicType": "msg", + "min": "50", + "max": "800", + "step": "50", + "className": "", + "x": 570, + "y": 840, + "wires": [["eb9966de.cf13c8"]] + }, + { + "id": "f59a2f0d.5e9af", + "type": "ui_numeric", + "z": "baa1e3d9.cb29d", + "name": "acq_minimum_mesh", + "label": "Min fraction size (μm)", + "tooltip": "", + "group": "404c301a.19c4e", + "order": 1, + "width": 5, + "height": 1, + "wrap": false, + "passthru": true, + "topic": "acq_minimum_mesh", + "format": "{{value}}", + "min": 0, + "max": "300", + "step": "10", + "x": 640, + "y": 160, + "wires": [["fb887036.12429"]] + }, + { + "id": "6008a8bb.259f08", + "type": "ui_numeric", + "z": "baa1e3d9.cb29d", + "name": "acq_maximum_mesh", + "label": "Max fraction size (μm)", + "tooltip": "", + "group": "404c301a.19c4e", + "order": 2, + "width": 5, + "height": 1, + "wrap": false, + "passthru": true, + "topic": "acq_maximum_mesh", + "format": "{{value}}", + "min": "200", + "max": "2000", + "step": "100", + "x": 640, + "y": 200, + "wires": [["fb887036.12429"]] + }, + { + "id": "6b34c456.83178c", + "type": "ui_text_input", + "z": "baa1e3d9.cb29d", + "name": "acq_id", + "label": "Acquisition unique ID*", + "tooltip": "", + "group": "4322c187.e73e5", + "order": 1, + "width": 5, + "height": 1, + "passthru": true, + "mode": "text", + "delay": 300, + "topic": "acq_id", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 690, + "y": 240, + "wires": [["fb887036.12429"]] + }, + { + "id": "cc0ca68b.4263a8", + "type": "ui_dropdown", + "z": "baa1e3d9.cb29d", + "name": "acq_celltype", + "label": "Flowcell thickness*", + "tooltip": "", + "place": "Select option", + "group": "4322c187.e73e5", + "order": 6, + "width": 5, + "height": 1, + "passthru": true, + "multiple": false, + "options": [ + { + "label": "200 μm µ-Slide I Luer", + "value": 200, + "type": "num" + }, + { + "label": "300 µm capillary", + "value": 300, + "type": "num" + }, + { + "label": "400 μm µ-Slide I Luer", + "value": 400, + "type": "num" + }, + { + "label": "600 μm µ-Slide I Luer", + "value": 600, + "type": "num" + }, + { + "label": "800 μm µ-Slide I Luer", + "value": 800, + "type": "num" + } + ], + "payload": "", + "topic": "acq_celltype", + "topicType": "str", + "className": "", + "x": 670, + "y": 80, + "wires": [["fb887036.12429", "99b11fe4.2795d"]] + }, + { + "id": "fb887036.12429", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "set global", + "func": "global.set(msg.topic, msg.payload);\nreturn msg", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 920, + "y": 220, + "wires": [["52ea7d01.711034"]] + }, + { + "id": "bb2bb7ce.1d1458", + "type": "ui_template", + "z": "baa1e3d9.cb29d", + "group": "858a0e3c.987fe", + "name": "Stream Pi Camera", + "order": 1, + "width": 10, + "height": 8, + "format": "
\n \"If\n
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "className": "", + "x": 650, + "y": 20, + "wires": [[]] + }, + { + "id": "d0c5b57d.590818", + "type": "ui_ui_control", + "z": "baa1e3d9.cb29d", + "name": "", + "events": "change", + "x": 1280, + "y": 660, + "wires": [[]] + }, + { + "id": "c72f8fae.23bd4", + "type": "ui_button", + "z": "baa1e3d9.cb29d", + "name": "", + "group": "b7919ae2.c01788", + "order": 1, + "width": 5, + "height": 1, + "passthru": false, + "label": "Previous", + "tooltip": "", + "color": "#097479", + "bgcolor": "white", + "icon": "keyboard_return", + "payload": "{\"tab\":\"Optic Configuration\"}", + "payloadType": "json", + "topic": "", + "x": 1140, + "y": 660, + "wires": [["d0c5b57d.590818"]] + }, + { + "id": "29be525e.0c87fe", + "type": "ui_template", + "z": "baa1e3d9.cb29d", + "group": "b5d61bc7.54fe48", + "name": "Show Metadata", + "order": 9, + "width": 0, + "height": 0, + "format": "
\n \n \n \n \n \n \n \n \n \n
\n

Sample

\n

id:

\n

project:\n

\n

ship:

\n

operator:\n

\n

sampling gear:\n

\n

concentrated volume:\n

\n

gear net opening:\n

\n

total volume filtered:\n

\n
\n

Acquisition

\n

id:

\n

instrument:\n

\n

instrument id:\n

\n

camera:

\n

celltype: \n

\n

minimum mesh:\n

\n

maximum mesh:\n

\n

min esd: \n

\n

max esd: \n

\n

volume:

\n

magnification:\n

\n

fnumber objective:\n

\n

software: \n

\n
\n

Object

\n

latitude: \n

\n

longitude: \n

\n

latitude end:\n

\n

longitude end:\n

\n

date:

\n

time:

\n

date end:\n

\n

time end:\n

\n

depth min:\n

\n

depth max:\n

\n
\n

Process

\n

pixel: \n

\n

id:

\n
\n
", + "storeOutMessages": false, + "fwdInMessages": false, + "resendOnRefresh": false, + "templateScope": "local", + "className": "", + "x": 1180, + "y": 380, + "wires": [[]] + }, + { + "id": "c9f510c0.7d1328", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "Image control", + "func": "// Reset the number of images taken\nflow.set('img_counter', 0);\n\nvar acq_celltype = global.get(\"acq_celltype\");\nvar acq_minimum_mesh = global.get(\"acq_minimum_mesh\");\nvar acq_maximum_mesh = global.get(\"acq_maximum_mesh\");\nvar imaging_pump_volume = global.get(\"imaging_pump_volume\");\nvar acq_id = global.get(\"acq_id\");\nvar nb_frame = global.get(\"nb_frame\");\nvar pump_direction = global.get(\"pump_direction\");\nvar sleep_before = global.get(\"sleep_before\");\nvar object_date = global.get(\"object_date\");\n\nif (acq_celltype === undefined || acq_celltype === \"\") {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Type of the flowcell\";\n return [null, msg];\n} else if (acq_minimum_mesh === undefined || acq_minimum_mesh === \"\") {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Lower fraction size\";\n return [null, msg];\n} else if (acq_maximum_mesh === undefined || acq_maximum_mesh === \"\") {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Upper fraction size\";\n return [null, msg];\n} else if (imaging_pump_volume === undefined || imaging_pump_volume === \"\" || imaging_pump_volume === null) {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Volume inbetween images\";\n return [null, msg];\n} else if (acq_id === undefined || acq_id === \"\") {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Acquisition ID\";\n return [null, msg];\n} else if (nb_frame === undefined || nb_frame === \"\" || nb_frame === null) {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Number of image to save\";\n return [null, msg];\n} else if (pump_direction === undefined || pump_direction === \"\" || pump_direction === null) {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Pump direction\";\n return [null, msg];\n} else if (sleep_before === undefined || sleep_before === \"\" || sleep_before === null) {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Delay before image\";\n return [null, msg];\n}else if (object_date === undefined || object_date === \"\" || object_date === null) {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Object date\";\n return [null, msg];\n}\n\nmsg.payload = {\n \"action\": \"image\",\n \"sleep\": sleep_before,\n \"pump_direction\": pump_direction,\n \"volume\": imaging_pump_volume,\n \"nb_frame\": nb_frame,\n}\nmsg.send = true\n\nreturn [msg, null];", + "outputs": 2, + "timeout": "", + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 680, + "y": 480, + "wires": [ + ["52ea7d01.711034", "40c12463.a1f84c", "a4abb1ae.2ae418"], + ["20e0a8c8.edbeb"] + ] + }, + { + "id": "20e0a8c8.edbeb", + "type": "ui_toast", + "z": "baa1e3d9.cb29d", + "position": "dialog", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 1, + "ok": "OK", + "cancel": "", + "raw": false, + "className": "", + "topic": "", + "name": "", + "x": 950, + "y": 560, + "wires": [[]] + }, + { + "id": "c3e50240.82aa58", + "type": "mqtt out", + "z": "baa1e3d9.cb29d", + "name": "", + "topic": "", + "qos": "", + "retain": "", + "respTopic": "", + "contentType": "", + "userProps": "", + "correl": "", + "expiry": "", + "broker": "8dc3722c.06efa8", + "x": 1150, + "y": 440, + "wires": [] + }, + { + "id": "3a4450b1.4459a8", + "type": "ui_button", + "z": "baa1e3d9.cb29d", + "name": "Stop Acquisition", + "group": "4322c187.e73e5", + "order": 11, + "width": 5, + "height": 1, + "passthru": true, + "label": "STOP ACQUISITION", + "tooltip": "", + "color": "", + "bgcolor": "#AD1625", + "className": "", + "icon": "cancel", + "payload": "{\"action\":\"stop\"}", + "payloadType": "json", + "topic": "imager/image", + "topicType": "str", + "x": 460, + "y": 520, + "wires": [["d74210ef.edc15"]] + }, + { + "id": "d74210ef.edc15", + "type": "mqtt out", + "z": "baa1e3d9.cb29d", + "name": "", + "topic": "", + "qos": "", + "retain": "", + "broker": "8dc3722c.06efa8", + "x": 650, + "y": 520, + "wires": [] + }, + { + "id": "bb62da8a.ebc328", + "type": "ui_switch", + "z": "baa1e3d9.cb29d", + "name": "Pump direction", + "label": "Pump direction", + "tooltip": "BACKWARD / FORWARD", + "group": "4322c187.e73e5", + "order": 9, + "width": 5, + "height": 1, + "passthru": true, + "decouple": "false", + "topic": "pump_direction", + "style": "", + "onvalue": "FORWARD", + "onvalueType": "str", + "onicon": "", + "oncolor": "", + "offvalue": "BACKWARD", + "offvalueType": "str", + "officon": "", + "offcolor": "", + "x": 460, + "y": 560, + "wires": [["6b2239f3.41fa3"]] + }, + { + "id": "52ea7d01.711034", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "Encapsulate config", + "func": "msg.payload = {\n\t\"action\": \"update_config\",\n\t\"config\": {\n \t\"description\": {\n \t\t\"sample_project\": \"Project's name\",\n \t\t\"sample_id\": \"Sample ID\",\n \t\t\"sample_uuid\": \"Sample UUID (Autogenerated)\",\n \t\t\"sample_ship\": \"Ship's name\",\n \t\t\"sample_operator\": \"Operator's name\",\n \t\t\"sample_sampling_gear\": \"Sampling gear used\",\n \t\t\"sample_concentrated_sample_volume\": \"Volume of concentrated sample, in mL\",\n \t\t\"sample_total_volume\": \"Total volume filtered by the net used, in L\",\n \t\t\"sample_dilution_factor\": \"Dilution factor of the sample, 0.5 if diluted by 2, 2 if concentrated by 2\",\n \t\t\"sample_speed_through_water\": \"Speed of the boat through water when sampling, in kts\",\n \t\t\"acq_id\": \"Acquisition ID\",\n \t\t\"acq_uuid\": \"Acquisition UUID (Autogenerated)\",\n \t\t\"acq_instrument\": \"Instrument type\",\n \t\t\"acq_instrument_id\": \"Instrument ID\",\n \t\t\"acq_celltype\": \"Flow cell dimension thickness, in µm\",\n \t\t\"acq_minimum_mesh\": \"Minimum filtration mesh size, in µm\",\n \t\t\"acq_maximum_mesh\": \"Maximum filtration mesh size, in µm\",\n \t\t\"acq_min_esd\": \"\",\n \t\t\"acq_max_esd\": \"\",\n \t\t\"acq_volume\": \"Pumped volume, in mL\",\n\t\t \"acq_imaged_volume\": \"Total imaged volume, in mL\",\n \t\t\"acq_magnification\": \"Optical magnification\",\n \t\t\"acq_fnumber_objective\": \"Focal length of the objective, in mm\",\n \t\t\"acq_camera_name\": \"Name of the camera used\",\n \t\t\"acq_nb_frame\": \"Number of picture taken\",\n \"acq_local_datetime\": \"Instrument local datetime\",\n \"acq_camera_resolution\": \"Resolution of the images\",\n \"acq_camera_iso\": \"ISO Number of the images\",\n \"acq_camera_shutter_speed\": \"Shutter speed of the images, in µs\",\n \"acq_software\": \"Software version number\",\n \t\t\"object_date\": \"Sample collection date (or beginning if using a net)\",\n \t\t\"object_time\": \"Sample collection time (or beginning if using a net)\",\n \t\t\"object_lat\": \"Sample collection latitude (or beginning if using a net)\",\n \t\t\"object_lon\": \"Sample collection longitude (or beginning if using a net)\",\n \t\t\"object_depth_min\": \"Sample collection minimal depth, in m\",\n \t\t\"object_depth_max\": \"Sample collection maximum depth, in m\",\n \t\t\"process_pixel\": \"Pixel imaging resolution, in µm/pixel\",\n \t\t\"process_datetime\": \"Segmentation timestamp\",\n \t\t\"process_id\": \"Segmentation ID\",\n \t\t\"process_uuid\": \"Segmentation UUID (Autogenerated)\",\n \t\t\"process_source\": \"Code source link of the executed code\",\n \t\t\"process_commit\": \"Version reference of the executed code\",\n \t\t\"sample_gear_net_opening\": \"Sample mouth opening dimension, in mm\",\n \t\t\"object_date_end\": \"Sample end collection date when using a net\",\n \t\t\"object_time_end\": \"Sample end collection time when using a net\",\n \t\t\"object_lat_end\": \"Sample end collection latitude when using a net\",\n \t\t\"object_lon_end\": \"Sample end collection longitude when using a net\",\n \t},\n\t\t\"sample_project\": global.get(\"sample_project\"),\n\t\t\"sample_id\": global.get(\"sample_project\") + \"_\" + global.get(\"sample_id\"),\n\t\t\"sample_ship\": global.get(\"sample_ship\"),\n\t\t\"sample_operator\": global.get(\"sample_operator\"),\n\t\t\"sample_sampling_gear\": global.get(\"sample_sampling_gear\"),\n\t\t\"sample_concentrated_sample_volume\": global.get(\"sample_concentrated_sample_volume\"),\n\t\t\"sample_total_volume\": global.get(\"sample_total_volume\"),\n\t\t\"sample_dilution_factor\": global.get(\"sample_dilution_factor\"),\n\t\t\"sample_speed_through_water\": global.get(\"sample_speed_through_water\"),\n\n\t\t\"acq_id\": global.get(\"sample_project\") + \"_\" + global.get(\"sample_id\")+ \"_\" + global.get(\"acq_id\"),\n\t\t\"acq_instrument\": global.get(\"acq_instrument\"),\n\t\t\"acq_instrument_id\": global.get(\"acq_instrument_id\"),\n\t\t\"acq_celltype\": global.get(\"acq_celltype\"),\n\t\t\"acq_minimum_mesh\": global.get(\"acq_minimum_mesh\"),\n\t\t\"acq_maximum_mesh\": global.get(\"acq_maximum_mesh\"),\n\t\t\"acq_min_esd\": global.get(\"acq_min_esd\"),\n\t\t\"acq_max_esd\": global.get(\"acq_max_esd\"),\n\t\t\"acq_volume\": global.get(\"acq_volume\"),\n\t\t\"acq_imaged_volume\": global.get(\"acq_imaged_volume\"),\n\t\t\"acq_magnification\": global.get(\"acq_magnification\"),\n\t\t\"acq_fnumber_objective\": global.get(\"acq_fnumber_objective\"),\n\t\t\"acq_camera\": global.get(\"acq_camera\"),\n\t\t\"acq_nb_frame\": global.get(\"nb_frame\"),\n\t\t\"acq_software\": global.get(\"acq_software\"),\n\n\t\t\"object_date\": global.get(\"object_date\"),\n\t\t\"object_time\": global.get(\"object_time\"),\n\t\t\"object_lat\": global.get(\"object_lat\"),\n\t\t\"object_lon\": global.get(\"object_lon\"),\n\t\t\"object_depth_min\": global.get(\"object_depth_min\"),\n\t\t\"object_depth_max\": global.get(\"object_depth_max\"),\n\n\t\t\"process_pixel\": global.get(\"process_pixel\"),\n\t\t\"process_source\": global.get(\"process_source\"),\n\t\t\"process_commit\": global.get(\"process_commit\")\n\t}\n};\n\nif (msg.payload.config.sample_sampling_gear.startsWith(\"net\")) {\n\tmsg.payload.config[\"sample_gear_net_opening\"] = global.get(\"sample_gear_net_opening\")\n\tmsg.payload.config[\"object_date_end\"] = global.get(\"object_date_end\")\n\tmsg.payload.config[\"object_time_end\"] = global.get(\"object_time_end\")\n\tmsg.payload.config[\"object_lat_end\"] = global.get(\"object_lat_end\")\n\tmsg.payload.config[\"object_lon_end\"] = global.get(\"object_lon_end\")\n}\n\nif ( msg.send == true){\n\treturn [msg, msg]\n}\nelse{\n\treturn [msg, null]\n}", + "outputs": 2, + "timeout": "", + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 910, + "y": 440, + "wires": [["29be525e.0c87fe"], ["c3e50240.82aa58"]] + }, + { + "id": "40c12463.a1f84c", + "type": "delay", + "z": "baa1e3d9.cb29d", + "name": "", + "pauseType": "delay", + "timeout": "1", + "timeoutUnits": "seconds", + "rate": "1", + "nbRateUnits": "1", + "rateUnits": "second", + "randomFirst": "1", + "randomLast": "5", + "randomUnits": "seconds", + "drop": false, + "outputs": 1, + "x": 940, + "y": 480, + "wires": [["c3e50240.82aa58"]] + }, + { + "id": "4d1b02cb.83b51c", + "type": "ui_button", + "z": "baa1e3d9.cb29d", + "name": "", + "group": "4322c187.e73e5", + "order": 10, + "width": 5, + "height": 1, + "passthru": false, + "label": "Update config", + "tooltip": "", + "color": "", + "bgcolor": "", + "className": "", + "icon": "save", + "payload": "", + "payloadType": "str", + "topic": "imager/image", + "topicType": "str", + "x": 680, + "y": 440, + "wires": [["52ea7d01.711034"]] + }, + { + "id": "5921d0d0.a3d568", + "type": "subflow:1c24ad9c.bebec2", + "z": "baa1e3d9.cb29d", + "name": "", + "env": [], + "x": 110, + "y": 220, + "wires": [ + [ + "f3658d30.b8448", + "de2c90cf.b73b08", + "4be09c97f86897d9", + "f573206abefa9518", + "f948151ab4031df4", + "5e3dec55.881074", + "d3ca8847.4d1ae" + ] + ] + }, + { + "id": "f3658d30.b8448", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "get acq_id", + "func": "msg.payload = msg.payload.acq_id;\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 330, + "y": 240, + "wires": [["6b34c456.83178c"]] + }, + { + "id": "de2c90cf.b73b08", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "get acq_celltype", + "func": "msg.topic = 'acq_celltype';\nmsg.payload = msg.payload.acq_celltype;\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 340, + "y": 80, + "wires": [["cc0ca68b.4263a8"]] + }, + { + "id": "5e3dec55.881074", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "get acq_minimum_mesh", + "func": "msg.payload = msg.payload.acq_minimum_mesh;\nreturn msg;", + "outputs": 1, + "noerr": 0, + "x": 370, + "y": 160, + "wires": [["f59a2f0d.5e9af"]] + }, + { + "id": "d3ca8847.4d1ae", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "get acq_maximum_mesh", + "func": "msg.payload = msg.payload.acq_maximum_mesh;\nreturn msg;", + "outputs": 1, + "noerr": 0, + "x": 370, + "y": 200, + "wires": [["6008a8bb.259f08"]] + }, + { + "id": "b402f719.55bc98", + "type": "inject", + "z": "baa1e3d9.cb29d", + "name": "Default: FORWARD", + "props": [ + { + "p": "payload" + }, + { + "p": "topic", + "vt": "str" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "pump_direction", + "payload": "FORWARD", + "payloadType": "str", + "x": 220, + "y": 560, + "wires": [["bb62da8a.ebc328"]] + }, + { + "id": "6b2239f3.41fa3", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "set global", + "func": "global.set(msg.topic, msg.payload);", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 660, + "y": 560, + "wires": [[]] + }, + { + "id": "51b4d0df.d70a88", + "type": "ui_text_input", + "z": "baa1e3d9.cb29d", + "name": "nb_frame", + "label": "Number of images to acquire", + "tooltip": "", + "group": "4322c187.e73e5", + "order": 2, + "width": 5, + "height": 1, + "passthru": true, + "mode": "number", + "delay": 300, + "topic": "nb_frame", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 680, + "y": 280, + "wires": [["fb887036.12429", "67091ac0.8f9f6c", "99b11fe4.2795d"]] + }, + { + "id": "999065ca.27edb8", + "type": "switch", + "z": "baa1e3d9.cb29d", + "name": "topic filter", + "property": "topic", + "propertyType": "msg", + "rules": [ + { + "t": "eq", + "v": "status/pump", + "vt": "str" + }, + { + "t": "eq", + "v": "status/focus", + "vt": "str" + }, + { + "t": "eq", + "v": "status/imager", + "vt": "str" + } + ], + "checkall": "true", + "repair": false, + "outputs": 3, + "x": 320, + "y": 800, + "wires": [ + ["a46a1e7f.88a92", "6742014e.1bb238"], + ["c516d9ea.f7f6e", "6742014e.1bb238"], + ["307c851e.fb0f7a", "2b9d6988.d84836"] + ] + }, + { + "id": "2b009bd7.c07004", + "type": "ui_text", + "z": "baa1e3d9.cb29d", + "group": "70de8209.68416c", + "order": 3, + "width": 10, + "height": 2, + "name": "imager", + "label": "Imager status:", + "format": "{{msg.payload.status}}", + "layout": "col-center", + "x": 770, + "y": 740, + "wires": [] + }, + { + "id": "c516d9ea.f7f6e", + "type": "ui_text", + "z": "baa1e3d9.cb29d", + "group": "70de8209.68416c", + "order": 1, + "width": 5, + "height": 1, + "name": "focus", + "label": "Focus status:", + "format": "{{msg.payload.status}}", + "layout": "col-center", + "x": 770, + "y": 700, + "wires": [] + }, + { + "id": "a46a1e7f.88a92", + "type": "ui_text", + "z": "baa1e3d9.cb29d", + "group": "70de8209.68416c", + "order": 2, + "width": 5, + "height": 1, + "name": "pump", + "label": "Pump status:", + "format": "{{msg.payload.status}}", + "layout": "col-center", + "x": 770, + "y": 660, + "wires": [] + }, + { + "id": "bb628f8d.98f108", + "type": "link in", + "z": "baa1e3d9.cb29d", + "name": "Status for fluidic module", + "links": ["58f2e0f.4e8b12"], + "x": 175, + "y": 800, + "wires": [["999065ca.27edb8"]] + }, + { + "id": "307c851e.fb0f7a", + "type": "switch", + "z": "baa1e3d9.cb29d", + "name": "Imaging state", + "property": "payload", + "propertyType": "msg", + "rules": [ + { + "t": "jsonata_exp", + "v": "$contains(msg.payload.status, \"jpg\")\t", + "vt": "jsonata" + }, + { + "t": "else" + } + ], + "checkall": "false", + "repair": false, + "outputs": 2, + "x": 540, + "y": 880, + "wires": [["db8e3dde.44efb8"], ["6742014e.1bb238"]] + }, + { + "id": "db8e3dde.44efb8", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "img_counter", + "func": "img_counter=flow.get('img_counter')\nif (img_counter === undefined || img_counter === \"\"){\n img_counter = 0\n}\nimg_counter=img_counter+1\nflow.set('img_counter',img_counter)\nmsg.payload = img_counter\nmsg.payload = (100 * img_counter/global.get('nb_frame')).toFixed(2)\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 770, + "y": 860, + "wires": [["1a2e721a.f5e876"]] + }, + { + "id": "59164d65.e7993c", + "type": "ui_toast", + "z": "baa1e3d9.cb29d", + "position": "top right", + "displayTime": "5", + "highlight": "", + "sendall": true, + "outputs": 0, + "ok": "OK", + "cancel": "", + "raw": false, + "topic": "", + "name": "", + "x": 1260, + "y": 900, + "wires": [] + }, + { + "id": "8c7348aa.1962e8", + "type": "template", + "z": "baa1e3d9.cb29d", + "name": "Create sentence", + "field": "payload", + "fieldType": "msg", + "format": "handlebars", + "syntax": "mustache", + "template": "The {{topic}} is {{payload.status}}", + "output": "str", + "x": 1050, + "y": 900, + "wires": [["59164d65.e7993c"]] + }, + { + "id": "6742014e.1bb238", + "type": "change", + "z": "baa1e3d9.cb29d", + "name": "Remove high-level topic", + "rules": [ + { + "t": "change", + "p": "topic", + "pt": "msg", + "from": "status/", + "fromt": "str", "to": "", - "reg": false, - "x": 210, - "y": 240, - "wires": [ - [ - "833dac7cbd693c53" - ] - ] - }, - { - "id": "833dac7cbd693c53", - "type": "exec", - "z": "1eaf21c8.f7a21e", - "command": "cp", - "addpay": "payload", - "append": "/home/pi/PlanktoScope/hardware.json", - "useSpawn": "false", - "timer": "", - "winHide": false, - "oldrc": false, - "name": "Copy default hardware config", - "x": 500, - "y": 240, - "wires": [ - [ - "0b67ccf37c034e90" - ], - [], - [] - ] - }, - { - "id": "0b67ccf37c034e90", - "type": "delay", - "z": "1eaf21c8.f7a21e", - "name": "", - "pauseType": "delay", - "timeout": "500", - "timeoutUnits": "milliseconds", - "rate": "1", - "nbRateUnits": "1", - "rateUnits": "second", - "randomFirst": "1", - "randomLast": "5", - "randomUnits": "seconds", - "drop": false, - "allowrate": false, - "outputs": 1, - "x": 730, - "y": 240, - "wires": [ - [ - "da3d4a90384d62a8", - "e4ead350b3d07578" - ] - ] - }, - { - "id": "2716aa5b3d027f95", - "type": "change", - "z": "1eaf21c8.f7a21e", - "name": "Get acq_instrument", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.acq_instrument", - "tot": "msg" - }, - { - "t": "set", - "p": "topic", - "pt": "msg", - "to": "acq_instrument", - "tot": "str" - } - ], - "action": "", - "property": "", - "from": "", + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 810, + "y": 900, + "wires": [["8c7348aa.1962e8"]] + }, + { + "id": "1a2e721a.f5e876", + "type": "ui_gauge", + "z": "baa1e3d9.cb29d", + "name": "progress donut", + "group": "b5d61bc7.54fe48", + "order": 3, + "width": 6, + "height": 3, + "gtype": "donut", + "title": "", + "label": "%", + "format": "{{value}}", + "min": 0, + "max": "100", + "colors": ["#ffa83f", "#e6ff02", "#00dfe9"], + "seg1": "50", + "seg2": "75", + "x": 1260, + "y": 860, + "wires": [] + }, + { + "id": "9bd72495.a8a098", + "type": "ui_text", + "z": "baa1e3d9.cb29d", + "group": "4322c187.e73e5", + "order": 5, + "width": 5, + "height": 1, + "name": "Total imaged volume", + "label": "Total imaged volume", + "format": "{{msg.payload}}", + "layout": "col-center", + "x": 1200, + "y": 140, + "wires": [] + }, + { + "id": "99b11fe4.2795d", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "imaged volume calc", + "func": "camera = global.get(\"acq_camera\");\ncell = global.get(\"acq_celltype\");\nnb_frame = global.get(\"nb_frame\");\nprocess_pixel = global.get(\"process_pixel\");\n\nvar volume = 0\nif (camera == \"HQ Camera\"){\n volume = nb_frame * (process_pixel*4056*process_pixel*3040*cell/1000000000) / 1000;\n}\nelse if (camera == \"Camera v2.1\"){\n volume = nb_frame * (process_pixel*3280*process_pixel*2464*cell/1000000000) / 1000;\n}\nelse{\n msg.payload = \"The camera is not known to this system\";\n return msg;\n}\n\nglobal.set(\"acq_imaged_volume\", volume.toFixed(4))\n\nmsg.payload = volume.toFixed(2) + \" mL\"\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 960, + "y": 140, + "wires": [["9bd72495.a8a098"]], + "info": "### Focusing\n##### focus.py `nb_step` `orientation`\n\n- `nb_step` : **integer** (from 1 to 100000) - number of step to perform by the stage (about 31um/step)\n- `orientation` : **string** - orientation of the focus either `up` or `down`\n\nExample:\n\n python3.7 $HOME/PlanktoScope/scripts/focus.py 650 up\n" + }, + { + "id": "8e16aa2f.e40398", + "type": "ui_text", + "z": "baa1e3d9.cb29d", + "group": "4322c187.e73e5", + "order": 7, + "width": 5, + "height": 1, + "name": "Total pumped volume", + "label": "Total pumped volume", + "format": "{{msg.payload}} mL", + "layout": "col-center", + "x": 1200, + "y": 300, + "wires": [] + }, + { + "id": "67091ac0.8f9f6c", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "acq_volume calc", + "func": "var imaging_pump_volume = global.get(\"imaging_pump_volume\");\nvar nb_frame = global.get(\"nb_frame\");\nvar acq_volume = 0\n\nacq_volume = (Number(nb_frame)*Number(imaging_pump_volume)).toFixed(2)\nglobal.set(\"acq_volume\", acq_volume)\n\nmsg.payload = acq_volume\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 950, + "y": 300, + "wires": [["8e16aa2f.e40398"]], + "info": "### Focusing\n##### focus.py `nb_step` `orientation`\n\n- `nb_step` : **integer** (from 1 to 100000) - number of step to perform by the stage (about 31um/step)\n- `orientation` : **string** - orientation of the focus either `up` or `down`\n\nExample:\n\n python3.7 $HOME/PlanktoScope/scripts/focus.py 650 up\n" + }, + { + "id": "2b9d6988.d84836", + "type": "switch", + "z": "baa1e3d9.cb29d", + "name": "", + "property": "payload", + "propertyType": "msg", + "rules": [ + { + "t": "hask", + "v": "status", + "vt": "str" + }, + { + "t": "hask", + "v": "camera_name", + "vt": "str" + } + ], + "checkall": "true", + "repair": false, + "outputs": 2, + "x": 650, + "y": 760, + "wires": [["2b009bd7.c07004"], ["3bbb756a.84190a"]] + }, + { + "id": "3bbb756a.84190a", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "set camera name", + "func": "global.set(\"acq_camera\", msg.payload.camera_name);\n\nmsg.payload = msg.payload.camera_name;\n\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 810, + "y": 780, + "wires": [["559a8085.1d6b9"]] + }, + { + "id": "559a8085.1d6b9", + "type": "link out", + "z": "baa1e3d9.cb29d", + "name": "Camera Name", + "links": ["30067f35.532f2", "572a6daa.6004c4"], + "x": 965, + "y": 780, + "wires": [] + }, + { + "id": "49ea1123.ee1768", + "type": "ui_numeric", + "z": "baa1e3d9.cb29d", + "name": "sleep_before", + "label": "Delay to stabilize image (s)", + "tooltip": "Happens before every capture", + "group": "4322c187.e73e5", + "order": 4, + "width": 5, + "height": 1, + "wrap": false, + "passthru": true, + "topic": "sleep_before", + "topicType": "str", + "format": "{{value}}", + "min": "0.1", + "max": "5", + "step": "0.1", + "className": "", + "x": 670, + "y": 120, + "wires": [["fb887036.12429"]] + }, + { + "id": "572a6daa.6004c4", + "type": "link in", + "z": "baa1e3d9.cb29d", + "name": "", + "links": ["559a8085.1d6b9"], + "x": 795, + "y": 140, + "wires": [["99b11fe4.2795d"]] + }, + { + "id": "8032ea50.1b57f", + "type": "ui_template", + "z": "baa1e3d9.cb29d", + "group": "b5d61bc7.54fe48", + "name": "progress header", + "order": 1, + "width": 0, + "height": 0, + "format": "

Capture progress

", + "storeOutMessages": false, + "fwdInMessages": false, + "resendOnRefresh": false, + "templateScope": "local", + "x": 1260, + "y": 820, + "wires": [[]] + }, + { + "id": "a4abb1ae.2ae418", + "type": "subflow:1c24ad9c.bebec2", + "z": "baa1e3d9.cb29d", + "name": "", + "env": [], + "x": 930, + "y": 520, + "wires": [[]] + }, + { + "id": "4be09c97f86897d9", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "get nb_frame", + "func": "msg.payload = msg.payload.nb_frame;\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 330, + "y": 280, + "wires": [["51b4d0df.d70a88"]] + }, + { + "id": "f573206abefa9518", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "get imaging_pump_volume", + "func": "msg.payload = msg.payload.imaging_pump_volume;\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 380, + "y": 320, + "wires": [["e1acc6c599033114"]] + }, + { + "id": "f948151ab4031df4", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "get sleep_before", + "func": "msg.payload = msg.payload.sleep_before;\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 340, + "y": 120, + "wires": [["49ea1123.ee1768"]] + }, + { + "id": "ad153212312f0347", + "type": "ui_ui_control", + "z": "baa1e3d9.cb29d", + "name": "onTab", + "events": "all", + "x": 330, + "y": 380, + "wires": [["9b69ea945b587192"]] + }, + { + "id": "9b69ea945b587192", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "check tab", + "func": "if (msg.name == \"Fluidic Acquisition\"){\n return { \"topic\": \"imager/ image\" }\n}", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 480, + "y": 380, + "wires": [["52ea7d01.711034"]], + "outputLabels": ["interface"] + }, + { + "id": "e1acc6c599033114", + "type": "ui_text_input", + "z": "baa1e3d9.cb29d", + "name": "imaging_pump_volume", + "label": "Pumped volume (mL)", + "tooltip": "between frames", + "group": "4322c187.e73e5", + "order": 3, + "width": 0, + "height": 0, + "passthru": true, + "mode": "text", + "delay": 300, + "topic": "imaging_pump_volume", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 630, + "y": 320, + "wires": [["fb887036.12429", "67091ac0.8f9f6c"]] + }, + { + "id": "f4caa15e2bbfd6e7", + "type": "ui_template", + "z": "baa1e3d9.cb29d", + "group": "4322c187.e73e5", + "name": "Start Acquisition", + "order": 13, + "width": "5", + "height": "1", + "format": "\n\n", + "storeOutMessages": false, + "fwdInMessages": false, + "resendOnRefresh": false, + "templateScope": "local", + "className": "", + "x": 460, + "y": 480, + "wires": [["c9f510c0.7d1328"]] + }, + { + "id": "9d6abe67.6bb3d", + "type": "ui_button", + "z": "cb95299c.2817c8", + "name": "", + "group": "64903b47.4034e4", + "order": 1, + "width": 0, + "height": 0, + "passthru": false, + "label": "Home", + "tooltip": "", + "color": "", + "bgcolor": "", + "icon": "home", + "payload": "{\"tab\":\"Home\"}", + "payloadType": "json", + "topic": "", + "x": 430, + "y": 600, + "wires": [["f0fb77cf.8f1c28"]] + }, + { + "id": "f0fb77cf.8f1c28", + "type": "ui_ui_control", + "z": "cb95299c.2817c8", + "name": "", + "events": "change", + "x": 740, + "y": 600, + "wires": [[]] + }, + { + "id": "8ec68b82.17e3d8", + "type": "ui_button", + "z": "cb95299c.2817c8", + "name": "Start segmentation", + "group": "abeb6dad.635a2", + "order": 10, + "width": 5, + "height": 1, + "passthru": false, + "label": "Start segmentation", + "tooltip": "", + "color": "", + "bgcolor": "", + "icon": "", + "payload": "{\"action\":\"segment\"}", + "payloadType": "json", + "topic": "segmenter/segment", + "x": 370, + "y": 460, + "wires": [["33c28dc1.238002", "c72a1064.1ec388"]] + }, + { + "id": "27be7971.b3fbce", + "type": "ui_button", + "z": "cb95299c.2817c8", + "d": true, + "name": "Stop segmentation", + "group": "abeb6dad.635a2", + "order": 12, + "width": 4, + "height": 1, + "passthru": true, + "label": "Stop segmentation", + "tooltip": "", + "color": "", + "bgcolor": "#AD1625", + "icon": "", + "payload": "{\"action\":\"stop\"}", + "payloadType": "json", + "topic": "segmenter/segment", + "x": 370, + "y": 520, + "wires": [["16f3cef4.0acac9"]] + }, + { + "id": "16f3cef4.0acac9", + "type": "mqtt out", + "z": "cb95299c.2817c8", + "name": "", + "topic": "", + "qos": "", + "retain": "", + "broker": "8dc3722c.06efa8", + "x": 850, + "y": 520, + "wires": [] + }, + { + "id": "8f3788f6.ddcf98", + "type": "function", + "z": "cb95299c.2817c8", + "name": "obj_counter", + "func": "obj_counter = flow.get('obj_counter')\nobj_counter = obj_counter + 1\nflow.set('obj_counter', obj_counter)\nmsg.payload = obj_counter\nmsg.topic = \"object count\"\nreturn msg", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 810, + "y": 800, + "wires": [["fa3b7929.ac7da8", "9d53dbe2.dbffe8"]] + }, + { + "id": "aa38dbbc.cf0a9", + "type": "switch", + "z": "cb95299c.2817c8", + "name": "Segmenter", + "property": "topic", + "propertyType": "msg", + "rules": [ + { + "t": "eq", + "v": "status/segmenter", + "vt": "str" + }, + { + "t": "eq", + "v": "status/segmenter/name", + "vt": "str" + }, + { + "t": "eq", + "v": "status/segmenter/object_id", + "vt": "str" + }, + { + "t": "eq", + "v": "status/segmenter/metric", + "vt": "str" + } + ], + "checkall": "true", + "repair": false, + "outputs": 4, + "x": 490, + "y": 740, + "wires": [ + ["b9a23b91.93638", "6919465f.332e5"], + ["49af3d24.1799e4"], + ["8f3788f6.ddcf98"], + [] + ] + }, + { + "id": "9d53dbe2.dbffe8", + "type": "ui_chart", + "z": "cb95299c.2817c8", + "name": "counter graph", + "group": "46be9c86.dea684", + "order": 7, + "width": 10, + "height": 2, + "label": "", + "chartType": "horizontalBar", + "legend": "false", + "xformat": "HH:mm:ss", + "interpolate": "linear", + "nodata": "Objects count will be shown here once the segmentation is started", + "dot": false, + "ymin": "", + "ymax": "", + "removeOlder": 1, + "removeOlderPoints": "", + "removeOlderUnit": "3600", + "cutout": 0, + "useOneColor": true, + "useUTC": false, + "colors": [ + "#1f77b4", + "#aec7e8", + "#ff7f0e", + "#2ca02c", + "#98df8a", + "#d62728", + "#ff9896", + "#9467bd", + "#c5b0d5" + ], + "outputs": 1, + "x": 1340, + "y": 840, + "wires": [[]] + }, + { + "id": "a4f0f0d1.3aca88", + "type": "ui_toast", + "z": "cb95299c.2817c8", + "position": "top right", + "displayTime": "5", + "highlight": "", + "sendall": true, + "outputs": 0, + "ok": "OK", + "cancel": "", + "raw": false, + "topic": "", + "name": "", + "x": 1340, + "y": 680, + "wires": [] + }, + { + "id": "49af3d24.1799e4", + "type": "debug", + "z": "cb95299c.2817c8", + "name": "segmentation name", + "active": true, + "tosidebar": true, + "console": false, + "tostatus": false, + "complete": "true", + "targetType": "full", + "statusVal": "", + "statusType": "auto", + "x": 830, + "y": 760, + "wires": [] + }, + { + "id": "7088a5be.0c79a4", + "type": "template", + "z": "cb95299c.2817c8", + "name": "Create sentence", + "field": "payload", + "fieldType": "msg", + "format": "handlebars", + "syntax": "mustache", + "template": "The {{topic}} is {{payload.status}}", + "output": "str", + "x": 1100, + "y": 680, + "wires": [["a4f0f0d1.3aca88"]] + }, + { + "id": "b9a23b91.93638", + "type": "change", + "z": "cb95299c.2817c8", + "name": "Remove high-level topic", + "rules": [ + { + "t": "change", + "p": "topic", + "pt": "msg", + "from": "status/", + "fromt": "str", "to": "", - "reg": false, - "x": 330, - "y": 160, - "wires": [ - [ - "a7e5c7f4.644678" - ] - ] - } + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 850, + "y": 680, + "wires": [["7088a5be.0c79a4"]] + }, + { + "id": "6919465f.332e5", + "type": "ui_text", + "z": "cb95299c.2817c8", + "group": "46be9c86.dea684", + "order": 1, + "width": 10, + "height": 1, + "name": "segmenter", + "label": "Segmenter status:", + "format": "{{msg.payload.status}}", + "layout": "row-spread", + "x": 810, + "y": 720, + "wires": [] + }, + { + "id": "fa3b7929.ac7da8", + "type": "ui_text", + "z": "cb95299c.2817c8", + "group": "46be9c86.dea684", + "order": 5, + "width": 4, + "height": 1, + "name": "counter", + "label": "", + "format": "{{msg.payload}}", + "layout": "col-center", + "x": 1320, + "y": 800, + "wires": [] + }, + { + "id": "640ece83.88cab", + "type": "inject", + "z": "cb95299c.2817c8", + "name": "Init graphs", + "props": [ + { + "p": "payload" + }, + { + "p": "topic", + "vt": "str" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "object count", + "payload": "0", + "payloadType": "num", + "x": 810, + "y": 880, + "wires": [["4f3f7c4a.cb21c4"]] + }, + { + "id": "25867454.a8e334", + "type": "link in", + "z": "cb95299c.2817c8", + "name": "Segmenter module status", + "links": ["dcf5bd45.16a8d"], + "x": 295, + "y": 740, + "wires": [["aa38dbbc.cf0a9"]] + }, + { + "id": "c8749cbb.55254", + "type": "function", + "z": "cb95299c.2817c8", + "name": "set global", + "func": "global.set(msg.topic, msg.payload);", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 960, + "y": 380, + "wires": [[]] + }, + { + "id": "d43c3ed9.e6cb1", + "type": "ui_template", + "z": "cb95299c.2817c8", + "group": "46be9c86.dea684", + "name": "Object counts", + "order": 3, + "width": 0, + "height": 0, + "format": "

Object counts

", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": true, + "templateScope": "local", + "className": "", + "x": 1340, + "y": 760, + "wires": [[]] + }, + { + "id": "33c28dc1.238002", + "type": "function", + "z": "cb95299c.2817c8", + "name": "prepare segmentation", + "func": "global.set('obj_counter', 0);\n\nvar segmentation_list = flow.get('segmentation_list')\nif (segmentation_list !== undefined && segmentation_list !== \"\") {\n msg.payload['path'] = segmentation_list\n}\n\n\nvar force = flow.get('force')\nif (force !== undefined && force !== \"\") {\n msg.payload['settings'] = {\"force\":Boolean(force)}\n}\n\n\nvar recursive = flow.get('recursive')\nif (recursive !== undefined && recursive !== \"\") {\n if (\"settings\" in msg.payload){\n msg.payload.settings[\"recursive\"] = Boolean(recursive)\n }\n else{\n msg.payload['settings'] = {\"recursive\": Boolean(recursive)}\n }\n}\n\nvar ecotaxa = flow.get('ecotaxa')\nif (ecotaxa !== undefined && ecotaxa !== \"\") {\n if (\"settings\" in msg.payload){\n msg.payload.settings[\"ecotaxa\"] = Boolean(ecotaxa)\n }\n else{\n msg.payload['settings'] = {\"ecotaxa\": Boolean(ecotaxa)}\n }\n}\n\nvar keep = flow.get('keep')\nif (keep !== undefined && keep !== \"\") {\n if (\"settings\" in msg.payload){\n msg.payload.settings[\"keep\"] = Boolean(keep)\n }\n else{\n msg.payload['settings'] = {\"keep\": Boolean(keep)}\n }\n}\n\nvar process_id = global.get('process_id')\nif (process_id !== undefined && process_id !== \"\") {\n if (\"settings\" in msg.payload){\n msg.payload.settings[\"process_id\"] = process_id\n }\n else{\n msg.payload['settings'] = {\"process_id\": process_id}\n }\n}\n\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 620, + "y": 460, + "wires": [["16f3cef4.0acac9"]] + }, + { + "id": "fa12f9f8.00cfa8", + "type": "subflow:1c24ad9c.bebec2", + "z": "cb95299c.2817c8", + "name": "", + "env": [], + "x": 430, + "y": 380, + "wires": [["3b72d11c.86e9e6"]] + }, + { + "id": "3b72d11c.86e9e6", + "type": "function", + "z": "cb95299c.2817c8", + "name": "get process_id", + "func": "msg.payload = msg.payload.process_id;\nmsg.topic = \"process_id\";\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 600, + "y": 380, + "wires": [["56971109c8be3b54"]] + }, + { + "id": "3ea12061.ce62c", + "type": "ui_list", + "z": "cb95299c.2817c8", + "group": "abeb6dad.635a2", + "name": "", + "order": 9, + "width": 10, + "height": 11, + "lineType": "one", + "actionType": "check", + "allowHTML": false, + "outputs": 1, + "topic": "", + "x": 790, + "y": 140, + "wires": [["cb3b87b5.63c4"]] + }, + { + "id": "8bd8fb2c.53fa4", + "type": "dir2files", + "z": "cb95299c.2817c8", + "name": "", + "dirname": "/home/pi/data/img/", + "pathRegex": "", + "isRecursive": true, + "findDir": true, + "isArray": true, + "x": 460, + "y": 140, + "wires": [["ba2947.c854deb8"]] + }, + { + "id": "127d4ee.f8ad1b1", + "type": "ui_button", + "z": "cb95299c.2817c8", + "name": "Refresh", + "group": "abeb6dad.635a2", + "order": 8, + "width": 0, + "height": 0, + "passthru": false, + "label": "Update acquisition's folder list", + "tooltip": "Refresh the list of previous acquisitions", + "color": "", + "bgcolor": "", + "icon": "mi-find_replace", + "payload": "", + "payloadType": "date", + "topic": "update", + "x": 260, + "y": 140, + "wires": [["8bd8fb2c.53fa4", "56f845f5.e7c054"]] + }, + { + "id": "946ce9ee.092cf", + "type": "inject", + "z": "cb95299c.2817c8", + "name": "Init", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "payload": "", + "payloadType": "date", + "x": 270, + "y": 100, + "wires": [["8bd8fb2c.53fa4", "56f845f5.e7c054"]] + }, + { + "id": "cb3b87b5.63c4", + "type": "function", + "z": "cb95299c.2817c8", + "name": "update segmentation_list", + "func": "var segmentation_list = flow.get('segmentation_list');\n\nif (segmentation_list === undefined || segmentation_list === \"\") {\n segmentation_list = []\n console.log(\"error\")\n}\n\npath = \"/home/pi/data/img/\" + msg.payload.title\n\nif (msg.payload.isChecked){\n if (segmentation_list.includes(path) === false){\n segmentation_list.push(path)\n }\n // Element already in list, don't push it more than once\n //segmentation_list.push(msg.payload[\"title\"])\n}\nelse {\n var pos = segmentation_list.indexOf(path)\n segmentation_list.splice(pos, 1)\n}\n\nflow.set('segmentation_list', segmentation_list)", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 990, + "y": 140, + "wires": [[]] + }, + { + "id": "56f845f5.e7c054", + "type": "change", + "z": "cb95299c.2817c8", + "name": "Reset segmentation_list", + "rules": [ + { + "t": "set", + "p": "segmentation_list", + "pt": "flow", + "to": "[]", + "tot": "json" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 510, + "y": 100, + "wires": [[]] + }, + { + "id": "7fc72364.8f038c", + "type": "ui_template", + "z": "cb95299c.2817c8", + "group": "abeb6dad.635a2", + "name": "Update message", + "order": 1, + "width": 10, + "height": 3, + "format": "
You can choose here in which folder(s) you want the segmentation script to run. A few details though:\n
The segmentation is run recursively in all folders. So if you select a top level folder, the segmentation will be run in all subfolders.\n
Also, you will be able to chose wether for force the segmentation for folders in which it has run already.
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": true, + "templateScope": "local", + "x": 270, + "y": 40, + "wires": [[]] + }, + { + "id": "ba2947.c854deb8", + "type": "function", + "z": "cb95299c.2817c8", + "name": "remove common", + "func": "function remove_path(item, index, array) {\n array[index] = item.replace(\"/home/pi/data/img/\", \"\")\n} \n\nmsg.payload.forEach(remove_path)\n\nreturn msg", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 630, + "y": 140, + "wires": [["3ea12061.ce62c"]] + }, + { + "id": "21af0db1.c2c182", + "type": "ui_multistate_switch", + "z": "cb95299c.2817c8", + "name": "recursive toggle", + "group": "abeb6dad.635a2", + "order": 4, + "width": 5, + "height": 1, + "label": "Recursive folder", + "stateField": "payload", + "enableField": "enable", + "rounded": true, + "useThemeColors": true, + "hideSelectedLabel": false, + "options": [ + { + "label": "No", + "value": "0", + "valueType": "num", + "color": "#009933" + }, + { + "label": "Yes", + "value": "1", + "valueType": "num", + "color": "#999999" + } + ], + "x": 480, + "y": 220, + "wires": [["880b192a.88e2d"]] + }, + { + "id": "dffb9881.feef8", + "type": "ui_multistate_switch", + "z": "cb95299c.2817c8", + "name": "force toggle", + "group": "abeb6dad.635a2", + "order": 3, + "width": 5, + "height": 1, + "label": "Force rework", + "stateField": "payload", + "enableField": "enable", + "rounded": true, + "useThemeColors": true, + "hideSelectedLabel": false, + "options": [ + { + "label": "No", + "value": "0", + "valueType": "num", + "color": "#009933" + }, + { + "label": "Yes", + "value": "1", + "valueType": "num", + "color": "#999999" + } + ], + "x": 470, + "y": 300, + "wires": [["a4f68fa6.5d77f8"]] + }, + { + "id": "880b192a.88e2d", + "type": "change", + "z": "cb95299c.2817c8", + "name": "", + "rules": [ + { + "t": "set", + "p": "recursive", + "pt": "flow", + "to": "payload", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 690, + "y": 240, + "wires": [[]] + }, + { + "id": "a4f68fa6.5d77f8", + "type": "change", + "z": "cb95299c.2817c8", + "name": "", + "rules": [ + { + "t": "set", + "p": "force", + "pt": "flow", + "to": "payload", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 670, + "y": 280, + "wires": [[]] + }, + { + "id": "1ef1b43b.b0f064", + "type": "inject", + "z": "cb95299c.2817c8", + "name": "0", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "payload": "0", + "payloadType": "num", + "x": 270, + "y": 280, + "wires": [["dffb9881.feef8", "a4f68fa6.5d77f8"]] + }, + { + "id": "f078c068.eacf58", + "type": "ui_template", + "z": "cb95299c.2817c8", + "group": "46be9c86.dea684", + "name": "Stream Segmented object", + "order": 2, + "width": 10, + "height": 8, + "format": "
\n Latest object segmented:
\n \"If\n
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "className": "", + "x": 1370, + "y": 600, + "wires": [[]] + }, + { + "id": "43f97b93.b76294", + "type": "inject", + "z": "cb95299c.2817c8", + "name": "1", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "payload": "1", + "payloadType": "num", + "x": 270, + "y": 240, + "wires": [["21af0db1.c2c182", "880b192a.88e2d"]] + }, + { + "id": "4f3f7c4a.cb21c4", + "type": "change", + "z": "cb95299c.2817c8", + "name": "", + "rules": [ + { + "t": "set", + "p": "obj_counter", + "pt": "flow", + "to": "0", + "tot": "num" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 1010, + "y": 840, + "wires": [["fa3b7929.ac7da8", "9d53dbe2.dbffe8"]] + }, + { + "id": "6bce0f60.f48998", + "type": "link in", + "z": "cb95299c.2817c8", + "name": "", + "links": ["596fc9d4.46c75"], + "x": 855, + "y": 840, + "wires": [["4f3f7c4a.cb21c4"]] + }, + { + "id": "596fc9d4.46c75", + "type": "link out", + "z": "cb95299c.2817c8", + "name": "", + "links": ["6bce0f60.f48998"], + "x": 715, + "y": 500, + "wires": [] + }, + { + "id": "c72a1064.1ec388", + "type": "change", + "z": "cb95299c.2817c8", + "name": "Reset counters", + "rules": [ + { + "t": "set", + "p": "topic", + "pt": "msg", + "to": "object count", + "tot": "str" + }, + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "0", + "tot": "num" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 600, + "y": 500, + "wires": [["596fc9d4.46c75"]] + }, + { + "id": "9367534a.fb8568", + "type": "ui_multistate_switch", + "z": "cb95299c.2817c8", + "name": "Ecotaxa archive", + "group": "abeb6dad.635a2", + "order": 6, + "width": 5, + "height": 1, + "label": "Ecotaxa archive", + "stateField": "payload", + "enableField": "enable", + "rounded": true, + "useThemeColors": true, + "hideSelectedLabel": false, + "options": [ + { + "label": "No", + "value": "0", + "valueType": "num", + "color": "#009933" + }, + { + "label": "Yes", + "value": "1", + "valueType": "num", + "color": "#999999" + } + ], + "x": 1080, + "y": 220, + "wires": [["25ac4f9a.5b05c8"]] + }, + { + "id": "25ac4f9a.5b05c8", + "type": "change", + "z": "cb95299c.2817c8", + "name": "", + "rules": [ + { + "t": "set", + "p": "ecotaxa", + "pt": "flow", + "to": "payload", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 1280, + "y": 240, + "wires": [[]] + }, + { + "id": "bef78886.8f0b98", + "type": "inject", + "z": "cb95299c.2817c8", + "name": "1", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "payload": "1", + "payloadType": "num", + "x": 910, + "y": 240, + "wires": [["9367534a.fb8568", "25ac4f9a.5b05c8"]] + }, + { + "id": "32465a4e.8fcac6", + "type": "ui_multistate_switch", + "z": "cb95299c.2817c8", + "name": "Keep objects", + "group": "abeb6dad.635a2", + "order": 5, + "width": 5, + "height": 1, + "label": "Keep objects", + "stateField": "payload", + "enableField": "enable", + "rounded": true, + "useThemeColors": true, + "hideSelectedLabel": false, + "options": [ + { + "label": "No", + "value": "0", + "valueType": "num", + "color": "#009933" + }, + { + "label": "Yes", + "value": "1", + "valueType": "num", + "color": "#999999" + } + ], + "x": 1070, + "y": 300, + "wires": [["8dd6f57f.b77f98"]] + }, + { + "id": "8dd6f57f.b77f98", + "type": "change", + "z": "cb95299c.2817c8", + "name": "", + "rules": [ + { + "t": "set", + "p": "keep", + "pt": "flow", + "to": "payload", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 1270, + "y": 280, + "wires": [[]] + }, + { + "id": "8090df89.c029e", + "type": "inject", + "z": "cb95299c.2817c8", + "name": "1", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "payload": "1", + "payloadType": "num", + "x": 910, + "y": 280, + "wires": [["32465a4e.8fcac6", "8dd6f57f.b77f98"]] + }, + { + "id": "56971109c8be3b54", + "type": "ui_text_input", + "z": "cb95299c.2817c8", + "name": "process_id", + "label": "Process unique ID*", + "tooltip": "", + "group": "abeb6dad.635a2", + "order": 2, + "width": 10, + "height": 1, + "passthru": true, + "mode": "text", + "delay": 300, + "topic": "process_id", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 790, + "y": 380, + "wires": [["c8749cbb.55254"]] + }, + { + "id": "2911fbc6.d28c24", + "type": "ui_template", + "z": "c1660bc.e7ff7f8", + "group": "c0ebfc57.42527", + "name": "Image browser", + "order": 1, + "width": "0", + "height": "0", + "format": "
\n\n
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "className": "", + "x": 400, + "y": 100, + "wires": [[]] + }, + { + "id": "4f02c726.de69b8", + "type": "ui_button", + "z": "9daf9e2b.019fc", + "name": "", + "group": "a7d64879.38298", + "order": 4, + "width": 6, + "height": 1, + "passthru": false, + "label": "Reboot", + "tooltip": "", + "color": "", + "bgcolor": "#AD1625", + "className": "", + "icon": "fa-repeat fa-2x", + "payload": "reboot", + "payloadType": "str", + "topic": "reboot", + "topicType": "str", + "x": 160, + "y": 240, + "wires": [["4af9112d.87767"]] + }, + { + "id": "611a8b1c.a829b4", + "type": "exec", + "z": "9daf9e2b.019fc", + "command": "sudo", + "addpay": "payload", + "append": "now", + "useSpawn": "false", + "timer": "2", + "winHide": false, + "oldrc": false, + "name": "sudo cmd now", + "x": 480, + "y": 280, + "wires": [[], [], []] + }, + { + "id": "bc76c4d6.a7ad28", + "type": "ui_button", + "z": "9daf9e2b.019fc", + "name": "", + "group": "a7d64879.38298", + "order": 5, + "width": 6, + "height": 1, + "passthru": false, + "label": "Shutdown", + "tooltip": "", + "color": "", + "bgcolor": "#AD1625", + "className": "", + "icon": "fa-power-off fa-2x", + "payload": "shutdown", + "payloadType": "str", + "topic": "shutdown", + "topicType": "str", + "x": 160, + "y": 320, + "wires": [["4af9112d.87767"]] + }, + { + "id": "4af9112d.87767", + "type": "python3-function", + "z": "9daf9e2b.019fc", + "name": "action", + "func": "#!/usr/bin/python3\nimport smbus2 as smbus\n\nbus = smbus.SMBus(1)\n#turn off LED\nbus.write_byte_data(0x0d, 0x07, 0x00)\n#turn off Fan\nbus.write_byte_data(0x0d, 0x08, 0x00)\n\n#msg[\"payload\"] = str(msg[\"topic\"])+' now'\nreturn msg", + "outputs": 1, + "x": 330, + "y": 280, + "wires": [["611a8b1c.a829b4"]] + }, + { + "id": "466eb611.4da048", + "type": "ui_button", + "z": "9daf9e2b.019fc", + "name": "", + "group": "a7d64879.38298", + "order": 2, + "width": 6, + "height": 1, + "passthru": true, + "label": "Restart Hardware Controller", + "tooltip": "", + "color": "", + "bgcolor": "#AD1625", + "className": "", + "icon": "fa-refresh fa-2x", + "payload": "Restarting hardware controller...", + "payloadType": "str", + "topic": "", + "topicType": "str", + "x": 460, + "y": 420, + "wires": [["bd5cceef.b17ad", "414353cde6a62346"]] + }, + { + "id": "bd5cceef.b17ad", + "type": "exec", + "z": "9daf9e2b.019fc", + "command": "sudo systemctl restart planktoscope-org.device-backend.controller.service", + "addpay": false, + "append": "", + "useSpawn": "false", + "timer": "", + "winHide": false, + "oldrc": false, + "name": "Restart hardware controller", + "x": 800, + "y": 420, + "wires": [[], [], []] + }, + { + "id": "43cf8ff7.75231", + "type": "rpi-gpio out", + "z": "9daf9e2b.019fc", + "name": "Pump Enable", + "pin": "4", + "set": true, + "level": "1", + "freq": "", + "out": "out", + "bcm": true, + "x": 420, + "y": 80, + "wires": [] + }, + { + "id": "4bca8a25.15be3c", + "type": "rpi-gpio out", + "z": "9daf9e2b.019fc", + "name": "Focus Enable", + "pin": "12", + "set": true, + "level": "1", + "freq": "", + "out": "out", + "bcm": true, + "x": 420, + "y": 120, + "wires": [] + }, + { + "id": "50f9b5b.a84bccc", + "type": "inject", + "z": "9daf9e2b.019fc", + "name": "Default: ON", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": "0.01", + "topic": "", + "payload": "true", + "payloadType": "bool", + "x": 150, + "y": 100, + "wires": [ + [ + "43cf8ff7.75231", + "4bca8a25.15be3c", + "6db0fcf5.f0effc", + "5fc4ede4.72516c" + ] + ] + }, + { + "id": "45a7b5aa.2ed20c", + "type": "link in", + "z": "9daf9e2b.019fc", + "name": "Restart Hardware Controller", + "links": ["e41870d7.300eb8", "e4ead350b3d07578"], + "x": 195, + "y": 420, + "wires": [["466eb611.4da048"]] + }, + { + "id": "b81b990a.d4dca", + "type": "link in", + "z": "9daf9e2b.019fc", + "name": "Shutdown", + "links": ["e08cfcb8.2a67e8"], + "x": 195, + "y": 280, + "wires": [["4af9112d.87767"]] + }, + { + "id": "5fc4ede4.72516c", + "type": "rpi-gpio out", + "z": "9daf9e2b.019fc", + "name": "HAT Pump Enable", + "pin": "23", + "set": true, + "level": "1", + "freq": "", + "out": "out", + "bcm": true, + "x": 430, + "y": 40, + "wires": [] + }, + { + "id": "6db0fcf5.f0effc", + "type": "rpi-gpio out", + "z": "9daf9e2b.019fc", + "name": "HAT Focus Enable", + "pin": "5", + "set": true, + "level": "1", + "freq": "", + "out": "out", + "bcm": true, + "x": 430, + "y": 160, + "wires": [] + }, + { + "id": "38c05fcb891c82bf", + "type": "exec", + "z": "9daf9e2b.019fc", + "command": "docker restart apps_ps_backend_proc-segmenter-server-1", + "addpay": false, + "append": "", + "useSpawn": "false", + "timer": "", + "winHide": false, + "oldrc": false, + "name": "Restart segmenter", + "x": 770, + "y": 500, + "wires": [[], [], []] + }, + { + "id": "631b8626185addfc", + "type": "ui_button", + "z": "9daf9e2b.019fc", + "name": "", + "group": "a7d64879.38298", + "order": 3, + "width": 6, + "height": 1, + "passthru": true, + "label": "Restart Segmenter", + "tooltip": "", + "color": "", + "bgcolor": "#AD1625", + "className": "", + "icon": "fa-refresh fa-2x", + "payload": "Restarting segmenter...", + "payloadType": "str", + "topic": "", + "topicType": "str", + "x": 430, + "y": 500, + "wires": [["38c05fcb891c82bf", "e036d07cf78fde85"]] + }, + { + "id": "cec5bd6f962f6903", + "type": "ui_template", + "z": "9daf9e2b.019fc", + "group": "a7d64879.38298", + "name": "Logs", + "order": 1, + "width": 0, + "height": 0, + "format": "

\n The PlanktoScope software application consists of three components: a Node-RED dashboard which provides the user interface you're using; a Hardware Controller\n which executes commands sent from the Node-RED dashboard for hardware control and image acquisition; and a Segmenter which processes an acquired dataset of\n images and isolates objects from those images. Each component has its own independent log of messages, managed separately from the logs for the other components.\n

\n

\n All three components have live-updating logs which you can monitor. Additionally, the Hardware Controller and the Segmenter also save all of their log messages\n to files which you can browse and download. Those software components create a new log file each time they start, and the name of the log file includes the time\n in the PlanktoScope's clock when the software component started. However, if your PlanktoScope's clock is usually wrong, it makes the log files difficult to navigate.\n This will be fixed in a future version of the software.\n

\n

\n If you need to share your logs with other people (e.g. on Slack or GitHub), you should open the \"Downloadable Logs\" links, and then you can select one file or multiple\n log files for downloading as a zip archive.\n

\n", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": true, + "templateScope": "local", + "className": "", + "x": 650, + "y": 180, + "wires": [[]] + }, + { + "id": "414353cde6a62346", + "type": "ui_toast", + "z": "9daf9e2b.019fc", + "position": "top right", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 0, + "ok": "OK", + "cancel": "", + "raw": false, + "className": "", + "topic": "", + "name": "", + "x": 770, + "y": 380, + "wires": [] + }, + { + "id": "e036d07cf78fde85", + "type": "ui_toast", + "z": "9daf9e2b.019fc", + "position": "top right", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 0, + "ok": "OK", + "cancel": "", + "raw": false, + "className": "", + "topic": "", + "name": "", + "x": 770, + "y": 460, + "wires": [] + }, + { + "id": "ddcbbfa5.cd158", + "type": "exec", + "z": "1371dec5.76e671", + "command": "vcgencmd measure_temp | tr -d \"temp=\" | tr -d \"'C\" | tr -d \"\\n\"", + "addpay": false, + "append": "", + "useSpawn": "", + "timer": "", + "name": "RPi Temp.", + "x": 330, + "y": 40, + "wires": [["bc503fa5.f46dd"], [], []] + }, + { + "id": "3910d662.fa1f7a", + "type": "exec", + "z": "1371dec5.76e671", + "command": "df -h | grep /dev/root | awk -F ' ' '{print $5}' | tr -d % | tr \"\\n$\" \"\\ \" | sed 's/,/./' | tr -d \" \"", + "addpay": false, + "append": "", + "useSpawn": "", + "timer": "", + "name": "Disk Usage", + "x": 330, + "y": 120, + "wires": [["eaf74a43.fa27d"], [], []] + }, + { + "id": "1cd5b4c0.46af9b", + "type": "inject", + "z": "1371dec5.76e671", + "name": "update: 5s", + "props": [ + { + "p": "payload" + }, + { + "p": "topic", + "vt": "str" + } + ], + "repeat": "5", + "crontab": "", + "once": false, + "onceDelay": "", + "topic": "", + "payload": "", + "payloadType": "date", + "x": 110, + "y": 160, + "wires": [ + [ + "3910d662.fa1f7a", + "ddcbbfa5.cd158", + "23a84a3856fb68bd", + "4ed64bd91fa9fbdf", + "ed5f2d963d85478b" + ] + ] + }, + { + "id": "2549f778.4eb828", + "type": "python3-function", + "z": "1371dec5.76e671", + "name": "fan control", + "func": "import smbus2 as smbus\n\nstate = msg[\"payload\"]\nbus = smbus.SMBus(1)\n\nDEVICE_ADDRESS = 0x0d\n# command happens twice, for reasons\nif state == \"off\":\n with smbus.SMBus(1) as bus:\n bus.write_byte_data(DEVICE_ADDRESS, 0x08, 0x00)\n bus.write_byte_data(DEVICE_ADDRESS, 0x08, 0x00)\n return msg\nif state == \"on\":\n with smbus.SMBus(1) as bus:\n bus.write_byte_data(DEVICE_ADDRESS, 0x08, 0x01)\n bus.write_byte_data(DEVICE_ADDRESS, 0x08, 0x01)\n return msg\n", + "outputs": 1, + "x": 1150, + "y": 40, + "wires": [["e640ebb5c397f424"]] + }, + { + "id": "b7ab1ada.1f4158", + "type": "exec", + "z": "1371dec5.76e671", + "command": "i2cdetect -y 1", + "addpay": false, + "append": "", + "useSpawn": "false", + "timer": "1", + "winHide": false, + "oldrc": false, + "name": "i2c update", + "x": 1440, + "y": 40, + "wires": [[], [], []] + }, + { + "id": "bc503fa5.f46dd", + "type": "switch", + "z": "1371dec5.76e671", + "name": "", + "property": "payload", + "propertyType": "msg", + "rules": [ + { + "t": "gt", + "v": "40", + "vt": "num" + }, + { + "t": "lte", + "v": "35", + "vt": "num" + } + ], + "checkall": "true", + "repair": false, + "outputs": 2, + "x": 570, + "y": 40, + "wires": [["a25d6486.e1ce28"], ["5d4f3e71.1bad4"]] + }, + { + "id": "5d4f3e71.1bad4", + "type": "change", + "z": "1371dec5.76e671", + "name": "Set OFF", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "off", + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 720, + "y": 60, + "wires": [["7fb13a4a53b612a0"]] + }, + { + "id": "a25d6486.e1ce28", + "type": "change", + "z": "1371dec5.76e671", + "name": "Set ON", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "on", + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 720, + "y": 20, + "wires": [["7fb13a4a53b612a0"]] + }, + { + "id": "569154a.b53182c", + "type": "inject", + "z": "1371dec5.76e671", + "name": "once", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": "", + "topic": "", + "payload": "start", + "payloadType": "str", + "x": 170, + "y": 680, + "wires": [["ccb5172d10c1ccaf"]] + }, + { + "id": "4828d2f4.7c712c", + "type": "function", + "z": "1371dec5.76e671", + "name": "set global", + "func": "global.set(\"acq_instrument_id\",msg.payload);\n", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 580, + "y": 700, + "wires": [[]] + }, + { + "id": "e2f39a35.f57298", + "type": "subflow:1c24ad9c.bebec2", + "z": "1371dec5.76e671", + "name": "", + "env": [], + "x": 170, + "y": 620, + "wires": [["950b773ad4c0fdfe"]] + }, + { + "id": "3e64877a.9684b", + "type": "function", + "z": "1371dec5.76e671", + "name": "set global", + "func": "global.set(\"acq_software\", \"PlanktoScope \" + msg.payload);\n", + "outputs": 1, + "timeout": "", + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 820, + "y": 500, + "wires": [[]] + }, + { + "id": "bdc6718a.dd5d48", + "type": "ui_text", + "z": "1371dec5.76e671", + "group": "ce9e278.781eed8", + "order": 2, + "width": 0, + "height": 0, + "name": "", + "label": "Instrument Type", + "format": "{{msg.payload}}", + "layout": "row-spread", + "className": "", + "style": false, + "font": "", + "fontSize": "", + "color": "#000000", + "x": 600, + "y": 620, + "wires": [] + }, + { + "id": "a400a97e.e333a8", + "type": "ui_text", + "z": "1371dec5.76e671", + "group": "ce9e278.781eed8", + "order": 1, + "width": 0, + "height": 0, + "name": "", + "label": "Instrument Name", + "format": "{{msg.payload}}", + "layout": "row-spread", + "className": "", + "style": false, + "font": "", + "fontSize": "", + "color": "#000000", + "x": 610, + "y": 660, + "wires": [] + }, + { + "id": "8343fa69.49339", + "type": "ui_text", + "z": "1371dec5.76e671", + "group": "ce9e278.781eed8", + "order": 3, + "width": 0, + "height": 0, + "name": "", + "label": "Software Version", + "format": "{{msg.payload}}", + "layout": "row-spread", + "className": "", + "style": false, + "font": "", + "fontSize": "", + "color": "#000000", + "x": 850, + "y": 540, + "wires": [] + }, + { + "id": "f783aefd.c3bfd8", + "type": "ui_text", + "z": "1371dec5.76e671", + "group": "ce9e278.781eed8", + "order": 4, + "width": 0, + "height": 0, + "name": "", + "label": "Camera Name", + "format": "{{msg.payload}}", + "layout": "row-spread", + "x": 600, + "y": 740, + "wires": [] + }, + { + "id": "30067f35.532f2", + "type": "link in", + "z": "1371dec5.76e671", + "name": "Camera Name", + "links": ["559a8085.1d6b9"], + "x": 205, + "y": 740, + "wires": [["f783aefd.c3bfd8"]] + }, + { + "id": "11b51f8f.acd308", + "type": "python3-function", + "z": "1371dec5.76e671", + "d": true, + "name": "fan temperature", + "func": "import smbus\nbus = smbus.SMBus(1)\n\naddr = 0x0d\nfan_reg = 0x08\n\ntemp = float( msg[\"payload\"])\n\n# 0x01 full speed, 0x02: 20% speed, ..., 0x09: 90% speed\n\nif temp < 38:\n bus.write_byte_data(addr, fan_reg, 0x00)\nelif temp < 43:\n bus.write_byte_data(addr, fan_reg, 0x02)\nelif temp < 46:\n bus.write_byte_data(addr, fan_reg, 0x04)\nelif temp < 48:\n bus.write_byte_data(addr, fan_reg, 0x06)\nelif temp < 52:\n bus.write_byte_data(addr, fan_reg, 0x08)\nelse:\n bus.write_byte_data(addr, fan_reg, 0x01)\n\nreturn msg", + "outputs": 1, + "x": 1440, + "y": 120, + "wires": [[]] + }, + { + "id": "eaf74a43.fa27d", + "type": "switch", + "z": "1371dec5.76e671", + "name": "if disk > 90%", + "property": "payload", + "propertyType": "msg", + "rules": [ + { + "t": "gte", + "v": "90", + "vt": "num" + } + ], + "checkall": "true", + "repair": false, + "outputs": 1, + "x": 590, + "y": 120, + "wires": [["6d09f428.930bcc"]] + }, + { + "id": "46d5e78b.15f998", + "type": "ui_toast", + "z": "1371dec5.76e671", + "position": "dialog", + "displayTime": "10", + "highlight": "", + "sendall": true, + "outputs": 1, + "ok": "OK", + "cancel": "", + "raw": false, + "className": "", + "topic": "", + "name": "", + "x": 1090, + "y": 120, + "wires": [[]] + }, + { + "id": "24df077a.cb252", + "type": "change", + "z": "1371dec5.76e671", + "name": "full disk msg", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "\"Your drive has reached 90% capacity, you should do a backup to an external drive and a purge.\"", + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 930, + "y": 120, + "wires": [["46d5e78b.15f998"]] + }, + { + "id": "6d09f428.930bcc", + "type": "delay", + "z": "1371dec5.76e671", + "name": "", + "pauseType": "rate", + "timeout": "5", + "timeoutUnits": "seconds", + "rate": "1", + "nbRateUnits": "5", + "rateUnits": "minute", + "randomFirst": "1", + "randomLast": "5", + "randomUnits": "seconds", + "drop": true, + "allowrate": false, + "outputs": 1, + "x": 760, + "y": 120, + "wires": [["24df077a.cb252"]] + }, + { + "id": "e640ebb5c397f424", + "type": "delay", + "z": "1371dec5.76e671", + "name": "", + "pauseType": "delay", + "timeout": "1", + "timeoutUnits": "seconds", + "rate": "1", + "nbRateUnits": "1", + "rateUnits": "second", + "randomFirst": "1", + "randomLast": "5", + "randomUnits": "seconds", + "drop": false, + "allowrate": false, + "outputs": 1, + "x": 1300, + "y": 40, + "wires": [["b7ab1ada.1f4158"]] + }, + { + "id": "7fb13a4a53b612a0", + "type": "rbe", + "z": "1371dec5.76e671", + "name": "", + "func": "rbe", + "gap": "", + "start": "", + "inout": "out", + "septopics": true, + "property": "payload", + "topi": "topic", + "x": 1010, + "y": 40, + "wires": [["2549f778.4eb828"]] + }, + { + "id": "ccb5172d10c1ccaf", + "type": "file in", + "z": "1371dec5.76e671", + "name": "Get machine name", + "filename": "/run/machine-name", + "filenameType": "str", + "format": "utf8", + "chunk": false, + "sendError": false, + "encoding": "none", + "allProps": false, + "x": 350, + "y": 680, + "wires": [["a400a97e.e333a8", "4828d2f4.7c712c"]] + }, + { + "id": "950b773ad4c0fdfe", + "type": "change", + "z": "1371dec5.76e671", + "name": "Get acq_instrument", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.acq_instrument", + "tot": "msg" + }, + { + "t": "set", + "p": "topic", + "pt": "msg", + "to": "acq_instrument", + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 350, + "y": 620, + "wires": [["bdc6718a.dd5d48"]] + }, + { + "id": "24de7407445d2087", + "type": "inject", + "z": "1371dec5.76e671", + "name": "once", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": "", + "topic": "", + "payload": "start", + "payloadType": "str", + "x": 90, + "y": 520, + "wires": [["e4f9ed2b337c2fa6"]] + }, + { + "id": "e4f9ed2b337c2fa6", + "type": "file in", + "z": "1371dec5.76e671", + "name": "Versioning File", + "filename": "/usr/share/planktoscope/installer-versioning.yml", + "filenameType": "str", + "format": "utf8", + "chunk": false, + "sendError": false, + "encoding": "none", + "allProps": false, + "x": 240, + "y": 520, + "wires": [["db79aae8a7fe3512"]] + }, + { + "id": "db79aae8a7fe3512", + "type": "yaml", + "z": "1371dec5.76e671", + "property": "payload", + "name": "", + "x": 390, + "y": 520, + "wires": [["04c313e8d9aac122", "ef1970121e57c5e8", "574361abfe75b3b3"]] + }, + { + "id": "04c313e8d9aac122", + "type": "change", + "z": "1371dec5.76e671", + "name": "Get repo", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.repo", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 580, + "y": 480, + "wires": [["57b3b083a2455e09"]] + }, + { + "id": "ef1970121e57c5e8", + "type": "change", + "z": "1371dec5.76e671", + "name": "Get version", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.version", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 590, + "y": 520, + "wires": [["3e64877a.9684b", "8343fa69.49339"]] + }, + { + "id": "57b3b083a2455e09", + "type": "function", + "z": "1371dec5.76e671", + "name": "set global", + "func": "global.set(\"process_source\", msg.payload);\n", + "outputs": 1, + "timeout": "", + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 820, + "y": 460, + "wires": [[]] + }, + { + "id": "574361abfe75b3b3", + "type": "change", + "z": "1371dec5.76e671", + "name": "Get commit", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.commit", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 590, + "y": 560, + "wires": [["016d1d2a2f19f1a6"]] + }, + { + "id": "016d1d2a2f19f1a6", + "type": "function", + "z": "1371dec5.76e671", + "name": "set global", + "func": "global.set(\"process_commit\", msg.payload);\n", + "outputs": 1, + "timeout": "", + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 820, + "y": 580, + "wires": [[]] + }, + { + "id": "4ed64bd91fa9fbdf", + "type": "ui_template", + "z": "1371dec5.76e671", + "group": "3da7da8f.179606", + "name": "Metrics panel", + "order": 1, + "width": "0", + "height": "0", + "format": "
\n

\n The instrument's system time is different from your web browser's time by {{drift}}.\n As a result, timestamps in your datasets will be incorrect.\n Additionally, system metrics will not be recorded or shown correctly.\n Additionally, you will see incorrectly-aligned graphs in the metrics below.\n

\n

Please change the instrument's system time or your web browser's time to accurate values.

\n

\n \n

\n
\n\n
\n

Loading system metrics, please wait...

\n
\n\n
\n \n
\n\n\n", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "className": "", + "x": 330, + "y": 280, + "wires": [[]] + }, + { + "id": "38bad1e220cd5d87", + "type": "ui_text", + "z": "1371dec5.76e671", + "group": "ce9e278.781eed8", + "order": 5, + "width": 0, + "height": 0, + "name": "", + "label": "System Time", + "format": "{{msg.payload}}", + "layout": "row-spread", + "className": "", + "style": false, + "font": "", + "fontSize": 16, + "color": "#000000", + "x": 590, + "y": 240, + "wires": [] + }, + { + "id": "ed5f2d963d85478b", + "type": "function", + "z": "1371dec5.76e671", + "name": "Get system time", + "func": "var date = new Date();\ndate.setSeconds(0, 0);\nmsg.payload = (\n date.toISOString().replace('T', ' ').replace(/:\\d+\\.\\d+Z/,' UTC')\n);\nreturn msg", + "outputs": 1, + "timeout": 0, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 340, + "y": 240, + "wires": [["38bad1e220cd5d87"]] + }, + { + "id": "23a84a3856fb68bd", + "type": "ui_template", + "z": "1371dec5.76e671", + "group": "ce9e278.781eed8", + "name": "Browser time", + "order": 6, + "width": "6", + "height": "1", + "format": "
\n

Browser Time

\n

{{time}}

\n
\n\n", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "className": "", + "x": 330, + "y": 200, + "wires": [[]] + }, + { + "id": "19a45f972be2b0f1", + "type": "function", + "z": "1371dec5.76e671", + "name": "Get system time", + "func": "var date = new Date(msg.payload.timestamp);\nmsg.payload = (\n date.toISOString().replace('T', ' ').replace(/:\\d+\\.\\d+Z/,' UTC')\n);\nreturn msg", + "outputs": 1, + "timeout": 0, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 340, + "y": 340, + "wires": [["ee2c5e7c29eb4760"]] + }, + { + "id": "8ba3e2774987fd58", + "type": "http in", + "z": "1371dec5.76e671", + "name": "POST /api/system-time", + "url": "/api/system-time", + "method": "post", + "upload": false, + "swaggerDoc": "", + "x": 120, + "y": 360, + "wires": [["19a45f972be2b0f1", "07bbdca8d6153210", "595df18543c8328e"]] + }, + { + "id": "ee2c5e7c29eb4760", + "type": "ui_toast", + "z": "1371dec5.76e671", + "position": "top right", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 0, + "ok": "OK", + "cancel": "", + "raw": false, + "className": "", + "topic": "Setting system time", + "name": "", + "x": 610, + "y": 340, + "wires": [] + }, + { + "id": "07bbdca8d6153210", + "type": "function", + "z": "1371dec5.76e671", + "name": "Prepare timestamp", + "func": "msg.payload = ('@' + msg.payload.timestamp).slice(0, -3);\nreturn msg;", + "outputs": 1, + "timeout": 0, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 350, + "y": 380, + "wires": [["7558e8f302d5b944"]] + }, + { + "id": "7558e8f302d5b944", + "type": "exec", + "z": "1371dec5.76e671", + "command": "sudo date -s", + "addpay": "payload", + "append": "", + "useSpawn": "", + "timer": "", + "winHide": false, + "name": "Set system time", + "x": 600, + "y": 380, + "wires": [[], [], []] + }, + { + "id": "c8be8dad272e1fa5", + "type": "http in", + "z": "1371dec5.76e671", + "name": "GET /api/system-time", + "url": "/api/system-time", + "method": "get", + "upload": false, + "swaggerDoc": "", + "x": 120, + "y": 420, + "wires": [["0f4ce59587fa14e1"]] + }, + { + "id": "0f4ce59587fa14e1", + "type": "function", + "z": "1371dec5.76e671", + "name": "Get system time", + "func": "var date = new Date();\nmsg.payload = {'timestamp': date.getTime()};\nreturn msg", + "outputs": 1, + "timeout": 0, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 340, + "y": 420, + "wires": [["433d48a4b1bc0b27"]] + }, + { + "id": "433d48a4b1bc0b27", + "type": "http response", + "z": "1371dec5.76e671", + "name": "Send GET response", + "statusCode": "", + "headers": { + "Content-Type": "application/json; charset=UTF-8" + }, + "x": 620, + "y": 420, + "wires": [] + }, + { + "id": "595df18543c8328e", + "type": "http response", + "z": "1371dec5.76e671", + "name": "Send POST response", + "statusCode": "", + "headers": {}, + "x": 620, + "y": 300, + "wires": [] + }, + { + "id": "1fdf77b5.24e4e", + "type": "mqtt in", + "z": "9a22e67a.378818", + "name": "", + "topic": "status/#", + "qos": "0", + "datatype": "json", + "broker": "8dc3722c.06efa8", + "inputs": 0, + "x": 290, + "y": 340, + "wires": [["fa73983d.318188"]] + }, + { + "id": "4a1e9e3e.27506", + "type": "switch", + "z": "9a22e67a.378818", + "name": "Filter segmenter out", + "property": "topic", + "propertyType": "msg", + "rules": [ + { + "t": "else" + }, + { + "t": "cont", + "v": "status/segmenter", + "vt": "str" + } + ], + "checkall": "true", + "repair": false, + "outputs": 2, + "x": 620, + "y": 340, + "wires": [["58f2e0f.4e8b12"], ["dcf5bd45.16a8d"]] + }, + { + "id": "fa73983d.318188", + "type": "json", + "z": "9a22e67a.378818", + "name": "", + "property": "payload", + "action": "obj", + "pretty": true, + "x": 430, + "y": 340, + "wires": [["4a1e9e3e.27506"]] + }, + { + "id": "58f2e0f.4e8b12", + "type": "link out", + "z": "9a22e67a.378818", + "name": "Fluidic module status", + "links": ["bb628f8d.98f108"], + "x": 795, + "y": 320, + "wires": [] + }, + { + "id": "dcf5bd45.16a8d", + "type": "link out", + "z": "9a22e67a.378818", + "name": "Segmenter module status", + "links": ["25867454.a8e334"], + "x": 795, + "y": 360, + "wires": [] + }, + { + "id": "e41870d7.300eb8", + "type": "link out", + "z": "1eaf21c8.f7a21e", + "name": "Stepper config change", + "links": ["45a7b5aa.2ed20c"], + "x": 1475, + "y": 380, + "wires": [] + }, + { + "id": "2068e7f.f4efb18", + "type": "delay", + "z": "1eaf21c8.f7a21e", + "name": "", + "pauseType": "delay", + "timeout": "1", + "timeoutUnits": "seconds", + "rate": "1", + "nbRateUnits": "1", + "rateUnits": "second", + "randomFirst": "1", + "randomLast": "5", + "randomUnits": "seconds", + "drop": false, + "outputs": 1, + "x": 1160, + "y": 380, + "wires": [["e41870d7.300eb8"]] + }, + { + "id": "8e3b3d3c.955148", + "type": "subflow:4ed26b8b.253504", + "z": "1eaf21c8.f7a21e", + "name": "", + "env": [], + "x": 1200, + "y": 420, + "wires": [] + }, + { + "id": "c534fd26.13741", + "type": "change", + "z": "1eaf21c8.f7a21e", + "name": "Get stepper_reverse", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.stepper_reverse", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 640, + "y": 440, + "wires": [["cd1987c7.027f58"]] + }, + { + "id": "cd1987c7.027f58", + "type": "ui_switch", + "z": "1eaf21c8.f7a21e", + "name": "stepper_reverse", + "label": "Invert stepper output", + "tooltip": "Stepper 1 is controlled by output 1 or the other way around", + "group": "6be36295.0ab324", + "order": 5, + "width": 0, + "height": 0, + "passthru": false, + "decouple": "false", + "topic": "stepper_reverse", + "style": "", + "onvalue": "true", + "onvalueType": "bool", + "onicon": "", + "oncolor": "", + "offvalue": "false", + "offvalueType": "bool", + "officon": "", + "offcolor": "", + "x": 940, + "y": 440, + "wires": [["8e3b3d3c.955148", "2068e7f.f4efb18"]] + }, + { + "id": "54ba7f16.709ad8", + "type": "change", + "z": "1eaf21c8.f7a21e", + "name": "Get pump_steps_per_ml", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.pump_steps_per_ml", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 650, + "y": 400, + "wires": [["ee58b91c.396108"]] + }, + { + "id": "ee58b91c.396108", + "type": "ui_text_input", + "z": "1eaf21c8.f7a21e", + "name": "pump_steps_per_ml", + "label": "Pump: steps per mL", + "tooltip": "", + "group": "6be36295.0ab324", + "order": 6, + "width": 0, + "height": 0, + "passthru": false, + "mode": "number", + "delay": "2000", + "topic": "pump_steps_per_ml", + "topicType": "str", + "x": 920, + "y": 400, + "wires": [["2068e7f.f4efb18", "8e3b3d3c.955148"]] + }, + { + "id": "7534dfd9.8cf3e8", + "type": "ui_template", + "z": "1eaf21c8.f7a21e", + "group": "6be36295.0ab324", + "name": "Information", + "order": 1, + "width": "8", + "height": 3, + "format": "
\n

\n Changing one of these values will cause the Python hardware controller to restart, to reload the new hardware configuration.\n

\n

\n Warning: selecting a hardware version from the dropdown menu below will also overwrite all of your hardware settings, including your camera white balance settings.\n

\n

\n If you are not sure, you probably should not be touching anything here!\n

\n
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": true, + "templateScope": "local", + "className": "", + "x": 590, + "y": 60, + "wires": [[]] + }, + { + "id": "a7e5c7f4.644678", + "type": "ui_dropdown", + "z": "1eaf21c8.f7a21e", + "name": "", + "label": "Hardware version", + "tooltip": "", + "place": "Select option", + "group": "6be36295.0ab324", + "order": 2, + "width": 0, + "height": 0, + "passthru": false, + "multiple": false, + "options": [ + { + "label": "", + "value": "PlanktoScope v2.1", + "type": "str" + }, + { + "label": "", + "value": "PlanktoScope v2.3", + "type": "str" + }, + { + "label": "", + "value": "PlanktoScope v2.5", + "type": "str" + }, + { + "label": "", + "value": "PlanktoScope v2.6", + "type": "str" + } + ], + "payload": "", + "topic": "acq_instrument", + "topicType": "str", + "className": "", + "x": 580, + "y": 160, + "wires": [["3e2c5c1c.4c57b4", "932a1ef8c2e81979", "025ad3cdaa557843"]] + }, + { + "id": "1cfadc66.3cde8c", + "type": "subflow:1c24ad9c.bebec2", + "z": "1eaf21c8.f7a21e", + "name": "", + "env": [], + "x": 970, + "y": 160, + "wires": [[]] + }, + { + "id": "3e2c5c1c.4c57b4", + "type": "function", + "z": "1eaf21c8.f7a21e", + "name": "Save global", + "func": "global.set(msg.topic,msg.payload);\nreturn msg;", + "outputs": 1, + "timeout": "", + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 810, + "y": 160, + "wires": [["1cfadc66.3cde8c"]] + }, + { + "id": "427c312.fc5e65", + "type": "subflow:1c24ad9c.bebec2", + "z": "1eaf21c8.f7a21e", + "name": "", + "env": [], + "x": 130, + "y": 160, + "wires": [["2716aa5b3d027f95"]] + }, + { + "id": "c67c305004f87e39", + "type": "change", + "z": "1eaf21c8.f7a21e", + "name": "Get process_pixel_fixed", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.process_pixel_fixed", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 650, + "y": 480, + "wires": [["244ca5dd62df2bcd"]] + }, + { + "id": "244ca5dd62df2bcd", + "type": "ui_text_input", + "z": "1eaf21c8.f7a21e", + "name": "process_pixel_fixed", + "label": "Pixel size calibration: um per pixel", + "tooltip": "Object size in µm / pixel. 0 will remove this calibration.", + "group": "6be36295.0ab324", + "order": 8, + "width": 0, + "height": 0, + "passthru": true, + "mode": "number", + "delay": "1000", + "topic": "process_pixel_fixed", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 930, + "y": 480, + "wires": [["8e3b3d3c.955148", "f9b47f4b1da15778"]] + }, + { + "id": "f9b47f4b1da15778", + "type": "function", + "z": "1eaf21c8.f7a21e", + "name": "Set or remove if null", + "func": "if (msg.payload == 0){\n global.set(msg.topic,undefined)\n}\nelse {\n global.set(msg.topic,msg.payload);\n}\n\nreturn msg", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 1200, + "y": 480, + "wires": [["5d5ad36d2c50dcc2"]] + }, + { + "id": "5d5ad36d2c50dcc2", + "type": "link out", + "z": "1eaf21c8.f7a21e", + "name": "Process_pixel calibration", + "links": [], + "x": 1475, + "y": 500, + "wires": [] + }, + { + "id": "6146ba22df928516", + "type": "ui_dropdown", + "z": "1eaf21c8.f7a21e", + "name": "acq_fnumber_objective", + "label": "M12 Lens", + "tooltip": "", + "place": "Select option", + "group": "6be36295.0ab324", + "order": 7, + "width": 0, + "height": 0, + "passthru": true, + "multiple": false, + "options": [ + { + "label": "f 25mm 1/2\" 5MP IR", + "value": 25, + "type": "num" + }, + { + "label": "f 16mm 1/2.5\" 5MP IR", + "value": 16, + "type": "num" + }, + { + "label": "f 12mm 1/2.5\" 5MP IR", + "value": 12, + "type": "num" + }, + { + "label": "f 8mm 1/2.5\" 5MP IR", + "value": 8, + "type": "num" + }, + { + "label": "f 6mm 1/2.5\" 5MP IR", + "value": 6, + "type": "num" + } + ], + "payload": "", + "topic": "acq_fnumber_objective", + "topicType": "str", + "x": 910, + "y": 520, + "wires": [["a6983d3232b570a7", "8e3b3d3c.955148"]] + }, + { + "id": "a6983d3232b570a7", + "type": "change", + "z": "1eaf21c8.f7a21e", + "name": "", + "rules": [ + { + "t": "set", + "p": "acq_fnumber_objective", + "pt": "global", + "to": "payload", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 1240, + "y": 520, + "wires": [["5d5ad36d2c50dcc2"]] + }, + { + "id": "11955bbeefc29ab4", + "type": "change", + "z": "1eaf21c8.f7a21e", + "name": "Get acq_fnumber_objective", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.acq_fnumber_objective", + "tot": "msg" + }, + { + "t": "set", + "p": "topic", + "pt": "msg", + "to": "acq_fnumber_objective", + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 660, + "y": 520, + "wires": [["6146ba22df928516"]] + }, + { + "id": "da3d4a90384d62a8", + "type": "subflow:e6665421f66ea4c8", + "z": "1eaf21c8.f7a21e", + "name": "", + "x": 360, + "y": 440, + "wires": [ + [ + "c534fd26.13741", + "54ba7f16.709ad8", + "c67c305004f87e39", + "11955bbeefc29ab4" + ] + ] + }, + { + "id": "f83560053c609914", + "type": "inject", + "z": "1eaf21c8.f7a21e", + "name": "Once", + "props": [], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "x": 130, + "y": 440, + "wires": [["da3d4a90384d62a8"]] + }, + { + "id": "e4ead350b3d07578", + "type": "link out", + "z": "1eaf21c8.f7a21e", + "name": "Reload hardware config", + "mode": "link", + "links": ["04920f50bbbf6a2a", "45a7b5aa.2ed20c"], + "x": 875, + "y": 240, + "wires": [] + }, + { + "id": "025ad3cdaa557843", + "type": "ui_toast", + "z": "1eaf21c8.f7a21e", + "position": "top right", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 0, + "ok": "OK", + "cancel": "", + "raw": false, + "className": "", + "topic": "Resetting hardware configuration to version-specific default", + "name": "", + "x": 830, + "y": 120, + "wires": [] + }, + { + "id": "932a1ef8c2e81979", + "type": "change", + "z": "1eaf21c8.f7a21e", + "name": "Choose default hardware config", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "$join([\"/home/pi/PlanktoScope/device-backend/default-configs/\", $substringAfter(msg.payload, \"PlanktoScope \"), \".hardware.json\"])", + "tot": "jsonata" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 210, + "y": 240, + "wires": [["833dac7cbd693c53"]] + }, + { + "id": "833dac7cbd693c53", + "type": "exec", + "z": "1eaf21c8.f7a21e", + "command": "cp", + "addpay": "payload", + "append": "/home/pi/PlanktoScope/hardware.json", + "useSpawn": "false", + "timer": "", + "winHide": false, + "oldrc": false, + "name": "Copy default hardware config", + "x": 500, + "y": 240, + "wires": [["0b67ccf37c034e90"], [], []] + }, + { + "id": "0b67ccf37c034e90", + "type": "delay", + "z": "1eaf21c8.f7a21e", + "name": "", + "pauseType": "delay", + "timeout": "500", + "timeoutUnits": "milliseconds", + "rate": "1", + "nbRateUnits": "1", + "rateUnits": "second", + "randomFirst": "1", + "randomLast": "5", + "randomUnits": "seconds", + "drop": false, + "allowrate": false, + "outputs": 1, + "x": 730, + "y": 240, + "wires": [["da3d4a90384d62a8", "e4ead350b3d07578"]] + }, + { + "id": "2716aa5b3d027f95", + "type": "change", + "z": "1eaf21c8.f7a21e", + "name": "Get acq_instrument", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.acq_instrument", + "tot": "msg" + }, + { + "t": "set", + "p": "topic", + "pt": "msg", + "to": "acq_instrument", + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 330, + "y": 160, + "wires": [["a7e5c7f4.644678"]] + } ] diff --git a/software/node-red-dashboard/planktoscopehat/flows.json b/software/node-red-dashboard/planktoscopehat/flows.json index d0671342e..d4964f0ab 100644 --- a/software/node-red-dashboard/planktoscopehat/flows.json +++ b/software/node-red-dashboard/planktoscopehat/flows.json @@ -1,8749 +1,7492 @@ [ - { - "id": "eaae323a.31b3", - "type": "tab", - "label": "Home", - "disabled": false, - "info": "" - }, - { - "id": "b771c342.49603", - "type": "tab", - "label": "Sample", - "disabled": false, - "info": "" - }, - { - "id": "bccd1f23.87219", - "type": "tab", - "label": "Optic Configuration", - "disabled": false, - "info": "" - }, - { - "id": "baa1e3d9.cb29d", - "type": "tab", - "label": "Fluidic Acquisition", - "disabled": false, - "info": "" - }, - { - "id": "cb95299c.2817c8", - "type": "tab", - "label": "Segmentation", - "disabled": false, - "info": "" - }, - { - "id": "c1660bc.e7ff7f8", - "type": "tab", - "label": "Gallery", - "disabled": false, - "info": "" - }, - { - "id": "9daf9e2b.019fc", - "type": "tab", - "label": "Administration", - "disabled": false, - "info": "" - }, - { - "id": "1371dec5.76e671", - "type": "tab", - "label": "System Monitoring", - "disabled": false, - "info": "" - }, - { - "id": "9a22e67a.378818", - "type": "tab", - "label": "MQTT Receive", - "disabled": false, - "info": "" - }, - { - "id": "1eaf21c8.f7a21e", - "type": "tab", - "label": "Hardware Settings", - "disabled": false, - "info": "" - }, - { - "id": "1c24ad9c.bebec2", - "type": "subflow", - "name": "Config", - "info": "An input to this subflow will get the configuration to be saved to disk.\n\nOn startup, this node outputs the loaded configuration", - "category": "", - "in": [ - { - "x": 220, - "y": 160, - "wires": [ - { - "id": "3ad9835.08c937c" - } - ] - } - ], - "out": [ - { - "x": 1040, - "y": 60, - "wires": [ - { - "id": "ad541674.4791c8", - "port": 0 - } - ] - } - ], - "env": [], - "color": "#DDAA99" - }, - { - "id": "4ed26b8b.253504", - "type": "subflow", - "name": "Save hardware config", - "info": "", - "category": "", - "in": [ - { - "x": 40, - "y": 40, - "wires": [ - { - "id": "53d163be.47cf24" - } - ] - } - ], - "out": [], - "env": [], - "meta": {}, - "color": "#DDAA99" - }, - { - "id": "b7861ce703215a01", - "type": "subflow", - "name": "Load hardware config", - "info": "", - "category": "", - "in": [ - { - "x": 40, - "y": 40, - "wires": [ - { - "id": "0f16258953fae292" - } - ] - } - ], - "out": [ - { - "x": 900, - "y": 40, - "wires": [ - { - "id": "d0fbcd200cd09981", - "port": 0 - } - ] - } - ], - "env": [], - "meta": {}, - "color": "#DDAA99" - }, - { - "id": "3a6bb13f.c9703e", - "type": "ui_tab", - "name": "Home", - "icon": "home", - "order": 1, - "disabled": false, - "hidden": false - }, - { - "id": "181bb236.1e94be", - "type": "ui_tab", - "name": "Optic Configuration", - "icon": "fa-eye", - "order": 3, - "disabled": false, - "hidden": false - }, - { - "id": "c9194f02.9d5e9", - "type": "ui_tab", - "name": "Fluidic Acquisition", - "icon": "fa-flask", - "order": 4, - "disabled": false, - "hidden": false - }, - { - "id": "8d16beb8.9b3fb", - "type": "ui_tab", - "name": "Segmentation", - "icon": "fa-crop", - "order": 5, - "disabled": false, - "hidden": false - }, - { - "id": "d9cd733b.ab73d", - "type": "ui_tab", - "name": "System Monitoring", - "icon": "fa-thermometer-full", - "order": 7, - "disabled": false, - "hidden": false - }, - { - "id": "4248342d.e55fac", - "type": "ui_group", - "name": "Optic Characterization", - "tab": "181bb236.1e94be", - "order": 4, - "disp": true, - "width": "6", - "collapse": false - }, - { - "id": "858a0e3c.987fe", - "type": "ui_group", - "name": "Preview", - "tab": "c9194f02.9d5e9", - "order": 1, - "disp": true, - "width": 10, - "collapse": false - }, - { - "id": "64903b47.4034e4", - "type": "ui_group", - "name": "Navigation", - "tab": "8d16beb8.9b3fb", - "order": 3, - "disp": false, - "width": "6", - "collapse": false - }, - { - "id": "3da7da8f.179606", - "type": "ui_group", - "name": "Metrics", - "tab": "d9cd733b.ab73d", - "order": 1, - "disp": true, - "width": "24", - "collapse": true, - "className": "" - }, - { - "id": "cc8bc4eb.651868", - "type": "ui_base", - "theme": { - "name": "theme-dark", - "lightTheme": { - "default": "#0094CE", - "baseColor": "#5900ce", - "baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif", - "edited": false, - "reset": false - }, - "darkTheme": { - "default": "#097479", - "baseColor": "#097479", - "baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif", - "edited": true, - "reset": false - }, - "customTheme": { - "name": "Untitled Theme 1", - "default": "#4B7930", - "baseColor": "#4B7930", - "baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif" - }, - "themeState": { - "base-color": { - "default": "#097479", - "value": "#097479", - "edited": true - }, - "page-titlebar-backgroundColor": { - "value": "#097479", - "edited": false - }, - "page-backgroundColor": { - "value": "#111111", - "edited": false - }, - "page-sidebar-backgroundColor": { - "value": "#333333", - "edited": false - }, - "group-textColor": { - "value": "#0eb8c0", - "edited": false - }, - "group-borderColor": { - "value": "#555555", - "edited": false - }, - "group-backgroundColor": { - "value": "#333333", - "edited": false - }, - "widget-textColor": { - "value": "#eeeeee", - "edited": false - }, - "widget-backgroundColor": { - "value": "#097479", - "edited": false - }, - "widget-borderColor": { - "value": "#333333", - "edited": false - }, - "base-font": { - "value": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif" - } - }, - "angularTheme": { - "primary": "indigo", - "accents": "blue", - "warn": "red", - "background": "grey", - "palette": "light" - } - }, - "site": { - "name": "PlanktoScope", - "hideToolbar": "false", - "allowSwipe": "false", - "lockMenu": "false", - "allowTempTheme": "true", - "dateFormat": "Y-MM-DD", - "sizes": { - "sx": 55, - "sy": 55, - "gx": 4, - "gy": 4, - "cx": 4, - "cy": 4, - "px": 4, - "py": 4 - } - } - }, - { - "id": "36739a35.7cce36", - "type": "ui_tab", - "name": "Gallery", - "icon": "fa-file-image-o", - "order": 6, - "disabled": false, - "hidden": false - }, - { - "id": "c0ebfc57.42527", - "type": "ui_group", - "name": "Group 1", - "tab": "36739a35.7cce36", - "order": 1, - "disp": false, - "width": "24", - "collapse": false, - "className": "" - }, - { - "id": "737ec584.2eea2c", - "type": "ui_tab", - "name": "Sample", - "icon": "fa-eyedropper", - "order": 2, - "disabled": false, - "hidden": false - }, - { - "id": "6f97e7ae.270c48", - "type": "ui_group", - "name": "Group 1", - "tab": "3a6bb13f.c9703e", - "order": 2, - "disp": false, - "width": "4", - "collapse": false, - "className": "" - }, - { - "id": "3e1ba03d.f01d8", - "type": "ui_group", - "name": "Sample Identification", - "tab": "737ec584.2eea2c", - "order": 1, - "disp": true, - "width": "10", - "collapse": false - }, - { - "id": "4e0cd5ea.17e59c", - "type": "ui_group", - "name": "Group 2", - "tab": "3a6bb13f.c9703e", - "order": 3, - "disp": false, - "width": "4", - "collapse": false - }, - { - "id": "ef590206.24f6", - "type": "ui_group", - "name": "Group 3", - "tab": "3a6bb13f.c9703e", - "order": 4, - "disp": false, - "width": "4", - "collapse": false - }, - { - "id": "ae8f6620.073358", - "type": "ui_group", - "name": "Group 4", - "tab": "3a6bb13f.c9703e", - "order": 5, - "disp": false, - "width": "4", - "collapse": false - }, - { - "id": "196518b2.4d53b7", - "type": "ui_group", - "name": "Group 5", - "tab": "3a6bb13f.c9703e", - "order": 6, - "disp": false, - "width": "4", - "collapse": false - }, - { - "id": "777a7c33.fcd804", - "type": "ui_group", - "name": "Group 6", - "tab": "3a6bb13f.c9703e", - "order": 7, - "disp": false, - "width": "4", - "collapse": false - }, - { - "id": "cef1e703.bcf3c8", - "type": "ui_group", - "name": "Sample Location", - "tab": "737ec584.2eea2c", - "order": 3, - "disp": false, - "width": "10", - "collapse": false - }, - { - "id": "5517c651.b2f668", - "type": "ui_group", - "name": "Validation", - "tab": "737ec584.2eea2c", - "order": 5, - "disp": false, - "width": 10, - "collapse": false - }, - { - "id": "fbd92986.1028c8", - "type": "ui_group", - "name": "Focus Adjustment", - "tab": "181bb236.1e94be", - "order": 2, - "disp": true, - "width": 4, - "collapse": false - }, - { - "id": "707d9797.c8e798", - "type": "ui_group", - "name": "Fluidic Manual Manipulation", - "tab": "181bb236.1e94be", - "order": 5, - "disp": true, - "width": 4, - "collapse": false - }, - { - "id": "7a0b4877.a5d268", - "type": "ui_group", - "name": "Navigation", - "tab": "181bb236.1e94be", - "order": 6, - "disp": false, - "width": 4, - "collapse": false - }, - { - "id": "4322c187.e73e5", - "type": "ui_group", - "name": "Acquisition", - "tab": "c9194f02.9d5e9", - "order": 3, - "disp": true, - "width": 10, - "collapse": false - }, - { - "id": "b7919ae2.c01788", - "type": "ui_group", - "name": "Navigation", - "tab": "c9194f02.9d5e9", - "order": 6, - "disp": false, - "width": "10", - "collapse": false - }, - { - "id": "b5d61bc7.54fe48", - "type": "ui_group", - "name": "Statistics", - "tab": "c9194f02.9d5e9", - "order": 4, - "disp": true, - "width": "10", - "collapse": false - }, - { - "id": "8dc3722c.06efa8", - "type": "mqtt-broker", - "name": "", - "broker": "0.0.0.0", - "port": "1883", - "clientid": "Client_node", - "autoConnect": true, - "usetls": false, - "compatmode": false, - "protocolVersion": 4, - "keepalive": "60", - "cleansession": true, - "birthTopic": "", - "birthQos": "0", - "birthPayload": "", - "closeTopic": "", - "closeQos": "0", - "closePayload": "", - "willTopic": "", - "willQos": "0", - "willPayload": "" - }, - { - "id": "abeb6dad.635a2", - "type": "ui_group", - "name": "Control", - "tab": "8d16beb8.9b3fb", - "order": 1, - "disp": true, - "width": 10, - "collapse": false - }, - { - "id": "cf5d9f0e.d57e7", - "type": "ui_group", - "name": "Net Metadata", - "tab": "737ec584.2eea2c", - "order": 4, - "disp": false, - "width": "10", - "collapse": false - }, - { - "id": "ce9e278.781eed8", - "type": "ui_group", - "name": "Information", - "tab": "d9cd733b.ab73d", - "order": 5, - "disp": true, - "width": 6, - "collapse": false - }, - { - "id": "70de8209.68416c", - "type": "ui_group", - "name": "Status", - "tab": "c9194f02.9d5e9", - "order": 5, - "disp": true, - "width": 10, - "collapse": false - }, - { - "id": "46be9c86.dea684", - "type": "ui_group", - "name": "Status", - "tab": "8d16beb8.9b3fb", - "order": 2, - "disp": true, - "width": 10, - "collapse": false - }, - { - "id": "8c38a81e.9897a8", - "type": "ui_group", - "name": "Camera Settings", - "tab": "181bb236.1e94be", - "order": 3, - "disp": true, - "width": 6, - "collapse": false - }, - { - "id": "2489e51c.eed77a", - "type": "ui_tab", - "name": "Administration", - "icon": "dashboard", - "order": 9, - "disabled": false, - "hidden": false - }, - { - "id": "b0fb559a.6966a8", - "type": "ui_tab", - "name": "Hardware Settings", - "icon": "fa-cogs", - "disabled": false, - "hidden": false - }, - { - "id": "6be36295.0ab324", - "type": "ui_group", - "name": "Settings", - "tab": "b0fb559a.6966a8", - "order": 1, - "disp": false, - "width": "8", - "collapse": false, - "className": "" - }, - { - "id": "f3ca28ef.4df0a8", - "type": "ui_group", - "name": "Shutdown", - "tab": "3a6bb13f.c9703e", - "order": 8, - "disp": true, - "width": 4, - "collapse": false - }, - { - "id": "3dfd8a69.69ed56", - "type": "ui_spacer", - "name": "spacer", - "group": "f3ca28ef.4df0a8", - "order": 3, - "width": 4, - "height": 1 - }, - { - "id": "72a9216.2ff48e", - "type": "ui_spacer", - "name": "spacer", - "group": "4322c187.e73e5", - "order": 8, - "width": 10, - "height": 1 - }, - { - "id": "1b664927.c91d1f", - "type": "ui_spacer", - "name": "spacer", - "group": "b5d61bc7.54fe48", - "order": 2, - "width": 2, - "height": 1 - }, - { - "id": "1a663b6a.ab5805", - "type": "ui_spacer", - "name": "spacer", - "group": "b5d61bc7.54fe48", - "order": 4, - "width": 2, - "height": 1 - }, - { - "id": "8eeed8d8.ad9098", - "type": "ui_spacer", - "name": "spacer", - "group": "b5d61bc7.54fe48", - "order": 5, - "width": 2, - "height": 1 - }, - { - "id": "be1c5ce7.004e", - "type": "ui_spacer", - "name": "spacer", - "group": "b5d61bc7.54fe48", - "order": 6, - "width": 2, - "height": 1 - }, - { - "id": "c2fe38e9.555e3", - "type": "ui_spacer", - "name": "spacer", - "group": "b5d61bc7.54fe48", - "order": 7, - "width": 2, - "height": 1 - }, - { - "id": "89bd18b7.c779a8", - "type": "ui_spacer", - "name": "spacer", - "group": "b5d61bc7.54fe48", - "order": 8, - "width": 2, - "height": 1 - }, - { - "id": "3cbbfa5d.efa636", - "type": "ui_spacer", - "name": "spacer", - "group": "b7919ae2.c01788", - "order": 2, - "width": 5, - "height": 1 - }, - { - "id": "97148e8d8e298f1a", - "type": "ui_spacer", - "z": "cb95299c.2817c8", - "name": "spacer", - "group": "abeb6dad.635a2", - "order": 7, - "width": 10, - "height": 1 - }, - { - "id": "3b2eccc574e6a9ae", - "type": "ui_spacer", - "z": "cb95299c.2817c8", - "name": "spacer", - "group": "abeb6dad.635a2", - "order": 11, - "width": 1, - "height": 1 - }, - { - "id": "bbd6431d97c86f97", - "type": "ui_spacer", - "z": "cb95299c.2817c8", - "name": "spacer", - "group": "46be9c86.dea684", - "order": 4, - "width": 3, - "height": 1 - }, - { - "id": "5f98f5f140f0ecde", - "type": "ui_spacer", - "z": "cb95299c.2817c8", - "name": "spacer", - "group": "46be9c86.dea684", - "order": 6, - "width": 3, - "height": 1 - }, - { - "id": "7bc0a4c416e4545c", - "type": "ui_group", - "name": "Culture Date and Time", - "tab": "737ec584.2eea2c", - "order": 2, - "disp": true, - "width": "10", - "collapse": false, - "className": "" - }, - { - "id": "6c31ad948a9d62fd", - "type": "ui_spacer", - "z": "b771c342.49603", - "name": "spacer", - "group": "3e1ba03d.f01d8", - "order": 5, - "width": 10, - "height": 1 - }, - { - "id": "0035a03e1490cd8c", - "type": "ui_group", - "name": "Setup", - "tab": "3a6bb13f.c9703e", - "order": 1, - "disp": true, - "width": "8", - "collapse": false, - "className": "" - }, - { - "id": "833bc5bb.217ba8", - "type": "ui_group", - "name": "Preview", - "tab": "181bb236.1e94be", - "order": 1, - "disp": true, - "width": 18, - "collapse": false - }, - { - "id": "a7d64879.38298", - "type": "ui_group", - "name": "Logs", - "tab": "2489e51c.eed77a", - "order": 1, - "disp": true, - "width": "12", - "collapse": true, - "className": "" - }, - { - "id": "6465bdd5.15eb8c", - "type": "file in", - "z": "1c24ad9c.bebec2", - "name": "", - "filename": "/home/pi/PlanktoScope/config.json", - "filenameType": "str", - "format": "utf8", - "chunk": false, - "sendError": false, - "encoding": "none", - "x": 560, - "y": 60, - "wires": [ - [ - "15ceb135.6628bf" - ] - ], - "info": "# PlanktoScope Help\nThis Node will read the content of the file named **config.txt** containing all the input placeholders.\n" - }, - { - "id": "15ceb135.6628bf", - "type": "json", - "z": "1c24ad9c.bebec2", - "name": "config.json", - "property": "payload", - "action": "", - "pretty": false, - "x": 730, - "y": 60, - "wires": [ - [ - "ad541674.4791c8" - ] - ] - }, - { - "id": "7205d267.36adcc", - "type": "file", - "z": "1c24ad9c.bebec2", - "name": "", - "filename": "/home/pi/PlanktoScope/config.json", - "appendNewline": true, - "createDir": true, - "overwriteFile": "true", - "encoding": "none", - "x": 990, - "y": 160, - "wires": [ - [] - ] - }, - { - "id": "2e6ddf51.c0dba", - "type": "json", - "z": "1c24ad9c.bebec2", - "name": "config.json", - "property": "payload", - "action": "str", - "pretty": true, - "x": 730, + { + "id": "eaae323a.31b3", + "type": "tab", + "label": "Home", + "disabled": false, + "info": "" + }, + { + "id": "b771c342.49603", + "type": "tab", + "label": "Sample", + "disabled": false, + "info": "" + }, + { + "id": "bccd1f23.87219", + "type": "tab", + "label": "Optic Configuration", + "disabled": false, + "info": "" + }, + { + "id": "baa1e3d9.cb29d", + "type": "tab", + "label": "Fluidic Acquisition", + "disabled": false, + "info": "" + }, + { + "id": "cb95299c.2817c8", + "type": "tab", + "label": "Segmentation", + "disabled": false, + "info": "" + }, + { + "id": "c1660bc.e7ff7f8", + "type": "tab", + "label": "Gallery", + "disabled": false, + "info": "" + }, + { + "id": "9daf9e2b.019fc", + "type": "tab", + "label": "Administration", + "disabled": false, + "info": "" + }, + { + "id": "1371dec5.76e671", + "type": "tab", + "label": "System Monitoring", + "disabled": false, + "info": "" + }, + { + "id": "9a22e67a.378818", + "type": "tab", + "label": "MQTT Receive", + "disabled": false, + "info": "" + }, + { + "id": "1eaf21c8.f7a21e", + "type": "tab", + "label": "Hardware Settings", + "disabled": false, + "info": "" + }, + { + "id": "1c24ad9c.bebec2", + "type": "subflow", + "name": "Config", + "info": "An input to this subflow will get the configuration to be saved to disk.\n\nOn startup, this node outputs the loaded configuration", + "category": "", + "in": [ + { + "x": 220, "y": 160, "wires": [ - [ - "7205d267.36adcc" - ] - ] - }, - { - "id": "ad541674.4791c8", - "type": "function", - "z": "1c24ad9c.bebec2", - "name": "Global Set", - "func": "global.set(\"config_keys\", Object.keys(msg.payload));\n\nfor (const key in msg.payload) {\n global.set(key, msg.payload[key]);\n}\n\nreturn msg;", - "outputs": 1, - "timeout": "", - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 910, - "y": 60, - "wires": [ - [] + { + "id": "3ad9835.08c937c" + } ] - }, - { - "id": "3e9a33c.141384c", - "type": "inject", - "z": "1c24ad9c.bebec2", - "name": "Load config", - "props": [ - { - "p": "topic", - "vt": "str" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "", - "payloadType": "str", - "x": 230, + } + ], + "out": [ + { + "x": 1040, "y": 60, "wires": [ - [ - "6465bdd5.15eb8c" - ] - ] - }, - { - "id": "3ad9835.08c937c", - "type": "function", - "z": "1c24ad9c.bebec2", - "name": "get config payload", - "func": "keys = global.get(\"config_keys\")\n\nvar payload = {}\n\nkeys.forEach(function(item, index, array) {\n payload[item] = global.get(item);\n})\n\nreturn {\"payload\": payload};", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 410, - "y": 160, - "wires": [ - [ - "2e6ddf51.c0dba" - ] - ] - }, - { - "id": "f439663c.8abd3", - "type": "ui_ui_control", - "z": "1c24ad9c.bebec2", - "name": "Connect Event", - "events": "connect", - "x": 220, - "y": 100, - "wires": [ - [ - "6465bdd5.15eb8c" - ] - ] - }, - { - "id": "82099021.9ceb08", - "type": "file", - "z": "4ed26b8b.253504", - "name": "", - "filename": "/home/pi/PlanktoScope/hardware.json", - "appendNewline": true, - "createDir": true, - "overwriteFile": "true", - "encoding": "none", - "x": 660, - "y": 40, - "wires": [ - [] - ] - }, - { - "id": "bb0a8725.a1849", - "type": "json", - "z": "4ed26b8b.253504", - "name": "Create JSON", - "property": "payload", - "action": "str", - "pretty": true, - "x": 490, - "y": 40, - "wires": [ - [ - "82099021.9ceb08" - ] - ] - }, - { - "id": "53d163be.47cf24", - "type": "function", - "z": "4ed26b8b.253504", - "name": "Update and retrieve hardware_conf", - "func": "// change global\nhardware_conf = global.get(\"hardware_conf\");\n\nif (msg.topic == \"process_pixel_fixed\" && msg.payload == 0){\n delete hardware_conf[msg.topic]\n delete msg.topic\n}\n\nif (msg.topic !== null && msg.topic !== undefined){\n hardware_conf[msg.topic] = msg.payload;\n global.set(\"hardware_conf\", hardware_conf);\n}\n\nreturn {\"payload\": hardware_conf};", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 240, - "y": 40, - "wires": [ - [ - "bb0a8725.a1849" - ] - ] - }, - { - "id": "0f16258953fae292", - "type": "file in", - "z": "b7861ce703215a01", - "name": "", - "filename": "/home/pi/PlanktoScope/hardware.json", - "filenameType": "str", - "format": "utf8", - "chunk": false, - "sendError": false, - "encoding": "none", - "allProps": false, - "x": 250, + { + "id": "ad541674.4791c8", + "port": 0 + } + ] + } + ], + "env": [], + "color": "#DDAA99" + }, + { + "id": "4ed26b8b.253504", + "type": "subflow", + "name": "Save hardware config", + "info": "", + "category": "", + "in": [ + { + "x": 40, "y": 40, "wires": [ - [ - "81c516291ab19acd" - ] - ], - "info": "# PlanktoScope Help\nThis Node will read the content of the file named **config.txt** containing all the input placeholders.\n" - }, - { - "id": "81c516291ab19acd", - "type": "json", - "z": "b7861ce703215a01", - "name": "Parse JSON", - "property": "payload", - "action": "", - "pretty": false, - "x": 510, + { + "id": "53d163be.47cf24" + } + ] + } + ], + "out": [], + "env": [], + "meta": {}, + "color": "#DDAA99" + }, + { + "id": "b7861ce703215a01", + "type": "subflow", + "name": "Load hardware config", + "info": "", + "category": "", + "in": [ + { + "x": 40, "y": 40, "wires": [ - [ - "d0fbcd200cd09981" - ] + { + "id": "0f16258953fae292" + } ] - }, - { - "id": "d0fbcd200cd09981", - "type": "change", - "z": "b7861ce703215a01", - "name": "", - "rules": [ - { - "t": "set", - "p": "hardware_conf", - "pt": "global", - "to": "payload", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 730, + } + ], + "out": [ + { + "x": 900, "y": 40, "wires": [ - [] - ] - }, - { - "id": "4e78af2d.90be7", - "type": "ui_ui_control", - "z": "eaae323a.31b3", - "name": "", - "events": "change", - "x": 440, - "y": 160, - "wires": [ - [] - ] - }, - { - "id": "7789839d.69b48c", - "type": "ui_template", - "z": "eaae323a.31b3", - "group": "4e0cd5ea.17e59c", - "name": "Optic Configuration", - "order": 1, - "width": 4, - "height": 4, - "format": "\n \n
Optic Configuration
\n
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "className": "", - "x": 130, - "y": 100, - "wires": [ - [ - "4e78af2d.90be7" - ] - ] - }, - { - "id": "6ea6c306.f9c12c", - "type": "ui_template", - "z": "eaae323a.31b3", - "group": "ef590206.24f6", - "name": "Fluidic Acquisition", - "order": 1, - "width": 4, - "height": 4, - "format": "\n \n
Fluidic Acquisition
\n
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "className": "", - "x": 130, - "y": 140, - "wires": [ - [ - "4e78af2d.90be7" - ] - ] - }, - { - "id": "bb9eb153.9e36c", - "type": "ui_template", - "z": "eaae323a.31b3", - "group": "ae8f6620.073358", - "name": "Segmentation", - "order": 1, - "width": 4, - "height": 4, - "format": "\n \n
Segmentation
\n
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "className": "", - "x": 140, - "y": 180, - "wires": [ - [ - "4e78af2d.90be7" - ] - ] - }, - { - "id": "eaf8ee7f.96f44", - "type": "ui_template", - "z": "eaae323a.31b3", - "group": "196518b2.4d53b7", - "name": "Gallery", - "order": 1, - "width": 4, - "height": 4, - "format": "\n \n
Gallery
\n
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "className": "", - "x": 160, - "y": 220, - "wires": [ - [ - "4e78af2d.90be7" - ] - ] - }, - { - "id": "c1b1469.9650eb8", - "type": "ui_template", - "z": "eaae323a.31b3", - "group": "777a7c33.fcd804", - "name": "System Monitoring", - "order": 1, - "width": 4, - "height": 4, - "format": "\n \n
System Monitoring
\n
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "className": "", - "x": 130, - "y": 260, - "wires": [ - [ - "4e78af2d.90be7" - ] - ] - }, - { - "id": "abafd6e6.04a5f8", - "type": "ui_template", - "z": "eaae323a.31b3", - "group": "6f97e7ae.270c48", - "name": "Sample", - "order": 1, - "width": 4, - "height": 4, - "format": "\n \n
Sample
\n
\n In doubt? Start Here!\n
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "className": "", - "x": 160, - "y": 60, - "wires": [ - [ - "4e78af2d.90be7" - ] - ] - }, - { - "id": "dab82064.26a8d", - "type": "ui_button", - "z": "eaae323a.31b3", - "name": "Unlock button", - "group": "f3ca28ef.4df0a8", - "order": 2, - "width": 0, - "height": 0, - "passthru": false, - "label": "Unlock button", - "tooltip": "", - "color": "", - "bgcolor": "", - "icon": "", - "payload": "shutdown", - "payloadType": "flow", - "topic": "", - "x": 120, - "y": 380, - "wires": [ - [ - "6c3a3b4.78cad44" - ] - ] - }, - { - "id": "1c658761.b852a1", - "type": "ui_toast", - "z": "eaae323a.31b3", - "position": "dialog", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 1, - "ok": "YES PLEASE", - "cancel": "NO!", - "raw": false, - "topic": "Are you sure?", - "name": "Confirmation message", - "x": 800, - "y": 380, - "wires": [ - [ - "8f1b8e23.daafe" - ] - ] - }, - { - "id": "a48ff63f.db5e18", - "type": "inject", - "z": "eaae323a.31b3", - "name": "disabled", - "props": [ - { - "p": "enabled", - "v": "false", - "vt": "bool" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "", - "x": 140, - "y": 420, - "wires": [ - [ - "d58039a9.6e7928" - ] - ] - }, - { - "id": "b67a7147.65fcd8", - "type": "ui_button", - "z": "eaae323a.31b3", - "name": "Shutdown button", - "group": "f3ca28ef.4df0a8", - "order": 4, - "width": 0, - "height": 0, - "passthru": false, - "label": "Shutdown", - "tooltip": "", - "color": "", - "bgcolor": "#AD1625", - "icon": "fa-power-off fa-2x", - "payload": "Do you want to turn the machine off now?", - "payloadType": "str", - "topic": "", - "x": 550, - "y": 380, - "wires": [ - [ - "1c658761.b852a1" - ] - ] - }, - { - "id": "d58039a9.6e7928", - "type": "change", - "z": "eaae323a.31b3", - "name": "", - "rules": [ - { - "t": "set", - "p": "shutdown", - "pt": "flow", - "to": "false", - "tot": "bool" - }, - { - "t": "set", - "p": "enabled", - "pt": "msg", - "to": "shutdown", - "tot": "flow" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 320, - "y": 420, - "wires": [ - [ - "b67a7147.65fcd8" - ] - ] - }, - { - "id": "6c3a3b4.78cad44", - "type": "function", - "z": "eaae323a.31b3", - "name": "Toggle", - "func": "flow.set(\"shutdown\", !flow.get(\"shutdown\"))\nmsg.enabled = flow.get(\"shutdown\")\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 290, - "y": 380, - "wires": [ - [ - "b67a7147.65fcd8" - ] - ] - }, - { - "id": "d1153ad6.40d738", - "type": "ui_template", - "z": "eaae323a.31b3", - "group": "f3ca28ef.4df0a8", - "name": "Shutdown information", - "order": 1, - "width": 0, - "height": 0, - "format": "
To prevent data corruption, please always shutdown the machine before unplugging the unit.\n

\nRemember to first unlock the shutdown button.\n
", - "storeOutMessages": true, - "fwdInMessages": false, - "resendOnRefresh": true, - "templateScope": "local", - "x": 120, - "y": 320, - "wires": [ - [] - ] - }, - { - "id": "e08cfcb8.2a67e8", - "type": "link out", - "z": "eaae323a.31b3", - "name": "Home shutdown button", - "links": [ - "b81b990a.d4dca" - ], - "x": 715, - "y": 500, - "wires": [] - }, - { - "id": "ce7087fc.dcc9e8", - "type": "ui_toast", - "z": "eaae323a.31b3", - "position": "dialog", - "displayTime": "10", - "highlight": "", - "sendall": true, - "outputs": 1, - "ok": "OK", - "cancel": "", - "raw": false, - "topic": "Turning off now!", - "name": "Shutdown message", - "x": 580, - "y": 540, - "wires": [ - [] - ] - }, - { - "id": "7d1626a0.deb85", - "type": "change", - "z": "eaae323a.31b3", - "name": "shutdown!", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "shutdown", - "tot": "str" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 310, - "y": 500, - "wires": [ - [ - "e08cfcb8.2a67e8" - ] - ] - }, - { - "id": "8f1b8e23.daafe", - "type": "switch", - "z": "eaae323a.31b3", - "name": "", - "property": "payload", - "propertyType": "msg", - "rules": [ - { - "t": "eq", - "v": "NO!", - "vt": "str" - }, - { - "t": "else" - } - ], - "checkall": "true", - "repair": false, - "outputs": 2, - "x": 150, - "y": 500, - "wires": [ - [ - "d58039a9.6e7928" - ], - [ - "7d1626a0.deb85", - "281a56c9.ec7902" - ] - ] - }, - { - "id": "281a56c9.ec7902", - "type": "change", - "z": "eaae323a.31b3", - "name": "Shutdown message", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "Please wait a minute before disconnecting the machine from its power supply!", - "tot": "str" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 340, - "y": 540, - "wires": [ - [ - "ce7087fc.dcc9e8" - ] - ] - }, - { - "id": "57db4f6279b5afe0", - "type": "comment", - "z": "eaae323a.31b3", - "name": "LICENSE", - "info": "Copyright 2022 Thibaut Pollina and Romain Bazile\nLicensed under GPL v3.0", - "x": 140, - "y": 600, - "wires": [] - }, - { - "id": "6af85f0e0fc21b11", - "type": "ui_ui_control", - "z": "eaae323a.31b3", - "name": "", - "events": "all", - "x": 700, - "y": 720, - "wires": [ - [] - ] - }, - { - "id": "382f8fcc81f904f1", - "type": "ui_dropdown", - "z": "eaae323a.31b3", - "name": "", - "label": "Hardware version", - "tooltip": "", - "place": "Select option", - "group": "0035a03e1490cd8c", - "order": 2, - "width": 0, - "height": 0, - "passthru": false, - "multiple": false, - "options": [ - { - "label": "", - "value": "PlanktoScope v2.3", - "type": "str" - }, - { - "label": "", - "value": "PlanktoScope v2.5", - "type": "str" - }, - { - "label": "", - "value": "PlanktoScope v2.6", - "type": "str" - }, - { - "label": "", - "value": "PlanktoScope v3.0", - "type": "str" - } - ], - "payload": "", - "topic": "acq_instrument", - "topicType": "str", - "className": "", - "x": 490, - "y": 640, - "wires": [ - [ - "9f34e4a2f33c4022" - ] - ] - }, - { - "id": "9f34e4a2f33c4022", - "type": "link out", - "z": "eaae323a.31b3", - "name": "Set hardware version", - "mode": "link", - "links": [ - "cb9009e8a49e93cc" - ], - "x": 655, - "y": 640, - "wires": [] - }, - { - "id": "e954204b947a0c70", - "type": "switch", - "z": "eaae323a.31b3", - "name": "", - "property": "payload", - "propertyType": "msg", - "rules": [ - { - "t": "null" - }, - { - "t": "else" - } - ], - "checkall": "true", - "repair": false, - "outputs": 2, - "x": 290, - "y": 680, - "wires": [ - [ - "382f8fcc81f904f1", - "e3736dd7be4b7522" - ], - [ - "f80babd43aa7cce4" - ] - ] - }, - { - "id": "e3736dd7be4b7522", - "type": "change", - "z": "eaae323a.31b3", - "name": "Show setup panel", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "{\"group\":{\"show\":[\"Home_Setup\"],\"hide\":[\"Home_Group_1\",\"Home_Group_2\",\"Home_Group_3\",\"Home_Group_4\",\"Home_Group_5\",\"Home_Group_6\"]}}", - "tot": "json" - } - ], - "action": "", - "property": "", - "from": "", + { + "id": "d0fbcd200cd09981", + "port": 0 + } + ] + } + ], + "env": [], + "meta": {}, + "color": "#DDAA99" + }, + { + "id": "3a6bb13f.c9703e", + "type": "ui_tab", + "name": "Home", + "icon": "home", + "order": 1, + "disabled": false, + "hidden": false + }, + { + "id": "181bb236.1e94be", + "type": "ui_tab", + "name": "Optic Configuration", + "icon": "fa-eye", + "order": 3, + "disabled": false, + "hidden": false + }, + { + "id": "c9194f02.9d5e9", + "type": "ui_tab", + "name": "Fluidic Acquisition", + "icon": "fa-flask", + "order": 4, + "disabled": false, + "hidden": false + }, + { + "id": "8d16beb8.9b3fb", + "type": "ui_tab", + "name": "Segmentation", + "icon": "fa-crop", + "order": 5, + "disabled": false, + "hidden": false + }, + { + "id": "d9cd733b.ab73d", + "type": "ui_tab", + "name": "System Monitoring", + "icon": "fa-thermometer-full", + "order": 7, + "disabled": false, + "hidden": false + }, + { + "id": "4248342d.e55fac", + "type": "ui_group", + "name": "Optic Characterization", + "tab": "181bb236.1e94be", + "order": 4, + "disp": true, + "width": "6", + "collapse": false + }, + { + "id": "858a0e3c.987fe", + "type": "ui_group", + "name": "Preview", + "tab": "c9194f02.9d5e9", + "order": 1, + "disp": true, + "width": 10, + "collapse": false + }, + { + "id": "64903b47.4034e4", + "type": "ui_group", + "name": "Navigation", + "tab": "8d16beb8.9b3fb", + "order": 3, + "disp": false, + "width": "6", + "collapse": false + }, + { + "id": "3da7da8f.179606", + "type": "ui_group", + "name": "Metrics", + "tab": "d9cd733b.ab73d", + "order": 1, + "disp": true, + "width": "24", + "collapse": true, + "className": "" + }, + { + "id": "cc8bc4eb.651868", + "type": "ui_base", + "theme": { + "name": "theme-dark", + "lightTheme": { + "default": "#0094CE", + "baseColor": "#5900ce", + "baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif", + "edited": false, + "reset": false + }, + "darkTheme": { + "default": "#097479", + "baseColor": "#097479", + "baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif", + "edited": true, + "reset": false + }, + "customTheme": { + "name": "Untitled Theme 1", + "default": "#4B7930", + "baseColor": "#4B7930", + "baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif" + }, + "themeState": { + "base-color": { + "default": "#097479", + "value": "#097479", + "edited": true + }, + "page-titlebar-backgroundColor": { + "value": "#097479", + "edited": false + }, + "page-backgroundColor": { + "value": "#111111", + "edited": false + }, + "page-sidebar-backgroundColor": { + "value": "#333333", + "edited": false + }, + "group-textColor": { + "value": "#0eb8c0", + "edited": false + }, + "group-borderColor": { + "value": "#555555", + "edited": false + }, + "group-backgroundColor": { + "value": "#333333", + "edited": false + }, + "widget-textColor": { + "value": "#eeeeee", + "edited": false + }, + "widget-backgroundColor": { + "value": "#097479", + "edited": false + }, + "widget-borderColor": { + "value": "#333333", + "edited": false + }, + "base-font": { + "value": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif" + } + }, + "angularTheme": { + "primary": "indigo", + "accents": "blue", + "warn": "red", + "background": "grey", + "palette": "light" + } + }, + "site": { + "name": "PlanktoScope", + "hideToolbar": "false", + "allowSwipe": "false", + "lockMenu": "false", + "allowTempTheme": "true", + "dateFormat": "Y-MM-DD", + "sizes": { + "sx": 55, + "sy": 55, + "gx": 4, + "gy": 4, + "cx": 4, + "cy": 4, + "px": 4, + "py": 4 + } + } + }, + { + "id": "36739a35.7cce36", + "type": "ui_tab", + "name": "Gallery", + "icon": "fa-file-image-o", + "order": 6, + "disabled": false, + "hidden": false + }, + { + "id": "c0ebfc57.42527", + "type": "ui_group", + "name": "Group 1", + "tab": "36739a35.7cce36", + "order": 1, + "disp": false, + "width": "24", + "collapse": false, + "className": "" + }, + { + "id": "737ec584.2eea2c", + "type": "ui_tab", + "name": "Sample", + "icon": "fa-eyedropper", + "order": 2, + "disabled": false, + "hidden": false + }, + { + "id": "6f97e7ae.270c48", + "type": "ui_group", + "name": "Group 1", + "tab": "3a6bb13f.c9703e", + "order": 2, + "disp": false, + "width": "4", + "collapse": false, + "className": "" + }, + { + "id": "3e1ba03d.f01d8", + "type": "ui_group", + "name": "Sample Identification", + "tab": "737ec584.2eea2c", + "order": 1, + "disp": true, + "width": "10", + "collapse": false + }, + { + "id": "4e0cd5ea.17e59c", + "type": "ui_group", + "name": "Group 2", + "tab": "3a6bb13f.c9703e", + "order": 3, + "disp": false, + "width": "4", + "collapse": false + }, + { + "id": "ef590206.24f6", + "type": "ui_group", + "name": "Group 3", + "tab": "3a6bb13f.c9703e", + "order": 4, + "disp": false, + "width": "4", + "collapse": false + }, + { + "id": "ae8f6620.073358", + "type": "ui_group", + "name": "Group 4", + "tab": "3a6bb13f.c9703e", + "order": 5, + "disp": false, + "width": "4", + "collapse": false + }, + { + "id": "196518b2.4d53b7", + "type": "ui_group", + "name": "Group 5", + "tab": "3a6bb13f.c9703e", + "order": 6, + "disp": false, + "width": "4", + "collapse": false + }, + { + "id": "777a7c33.fcd804", + "type": "ui_group", + "name": "Group 6", + "tab": "3a6bb13f.c9703e", + "order": 7, + "disp": false, + "width": "4", + "collapse": false + }, + { + "id": "cef1e703.bcf3c8", + "type": "ui_group", + "name": "Sample Location", + "tab": "737ec584.2eea2c", + "order": 3, + "disp": false, + "width": "10", + "collapse": false + }, + { + "id": "5517c651.b2f668", + "type": "ui_group", + "name": "Validation", + "tab": "737ec584.2eea2c", + "order": 5, + "disp": false, + "width": 10, + "collapse": false + }, + { + "id": "fbd92986.1028c8", + "type": "ui_group", + "name": "Focus Adjustment", + "tab": "181bb236.1e94be", + "order": 2, + "disp": true, + "width": 4, + "collapse": false + }, + { + "id": "707d9797.c8e798", + "type": "ui_group", + "name": "Fluidic Manual Manipulation", + "tab": "181bb236.1e94be", + "order": 5, + "disp": true, + "width": 4, + "collapse": false + }, + { + "id": "7a0b4877.a5d268", + "type": "ui_group", + "name": "Navigation", + "tab": "181bb236.1e94be", + "order": 6, + "disp": false, + "width": 4, + "collapse": false + }, + { + "id": "4322c187.e73e5", + "type": "ui_group", + "name": "Acquisition", + "tab": "c9194f02.9d5e9", + "order": 3, + "disp": true, + "width": 10, + "collapse": false + }, + { + "id": "b7919ae2.c01788", + "type": "ui_group", + "name": "Navigation", + "tab": "c9194f02.9d5e9", + "order": 6, + "disp": false, + "width": "10", + "collapse": false + }, + { + "id": "b5d61bc7.54fe48", + "type": "ui_group", + "name": "Statistics", + "tab": "c9194f02.9d5e9", + "order": 4, + "disp": true, + "width": "10", + "collapse": false + }, + { + "id": "8dc3722c.06efa8", + "type": "mqtt-broker", + "name": "", + "broker": "0.0.0.0", + "port": "1883", + "clientid": "Client_node", + "autoConnect": true, + "usetls": false, + "compatmode": false, + "protocolVersion": 4, + "keepalive": "60", + "cleansession": true, + "birthTopic": "", + "birthQos": "0", + "birthPayload": "", + "closeTopic": "", + "closeQos": "0", + "closePayload": "", + "willTopic": "", + "willQos": "0", + "willPayload": "" + }, + { + "id": "abeb6dad.635a2", + "type": "ui_group", + "name": "Control", + "tab": "8d16beb8.9b3fb", + "order": 1, + "disp": true, + "width": 10, + "collapse": false + }, + { + "id": "cf5d9f0e.d57e7", + "type": "ui_group", + "name": "Net Metadata", + "tab": "737ec584.2eea2c", + "order": 4, + "disp": false, + "width": "10", + "collapse": false + }, + { + "id": "ce9e278.781eed8", + "type": "ui_group", + "name": "Information", + "tab": "d9cd733b.ab73d", + "order": 5, + "disp": true, + "width": 6, + "collapse": false + }, + { + "id": "70de8209.68416c", + "type": "ui_group", + "name": "Status", + "tab": "c9194f02.9d5e9", + "order": 5, + "disp": true, + "width": 10, + "collapse": false + }, + { + "id": "46be9c86.dea684", + "type": "ui_group", + "name": "Status", + "tab": "8d16beb8.9b3fb", + "order": 2, + "disp": true, + "width": 10, + "collapse": false + }, + { + "id": "8c38a81e.9897a8", + "type": "ui_group", + "name": "Camera Settings", + "tab": "181bb236.1e94be", + "order": 3, + "disp": true, + "width": 6, + "collapse": false + }, + { + "id": "2489e51c.eed77a", + "type": "ui_tab", + "name": "Administration", + "icon": "dashboard", + "order": 9, + "disabled": false, + "hidden": false + }, + { + "id": "b0fb559a.6966a8", + "type": "ui_tab", + "name": "Hardware Settings", + "icon": "fa-cogs", + "disabled": false, + "hidden": false + }, + { + "id": "6be36295.0ab324", + "type": "ui_group", + "name": "Settings", + "tab": "b0fb559a.6966a8", + "order": 1, + "disp": false, + "width": "8", + "collapse": false, + "className": "" + }, + { + "id": "f3ca28ef.4df0a8", + "type": "ui_group", + "name": "Shutdown", + "tab": "3a6bb13f.c9703e", + "order": 8, + "disp": true, + "width": 4, + "collapse": false + }, + { + "id": "3dfd8a69.69ed56", + "type": "ui_spacer", + "name": "spacer", + "group": "f3ca28ef.4df0a8", + "order": 3, + "width": 4, + "height": 1 + }, + { + "id": "72a9216.2ff48e", + "type": "ui_spacer", + "name": "spacer", + "group": "4322c187.e73e5", + "order": 8, + "width": 10, + "height": 1 + }, + { + "id": "1b664927.c91d1f", + "type": "ui_spacer", + "name": "spacer", + "group": "b5d61bc7.54fe48", + "order": 2, + "width": 2, + "height": 1 + }, + { + "id": "1a663b6a.ab5805", + "type": "ui_spacer", + "name": "spacer", + "group": "b5d61bc7.54fe48", + "order": 4, + "width": 2, + "height": 1 + }, + { + "id": "8eeed8d8.ad9098", + "type": "ui_spacer", + "name": "spacer", + "group": "b5d61bc7.54fe48", + "order": 5, + "width": 2, + "height": 1 + }, + { + "id": "be1c5ce7.004e", + "type": "ui_spacer", + "name": "spacer", + "group": "b5d61bc7.54fe48", + "order": 6, + "width": 2, + "height": 1 + }, + { + "id": "c2fe38e9.555e3", + "type": "ui_spacer", + "name": "spacer", + "group": "b5d61bc7.54fe48", + "order": 7, + "width": 2, + "height": 1 + }, + { + "id": "89bd18b7.c779a8", + "type": "ui_spacer", + "name": "spacer", + "group": "b5d61bc7.54fe48", + "order": 8, + "width": 2, + "height": 1 + }, + { + "id": "3cbbfa5d.efa636", + "type": "ui_spacer", + "name": "spacer", + "group": "b7919ae2.c01788", + "order": 2, + "width": 5, + "height": 1 + }, + { + "id": "97148e8d8e298f1a", + "type": "ui_spacer", + "z": "cb95299c.2817c8", + "name": "spacer", + "group": "abeb6dad.635a2", + "order": 7, + "width": 10, + "height": 1 + }, + { + "id": "3b2eccc574e6a9ae", + "type": "ui_spacer", + "z": "cb95299c.2817c8", + "name": "spacer", + "group": "abeb6dad.635a2", + "order": 11, + "width": 1, + "height": 1 + }, + { + "id": "bbd6431d97c86f97", + "type": "ui_spacer", + "z": "cb95299c.2817c8", + "name": "spacer", + "group": "46be9c86.dea684", + "order": 4, + "width": 3, + "height": 1 + }, + { + "id": "5f98f5f140f0ecde", + "type": "ui_spacer", + "z": "cb95299c.2817c8", + "name": "spacer", + "group": "46be9c86.dea684", + "order": 6, + "width": 3, + "height": 1 + }, + { + "id": "7bc0a4c416e4545c", + "type": "ui_group", + "name": "Culture Date and Time", + "tab": "737ec584.2eea2c", + "order": 2, + "disp": true, + "width": "10", + "collapse": false, + "className": "" + }, + { + "id": "6c31ad948a9d62fd", + "type": "ui_spacer", + "z": "b771c342.49603", + "name": "spacer", + "group": "3e1ba03d.f01d8", + "order": 5, + "width": 10, + "height": 1 + }, + { + "id": "0035a03e1490cd8c", + "type": "ui_group", + "name": "Setup", + "tab": "3a6bb13f.c9703e", + "order": 1, + "disp": true, + "width": "8", + "collapse": false, + "className": "" + }, + { + "id": "833bc5bb.217ba8", + "type": "ui_group", + "name": "Preview", + "tab": "181bb236.1e94be", + "order": 1, + "disp": true, + "width": 18, + "collapse": false + }, + { + "id": "a7d64879.38298", + "type": "ui_group", + "name": "Logs", + "tab": "2489e51c.eed77a", + "order": 1, + "disp": true, + "width": "12", + "collapse": true, + "className": "" + }, + { + "id": "6465bdd5.15eb8c", + "type": "file in", + "z": "1c24ad9c.bebec2", + "name": "", + "filename": "/home/pi/PlanktoScope/config.json", + "filenameType": "str", + "format": "utf8", + "chunk": false, + "sendError": false, + "encoding": "none", + "x": 560, + "y": 60, + "wires": [["15ceb135.6628bf"]], + "info": "# PlanktoScope Help\nThis Node will read the content of the file named **config.txt** containing all the input placeholders.\n" + }, + { + "id": "15ceb135.6628bf", + "type": "json", + "z": "1c24ad9c.bebec2", + "name": "config.json", + "property": "payload", + "action": "", + "pretty": false, + "x": 730, + "y": 60, + "wires": [["ad541674.4791c8"]] + }, + { + "id": "7205d267.36adcc", + "type": "file", + "z": "1c24ad9c.bebec2", + "name": "", + "filename": "/home/pi/PlanktoScope/config.json", + "appendNewline": true, + "createDir": true, + "overwriteFile": "true", + "encoding": "none", + "x": 990, + "y": 160, + "wires": [[]] + }, + { + "id": "2e6ddf51.c0dba", + "type": "json", + "z": "1c24ad9c.bebec2", + "name": "config.json", + "property": "payload", + "action": "str", + "pretty": true, + "x": 730, + "y": 160, + "wires": [["7205d267.36adcc"]] + }, + { + "id": "ad541674.4791c8", + "type": "function", + "z": "1c24ad9c.bebec2", + "name": "Global Set", + "func": "global.set(\"config_keys\", Object.keys(msg.payload));\n\nfor (const key in msg.payload) {\n global.set(key, msg.payload[key]);\n}\n\nreturn msg;", + "outputs": 1, + "timeout": "", + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 910, + "y": 60, + "wires": [[]] + }, + { + "id": "3e9a33c.141384c", + "type": "inject", + "z": "1c24ad9c.bebec2", + "name": "Load config", + "props": [ + { + "p": "topic", + "vt": "str" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "payloadType": "str", + "x": 230, + "y": 60, + "wires": [["6465bdd5.15eb8c"]] + }, + { + "id": "3ad9835.08c937c", + "type": "function", + "z": "1c24ad9c.bebec2", + "name": "get config payload", + "func": "keys = global.get(\"config_keys\")\n\nvar payload = {}\n\nkeys.forEach(function(item, index, array) {\n payload[item] = global.get(item);\n})\n\nreturn {\"payload\": payload};", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 410, + "y": 160, + "wires": [["2e6ddf51.c0dba"]] + }, + { + "id": "f439663c.8abd3", + "type": "ui_ui_control", + "z": "1c24ad9c.bebec2", + "name": "Connect Event", + "events": "connect", + "x": 220, + "y": 100, + "wires": [["6465bdd5.15eb8c"]] + }, + { + "id": "82099021.9ceb08", + "type": "file", + "z": "4ed26b8b.253504", + "name": "", + "filename": "/home/pi/PlanktoScope/hardware.json", + "appendNewline": true, + "createDir": true, + "overwriteFile": "true", + "encoding": "none", + "x": 660, + "y": 40, + "wires": [[]] + }, + { + "id": "bb0a8725.a1849", + "type": "json", + "z": "4ed26b8b.253504", + "name": "Create JSON", + "property": "payload", + "action": "str", + "pretty": true, + "x": 490, + "y": 40, + "wires": [["82099021.9ceb08"]] + }, + { + "id": "53d163be.47cf24", + "type": "function", + "z": "4ed26b8b.253504", + "name": "Update and retrieve hardware_conf", + "func": "// change global\nhardware_conf = global.get(\"hardware_conf\");\n\nif (msg.topic == \"process_pixel_fixed\" && msg.payload == 0){\n delete hardware_conf[msg.topic]\n delete msg.topic\n}\n\nif (msg.topic !== null && msg.topic !== undefined){\n hardware_conf[msg.topic] = msg.payload;\n global.set(\"hardware_conf\", hardware_conf);\n}\n\nreturn {\"payload\": hardware_conf};", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 240, + "y": 40, + "wires": [["bb0a8725.a1849"]] + }, + { + "id": "0f16258953fae292", + "type": "file in", + "z": "b7861ce703215a01", + "name": "", + "filename": "/home/pi/PlanktoScope/hardware.json", + "filenameType": "str", + "format": "utf8", + "chunk": false, + "sendError": false, + "encoding": "none", + "allProps": false, + "x": 250, + "y": 40, + "wires": [["81c516291ab19acd"]], + "info": "# PlanktoScope Help\nThis Node will read the content of the file named **config.txt** containing all the input placeholders.\n" + }, + { + "id": "81c516291ab19acd", + "type": "json", + "z": "b7861ce703215a01", + "name": "Parse JSON", + "property": "payload", + "action": "", + "pretty": false, + "x": 510, + "y": 40, + "wires": [["d0fbcd200cd09981"]] + }, + { + "id": "d0fbcd200cd09981", + "type": "change", + "z": "b7861ce703215a01", + "name": "", + "rules": [ + { + "t": "set", + "p": "hardware_conf", + "pt": "global", + "to": "payload", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 730, + "y": 40, + "wires": [[]] + }, + { + "id": "4e78af2d.90be7", + "type": "ui_ui_control", + "z": "eaae323a.31b3", + "name": "", + "events": "change", + "x": 440, + "y": 160, + "wires": [[]] + }, + { + "id": "7789839d.69b48c", + "type": "ui_template", + "z": "eaae323a.31b3", + "group": "4e0cd5ea.17e59c", + "name": "Optic Configuration", + "order": 1, + "width": 4, + "height": 4, + "format": "\n \n
Optic Configuration
\n
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "className": "", + "x": 130, + "y": 100, + "wires": [["4e78af2d.90be7"]] + }, + { + "id": "6ea6c306.f9c12c", + "type": "ui_template", + "z": "eaae323a.31b3", + "group": "ef590206.24f6", + "name": "Fluidic Acquisition", + "order": 1, + "width": 4, + "height": 4, + "format": "\n \n
Fluidic Acquisition
\n
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "className": "", + "x": 130, + "y": 140, + "wires": [["4e78af2d.90be7"]] + }, + { + "id": "bb9eb153.9e36c", + "type": "ui_template", + "z": "eaae323a.31b3", + "group": "ae8f6620.073358", + "name": "Segmentation", + "order": 1, + "width": 4, + "height": 4, + "format": "\n \n
Segmentation
\n
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "className": "", + "x": 140, + "y": 180, + "wires": [["4e78af2d.90be7"]] + }, + { + "id": "eaf8ee7f.96f44", + "type": "ui_template", + "z": "eaae323a.31b3", + "group": "196518b2.4d53b7", + "name": "Gallery", + "order": 1, + "width": 4, + "height": 4, + "format": "\n \n
Gallery
\n
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "className": "", + "x": 160, + "y": 220, + "wires": [["4e78af2d.90be7"]] + }, + { + "id": "c1b1469.9650eb8", + "type": "ui_template", + "z": "eaae323a.31b3", + "group": "777a7c33.fcd804", + "name": "System Monitoring", + "order": 1, + "width": 4, + "height": 4, + "format": "\n \n
System Monitoring
\n
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "className": "", + "x": 130, + "y": 260, + "wires": [["4e78af2d.90be7"]] + }, + { + "id": "abafd6e6.04a5f8", + "type": "ui_template", + "z": "eaae323a.31b3", + "group": "6f97e7ae.270c48", + "name": "Sample", + "order": 1, + "width": 4, + "height": 4, + "format": "\n \n
Sample
\n
\n In doubt? Start Here!\n
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "className": "", + "x": 160, + "y": 60, + "wires": [["4e78af2d.90be7"]] + }, + { + "id": "dab82064.26a8d", + "type": "ui_button", + "z": "eaae323a.31b3", + "name": "Unlock button", + "group": "f3ca28ef.4df0a8", + "order": 2, + "width": 0, + "height": 0, + "passthru": false, + "label": "Unlock button", + "tooltip": "", + "color": "", + "bgcolor": "", + "icon": "", + "payload": "shutdown", + "payloadType": "flow", + "topic": "", + "x": 120, + "y": 380, + "wires": [["6c3a3b4.78cad44"]] + }, + { + "id": "1c658761.b852a1", + "type": "ui_toast", + "z": "eaae323a.31b3", + "position": "dialog", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 1, + "ok": "YES PLEASE", + "cancel": "NO!", + "raw": false, + "topic": "Are you sure?", + "name": "Confirmation message", + "x": 800, + "y": 380, + "wires": [["8f1b8e23.daafe"]] + }, + { + "id": "a48ff63f.db5e18", + "type": "inject", + "z": "eaae323a.31b3", + "name": "disabled", + "props": [ + { + "p": "enabled", + "v": "false", + "vt": "bool" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "x": 140, + "y": 420, + "wires": [["d58039a9.6e7928"]] + }, + { + "id": "b67a7147.65fcd8", + "type": "ui_button", + "z": "eaae323a.31b3", + "name": "Shutdown button", + "group": "f3ca28ef.4df0a8", + "order": 4, + "width": 0, + "height": 0, + "passthru": false, + "label": "Shutdown", + "tooltip": "", + "color": "", + "bgcolor": "#AD1625", + "icon": "fa-power-off fa-2x", + "payload": "Do you want to turn the machine off now?", + "payloadType": "str", + "topic": "", + "x": 550, + "y": 380, + "wires": [["1c658761.b852a1"]] + }, + { + "id": "d58039a9.6e7928", + "type": "change", + "z": "eaae323a.31b3", + "name": "", + "rules": [ + { + "t": "set", + "p": "shutdown", + "pt": "flow", + "to": "false", + "tot": "bool" + }, + { + "t": "set", + "p": "enabled", + "pt": "msg", + "to": "shutdown", + "tot": "flow" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 320, + "y": 420, + "wires": [["b67a7147.65fcd8"]] + }, + { + "id": "6c3a3b4.78cad44", + "type": "function", + "z": "eaae323a.31b3", + "name": "Toggle", + "func": "flow.set(\"shutdown\", !flow.get(\"shutdown\"))\nmsg.enabled = flow.get(\"shutdown\")\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 290, + "y": 380, + "wires": [["b67a7147.65fcd8"]] + }, + { + "id": "d1153ad6.40d738", + "type": "ui_template", + "z": "eaae323a.31b3", + "group": "f3ca28ef.4df0a8", + "name": "Shutdown information", + "order": 1, + "width": 0, + "height": 0, + "format": "
To prevent data corruption, please always shutdown the machine before unplugging the unit.\n

\nRemember to first unlock the shutdown button.\n
", + "storeOutMessages": true, + "fwdInMessages": false, + "resendOnRefresh": true, + "templateScope": "local", + "x": 120, + "y": 320, + "wires": [[]] + }, + { + "id": "e08cfcb8.2a67e8", + "type": "link out", + "z": "eaae323a.31b3", + "name": "Home shutdown button", + "links": ["b81b990a.d4dca"], + "x": 715, + "y": 500, + "wires": [] + }, + { + "id": "ce7087fc.dcc9e8", + "type": "ui_toast", + "z": "eaae323a.31b3", + "position": "dialog", + "displayTime": "10", + "highlight": "", + "sendall": true, + "outputs": 1, + "ok": "OK", + "cancel": "", + "raw": false, + "topic": "Turning off now!", + "name": "Shutdown message", + "x": 580, + "y": 540, + "wires": [[]] + }, + { + "id": "7d1626a0.deb85", + "type": "change", + "z": "eaae323a.31b3", + "name": "shutdown!", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "shutdown", + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 310, + "y": 500, + "wires": [["e08cfcb8.2a67e8"]] + }, + { + "id": "8f1b8e23.daafe", + "type": "switch", + "z": "eaae323a.31b3", + "name": "", + "property": "payload", + "propertyType": "msg", + "rules": [ + { + "t": "eq", + "v": "NO!", + "vt": "str" + }, + { + "t": "else" + } + ], + "checkall": "true", + "repair": false, + "outputs": 2, + "x": 150, + "y": 500, + "wires": [["d58039a9.6e7928"], ["7d1626a0.deb85", "281a56c9.ec7902"]] + }, + { + "id": "281a56c9.ec7902", + "type": "change", + "z": "eaae323a.31b3", + "name": "Shutdown message", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "Please wait a minute before disconnecting the machine from its power supply!", + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 340, + "y": 540, + "wires": [["ce7087fc.dcc9e8"]] + }, + { + "id": "57db4f6279b5afe0", + "type": "comment", + "z": "eaae323a.31b3", + "name": "LICENSE", + "info": "Copyright 2022 Thibaut Pollina and Romain Bazile\nLicensed under GPL v3.0", + "x": 140, + "y": 600, + "wires": [] + }, + { + "id": "6af85f0e0fc21b11", + "type": "ui_ui_control", + "z": "eaae323a.31b3", + "name": "", + "events": "all", + "x": 700, + "y": 720, + "wires": [[]] + }, + { + "id": "382f8fcc81f904f1", + "type": "ui_dropdown", + "z": "eaae323a.31b3", + "name": "", + "label": "Hardware version", + "tooltip": "", + "place": "Select option", + "group": "0035a03e1490cd8c", + "order": 2, + "width": 0, + "height": 0, + "passthru": false, + "multiple": false, + "options": [ + { + "label": "", + "value": "PlanktoScope v2.3", + "type": "str" + }, + { + "label": "", + "value": "PlanktoScope v2.5", + "type": "str" + }, + { + "label": "", + "value": "PlanktoScope v2.6", + "type": "str" + }, + { + "label": "", + "value": "PlanktoScope v3.0", + "type": "str" + } + ], + "payload": "", + "topic": "acq_instrument", + "topicType": "str", + "className": "", + "x": 490, + "y": 640, + "wires": [["9f34e4a2f33c4022"]] + }, + { + "id": "9f34e4a2f33c4022", + "type": "link out", + "z": "eaae323a.31b3", + "name": "Set hardware version", + "mode": "link", + "links": ["cb9009e8a49e93cc"], + "x": 655, + "y": 640, + "wires": [] + }, + { + "id": "e954204b947a0c70", + "type": "switch", + "z": "eaae323a.31b3", + "name": "", + "property": "payload", + "propertyType": "msg", + "rules": [ + { + "t": "null" + }, + { + "t": "else" + } + ], + "checkall": "true", + "repair": false, + "outputs": 2, + "x": 290, + "y": 680, + "wires": [["382f8fcc81f904f1", "e3736dd7be4b7522"], ["f80babd43aa7cce4"]] + }, + { + "id": "e3736dd7be4b7522", + "type": "change", + "z": "eaae323a.31b3", + "name": "Show setup panel", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "{\"group\":{\"show\":[\"Home_Setup\"],\"hide\":[\"Home_Group_1\",\"Home_Group_2\",\"Home_Group_3\",\"Home_Group_4\",\"Home_Group_5\",\"Home_Group_6\"]}}", + "tot": "json" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 490, + "y": 680, + "wires": [["6af85f0e0fc21b11"]] + }, + { + "id": "f80babd43aa7cce4", + "type": "change", + "z": "eaae323a.31b3", + "name": "Show home buttons", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "{\"group\":{\"hide\":[\"Home_Setup\"],\"show\":[\"Home_Group_1\",\"Home_Group_2\",\"Home_Group_3\",\"Home_Group_4\",\"Home_Group_5\",\"Home_Group_6\"]}}", + "tot": "json" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 500, + "y": 720, + "wires": [["6af85f0e0fc21b11"]] + }, + { + "id": "438439b4ae62444c", + "type": "ui_template", + "z": "eaae323a.31b3", + "group": "0035a03e1490cd8c", + "name": "Information", + "order": 1, + "width": "0", + "height": "0", + "format": "
\n

\n To start using your PlanktoScope, please indicate the version of your PlanktoScope hardware:\n

\n
\n", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": true, + "templateScope": "local", + "className": "", + "x": 710, + "y": 680, + "wires": [[]] + }, + { + "id": "a2f2a4c7cbae4446", + "type": "link in", + "z": "eaae323a.31b3", + "name": "Load hardware version", + "links": ["3973b999ee7b3b1d", "56dd3f82c45717f0"], + "x": 185, + "y": 680, + "wires": [["e954204b947a0c70"]] + }, + { + "id": "4557d689.a4fa88", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "sample_ship", + "label": "Name of the ship", + "tooltip": "", + "group": "3e1ba03d.f01d8", + "order": 2, + "width": 0, + "height": 0, + "passthru": true, + "mode": "text", + "delay": "300", + "topic": "sample_ship", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 670, + "y": 80, + "wires": [["9f501f49.45645"]] + }, + { + "id": "fcfc31ae.af3af", + "type": "ui_dropdown", + "z": "b771c342.49603", + "name": "sample_sampling_gear", + "label": "Sampling gear*", + "tooltip": "", + "place": "Choose from list", + "group": "3e1ba03d.f01d8", + "order": 6, + "width": 0, + "height": 0, + "passthru": true, + "multiple": false, + "options": [ + { + "label": "High Speed Net", + "value": "net_hsn", + "type": "str" + }, + { + "label": "Tara Decknet", + "value": "net_decknet", + "type": "str" + }, + { + "label": "Plankton net", + "value": "net", + "type": "str" + }, + { + "label": "Niskin bottle 12L", + "value": "niskin_12L", + "type": "str" + }, + { + "label": "Niskin bottle 24L", + "value": "niskin_24L", + "type": "str" + }, + { + "label": "Pass Hull", + "value": "pass_hull", + "type": "str" + }, + { + "label": "Single location (with net or bucket)", + "value": "single_location", + "type": "str" + }, + { + "label": "Lab culture", + "value": "culture", + "type": "str" + }, + { + "label": "Test", + "value": "test", + "type": "str" + } + ], + "payload": "", + "topic": "sample_sampling_gear", + "topicType": "str", + "className": "", + "x": 630, + "y": 200, + "wires": [["9f501f49.45645", "46eb1bf8.3dc5f4", "3ac7b631f5d8ef90"]] + }, + { + "id": "82c5fc77.59c97", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "sample_operator", + "label": "Name of the operator*", + "tooltip": "", + "group": "3e1ba03d.f01d8", + "order": 3, + "width": 0, + "height": 0, + "passthru": true, + "mode": "text", + "delay": "300", + "topic": "sample_operator", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 650, + "y": 160, + "wires": [["9f501f49.45645"]] + }, + { + "id": "9c882b37.fde668", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "sample_project", + "label": "Name of the project*", + "tooltip": "", + "group": "3e1ba03d.f01d8", + "order": 1, + "width": 0, + "height": 0, + "passthru": true, + "mode": "text", + "delay": "300", + "topic": "sample_project", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 660, + "y": 40, + "wires": [["9f501f49.45645"]] + }, + { + "id": "94eb4221.9b92c", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "sample_id", + "label": "Station ID*", + "tooltip": "", + "group": "3e1ba03d.f01d8", + "order": 4, + "width": 0, + "height": 0, + "passthru": true, + "mode": "text", + "delay": "300", + "topic": "sample_id", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 670, + "y": 120, + "wires": [["9f501f49.45645"]] + }, + { + "id": "9f501f49.45645", + "type": "function", + "z": "b771c342.49603", + "name": "set global", + "func": "global.set(msg.topic,msg.payload);", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 1080, + "y": 200, + "wires": [[]] + }, + { + "id": "222c851d.5d0a3a", + "type": "ui_ui_control", + "z": "b771c342.49603", + "name": "", + "events": "change", + "x": 400, + "y": 880, + "wires": [[]] + }, + { + "id": "52f6b103.1efb6", + "type": "ui_toast", + "z": "b771c342.49603", + "position": "dialog", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 1, + "ok": "OK", + "cancel": "", + "raw": false, + "topic": "", + "name": "", + "x": 710, + "y": 980, + "wires": [[]] + }, + { + "id": "986d960a.c75908", + "type": "function", + "z": "b771c342.49603", + "name": "Check form", + "func": "var sample_project= global.get(\"sample_project\");\nvar sample_id= global.get(\"sample_id\");\nvar sample_operator= global.get(\"sample_operator\");\nvar sample_sampling_gear= global.get(\"sample_sampling_gear\");\nvar object_lat= global.get(\"object_lat\");\nvar object_lon= global.get(\"object_lon\");\nvar object_date= global.get(\"object_date\");\nvar object_time= global.get(\"object_time\");\nif (sample_project === undefined || sample_project === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Sample project\"\n return [null, msg];\n}\n\nelse if (sample_id === undefined || sample_id === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Sample ID\"\n return [null, msg];\n}\n\nelse if (sample_operator === undefined || sample_operator === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Sample operator\"\n return [null, msg];\n}\n\nelse if (sample_sampling_gear === undefined || sample_sampling_gear === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Sample sampling gear\"\n return [null, msg];\n}\n\nelse if (object_lat === undefined || object_lat === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Latitude of sample\"\n return [null, msg];\n}\n\nelse if (object_lon === undefined || object_lon === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Longitude of sample\"\n return [null, msg];\n}\n\nelse if (object_date === undefined || object_date === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Date of sample\"\n return [null, msg];\n}\n\nelse if (object_time === undefined || object_time === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Time of sample\"\n return [null, msg];\n}\nelse if (sample_sampling_gear.startsWith(\"net\")){\n var object_lat_end = global.get(\"object_lat_end\");\n var object_lon_end = global.get(\"object_lon_end\");\n var object_date_end = global.get(\"object_date_end\");\n var object_time_end = global.get(\"object_time_end\");\n var sample_gear_net_opening = global.get(\"sample_gear_net_opening\");\n\n if (object_lat_end === undefined || object_lat_end === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Latitude of retrieval\"\n return [null, msg];\n }\n \n else if (object_lon_end === undefined || object_lon_end === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Longitude of retrieval\"\n return [null, msg];\n }\n \n else if (object_date_end === undefined || object_date_end === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Date of retrieval\"\n return [null, msg];\n }\n \n else if (object_time_end === undefined || object_time_end === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Time of retrieval\"\n return [null, msg];\n }\n \n else if (sample_gear_net_opening === undefined || sample_gear_net_opening === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Net opening dimension\"\n return [null, msg];\n }\n \n if (sample_sampling_gear == \"net_decknet\"){\n var sample_total_volume = global.get(\"sample_total_volume\");\n if (sample_total_volume === undefined || sample_total_volume === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Decknet flowmeter readings\"\n return [null, msg];\n }\n }\n}\nmsg.topic = \"config_save\"\nmsg.payload={\"tab\":\"Optic Configuration\"};\n\nreturn [msg, null];", + "outputs": 2, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 470, + "y": 940, + "wires": [["726a7822.cd6298", "e2b277c1.07283"], ["52f6b103.1efb6"]], + "outputLabels": ["message", "error"] + }, + { + "id": "726a7822.cd6298", + "type": "ui_ui_control", + "z": "b771c342.49603", + "name": "", + "events": "change", + "x": 700, + "y": 900, + "wires": [[]] + }, + { + "id": "16de754c.cc969b", + "type": "ui_button", + "z": "b771c342.49603", + "name": "", + "group": "5517c651.b2f668", + "order": 1, + "width": 5, + "height": 1, + "passthru": false, + "label": "Previous", + "tooltip": "", + "color": "#097479", + "bgcolor": "white", + "icon": "keyboard_return", + "payload": "{\"tab\":\"Home\"}", + "payloadType": "json", + "topic": "", + "x": 240, + "y": 880, + "wires": [["222c851d.5d0a3a"]] + }, + { + "id": "84f3d040.5f7ea", + "type": "ui_button", + "z": "b771c342.49603", + "name": "", + "group": "5517c651.b2f668", + "order": 2, + "width": 5, + "height": 1, + "passthru": false, + "label": "Continue", + "tooltip": "", + "color": "#097479", + "bgcolor": "white", + "icon": "keyboard_tab", + "payload": "{\"tab\":\"Home\"}", + "payloadType": "json", + "topic": "", + "x": 240, + "y": 940, + "wires": [["986d960a.c75908"]] + }, + { + "id": "d027a6bf.7049e8", + "type": "function", + "z": "b771c342.49603", + "name": "get sample_projet", + "func": "msg.payload = msg.payload.sample_project;\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 310, + "y": 40, + "wires": [["9c882b37.fde668"]] + }, + { + "id": "5a811caf.0f3144", + "type": "function", + "z": "b771c342.49603", + "name": "get sample_ship", + "func": "msg.payload = msg.payload.sample_ship;\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 300, + "y": 80, + "wires": [["4557d689.a4fa88"]] + }, + { + "id": "45911c98.2bd83c", + "type": "function", + "z": "b771c342.49603", + "name": "get sample_id", + "func": "msg.payload = msg.payload.sample_id;\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 300, + "y": 120, + "wires": [["94eb4221.9b92c"]] + }, + { + "id": "1e09a4ab.72996b", + "type": "function", + "z": "b771c342.49603", + "name": "get sample_operator", + "func": "msg.payload = msg.payload.sample_operator;\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 320, + "y": 160, + "wires": [["82c5fc77.59c97"]] + }, + { + "id": "a3272681.f271c8", + "type": "function", + "z": "b771c342.49603", + "name": "get sample_sampling_gear", + "func": "msg.topic = \"sample_sampling_gear\"\nif (msg.payload.sample_sampling_gear === undefined){\n msg.payload = \"net\";\n}\nelse\n{\n msg.payload = msg.payload.sample_sampling_gear;\n}\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 340, + "y": 200, + "wires": [["fcfc31ae.af3af"]] + }, + { + "id": "a6907a38.f6611", + "type": "subflow:1c24ad9c.bebec2", + "z": "b771c342.49603", + "name": "", + "env": [], + "x": 70, + "y": 220, + "wires": [ + [ + "d027a6bf.7049e8", + "5a811caf.0f3144", + "45911c98.2bd83c", + "1e09a4ab.72996b", + "8dff1648.82e42", + "9f04c5ec.75f3d8", + "f408a273.4fb538", + "e73fd87d.d24e4", + "489c8e06.cc7d6", + "a3272681.f271c8" + ] + ] + }, + { + "id": "e2b277c1.07283", + "type": "subflow:1c24ad9c.bebec2", + "z": "b771c342.49603", + "name": "", + "env": [], + "x": 690, + "y": 940, + "wires": [[]] + }, + { + "id": "9c7f7fc9.c8d3a", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "object_depth_max", + "label": "Max sampling depth (m)", + "tooltip": "in m", + "group": "3e1ba03d.f01d8", + "order": 10, + "width": 5, + "height": 1, + "passthru": true, + "mode": "number", + "delay": "300", + "topic": "object_depth_max", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 650, + "y": 240, + "wires": [["9f501f49.45645"]] + }, + { + "id": "317eeeb7.8d3042", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "object_depth_min", + "label": "Min sampling depth (m)", + "tooltip": "in m", + "group": "3e1ba03d.f01d8", + "order": 9, + "width": 5, + "height": 1, + "passthru": true, + "mode": "number", + "delay": "300", + "topic": "object_depth_min", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 650, + "y": 280, + "wires": [["9f501f49.45645"]] + }, + { + "id": "cbb123ab.fd3428", + "type": "ui_ui_control", + "z": "b771c342.49603", + "name": "show/hide net groups", + "events": "change", + "x": 1320, + "y": 300, + "wires": [[]] + }, + { + "id": "642ff403.1ed91c", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "sample_concentrated_sample_volume", + "label": "Concentrated sample volume (mL)", + "tooltip": "Volume extracted from the net codend (in mL)", + "group": "3e1ba03d.f01d8", + "order": 12, + "width": 10, + "height": 1, + "passthru": true, + "mode": "number", + "delay": "300", + "topic": "sample_concentrated_sample_volume", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 590, + "y": 440, + "wires": [["9f501f49.45645"]] + }, + { + "id": "e967b844.46aa48", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "sample_gear_net_opening", + "label": "Net opening dimension (mm)", + "tooltip": "Size of the net mouth opening (in mm)", + "group": "cf5d9f0e.d57e7", + "order": 1, + "width": 10, + "height": 1, + "passthru": true, + "mode": "number", + "delay": "300", + "topic": "sample_gear_net_opening", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 620, + "y": 320, + "wires": [["9f501f49.45645"]] + }, + { + "id": "c0ce5626.b6c5", + "type": "ui_toast", + "z": "b771c342.49603", + "position": "dialog", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 1, + "ok": "OK", + "cancel": "", + "raw": false, + "topic": "", + "name": "", + "x": 1230, + "y": 620, + "wires": [[]] + }, + { + "id": "c33f1124.af6688", + "type": "ui_form", + "z": "b771c342.49603", + "name": "sample_location", + "label": "Sample Location", + "group": "cef1e703.bcf3c8", + "order": 1, + "width": 0, + "height": 0, + "options": [ + { + "label": "Latitude (36.574439°N or 36°57.4439'N)", + "value": "object_lat", + "type": "text", + "required": true, + "rows": null + }, + { + "label": "Longitude (110.42100°W or 110°4.2100'W)", + "value": "object_lon", + "type": "text", + "required": true, + "rows": null + }, + { + "label": "Date (YYYY-MM-DD, UTC)", + "value": "object_date", + "type": "text", + "required": true, + "rows": null + }, + { + "label": "Time (HH:MM(:SS), UTC 24h)", + "value": "object_time", + "type": "text", + "required": true, + "rows": null + } + ], + "formValue": { + "object_lat": "", + "object_lon": "", + "object_date": "", + "object_time": "" + }, + "payload": "", + "submit": "Validate", + "cancel": "Reset", + "topic": "sample_location", + "x": 660, + "y": 580, + "wires": [["14658615.47c862", "a9fb1f4b83fc25a7"]] + }, + { + "id": "358908cd.416ab", + "type": "ui_form", + "z": "b771c342.49603", + "name": "net_throw_location", + "label": "Net Throw Location", + "group": "cf5d9f0e.d57e7", + "order": 3, + "width": 0, + "height": 0, + "options": [ + { + "label": "Latitude (36.574439°N or 36°57.4439'N)", + "value": "object_lat", + "type": "text", + "required": true, + "rows": null + }, + { + "label": "Longitude (110.42100°W or 110°4.2100'W)", + "value": "object_lon", + "type": "text", + "required": true, + "rows": null + }, + { + "label": "Date (YYYY-MM-DD UTC)", + "value": "object_date", + "type": "text", + "required": true, + "rows": null + }, + { + "label": "Time (HH:MM, UTC 24h)", + "value": "object_time", + "type": "text", + "required": true, + "rows": null + } + ], + "formValue": { + "object_lat": "", + "object_lon": "", + "object_date": "", + "object_time": "" + }, + "payload": "", + "submit": "Validate", + "cancel": "", + "topic": "net_throw_location", + "topicType": "str", + "splitLayout": false, + "className": "", + "x": 650, + "y": 620, + "wires": [["14658615.47c862", "ad54b89540460d27"]] + }, + { + "id": "56d40584.eff4e4", + "type": "ui_form", + "z": "b771c342.49603", + "name": "net_retrieval_location", + "label": "Net Retrieval Location", + "group": "cf5d9f0e.d57e7", + "order": 4, + "width": 0, + "height": 0, + "options": [ + { + "label": "Latitude (36.574439°N or 36°57.4439'N)", + "value": "object_lat_end", + "type": "text", + "required": true, + "rows": null + }, + { + "label": "Longitude (110.42100°W or 110°4.2100'W)", + "value": "object_lon_end", + "type": "text", + "required": true, + "rows": null + }, + { + "label": "Date (YYYY-MM-DD UTC)", + "value": "object_date_end", + "type": "text", + "required": true, + "rows": null + }, + { + "label": "Time (HH:MM, UTC 24h)", + "value": "object_time_end", + "type": "text", + "required": true, + "rows": null + } + ], + "formValue": { + "object_lat_end": "", + "object_lon_end": "", + "object_date_end": "", + "object_time_end": "" + }, + "payload": "", + "submit": "Validate", + "cancel": "", + "topic": "net_retrieval_location", + "topicType": "str", + "splitLayout": false, + "x": 640, + "y": 660, + "wires": [["14658615.47c862", "c21bf0244e67e40a"]] + }, + { + "id": "14658615.47c862", + "type": "function", + "z": "b771c342.49603", + "name": "Validate Location / Timestamp", + "func": "// Code added here will be run once\n// whenever the node is started.\nfunction ConvertDDMMToDD(input) {\n // Input Format 36°57.4439'N, 110°4.2100'W\n // From https://stackoverflow.com/questions/1140189/converting-latitude-and-longitude-to-decimal-values\n if (!input.match(/\\d+°\\d+\\.*\\d*\\'[NSEW]/)){\n \treturn \"parsing error\"\n }\n var parts = input.split(/[^\\d.\\w]+/)\n if (parts.length != 3){\n \treturn \"parsing error\"\n }\n var dd = Number(parts[0]) + Number(parts[1])/60\n return dd.toFixed(6) + parts[2]\n}\n\nfunction ValidateCoordinates(input, lat){\n // Input Format 36.574439°N, 110.42100°W\n // Or 36°57.4439'N, 110°4.2100'W\n if (input.match(\"'\")){\n input = ConvertDDMMToDD(input)\n }\n \n var error = {}\n\n if (input.startsWith(\"parsing error\")){\n error.topic = \"Error with the \"\n error.payload = \"You need to respect the format example, 36.574439°N or 36°57.4439'N\"\n return [null, error]\n }\n \n var direction = input.match(/[NSEW]/)\n var position = input.match(/[\\+\\-\\d\\.]+/)\n \n if (direction === null){\n error.topic = \"Error with the \"\n error.payload = \"You need to explicitely enter N/S/E/W\"\n return [null, error]\n }\n \n // Test that position is only made of digits!\n if(/^[\\+\\-]/.test(position)){\n error.topic = \"Error with the \"\n error.payload = \"Use of +/- sign is inconsistent with N/S/E/W letter! Please only use N/S/E/W!\"\n return [null, error]\n }\n \n var dd = Number(position)\n if (lat){\n // Check latitude\n if (direction == \"S\" || direction == \"N\") {\n if (dd>90.0){\n error.topic = \"Error with the \"\n error.payload = \"Latitude is more than 90°\"\n return [null, error]\n }\n }\n if (direction == \"W\" || direction == \"E\") {\n error.topic = \"Error with the \"\n error.payload = \"This is not a Latitude!\"\n return [null, error]\n }\n }\n else{\n // Check longitude\n if (direction == \"W\" || direction == \"E\") {\n if (dd>180.0){\n error.topic = \"Error with the \"\n error.payload = \"Longitude is more than 180°\"\n return [null, error]\n }\n }\n if (direction == \"N\" || direction == \"S\") {\n error.topic = \"Error with the \"\n error.payload = \"This is not a Longitude!\"\n return [null, error]\n }\n }\n \n if (direction == \"S\" || direction == \"W\") {\n dd = dd * -1\n } // Don't do anything for N or E\n return [dd.toFixed(4), null]\n \n}\n\nfunction ValidateDate(input){\n // Input Format 2020-12-25\n var error = {};\n \n if (! /20\\d{2}-[0-1]\\d-[0-3]\\d/.test(input)){\n error.topic = \"Error with the date\";\n error.payload = \"The date should respect the ISO format YYYY-MM-DD\";\n return [null, error];\n }\n else {\n var date = input.match(/\\d+/g);\n if (!((2000 < date[0]) && (date[0] < 2100))){\n error.topic = \"Error with the date\"\n error.payload = \"The year should be between 2000 and 2100\"\n return [null, error]\n }\n else if (!((0 < date[1]) && (date[1] <= 12))){\n error.topic = \"Error with the date\"\n error.payload = \"The month should be between 01 and 12\"\n return [null, error]\n }\n else if (!((0 < date[2]) && (date[2] <= 31))){\n error.topic = \"Error with the date\"\n error.payload = \"The day should be between 01 and 31\"\n return [null, error]\n }\n }\n return [input.replace(/-/g, ''), null]\n}\n\nfunction ValidateTime(input){\n // Input Format 12:00\n var error = {}\n \n if (! /[0-2]?\\d:[0-5]\\d/.test(input)){\n error.topic = \"Error with the time\"\n error.payload = \"The date should respect the ISO format HH:MM\"\n return [null, error]\n }\n else {\n var time = input.match(/\\d+/g)\n \n if (!((0 <= time[0]) && (time[0] < 24))){\n error.topic = \"Error with the time\"\n error.payload = \"The hours should be 0 and 23.\"\n return [null, error]\n }\n else if (!((0 <= time[1]) && (time[1] < 60))){\n error.topic = \"Error with the time\"\n error.payload = \"The minutes should be between 0 and 59\"\n return [null, error]\n }\n }\n return [input.replace(/:/g, ''), null]\n}\n\n\nvar ret\nvar payload_for_form = {payload:{}}\nmsg.valid = false\n\nif (msg.topic == \"culture_timestamp\"){\n ret = ValidateDate(msg.payload.object_date)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_date\", ret[0])\n \n ret = ValidateTime(msg.payload.object_time)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_time\", ret[0])\n return [{topic: \"Date and time format valid!\", payload: \"All good!\", valid: true}, payload_for_form]\n}\nelse if (msg.topic == \"net_retrieval_location\"){\n ret = ValidateCoordinates(msg.payload.object_lat_end, true);\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" Latitude\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_lat_end\", ret[0])\n ret = ValidateCoordinates(msg.payload.object_lon_end, false)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" Longitude\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_lon_end\", ret[0]);\n \n ret = ValidateDate(msg.payload.object_date_end)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample retrieval\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_date_end\", ret[0])\n \n ret = ValidateTime(msg.payload.object_time_end)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample retrieval\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_time_end\", ret[0])\n}\nelse{\n ret = ValidateCoordinates(msg.payload.object_lat, true);\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" Latitude\";\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_lat\", ret[0]);\n payload_for_form.payload[\"object_lat_end\"] = msg.payload.object_lat;\n \n ret = ValidateCoordinates(msg.payload.object_lon, false);\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" Longitude\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_lon\", ret[0])\n payload_for_form.payload[\"object_lon_end\"] = msg.payload.object_lon;\n\n ret = ValidateDate(msg.payload.object_date)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_date\", ret[0])\n payload_for_form.payload[\"object_date_end\"] = msg.payload.object_date;\n \n ret = ValidateTime(msg.payload.object_time)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_time\", ret[0])\n payload_for_form.payload[\"object_time_end\"] = msg.payload.object_time;\n}\nreturn [{topic: \"Coordinates valid!\", payload: \"All good!\", valid: true}, payload_for_form]\n", + "outputs": 2, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 930, + "y": 620, + "wires": [["c0ce5626.b6c5", "9a18a4b4.178448"], ["56d40584.eff4e4"]], + "inputLabels": ["Location form data"], + "outputLabels": ["Message", "Location validated"] + }, + { + "id": "46eb1bf8.3dc5f4", + "type": "function", + "z": "b771c342.49603", + "name": "Net check", + "func": "var decknet = {}\nvar activation_msg = {}\n\nif (msg.payload.startsWith(\"net_decknet\")){\n decknet.enabled = true;\n}\nelse {\n decknet.enabled = false;\n}\n\nif (msg.payload.startsWith(\"net\")){\n activation_msg.payload = {\"group\":{\"show\":[\"Sample_Net_Metadata\"],\"hide\":[\"Sample_Sample_Location\",\"Sample_Culture_Date_and_Time\"]}};\n}\nelse if (msg.payload != \"culture\" && msg.payload != \"test\"){\n activation_msg.payload = {\"group\":{\"show\":[\"Sample_Sample_Location\"], \"hide\":[\"Sample_Net_Metadata\",\"Sample_Culture_Date_and_Time\"]}};\n}\n\n\nreturn [decknet, activation_msg];", + "outputs": 2, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 1080, + "y": 240, + "wires": [ + ["516375fd.2ed61c", "470e382a.25691", "fbe32ac8.ff6a38"], + ["cbb123ab.fd3428"] + ], + "outputLabels": ["decknet activation", "group display control"] + }, + { + "id": "516375fd.2ed61c", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "sample_total_flowmeter_start", + "label": "Decknet flowmeter start", + "tooltip": "in L", + "group": "cf5d9f0e.d57e7", + "order": 6, + "width": 5, + "height": 1, + "passthru": false, + "mode": "text", + "delay": "300", + "topic": "sample_total_flowmeter_start", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 1340, + "y": 220, + "wires": [["e9bc112c.eb75f8"]] + }, + { + "id": "470e382a.25691", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "sample_total_flowmeter_end", + "label": "Decknet flowmeter end", + "tooltip": "in L", + "group": "cf5d9f0e.d57e7", + "order": 7, + "width": 5, + "height": 1, + "passthru": false, + "mode": "text", + "delay": "300", + "topic": "sample_total_flowmeter_end", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 1340, + "y": 260, + "wires": [["e9bc112c.eb75f8"]] + }, + { + "id": "fbe32ac8.ff6a38", + "type": "ui_template", + "z": "b771c342.49603", + "group": "cf5d9f0e.d57e7", + "name": "Decknet flowmeter read", + "order": 5, + "width": 10, + "height": 1, + "format": "
\n

Decknet flowmeter readings

\n

Those values are used to calculate sample_total_volume. Values are in L.

\n
\n", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": true, + "templateScope": "local", + "x": 1330, + "y": 180, + "wires": [[]] + }, + { + "id": "f408a273.4fb538", + "type": "function", + "z": "b771c342.49603", + "name": "get sample_gear_net_opening", + "func": "if (msg.payload.sample_gear_net_opening === null){\n msg.payload = 0;\n global.set(\"sample_gear_net_opening\",msg.payload);\n}\nelse\n{\n msg.payload = msg.payload.sample_gear_net_opening;\n}\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 350, + "y": 320, + "wires": [["e967b844.46aa48"]] + }, + { + "id": "8dff1648.82e42", + "type": "function", + "z": "b771c342.49603", + "name": "get object_depth_max", + "func": "if (msg.payload.object_depth_max === null){\n msg.payload = 0;\n global.set(\"object_depth_max\",msg.payload);\n}\nelse\n{\n msg.payload = msg.payload.object_depth_max;\n}\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 320, + "y": 240, + "wires": [["9c7f7fc9.c8d3a"]] + }, + { + "id": "9f04c5ec.75f3d8", + "type": "function", + "z": "b771c342.49603", + "name": "get object_depth_min", + "func": "if (msg.payload.object_depth_min === null){\n msg.payload = 0;\n global.set(\"object_depth_min\",msg.payload);\n}\nelse\n{\n msg.payload = msg.payload.object_depth_min;\n}\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 320, + "y": 280, + "wires": [["317eeeb7.8d3042"]] + }, + { + "id": "9a18a4b4.178448", + "type": "function", + "z": "b771c342.49603", + "name": "calculate sample_total_volume", + "func": "\n/*object_lat = 33.95 \nobject_lon = 118.4 \nobject_lat_end = 40.6333 \nobject_lon_end = 73.78333\nsample_gear_net_opening = 40*/\n\n// Copyright 1997 Ed Williams. All rights reserved\n// Adapted by Romain Bazile - Ocean Trotter - 01-2021\n\ndecpl=4 // Dec places of minutes output\n\nellipse = {\"name\":\"WSG84\", \"a\":6378.137/1.852, \"invf\":298.257223563}\n\nfunction ComputeDistance(lat1, lon1, lat2, lon2){\n var d,crs12,crs21\n var argacos\n var a,invf\n \n // lat and lon in radian\n lat1=(Math.PI/180)*lat1\n lat2=(Math.PI/180)*lat2\n lon1=(Math.PI/180)*lon1\n lon2=(Math.PI/180)*lon2\n \n //alert(\"lat1=\" + lat1 + \"lon1=\" + lon1 +\"\\nlat2=\" +lat2+ \"lon2=\"+lon2)\n \n /* get distance conversion factor */\n dc=1.852 //km\n //alert(\"dc=\" +dc)\n \n //showProps(ellipse,\"ellipse\")\n \n // elliptic code\n d=crsdist_ell(lat1,-lon1,lat2,-lon2,ellipse) // ellipse uses East negative\n d=d*dc // go to physical units\n \n //alert(\"d=\"+d+\" crs12=\"+crs12+\" crs21=\"+crs21)\n return d\n}\n\nfunction crsdist(lat1,lon1,lat2,lon2){ // radian args\n /* compute course and distance (spherical) */\n if ((lat1+lat2===0) && (Math.abs(lon1-lon2)==Math.PI) && \n (Math.abs(lat1) != (Math.PI/180)*90)){\t\n \talert(\"Course between antipodal points is undefined\")\n }\n \n d = Math.acos(Math.sin(lat1)*Math.sin(lat2)+Math.cos(lat1)*Math.cos(lat2)*Math.cos(lon1-lon2))\n return d\n}\n\nfunction crsdist_ell(glat1,glon1,glat2,glon2,ellipse){\n // glat1 initial geodetic latitude in radians N positive \n // glon1 initial geodetic longitude in radians E positive \n // glat2 final geodetic latitude in radians N positive \n // glon2 final geodetic longitude in radians E positive \n a=ellipse.a\n f=1/ellipse.invf\n //alert(\"a=\"+a+\" f=\"+f)\n var r, tu1, tu2, cu1, su1, cu2, s1, b1, f1\n var x, sx, cx, sy, cy,y, sa, c2a, cz, e, c, d\n var EPS= 0.00000000005\n var faz, baz, s\n var iter=1\n var MAXITER=100\n if ((glat1+glat2===0) && (Math.abs(glon1-glon2)==Math.PI)){\n alert(\"Course and distance between antipodal points is undefined\")\n glat1=glat1+0.00001 // allow algorithm to complete\n }\n if (glat1==glat2 && (glon1==glon2 || Math.abs(Math.abs(glon1-glon2)-2*Math.PI) < EPS)){\n alert(\"Points 1 and 2 are identical- course undefined\")\n out=new MakeArray(0)\n out.d=0\n out.crs12=0\n out.crs21=Math.PI\n return out\n }\n r = 1 - f\n tu1 = r * Math.tan (glat1)\n tu2 = r * Math.tan (glat2)\n cu1 = 1 / Math.sqrt (1 + tu1 * tu1)\n su1 = cu1 * tu1\n cu2 = 1 / Math.sqrt (1 + tu2 * tu2)\n s1 = cu1 * cu2\n b1 = s1 * tu2\n f1 = b1 * tu1\n x = glon2 - glon1\n d = x + 1 // force one pass\n while ((Math.abs(d - x) > EPS) && (iter < MAXITER))\n {\n iter=iter+1\n sx = Math.sin (x)\n // alert(\"sx=\"+sx)\n cx = Math.cos (x)\n tu1 = cu2 * sx\n tu2 = b1 - su1 * cu2 * cx\n sy = Math.sqrt(tu1 * tu1 + tu2 * tu2)\n cy = s1 * cx + f1\n y = atan2 (sy, cy)\n sa = s1 * sx / sy\n c2a = 1 - sa * sa\n cz = f1 + f1\n if (c2a > 0)\n cz = cy - cz / c2a\n e = cz * cz * 2 - 1\n c = ((-3 * c2a + 4) * f + 4) * c2a * f / 16\n d = x\n x = ((e * cy * c + cz) * sy * c + y) * sa\n x = (1 - c) * x * f + glon2 - glon1\n }\n x = Math.sqrt ((1 / (r * r) - 1) * c2a + 1)\n x +=1\n x = (x - 2) / x\n c = 1 - x\n c = (x * x / 4 + 1) / c\n d = (0.375 * x * x - 1) * x\n x = e * cy\n d = ((((sy*sy*4-3)*(1-e-e)*cz*d/6-x)*d/4+cz)*sy*d+y)*c*a*r\n if (Math.abs(iter-MAXITER)0) && (y>=0)){ out= Math.atan(y/x)}\n if ((x >0) && (y<0)) { out= Math.atan(y/x)+2*Math.PI}\n if ((x===0) && (y>0)) { out= Math.PI/2}\n if ((x===0) && (y<0)) { out= 3*Math.PI/2} \n if ((x===0) && (y===0)) {\n alert(\"atan2(0,0) undefined\")\n out= 0\n } \n return out\n}\n\nfunction showProps(obj,objName){\n var result=\"\"\n for (var i in obj){\n result +=objName + \".\" + i + \" = \" + obj[i] + \"\\n\"\n }\n alert(result)\n}\n\n\nif (msg.valid){\n msg.topic=\"sample_total_volume\"\n \n var object_lat_end = global.get(\"object_lat_end\")\n var object_lon_end = global.get(\"object_lon_end\")\n var sample_sampling_gear = global.get(\"sample_sampling_gear\")\n \n if (sample_sampling_gear.startsWith(\"net\") && sample_sampling_gear != \"net_decknet\") {\n if (!(isNaN(object_lat_end) && isNaN(object_lon_end))){\n var object_lat = global.get(\"object_lat\")\n var object_lon = global.get(\"object_lon\")\n var sample_gear_net_opening = global.get(\"sample_gear_net_opening\");\n\n distance_km = ComputeDistance(object_lat, object_lon, object_lat_end, object_lon_end)\n\n sample_total_volume = distance_km*(Math.PI*(sample_gear_net_opening/2)*(sample_gear_net_opening/2)) // liters\n sample_total_volume = Math.round(sample_total_volume + Number.EPSILON)\n msg.payload = sample_total_volume\n return msg\n }\n }\n}", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 930, + "y": 760, + "wires": [["4f6afc5a.81e454"]] + }, + { + "id": "e73fd87d.d24e4", + "type": "function", + "z": "b771c342.49603", + "name": "get acq_minimum_mesh", + "func": "msg.payload = msg.payload.acq_minimum_mesh;\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 330, + "y": 360, + "wires": [["1aad56b31b5647ce"]] + }, + { + "id": "489c8e06.cc7d6", + "type": "function", + "z": "b771c342.49603", + "name": "get acq_maximum_mesh", + "func": "msg.payload = msg.payload.acq_maximum_mesh;\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 330, + "y": 400, + "wires": [["10eb31a2d7a6590c"]] + }, + { + "id": "58de1340.3cc354", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "sample_dilution_factor", + "label": "Concentration Factor", + "tooltip": "0.5 if diluted by two; 2 if concentrated by a factor 2", + "group": "3e1ba03d.f01d8", + "order": 13, + "width": 10, + "height": 1, + "passthru": true, + "mode": "number", + "delay": "300", + "topic": "sample_dilution_factor", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 640, + "y": 480, + "wires": [["9f501f49.45645"]] + }, + { + "id": "4f6afc5a.81e454", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "sample_total_volume", + "label": "Filtered volume (in L)", + "tooltip": "Calculated or hand filled", + "group": "3e1ba03d.f01d8", + "order": 11, + "width": 0, + "height": 0, + "passthru": true, + "mode": "text", + "delay": "300", + "topic": "sample_total_volume", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 1220, + "y": 760, + "wires": [["e1f2f6eb.fe1dd"]] + }, + { + "id": "e1f2f6eb.fe1dd", + "type": "function", + "z": "b771c342.49603", + "name": "set global", + "func": "global.set(msg.topic,msg.payload);", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 1420, + "y": 760, + "wires": [[]] + }, + { + "id": "e9bc112c.eb75f8", + "type": "function", + "z": "b771c342.49603", + "name": "Calculate volume", + "func": "if (msg.topic == \"sample_total_flowmeter_start\"){\n context.set(\"sample_total_flowmeter_start\", msg.payload);\n}\nif (msg.topic == \"sample_total_flowmeter_end\"){\n context.set(\"sample_total_flowmeter_end\", msg.payload);\n}\n\nif (context.keys().length == 2){\n sample_total_volume = context.get(\"sample_total_flowmeter_end\") - context.get(\"sample_total_flowmeter_start\");\n msg.topic=\"sample_total_volume\"\n msg.payload=sample_total_volume\n return msg\n}\n", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 1610, + "y": 240, + "wires": [["4f6afc5a.81e454"]] + }, + { + "id": "cdd4181922eecf11", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "sample_speed_through_water", + "label": "Speed Through Water (kts)", + "tooltip": "in knots", + "group": "cf5d9f0e.d57e7", + "order": 2, + "width": 10, + "height": 1, + "passthru": true, + "mode": "number", + "delay": "300", + "topic": "sample_speed_through_water", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 610, + "y": 520, + "wires": [["9f501f49.45645"]] + }, + { + "id": "1aad56b31b5647ce", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "acq_minimum_mesh", + "label": "Minimal fraction size (μm)", + "tooltip": "Net mesh pore size or minimal filtration mesh pore size", + "group": "3e1ba03d.f01d8", + "order": 7, + "width": 5, + "height": 1, + "passthru": true, + "mode": "number", + "delay": "300", + "topic": "acq_minimum_mesh", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 640, + "y": 360, + "wires": [["9f501f49.45645"]] + }, + { + "id": "10eb31a2d7a6590c", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "acq_maximum_mesh", + "label": "Maximal fraction size (μm)", + "tooltip": "Maximal filtration mesh pore size", + "group": "3e1ba03d.f01d8", + "order": 8, + "width": 5, + "height": 1, + "passthru": true, + "mode": "number", + "delay": "300", + "topic": "acq_maximum_mesh", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 640, + "y": 400, + "wires": [["9f501f49.45645"]] + }, + { + "id": "3ac7b631f5d8ef90", + "type": "function", + "z": "b771c342.49603", + "name": "Culture check", + "func": "var activation_msg = {}\nvar date_msg = {}\nvar timestamp=new Date().toISOString();\n\nif (msg.payload === \"culture\"){\n activation_msg.payload = {\"group\":{\"show\":[\"Sample_Culture_Date_and_Time\"],\"hide\":[\"Sample_Sample_Location\", \"Sample_Net_Metadata\"]}};\n global.set(\"object_lat\", \"-90.0000\")\n global.set(\"object_lon\", \"0.0000\")\n date_msg.payload = {\"object_date\": timestamp.split('T')[0],\n \"object_time\": timestamp.split('T')[1].split('.')[0]}\n return [activation_msg, date_msg];\n}\nelse if (msg.payload === \"test\"){\n activation_msg.payload = {\"group\":{\"hide\":[\"Sample_Culture_Date_and_Time\", \"Sample_Sample_Location\", \"Sample_Net_Metadata\"]}};\n global.set(\"object_lat\", \"-90.0000\")\n global.set(\"object_lon\", \"0.0000\")\n global.set(\"object_date\", timestamp.split('T')[0])\n global.set(\"object_time\", timestamp.split('T')[1].split('.')[0])\n return [activation_msg, null];\n}\nelse{\n return [null, null]\n}\n\n", + "outputs": 2, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 1100, + "y": 320, + "wires": [["cbb123ab.fd3428"], ["05c6aff2afbd69cf"]], + "outputLabels": ["decknet activation", ""] + }, + { + "id": "05c6aff2afbd69cf", + "type": "ui_form", + "z": "b771c342.49603", + "name": "culture_timestamp", + "label": "Culture timestamp", + "group": "7bc0a4c416e4545c", + "order": 1, + "width": 0, + "height": 0, + "options": [ + { + "label": "Date (YYYY-MM-DD, UTC)", + "value": "object_date", + "type": "text", + "required": true, + "rows": null + }, + { + "label": "Time (HH:MM(:SS), UTC 24h)", + "value": "object_time", + "type": "text", + "required": true, + "rows": null + } + ], + "formValue": { + "object_date": "", + "object_time": "" + }, + "payload": "", + "submit": "Validate", + "cancel": "Reset", + "topic": "culture_timestamp", + "topicType": "str", + "splitLayout": false, + "className": "", + "x": 650, + "y": 700, + "wires": [["14658615.47c862", "f8044c35996322e6"]] + }, + { + "id": "a9fb1f4b83fc25a7", + "type": "change", + "z": "b771c342.49603", + "name": "Repopulate input fields", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 400, + "y": 580, + "wires": [["c33f1124.af6688"]] + }, + { + "id": "ad54b89540460d27", + "type": "change", + "z": "b771c342.49603", + "name": "Repopulate input fields", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 400, + "y": 620, + "wires": [["358908cd.416ab"]] + }, + { + "id": "c21bf0244e67e40a", + "type": "change", + "z": "b771c342.49603", + "name": "Repopulate input fields", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 400, + "y": 660, + "wires": [["56d40584.eff4e4"]] + }, + { + "id": "f8044c35996322e6", + "type": "change", + "z": "b771c342.49603", + "name": "Repopulate input fields", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 400, + "y": 700, + "wires": [["05c6aff2afbd69cf"]] + }, + { + "id": "8b48a02877b7b6d6", + "type": "inject", + "z": "b771c342.49603", + "name": "", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "payload": "1", + "payloadType": "num", + "x": 270, + "y": 480, + "wires": [["58de1340.3cc354"]] + }, + { + "id": "6a84252a.d52a0c", + "type": "ui_template", + "z": "bccd1f23.87219", + "group": "833bc5bb.217ba8", + "name": "Stream Pi Camera", + "order": 1, + "width": 18, + "height": 14, + "format": "
\n \"If\n
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "className": "", + "x": 610, + "y": 40, + "wires": [[]] + }, + { + "id": "dc48dc42.98d18", + "type": "function", + "z": "bccd1f23.87219", + "name": "set global", + "func": "global.set(msg.topic,msg.payload);", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 880, + "y": 440, + "wires": [[]] + }, + { + "id": "811cd88c.daf528", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "down", + "group": "fbd92986.1028c8", + "order": 8, + "width": 4, + "height": 1, + "passthru": true, + "label": "", + "tooltip": "", + "color": "", + "bgcolor": "", + "icon": "fa-angle-double-down fa-3x", + "payload": "DOWN", + "payloadType": "str", + "topic": "actuator/focus", + "x": 550, + "y": 800, + "wires": [["65ad39d.b6d4d48"]] + }, + { + "id": "edda4df4.76de2", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "up", + "group": "fbd92986.1028c8", + "order": 1, + "width": 4, + "height": 1, + "passthru": false, + "label": "", + "tooltip": "", + "color": "", + "bgcolor": "", + "icon": "fa-angle-double-up fa-3x", + "payload": "UP", + "payloadType": "str", + "topic": "actuator/focus", + "x": 550, + "y": 760, + "wires": [["65ad39d.b6d4d48"]] + }, + { + "id": "68962547.34a67c", + "type": "ui_text_input", + "z": "bccd1f23.87219", + "name": "pump_manual_volume", + "label": "Volume to pass (ml)", + "tooltip": "Tiny values are accepted down to 0.001mL", + "group": "707d9797.c8e798", + "order": 3, + "width": 2, + "height": 1, + "passthru": true, + "mode": "text", + "delay": "300", + "topic": "pump_manual_volume", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 600, + "y": 420, + "wires": [["dc48dc42.98d18"]] + }, + { + "id": "6c792043.b6ff9", + "type": "ui_ui_control", + "z": "bccd1f23.87219", + "name": "", + "events": "change", + "x": 560, + "y": 1140, + "wires": [[]] + }, + { + "id": "902429eb.ceacb8", + "type": "ui_toast", + "z": "bccd1f23.87219", + "position": "dialog", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 1, + "ok": "OK", + "cancel": "", + "raw": false, + "topic": "", + "name": "", + "x": 570, + "y": 1220, + "wires": [[]] + }, + { + "id": "fe840e05.b46f3", + "type": "function", + "z": "bccd1f23.87219", + "name": "Check form", + "func": "var acq_fnumber_objective= global.get(\"acq_fnumber_objective\");\n\nif (acq_fnumber_objective === undefined || acq_fnumber_objective === \"\") {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Focal Length of the objective\";\n return [null, msg];\n}\n\nmsg.topic = \"Change Tab\";\nmsg.payload={\"tab\":\"Fluidic Acquisition\"};\nreturn [msg, null];", + "outputs": 2, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 330, + "y": 1180, + "wires": [["6c792043.b6ff9", "326a1d95.ca21aa"], ["902429eb.ceacb8"]], + "outputLabels": ["message", "error"] + }, + { + "id": "5846b1d4.7971b", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "Backward", + "group": "707d9797.c8e798", + "order": 2, + "width": 1, + "height": 1, + "passthru": false, + "label": "", + "tooltip": "", + "color": "", + "bgcolor": "", + "icon": "fa-rotate-left fa-2x", + "payload": "BACKWARD", + "payloadType": "str", + "topic": "actuator/pump", + "x": 560, + "y": 280, + "wires": [["3cb96380.e575ec"]] + }, + { + "id": "2cab680b.baf888", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "Forward", + "group": "707d9797.c8e798", + "order": 4, + "width": 1, + "height": 1, + "passthru": true, + "label": "", + "tooltip": "", + "color": "", + "bgcolor": "", + "icon": "fa-rotate-right fa-2x", + "payload": "FORWARD", + "payloadType": "str", + "topic": "actuator/pump", + "x": 560, + "y": 320, + "wires": [["3cb96380.e575ec"]] + }, + { + "id": "8038414a.34461", + "type": "function", + "z": "bccd1f23.87219", + "name": "Calculate optics", + "func": "var acq_fnumber_objective = String(global.get(\"acq_fnumber_objective\"));\nvar acq_camera = global.get(\"acq_camera\")\n\n// Those values needs to be recalculated, they are not good!\nif (acq_camera == \"HQ Camera\"){\n switch(acq_fnumber_objective) {\n case \"25\":\n acq_magnification= 0.6;\n process_pixel= 1.56;\n sug_min= 60;\n sug_max= 670;\n sug_flowrate= 3;\n break;\n case \"16\":\n acq_magnification= 1.6;\n process_pixel= 1.01;\n sug_min= 40;\n sug_max= 430;\n sug_flowrate= 2.4;\n break;\n case \"12\":\n acq_magnification= 1.20;\n process_pixel= 0.79;\n sug_min= 30;\n sug_max= 340;\n sug_flowrate= 1.25;\n break;\n case \"8\":\n acq_magnification= 1.78;\n process_pixel= 0.53;\n sug_min= 20;\n sug_max= 230;\n sug_flowrate= 0.42;\n break;\n case \"6\":\n acq_magnification= 2.36;\n process_pixel= 0.41;\n sug_min= 15;\n sug_max= 170;\n sug_flowrate= 0.32;\n break;\n }\n}\nelse if (acq_camera == \"Camera v2.1\"){\n switch(acq_fnumber_objective) {\n case \"25\":\n acq_magnification= 0.6;\n process_pixel= 1.86;\n sug_min= 60;\n sug_max= 670;\n sug_flowrate= 3;\n break;\n case \"16\":\n acq_magnification= 1.6;\n process_pixel= 0.7;\n sug_min= 40;\n sug_max= 430;\n sug_flowrate= 2.4;\n break;\n case \"12\":\n acq_magnification= 1.20;\n process_pixel= 0.94;\n sug_min= 30;\n sug_max= 340;\n sug_flowrate= 1.25;\n break;\n case \"8\":\n acq_magnification= 1.78;\n process_pixel= 0.63;\n sug_min= 20;\n sug_max= 230;\n sug_flowrate= 0.42;\n break;\n case \"6\":\n acq_magnification= 2.36;\n process_pixel= 0.48;\n sug_min= 15;\n sug_max= 170;\n sug_flowrate= 0.32;\n break;\n }\n}else {\n acq_magnification= \"ERROR\";\n process_pixel= \"ERROR\";\n sug_min= \"ERROR\";\n sug_max= \"ERROR\";\n sug_flowrate= \"ERROR\";\n}\n\nvar process_pixel_fixed = global.get(\"process_pixel_fixed\")\n\nif (process_pixel_fixed !== undefined && process_pixel_fixed !== \"\") {\n process_pixel = process_pixel_fixed\n}\n\nglobal.set(\"process_pixel\",process_pixel);\n\nglobal.set(\"acq_magnification\",acq_magnification);\n\n\nreturn [{payload: acq_fnumber_objective}, {payload: acq_magnification}, {payload: process_pixel}, {payload: sug_min}, {payload: sug_max}];", + "outputs": 5, + "timeout": "", + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 1080, + "y": 120, + "wires": [[], [], [], [], []], + "inputLabels": ["acq_fnumber_objective"], + "outputLabels": [ + "acq_magnification", + "process_pixel", + "sug_min", + "sug_max", + "" + ] + }, + { + "id": "f61aaed5.1e64", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "", + "group": "7a0b4877.a5d268", + "order": 1, + "width": 2, + "height": 1, + "passthru": false, + "label": "Previous", + "tooltip": "", + "color": "#097479", + "bgcolor": "white", + "icon": "keyboard_return", + "payload": "{\"tab\":\"Sample\"}", + "payloadType": "json", + "topic": "", + "x": 140, + "y": 1140, + "wires": [["6c792043.b6ff9"]] + }, + { + "id": "9ba6ec0a.22c96", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "", + "group": "7a0b4877.a5d268", + "order": 2, + "width": 2, + "height": 1, + "passthru": false, + "label": "Continue", + "tooltip": "", + "color": "#097479", + "bgcolor": "white", + "icon": "keyboard_tab", + "payload": "{\"tab\":\"Home\"}", + "payloadType": "json", + "topic": "", + "x": 140, + "y": 1180, + "wires": [["fe840e05.b46f3"]] + }, + { + "id": "3cb96380.e575ec", + "type": "function", + "z": "bccd1f23.87219", + "name": "pump", + "func": "var manual_volume= global.get(\"pump_manual_volume\");\nvar flowrate= global.get(\"pump_flowrate\");\n\nif (manual_volume === undefined || manual_volume === \"\" || manual_volume === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Volume to pass\";\n return [null, msg];\n}\nelse if (flowrate === undefined || flowrate === \"\" || flowrate === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Flowrate\";\n return [null, msg];\n}\nelse {\n msg.topic = \"actuator/pump\";\n // msg.payload is FORWARD or BACKWARD here\n msg.payload={\"action\":\"move\", \n \"direction\":msg.payload,\n \"volume\":manual_volume,\n \"flowrate\":flowrate};\n}\nreturn [msg, null];", + "outputs": 2, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 750, + "y": 300, + "wires": [["bdc8ce57.de1f08"], ["8bcce348.efc1a"]], + "inputLabels": ["direction"], + "outputLabels": ["message", "error"] + }, + { + "id": "8bcce348.efc1a", + "type": "ui_toast", + "z": "bccd1f23.87219", + "position": "dialog", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 1, + "ok": "OK", + "cancel": "", + "raw": false, + "topic": "", + "name": "", + "x": 1090, + "y": 300, + "wires": [[]] + }, + { + "id": "bdc8ce57.de1f08", + "type": "mqtt out", + "z": "bccd1f23.87219", + "name": "", + "topic": "", + "qos": "", + "retain": "", + "broker": "8dc3722c.06efa8", + "x": 1210, + "y": 260, + "wires": [] + }, + { + "id": "d71d224f.0585d8", + "type": "ui_toast", + "z": "bccd1f23.87219", + "position": "dialog", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 1, + "ok": "OK", + "cancel": "", + "raw": false, + "topic": "", + "name": "", + "x": 1090, + "y": 800, + "wires": [[]] + }, + { + "id": "65ad39d.b6d4d48", + "type": "function", + "z": "bccd1f23.87219", + "name": "focus", + "func": "var distance = global.get(\"focus_distance\");\nvar speed = global.get(\"focus_speed\");\n\nif (distance === undefined || distance === \"\" || distance === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Distance\";\n return [null, msg]\n}\nif (speed === undefined || speed === \"\" || speed === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Speed\";\n return [null, msg]\n}\n// msg.payload is UP or DOWN here\nmsg.payload={\"action\":\"move\", \n \"direction\":msg.payload,\n \"distance\":(distance/1000),\n \"speed\": (speed/1000)\n};\nreturn [msg, null];", + "outputs": 2, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 850, + "y": 780, + "wires": [["62030521.88317c"], ["d71d224f.0585d8"]], + "inputLabels": ["direction"], + "outputLabels": ["message", "error"] + }, + { + "id": "1962d999.4a97e6", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "stop focus", + "group": "fbd92986.1028c8", + "order": 9, + "width": 0, + "height": 0, + "passthru": true, + "label": " STOP FOCUS", + "tooltip": "", + "color": "", + "bgcolor": "#AD1625", + "icon": "fa-pause fa-2x", + "payload": "{\"action\":\"stop\"}", + "payloadType": "json", + "topic": "actuator/focus", + "x": 570, + "y": 560, + "wires": [["62030521.88317c"]] + }, + { + "id": "62030521.88317c", + "type": "mqtt out", + "z": "bccd1f23.87219", + "name": "", + "topic": "", + "qos": "", + "retain": "", + "broker": "8dc3722c.06efa8", + "x": 1210, + "y": 720, + "wires": [] + }, + { + "id": "3bd43039.bc5fb8", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "", + "group": "fbd92986.1028c8", + "order": 2, + "width": 4, + "height": 1, + "passthru": false, + "label": "UP 1mm", + "tooltip": "", + "color": "", + "bgcolor": "", + "icon": "fa-angle-up fa-3x", + "payload": "{\"action\":\"move\",\"direction\":\"UP\",\"distance\":1}", + "payloadType": "json", + "topic": "actuator/focus", + "topicType": "str", + "x": 560, + "y": 600, + "wires": [["62030521.88317c"]] + }, + { + "id": "c0663029.2d03b", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "", + "group": "fbd92986.1028c8", + "order": 7, + "width": 4, + "height": 1, + "passthru": false, + "label": "DOWN 1mm", + "tooltip": "", + "color": "", + "bgcolor": "", + "icon": "fa-angle-down fa-3x", + "payload": "{\"action\":\"move\",\"direction\":\"DOWN\",\"distance\":1}", + "payloadType": "json", + "topic": "actuator/focus", + "topicType": "str", + "x": 570, + "y": 720, + "wires": [["62030521.88317c"]] + }, + { + "id": "71f55a58.d7eaf4", + "type": "inject", + "z": "bccd1f23.87219", + "name": "Default: 500µm", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": "0.5", + "topic": "", + "payload": "500", + "payloadType": "num", + "x": 120, + "y": 460, + "wires": [["be33e564.029358"]] + }, + { + "id": "9a1d0e7c.2d5a1", + "type": "inject", + "z": "bccd1f23.87219", + "name": "Default: OFF", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "payload": "off", + "payloadType": "str", + "x": 130, + "y": 120, + "wires": [["f0775525.cf806"]] + }, + { + "id": "f782a471.447748", + "type": "inject", + "z": "bccd1f23.87219", + "name": "Default: 2mL/min", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": "0.5", + "topic": "", + "payload": "2", + "payloadType": "num", + "x": 130, + "y": 380, + "wires": [["cb2d5174.cfe9f"]] + }, + { + "id": "73b8252a.5ca754", + "type": "inject", + "z": "bccd1f23.87219", + "name": "Default: 2mL", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": "0.5", + "topic": "", + "payload": "2", + "payloadType": "num", + "x": 110, + "y": 420, + "wires": [["68962547.34a67c"]] + }, + { + "id": "6451f991.aaac1", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "stop pump", + "group": "707d9797.c8e798", + "order": 5, + "width": 4, + "height": 1, + "passthru": true, + "label": " STOP PUMP", + "tooltip": "", + "color": "", + "bgcolor": "#AD1625", + "icon": "fa-pause fa-2x", + "payload": "{\"action\":\"stop\"}", + "payloadType": "json", + "topic": "actuator/pump", + "x": 570, + "y": 240, + "wires": [["bdc8ce57.de1f08"]] + }, + { + "id": "cfc783d7.d6ceb", + "type": "link in", + "z": "bccd1f23.87219", + "name": "Optics recalculation", + "links": ["559a8085.1d6b9", "5d5ad36d2c50dcc2"], + "x": 915, + "y": 120, + "wires": [["8038414a.34461"]] + }, + { + "id": "326a1d95.ca21aa", + "type": "subflow:1c24ad9c.bebec2", + "z": "bccd1f23.87219", + "name": "", + "x": 550, + "y": 1180, + "wires": [[]] + }, + { + "id": "2d371e59.b0e50a", + "type": "inject", + "z": "bccd1f23.87219", + "name": "Default: 1000µm/s", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": "0.5", + "topic": "", + "payload": "1000", + "payloadType": "num", + "x": 130, + "y": 500, + "wires": [["3a86de51.765b9a"]] + }, + { + "id": "167cda35.c9b6ae", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "", + "group": "fbd92986.1028c8", + "order": 3, + "width": 4, + "height": 1, + "passthru": false, + "label": "UP 100um", + "tooltip": "", + "color": "", + "bgcolor": "", + "icon": "fa-angle-up fa-3x", + "payload": "{\"action\":\"move\",\"direction\":\"UP\",\"distance\":0.1}", + "payloadType": "json", + "topic": "actuator/focus", + "topicType": "str", + "x": 570, + "y": 640, + "wires": [["62030521.88317c"]] + }, + { + "id": "72a7c597.9374fc", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "", + "group": "fbd92986.1028c8", + "order": 6, + "width": 4, + "height": 1, + "passthru": false, + "label": "DOWN 100um", + "tooltip": "", + "color": "", + "bgcolor": "", + "icon": "fa-angle-down fa-3x", + "payload": "{\"action\":\"move\",\"direction\":\"DOWN\",\"distance\":0.1}", + "payloadType": "json", + "topic": "actuator/focus", + "topicType": "str", + "x": 580, + "y": 680, + "wires": [["62030521.88317c"]] + }, + { + "id": "f0775525.cf806", + "type": "ui_multistate_switch", + "z": "bccd1f23.87219", + "name": "light_control", + "group": "4248342d.e55fac", + "order": 1, + "width": 6, + "height": 1, + "label": "Light ", + "stateField": "payload", + "enableField": "enable", + "passthroughField": "passthrough", + "inputMsgField": "inputmsg", + "rounded": true, + "useThemeColors": true, + "hideSelectedLabel": false, + "multilineLabel": false, + "passThrough": "never", + "inputMsg": "all", + "userInput": "enabled_show", + "options": [ + { + "label": "Off", + "value": "off", + "valueType": "str", + "color": "#009933" + }, + { + "label": "On", + "value": "on", + "valueType": "str", + "color": "#999999" + } + ], + "topic": "", + "x": 310, + "y": 120, + "wires": [["99ae4886.8d43c"]] + }, + { + "id": "99ae4886.8d43c", + "type": "function", + "z": "bccd1f23.87219", + "name": "Prepare message", + "func": "msg.topic = \"light\"\nmsg.payload = {\"action\":msg.payload}\n\nreturn msg;", + "outputs": 1, + "timeout": "", + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 490, + "y": 120, + "wires": [["d31fcead.7e2ef"]] + }, + { + "id": "d31fcead.7e2ef", + "type": "mqtt out", + "z": "bccd1f23.87219", + "name": "", + "topic": "", + "qos": "", + "retain": "", + "respTopic": "", + "contentType": "", + "userProps": "", + "correl": "", + "expiry": "", + "broker": "8dc3722c.06efa8", + "x": 650, + "y": 120, + "wires": [] + }, + { + "id": "8ea9dc9a.c7d87", + "type": "function", + "z": "bccd1f23.87219", + "name": "Encapsulate settings", + "func": "msg.payload = {\n \"action\":\"settings\", \n \"settings\":{[msg.topic]:msg.payload}\n}\n\nmsg.topic = \"imager/image\"\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 1120, + "y": 940, + "wires": [["845e06e1.0d812"]] + }, + { + "id": "5765a825.a595c8", + "type": "ui_slider", + "z": "bccd1f23.87219", + "name": "Shutter speed slider", + "label": "Shutter Speed", + "tooltip": "In microseconds, up to 1000µs, 125µs by default", + "group": "8c38a81e.9897a8", + "order": 4, + "width": 0, + "height": 0, + "passthru": true, + "outs": "end", + "topic": "shutter_speed", + "topicType": "str", + "min": "125", + "max": "1000", + "step": "1", + "className": "", + "x": 600, + "y": 880, + "wires": [["8ea9dc9a.c7d87"]] + }, + { + "id": "845e06e1.0d812", + "type": "mqtt out", + "z": "bccd1f23.87219", + "name": "", + "topic": "", + "qos": "", + "retain": "", + "broker": "8dc3722c.06efa8", + "x": 1390, + "y": 980, + "wires": [] + }, + { + "id": "2350e507.d4e302", + "type": "inject", + "z": "bccd1f23.87219", + "name": "Default: 125µs", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": "1", + "topic": "", + "payload": "125", + "payloadType": "num", + "x": 120, + "y": 880, + "wires": [["5765a825.a595c8"]] + }, + { + "id": "5e147425.7666ec", + "type": "function", + "z": "bccd1f23.87219", + "name": "Encapsulate wb gain settings", + "func": "msg.payload = {\n \"action\":\"settings\", \n \"settings\":{\"white_balance_gain\":{\n [msg.topic]:Math.round(msg.payload*100)\n }\n }\n}\nmsg.topic = \"imager/image\"\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 1100, + "y": 1060, + "wires": [["845e06e1.0d812"]] + }, + { + "id": "82722a3c.846b3", + "type": "inject", + "z": "bccd1f23.87219", + "name": "Default: OFF", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": "1", + "topic": "", + "payload": "false", + "payloadType": "bool", + "x": 110, + "y": 920, + "wires": [["60e44330.50bdec"]] + }, + { + "id": "60e44330.50bdec", + "type": "ui_switch", + "z": "bccd1f23.87219", + "name": "AWB", + "label": "Auto White Balance", + "tooltip": "", + "group": "8c38a81e.9897a8", + "order": 5, + "width": 2, + "height": 2, + "passthru": true, + "decouple": "false", + "topic": "white_balance", + "topicType": "str", + "style": "", + "onvalue": "auto", + "onvalueType": "str", + "onicon": "", + "oncolor": "", + "offvalue": "off", + "offvalueType": "str", + "officon": "", + "offcolor": "", + "animate": true, + "className": "", + "x": 550, + "y": 920, + "wires": [["8ea9dc9a.c7d87"]] + }, + { + "id": "6be64480.7e7e24", + "type": "change", + "z": "bccd1f23.87219", + "name": "Get red_gain", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.red_gain", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 370, + "y": 1040, + "wires": [["d5415af6.e06cc"]] + }, + { + "id": "6d49d161.13628", + "type": "change", + "z": "bccd1f23.87219", + "name": "Get blue_gain", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.blue_gain", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 380, + "y": 1080, + "wires": [["dba68c1f.e3144"]] + }, + { + "id": "56835fa1.2fe538", + "type": "subflow:4ed26b8b.253504", + "z": "bccd1f23.87219", + "name": "", + "env": [], + "x": 1160, + "y": 1020, + "wires": [] + }, + { + "id": "8ef294ba.12213", + "type": "change", + "z": "bccd1f23.87219", + "name": "Get analog_gain", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "1", + "tot": "num" + }, + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.analog_gain", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 380, + "y": 960, + "wires": [["a6c7eec4.f7a918"]] + }, + { + "id": "8e336e58.14722", + "type": "change", + "z": "bccd1f23.87219", + "name": "Get digital_gain", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "1", + "tot": "num" + }, + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.digital_gain", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 380, + "y": 1000, + "wires": [["66b37eef.f3f9e"]] + }, + { + "id": "a6c7eec4.f7a918", + "type": "ui_text_input", + "z": "bccd1f23.87219", + "d": true, + "name": "Analog gain field", + "label": "Analog Gain", + "tooltip": "From 1.0 to 12.0", + "group": "8c38a81e.9897a8", + "order": 2, + "width": 0, + "height": 0, + "passthru": true, + "mode": "number", + "delay": 300, + "topic": "analog", + "topicType": "str", + "x": 580, + "y": 960, + "wires": [["44e02933.a66688", "d361a2c4.0990f8"]] + }, + { + "id": "66b37eef.f3f9e", + "type": "ui_text_input", + "z": "bccd1f23.87219", + "d": true, + "name": "Digital gain field", + "label": "Digital Gain", + "tooltip": "From 1.0 to 64.0. Overexpose starting at 4.0", + "group": "8c38a81e.9897a8", + "order": 3, + "width": 0, + "height": 0, + "passthru": true, + "mode": "number", + "delay": 300, + "topic": "digital", + "topicType": "str", + "x": 580, + "y": 1000, + "wires": [["44e02933.a66688", "d361a2c4.0990f8"]] + }, + { + "id": "44e02933.a66688", + "type": "function", + "z": "bccd1f23.87219", + "name": "Encapsulate image gain settings", + "func": "msg.payload = {\n \"action\":\"settings\", \n \"settings\":{\"image_gain\":{\n [msg.topic]:Math.round(msg.payload*100)\n }\n }\n}\nmsg.topic = \"imager/image\"\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 1090, + "y": 980, + "wires": [["845e06e1.0d812"]] + }, + { + "id": "d361a2c4.0990f8", + "type": "change", + "z": "bccd1f23.87219", + "name": "topic *_gain", + "rules": [ + { + "t": "set", + "p": "topic", + "pt": "msg", + "to": "topic&'_gain'", + "tot": "jsonata" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 970, + "y": 1020, + "wires": [["56835fa1.2fe538"]] + }, + { + "id": "d8d006bf.2947f", + "type": "inject", + "z": "bccd1f23.87219", + "name": "Default: ISO 150", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": "1", + "topic": "", + "payload": "150", + "payloadType": "num", + "x": 130, + "y": 840, + "wires": [["f62c3241bd753f24"]] + }, + { + "id": "eb9966de.cf13c8", + "type": "change", + "z": "bccd1f23.87219", + "name": "", + "rules": [ + { + "t": "set", + "p": "topic", + "pt": "msg", + "to": "iso", + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 740, + "y": 840, + "wires": [["8ea9dc9a.c7d87"]] + }, + { + "id": "be33e564.029358", + "type": "ui_text_input", + "z": "bccd1f23.87219", + "name": "focus_distance", + "label": "Focus Distance (in µm)", + "tooltip": "in µm, 25µm resolution", + "group": "fbd92986.1028c8", + "order": 4, + "width": 0, + "height": 0, + "passthru": true, + "mode": "number", + "delay": 300, + "topic": "focus_distance", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 580, + "y": 460, + "wires": [["dc48dc42.98d18"]] + }, + { + "id": "3a86de51.765b9a", + "type": "ui_text_input", + "z": "bccd1f23.87219", + "name": "focus_speed", + "label": "Focus Speed (in µm/sec)", + "tooltip": "in µm/sec", + "group": "fbd92986.1028c8", + "order": 5, + "width": 0, + "height": 0, + "passthru": true, + "mode": "number", + "delay": 300, + "topic": "focus_speed", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 570, + "y": 500, + "wires": [["dc48dc42.98d18"]] + }, + { + "id": "cb2d5174.cfe9f", + "type": "ui_text_input", + "z": "bccd1f23.87219", + "name": "pump_flowrate", + "label": "Flowrate (ml/min)*", + "tooltip": "", + "group": "707d9797.c8e798", + "order": 1, + "width": 0, + "height": 0, + "passthru": true, + "mode": "text", + "delay": 300, + "topic": "pump_flowrate", + "topicType": "str", + "x": 580, + "y": 380, + "wires": [["dc48dc42.98d18"]] + }, + { + "id": "dba68c1f.e3144", + "type": "ui_text_input", + "z": "bccd1f23.87219", + "name": "WB Blue input", + "label": "WB: Blue", + "tooltip": "From 0.0 to 64.0", + "group": "8c38a81e.9897a8", + "order": 7, + "width": 4, + "height": 1, + "passthru": true, + "mode": "number", + "delay": "0", + "topic": "blue", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 580, + "y": 1080, + "wires": [["3ece53716a02e09e"]] + }, + { + "id": "33ef60a6a80aa3a7", + "type": "subflow:b7861ce703215a01", + "z": "bccd1f23.87219", + "name": "", + "x": 160, + "y": 1020, + "wires": [ + ["8ef294ba.12213", "8e336e58.14722", "6be64480.7e7e24", "6d49d161.13628"] + ] + }, + { + "id": "a3d034643b56796f", + "type": "inject", + "z": "bccd1f23.87219", + "name": "Once", + "props": [], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "x": 70, + "y": 1080, + "wires": [["33ef60a6a80aa3a7"]] + }, + { + "id": "5984b086eddc9311", + "type": "link in", + "z": "bccd1f23.87219", + "name": "Load hardware config", + "links": ["3973b999ee7b3b1d", "5d3df1564b9af89c"], + "x": 25, + "y": 1000, + "wires": [["33ef60a6a80aa3a7"]] + }, + { + "id": "d5415af6.e06cc", + "type": "ui_text_input", + "z": "bccd1f23.87219", + "name": "WB Red input", + "label": "WB: Red", + "tooltip": "From 0.0 to 32.0", + "group": "8c38a81e.9897a8", + "order": 6, + "width": 4, + "height": 1, + "passthru": true, + "mode": "number", + "delay": "0", + "topic": "red", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 580, + "y": 1040, + "wires": [["01c2b633558b0b02"]] + }, + { + "id": "01c2b633558b0b02", + "type": "switch", + "z": "bccd1f23.87219", + "name": "Validate", + "property": "payload", + "propertyType": "msg", + "rules": [ + { + "t": "btwn", + "v": "0.0", + "vt": "num", + "v2": "32.0", + "v2t": "num" + }, + { + "t": "else" + } + ], + "checkall": "false", + "repair": false, + "outputs": 2, + "x": 740, + "y": 1040, + "wires": [ + ["d361a2c4.0990f8", "5e147425.7666ec"], + ["cbfaf049d92be90e", "5d3df1564b9af89c"] + ] + }, + { + "id": "3ece53716a02e09e", + "type": "switch", + "z": "bccd1f23.87219", + "name": "Validate", + "property": "payload", + "propertyType": "msg", + "rules": [ + { + "t": "btwn", + "v": "0.0", + "vt": "num", + "v2": "32.0", + "v2t": "num" + }, + { + "t": "else" + } + ], + "checkall": "false", + "repair": false, + "outputs": 2, + "x": 740, + "y": 1080, + "wires": [ + ["d361a2c4.0990f8", "5e147425.7666ec"], + ["cbfaf049d92be90e", "5d3df1564b9af89c"] + ] + }, + { + "id": "cbfaf049d92be90e", + "type": "ui_toast", + "z": "bccd1f23.87219", + "position": "top right", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 0, + "ok": "OK", + "cancel": "", + "raw": false, + "className": "", + "topic": "Invalid white balance value", + "name": "", + "x": 990, + "y": 1100, + "wires": [] + }, + { + "id": "5d3df1564b9af89c", + "type": "link out", + "z": "bccd1f23.87219", + "name": "Reload hardware config", + "mode": "link", + "links": ["5984b086eddc9311"], + "x": 915, + "y": 1140, + "wires": [] + }, + { + "id": "f62c3241bd753f24", + "type": "ui_slider", + "z": "bccd1f23.87219", + "name": "ISO selector", + "label": "ISO", + "tooltip": "", + "group": "8c38a81e.9897a8", + "order": 1, + "width": 0, + "height": 0, + "passthru": true, + "outs": "end", + "topic": "topic", + "topicType": "msg", + "min": "50", + "max": "650", + "step": "50", + "className": "", + "x": 570, + "y": 840, + "wires": [["eb9966de.cf13c8"]] + }, + { + "id": "6b34c456.83178c", + "type": "ui_text_input", + "z": "baa1e3d9.cb29d", + "name": "acq_id", + "label": "Acquisition unique ID*", + "tooltip": "", + "group": "4322c187.e73e5", + "order": 1, + "width": 5, + "height": 1, + "passthru": true, + "mode": "text", + "delay": 300, + "topic": "acq_id", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 690, + "y": 180, + "wires": [["fb887036.12429"]] + }, + { + "id": "cc0ca68b.4263a8", + "type": "ui_dropdown", + "z": "baa1e3d9.cb29d", + "name": "acq_celltype", + "label": "Flowcell thickness*", + "tooltip": "", + "place": "Select option", + "group": "4322c187.e73e5", + "order": 6, + "width": 5, + "height": 1, + "passthru": true, + "multiple": false, + "options": [ + { + "label": "200 μm µ-Slide I Luer", + "value": 200, + "type": "num" + }, + { + "label": "300 µm capillary", + "value": 300, + "type": "num" + }, + { + "label": "400 μm µ-Slide I Luer", + "value": 400, + "type": "num" + }, + { + "label": "600 μm µ-Slide I Luer", + "value": 600, + "type": "num" + }, + { + "label": "800 μm µ-Slide I Luer", + "value": 800, + "type": "num" + } + ], + "payload": "", + "topic": "acq_celltype", + "topicType": "str", + "className": "", + "x": 670, + "y": 100, + "wires": [["fb887036.12429", "99b11fe4.2795d"]] + }, + { + "id": "fb887036.12429", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "set global", + "func": "global.set(msg.topic, msg.payload);\nreturn msg", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 920, + "y": 180, + "wires": [["52ea7d01.711034"]] + }, + { + "id": "bb2bb7ce.1d1458", + "type": "ui_template", + "z": "baa1e3d9.cb29d", + "group": "858a0e3c.987fe", + "name": "Stream Pi Camera", + "order": 1, + "width": 10, + "height": 8, + "format": "
\n \"If\n
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "className": "", + "x": 550, + "y": 40, + "wires": [[]] + }, + { + "id": "d0c5b57d.590818", + "type": "ui_ui_control", + "z": "baa1e3d9.cb29d", + "name": "", + "events": "change", + "x": 1280, + "y": 660, + "wires": [[]] + }, + { + "id": "c72f8fae.23bd4", + "type": "ui_button", + "z": "baa1e3d9.cb29d", + "name": "", + "group": "b7919ae2.c01788", + "order": 1, + "width": 5, + "height": 1, + "passthru": false, + "label": "Previous", + "tooltip": "", + "color": "#097479", + "bgcolor": "white", + "icon": "keyboard_return", + "payload": "{\"tab\":\"Optic Configuration\"}", + "payloadType": "json", + "topic": "", + "x": 1140, + "y": 660, + "wires": [["d0c5b57d.590818"]] + }, + { + "id": "29be525e.0c87fe", + "type": "ui_template", + "z": "baa1e3d9.cb29d", + "group": "b5d61bc7.54fe48", + "name": "Show Metadata", + "order": 9, + "width": 0, + "height": 0, + "format": "
\n \n \n \n \n \n \n \n \n \n
\n

Sample

\n

id:

\n

project:\n

\n

ship:

\n

operator:\n

\n

sampling gear:\n

\n

concentrated volume:\n

\n

gear net opening:\n

\n

total volume filtered:\n

\n
\n

Acquisition

\n

id:

\n

instrument:\n

\n

instrument id:\n

\n

camera:

\n

celltype: \n

\n

minimum mesh:\n

\n

maximum mesh:\n

\n

min esd: \n

\n

max esd: \n

\n

volume:

\n

magnification:\n

\n

fnumber objective:\n

\n

software: \n

\n
\n

Object

\n

latitude: \n

\n

longitude: \n

\n

latitude end:\n

\n

longitude end:\n

\n

date:

\n

time:

\n

date end:\n

\n

time end:\n

\n

depth min:\n

\n

depth max:\n

\n
\n

Process

\n

pixel: \n

\n

id:

\n
\n
", + "storeOutMessages": false, + "fwdInMessages": false, + "resendOnRefresh": false, + "templateScope": "local", + "className": "", + "x": 1160, + "y": 380, + "wires": [[]] + }, + { + "id": "c9f510c0.7d1328", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "Image control", + "func": "// Reset the number of images taken\nflow.set('img_counter', 0);\n\nvar acq_celltype = global.get(\"acq_celltype\");\nvar acq_minimum_mesh = global.get(\"acq_minimum_mesh\");\nvar acq_maximum_mesh = global.get(\"acq_maximum_mesh\");\nvar imaging_pump_volume = global.get(\"imaging_pump_volume\");\nvar acq_id = global.get(\"acq_id\");\nvar nb_frame = global.get(\"nb_frame\");\nvar pump_direction = global.get(\"pump_direction\");\nvar sleep_before = global.get(\"sleep_before\");\nvar object_date = global.get(\"object_date\");\n\nif (acq_celltype === undefined || acq_celltype === \"\") {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Type of the flowcell\";\n return [null, msg];\n} else if (acq_minimum_mesh === undefined || acq_minimum_mesh === \"\") {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Lower fraction size\";\n return [null, msg];\n} else if (acq_maximum_mesh === undefined || acq_maximum_mesh === \"\") {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Upper fraction size\";\n return [null, msg];\n} else if (imaging_pump_volume === undefined || imaging_pump_volume === \"\" || imaging_pump_volume === null) {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Volume inbetween images\";\n return [null, msg];\n} else if (acq_id === undefined || acq_id === \"\") {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Acquisition ID\";\n return [null, msg];\n} else if (nb_frame === undefined || nb_frame === \"\" || nb_frame === null) {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Number of image to save\";\n return [null, msg];\n} else if (pump_direction === undefined || pump_direction === \"\" || pump_direction === null) {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Pump direction\";\n return [null, msg];\n} else if (sleep_before === undefined || sleep_before === \"\" || sleep_before === null) {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Delay before image\";\n return [null, msg];\n}else if (object_date === undefined || object_date === \"\" || object_date === null) {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Object date\";\n return [null, msg];\n}\n\nmsg.payload = {\n \"action\": \"image\",\n \"sleep\": sleep_before,\n \"pump_direction\": pump_direction,\n \"volume\": imaging_pump_volume,\n \"nb_frame\": nb_frame,\n}\nmsg.send = true\n\nreturn [msg, null];", + "outputs": 2, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 640, + "y": 440, + "wires": [ + ["52ea7d01.711034", "40c12463.a1f84c", "a4abb1ae.2ae418"], + ["20e0a8c8.edbeb"] + ] + }, + { + "id": "20e0a8c8.edbeb", + "type": "ui_toast", + "z": "baa1e3d9.cb29d", + "position": "dialog", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 1, + "ok": "OK", + "cancel": "", + "raw": false, + "topic": "", + "name": "", + "x": 890, + "y": 520, + "wires": [[]] + }, + { + "id": "c3e50240.82aa58", + "type": "mqtt out", + "z": "baa1e3d9.cb29d", + "name": "", + "topic": "", + "qos": "", + "retain": "", + "broker": "8dc3722c.06efa8", + "x": 1130, + "y": 420, + "wires": [] + }, + { + "id": "3a4450b1.4459a8", + "type": "ui_button", + "z": "baa1e3d9.cb29d", + "name": "Stop Acquisition", + "group": "4322c187.e73e5", + "order": 11, + "width": 5, + "height": 1, + "passthru": true, + "label": "STOP ACQUISITION", + "tooltip": "", + "color": "", + "bgcolor": "#AD1625", + "icon": "cancel", + "payload": "{\"action\":\"stop\"}", + "payloadType": "json", + "topic": "imager/image", + "x": 420, + "y": 480, + "wires": [["d74210ef.edc15"]] + }, + { + "id": "d74210ef.edc15", + "type": "mqtt out", + "z": "baa1e3d9.cb29d", + "name": "", + "topic": "", + "qos": "", + "retain": "", + "broker": "8dc3722c.06efa8", + "x": 610, + "y": 480, + "wires": [] + }, + { + "id": "bb62da8a.ebc328", + "type": "ui_switch", + "z": "baa1e3d9.cb29d", + "name": "Pump direction", + "label": "Pump direction", + "tooltip": "BACKWARD / FORWARD", + "group": "4322c187.e73e5", + "order": 9, + "width": 5, + "height": 1, + "passthru": true, + "decouple": "false", + "topic": "pump_direction", + "style": "", + "onvalue": "FORWARD", + "onvalueType": "str", + "onicon": "", + "oncolor": "", + "offvalue": "BACKWARD", + "offvalueType": "str", + "officon": "", + "offcolor": "", + "x": 420, + "y": 520, + "wires": [["6b2239f3.41fa3"]] + }, + { + "id": "52ea7d01.711034", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "Encapsulate config", + "func": "msg.payload = {\n\t\"action\": \"update_config\",\n\t\"config\": {\n \t\"description\": {\n \t\t\"sample_project\": \"Project's name\",\n \t\t\"sample_id\": \"Sample ID\",\n \t\t\"sample_uuid\": \"Sample UUID (Autogenerated)\",\n \t\t\"sample_ship\": \"Ship's name\",\n \t\t\"sample_operator\": \"Operator's name\",\n \t\t\"sample_sampling_gear\": \"Sampling gear used\",\n \t\t\"sample_concentrated_sample_volume\": \"Volume of concentrated sample, in mL\",\n \t\t\"sample_total_volume\": \"Total volume filtered by the net used, in L\",\n \t\t\"sample_dilution_factor\": \"Dilution factor of the sample, 0.5 if diluted by 2, 2 if concentrated by 2\",\n \t\t\"sample_speed_through_water\": \"Speed of the boat through water when sampling, in kts\",\n \t\t\"acq_id\": \"Acquisition ID\",\n \t\t\"acq_uuid\": \"Acquisition UUID (Autogenerated)\",\n \t\t\"acq_instrument\": \"Instrument type\",\n \t\t\"acq_instrument_id\": \"Instrument ID\",\n \t\t\"acq_celltype\": \"Flow cell dimension thickness, in µm\",\n \t\t\"acq_minimum_mesh\": \"Minimum filtration mesh size, in µm\",\n \t\t\"acq_maximum_mesh\": \"Maximum filtration mesh size, in µm\",\n \t\t\"acq_min_esd\": \"\",\n \t\t\"acq_max_esd\": \"\",\n \t\t\"acq_volume\": \"Pumped volume, in mL\",\n\t\t \"acq_imaged_volume\": \"Total imaged volume, in mL\",\n \t\t\"acq_magnification\": \"Optical magnification\",\n \t\t\"acq_fnumber_objective\": \"Focal length of the objective, in mm\",\n \t\t\"acq_camera_name\": \"Name of the camera used\",\n \t\t\"acq_nb_frame\": \"Number of picture taken\",\n \"acq_local_datetime\": \"Instrument local datetime\",\n \"acq_camera_resolution\": \"Resolution of the images\",\n \"acq_camera_iso\": \"ISO Number of the images\",\n \"acq_camera_shutter_speed\": \"Shutter speed of the images, in µs\",\n \"acq_software\": \"Software version number\",\n \t\t\"object_date\": \"Sample collection date (or beginning if using a net)\",\n \t\t\"object_time\": \"Sample collection time (or beginning if using a net)\",\n \t\t\"object_lat\": \"Sample collection latitude (or beginning if using a net)\",\n \t\t\"object_lon\": \"Sample collection longitude (or beginning if using a net)\",\n \t\t\"object_depth_min\": \"Sample collection minimal depth, in m\",\n \t\t\"object_depth_max\": \"Sample collection maximum depth, in m\",\n \t\t\"process_pixel\": \"Pixel imaging resolution, in µm/pixel\",\n \t\t\"process_datetime\": \"Segmentation timestamp\",\n \t\t\"process_id\": \"Segmentation ID\",\n \t\t\"process_uuid\": \"Segmentation UUID (Autogenerated)\",\n \t\t\"process_source\": \"Code source link of the executed code\",\n \t\t\"process_commit\": \"Version reference of the executed code\",\n \t\t\"sample_gear_net_opening\": \"Sample mouth opening dimension, in mm\",\n \t\t\"object_date_end\": \"Sample end collection date when using a net\",\n \t\t\"object_time_end\": \"Sample end collection time when using a net\",\n \t\t\"object_lat_end\": \"Sample end collection latitude when using a net\",\n \t\t\"object_lon_end\": \"Sample end collection longitude when using a net\",\n \t},\n\t\t\"sample_project\": global.get(\"sample_project\"),\n\t\t\"sample_id\": global.get(\"sample_project\") + \"_\" + global.get(\"sample_id\"),\n\t\t\"sample_ship\": global.get(\"sample_ship\"),\n\t\t\"sample_operator\": global.get(\"sample_operator\"),\n\t\t\"sample_sampling_gear\": global.get(\"sample_sampling_gear\"),\n\t\t\"sample_concentrated_sample_volume\": global.get(\"sample_concentrated_sample_volume\"),\n\t\t\"sample_total_volume\": global.get(\"sample_total_volume\"),\n\t\t\"sample_dilution_factor\": global.get(\"sample_dilution_factor\"),\n\t\t\"sample_speed_through_water\": global.get(\"sample_speed_through_water\"),\n\n\t\t\"acq_id\": global.get(\"sample_project\") + \"_\" + global.get(\"sample_id\")+ \"_\" + global.get(\"acq_id\"),\n\t\t\"acq_instrument\": global.get(\"acq_instrument\"),\n\t\t\"acq_instrument_id\": global.get(\"acq_instrument_id\"),\n\t\t\"acq_celltype\": global.get(\"acq_celltype\"),\n\t\t\"acq_minimum_mesh\": global.get(\"acq_minimum_mesh\"),\n\t\t\"acq_maximum_mesh\": global.get(\"acq_maximum_mesh\"),\n\t\t\"acq_min_esd\": global.get(\"acq_min_esd\"),\n\t\t\"acq_max_esd\": global.get(\"acq_max_esd\"),\n\t\t\"acq_volume\": global.get(\"acq_volume\"),\n\t\t\"acq_imaged_volume\": global.get(\"acq_imaged_volume\"),\n\t\t\"acq_magnification\": global.get(\"acq_magnification\"),\n\t\t\"acq_fnumber_objective\": global.get(\"acq_fnumber_objective\"),\n\t\t\"acq_camera\": global.get(\"acq_camera\"),\n\t\t\"acq_nb_frame\": global.get(\"nb_frame\"),\n\t\t\"acq_software\": global.get(\"acq_software\"),\n\n\t\t\"object_date\": global.get(\"object_date\"),\n\t\t\"object_time\": global.get(\"object_time\"),\n\t\t\"object_lat\": global.get(\"object_lat\"),\n\t\t\"object_lon\": global.get(\"object_lon\"),\n\t\t\"object_depth_min\": global.get(\"object_depth_min\"),\n\t\t\"object_depth_max\": global.get(\"object_depth_max\"),\n\n\t\t\"process_pixel\": global.get(\"process_pixel\"),\n\t\t\"process_source\": global.get(\"process_source\"),\n\t\t\"process_commit\": global.get(\"process_commit\")\n\t}\n};\n\nif (msg.payload.config.sample_sampling_gear.startsWith(\"net\")) {\n\tmsg.payload.config[\"sample_gear_net_opening\"] = global.get(\"sample_gear_net_opening\")\n\tmsg.payload.config[\"object_date_end\"] = global.get(\"object_date_end\")\n\tmsg.payload.config[\"object_time_end\"] = global.get(\"object_time_end\")\n\tmsg.payload.config[\"object_lat_end\"] = global.get(\"object_lat_end\")\n\tmsg.payload.config[\"object_lon_end\"] = global.get(\"object_lon_end\")\n}\n\nif ( msg.send == true){\n\treturn [msg, msg]\n}\nelse{\n\treturn [msg, null]\n}", + "outputs": 2, + "timeout": "", + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 870, + "y": 400, + "wires": [["29be525e.0c87fe"], ["c3e50240.82aa58"]] + }, + { + "id": "40c12463.a1f84c", + "type": "delay", + "z": "baa1e3d9.cb29d", + "name": "", + "pauseType": "delay", + "timeout": "1", + "timeoutUnits": "seconds", + "rate": "1", + "nbRateUnits": "1", + "rateUnits": "second", + "randomFirst": "1", + "randomLast": "5", + "randomUnits": "seconds", + "drop": false, + "outputs": 1, + "x": 900, + "y": 440, + "wires": [["c3e50240.82aa58"]] + }, + { + "id": "4d1b02cb.83b51c", + "type": "ui_button", + "z": "baa1e3d9.cb29d", + "name": "", + "group": "4322c187.e73e5", + "order": 10, + "width": 5, + "height": 1, + "passthru": false, + "label": "Update config", + "tooltip": "", + "color": "", + "bgcolor": "", + "className": "", + "icon": "save", + "payload": "", + "payloadType": "str", + "topic": "imager/image", + "topicType": "str", + "x": 420, + "y": 400, + "wires": [["52ea7d01.711034"]] + }, + { + "id": "5921d0d0.a3d568", + "type": "subflow:1c24ad9c.bebec2", + "z": "baa1e3d9.cb29d", + "name": "", + "env": [], + "x": 110, + "y": 180, + "wires": [ + [ + "f3658d30.b8448", + "de2c90cf.b73b08", + "4be09c97f86897d9", + "f573206abefa9518", + "f948151ab4031df4" + ] + ] + }, + { + "id": "f3658d30.b8448", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "get acq_id", + "func": "msg.payload = msg.payload.acq_id;\nreturn msg;", + "outputs": 1, + "timeout": "", + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 330, + "y": 180, + "wires": [["6b34c456.83178c"]] + }, + { + "id": "de2c90cf.b73b08", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "get acq_celltype", + "func": "msg.topic = 'acq_celltype';\nmsg.payload = msg.payload.acq_celltype;\nreturn msg;", + "outputs": 1, + "timeout": "", + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 340, + "y": 100, + "wires": [["cc0ca68b.4263a8"]] + }, + { + "id": "b402f719.55bc98", + "type": "inject", + "z": "baa1e3d9.cb29d", + "name": "Default: FORWARD", + "props": [ + { + "p": "payload" + }, + { + "p": "topic", + "vt": "str" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "pump_direction", + "payload": "FORWARD", + "payloadType": "str", + "x": 180, + "y": 520, + "wires": [["bb62da8a.ebc328"]] + }, + { + "id": "6b2239f3.41fa3", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "set global", + "func": "global.set(msg.topic, msg.payload);", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 620, + "y": 520, + "wires": [[]] + }, + { + "id": "51b4d0df.d70a88", + "type": "ui_text_input", + "z": "baa1e3d9.cb29d", + "name": "nb_frame", + "label": "Number of images to acquire", + "tooltip": "", + "group": "4322c187.e73e5", + "order": 2, + "width": 5, + "height": 1, + "passthru": true, + "mode": "number", + "delay": 300, + "topic": "nb_frame", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 680, + "y": 220, + "wires": [["fb887036.12429", "67091ac0.8f9f6c", "99b11fe4.2795d"]] + }, + { + "id": "999065ca.27edb8", + "type": "switch", + "z": "baa1e3d9.cb29d", + "name": "topic filter", + "property": "topic", + "propertyType": "msg", + "rules": [ + { + "t": "eq", + "v": "status/pump", + "vt": "str" + }, + { + "t": "eq", + "v": "status/focus", + "vt": "str" + }, + { + "t": "eq", + "v": "status/light", + "vt": "str" + }, + { + "t": "eq", + "v": "status/imager", + "vt": "str" + } + ], + "checkall": "true", + "repair": false, + "outputs": 4, + "x": 320, + "y": 800, + "wires": [ + ["a46a1e7f.88a92", "6742014e.1bb238"], + ["c516d9ea.f7f6e", "6742014e.1bb238"], + ["6742014e.1bb238"], + ["307c851e.fb0f7a", "2b9d6988.d84836"] + ] + }, + { + "id": "2b009bd7.c07004", + "type": "ui_text", + "z": "baa1e3d9.cb29d", + "group": "70de8209.68416c", + "order": 3, + "width": 10, + "height": 2, + "name": "imager", + "label": "Imager status:", + "format": "{{msg.payload.status}}", + "layout": "col-center", + "x": 770, + "y": 740, + "wires": [] + }, + { + "id": "c516d9ea.f7f6e", + "type": "ui_text", + "z": "baa1e3d9.cb29d", + "group": "70de8209.68416c", + "order": 1, + "width": 5, + "height": 1, + "name": "focus", + "label": "Focus status:", + "format": "{{msg.payload.status}}", + "layout": "col-center", + "x": 770, + "y": 700, + "wires": [] + }, + { + "id": "a46a1e7f.88a92", + "type": "ui_text", + "z": "baa1e3d9.cb29d", + "group": "70de8209.68416c", + "order": 2, + "width": 5, + "height": 1, + "name": "pump", + "label": "Pump status:", + "format": "{{msg.payload.status}}", + "layout": "col-center", + "x": 770, + "y": 660, + "wires": [] + }, + { + "id": "bb628f8d.98f108", + "type": "link in", + "z": "baa1e3d9.cb29d", + "name": "Status for fluidic module", + "links": ["58f2e0f.4e8b12"], + "x": 175, + "y": 800, + "wires": [["999065ca.27edb8"]] + }, + { + "id": "307c851e.fb0f7a", + "type": "switch", + "z": "baa1e3d9.cb29d", + "name": "Imaging state", + "property": "payload", + "propertyType": "msg", + "rules": [ + { + "t": "jsonata_exp", + "v": "$contains(msg.payload.status, \"jpg\")\t", + "vt": "jsonata" + }, + { + "t": "else" + } + ], + "checkall": "false", + "repair": false, + "outputs": 2, + "x": 540, + "y": 880, + "wires": [["db8e3dde.44efb8"], ["6742014e.1bb238"]] + }, + { + "id": "db8e3dde.44efb8", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "img_counter", + "func": "img_counter=flow.get('img_counter')\nif (img_counter === undefined || img_counter === \"\"){\n img_counter = 0\n}\nimg_counter=img_counter+1\nflow.set('img_counter',img_counter)\nmsg.payload = img_counter\nmsg.payload = (100 * img_counter/global.get('nb_frame')).toFixed(2)\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 770, + "y": 860, + "wires": [["1a2e721a.f5e876"]] + }, + { + "id": "59164d65.e7993c", + "type": "ui_toast", + "z": "baa1e3d9.cb29d", + "position": "top right", + "displayTime": "5", + "highlight": "", + "sendall": true, + "outputs": 0, + "ok": "OK", + "cancel": "", + "raw": false, + "topic": "", + "name": "", + "x": 1270, + "y": 900, + "wires": [] + }, + { + "id": "8c7348aa.1962e8", + "type": "template", + "z": "baa1e3d9.cb29d", + "name": "Create sentence", + "field": "payload", + "fieldType": "msg", + "format": "handlebars", + "syntax": "mustache", + "template": "The {{topic}} is {{payload.status}}", + "output": "str", + "x": 1050, + "y": 900, + "wires": [["59164d65.e7993c"]] + }, + { + "id": "6742014e.1bb238", + "type": "change", + "z": "baa1e3d9.cb29d", + "name": "Remove high-level topic", + "rules": [ + { + "t": "change", + "p": "topic", + "pt": "msg", + "from": "status/", + "fromt": "str", "to": "", - "reg": false, - "x": 490, - "y": 680, - "wires": [ - [ - "6af85f0e0fc21b11" - ] - ] - }, - { - "id": "f80babd43aa7cce4", - "type": "change", - "z": "eaae323a.31b3", - "name": "Show home buttons", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "{\"group\":{\"hide\":[\"Home_Setup\"],\"show\":[\"Home_Group_1\",\"Home_Group_2\",\"Home_Group_3\",\"Home_Group_4\",\"Home_Group_5\",\"Home_Group_6\"]}}", - "tot": "json" - } - ], - "action": "", - "property": "", - "from": "", + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 810, + "y": 900, + "wires": [["8c7348aa.1962e8"]] + }, + { + "id": "1a2e721a.f5e876", + "type": "ui_gauge", + "z": "baa1e3d9.cb29d", + "name": "progress donut", + "group": "b5d61bc7.54fe48", + "order": 3, + "width": 6, + "height": 3, + "gtype": "donut", + "title": "", + "label": "%", + "format": "{{value}}", + "min": 0, + "max": "100", + "colors": ["#ffa83f", "#e6ff02", "#00dfe9"], + "seg1": "50", + "seg2": "75", + "x": 1260, + "y": 860, + "wires": [] + }, + { + "id": "9bd72495.a8a098", + "type": "ui_text", + "z": "baa1e3d9.cb29d", + "group": "4322c187.e73e5", + "order": 5, + "width": 5, + "height": 1, + "name": "Total imaged volume", + "label": "Total imaged volume", + "format": "{{msg.payload}}", + "layout": "col-center", + "x": 1200, + "y": 100, + "wires": [] + }, + { + "id": "99b11fe4.2795d", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "imaged volume calc", + "func": "camera = global.get(\"acq_camera\");\ncell = global.get(\"acq_celltype\");\nnb_frame = global.get(\"nb_frame\");\nprocess_pixel = global.get(\"process_pixel\");\n\nvar volume = 0\nif (camera == \"HQ Camera\"){\n volume = nb_frame * (process_pixel*4056*process_pixel*3040*cell/1000000000) / 1000;\n}\nelse if (camera == \"Camera v2.1\"){\n volume = nb_frame * (process_pixel*3280*process_pixel*2464*cell/1000000000) / 1000;\n}\nelse{\n msg.payload = \"The camera is not known to this system\";\n return msg;\n}\n\nglobal.set(\"acq_imaged_volume\", volume.toFixed(4))\n\nmsg.payload = volume.toFixed(2) + \" mL\"\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 960, + "y": 100, + "wires": [["9bd72495.a8a098"]], + "info": "### Focusing\n##### focus.py `nb_step` `orientation`\n\n- `nb_step` : **integer** (from 1 to 100000) - number of step to perform by the stage (about 31um/step)\n- `orientation` : **string** - orientation of the focus either `up` or `down`\n\nExample:\n\n python3.7 $HOME/PlanktoScope/scripts/focus.py 650 up\n" + }, + { + "id": "8e16aa2f.e40398", + "type": "ui_text", + "z": "baa1e3d9.cb29d", + "group": "4322c187.e73e5", + "order": 7, + "width": 5, + "height": 1, + "name": "Total pumped volume", + "label": "Total pumped volume", + "format": "{{msg.payload}} mL", + "layout": "col-center", + "x": 1200, + "y": 260, + "wires": [] + }, + { + "id": "67091ac0.8f9f6c", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "acq_volume calc", + "func": "var imaging_pump_volume = global.get(\"imaging_pump_volume\");\nvar nb_frame = global.get(\"nb_frame\");\nvar acq_volume = 0\n\nacq_volume = (Number(nb_frame)*Number(imaging_pump_volume)).toFixed(2)\nglobal.set(\"acq_volume\", acq_volume)\n\nmsg.payload = acq_volume\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 950, + "y": 260, + "wires": [["8e16aa2f.e40398"]], + "info": "### Focusing\n##### focus.py `nb_step` `orientation`\n\n- `nb_step` : **integer** (from 1 to 100000) - number of step to perform by the stage (about 31um/step)\n- `orientation` : **string** - orientation of the focus either `up` or `down`\n\nExample:\n\n python3.7 $HOME/PlanktoScope/scripts/focus.py 650 up\n" + }, + { + "id": "2b9d6988.d84836", + "type": "switch", + "z": "baa1e3d9.cb29d", + "name": "", + "property": "payload", + "propertyType": "msg", + "rules": [ + { + "t": "hask", + "v": "status", + "vt": "str" + }, + { + "t": "hask", + "v": "camera_name", + "vt": "str" + } + ], + "checkall": "true", + "repair": false, + "outputs": 2, + "x": 650, + "y": 760, + "wires": [["2b009bd7.c07004"], ["3bbb756a.84190a"]] + }, + { + "id": "3bbb756a.84190a", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "set camera name", + "func": "global.set(\"acq_camera\", msg.payload.camera_name);\n\nmsg.payload = msg.payload.camera_name;\n\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 810, + "y": 780, + "wires": [["559a8085.1d6b9"]] + }, + { + "id": "559a8085.1d6b9", + "type": "link out", + "z": "baa1e3d9.cb29d", + "name": "Camera Name", + "links": ["30067f35.532f2", "572a6daa.6004c4"], + "x": 965, + "y": 780, + "wires": [] + }, + { + "id": "49ea1123.ee1768", + "type": "ui_numeric", + "z": "baa1e3d9.cb29d", + "name": "sleep_before", + "label": "Delay to stabilize image (s)", + "tooltip": "Happens before every capture", + "group": "4322c187.e73e5", + "order": 4, + "width": 5, + "height": 1, + "wrap": false, + "passthru": true, + "topic": "sleep_before", + "topicType": "str", + "format": "{{value}}", + "min": "0.1", + "max": "5", + "step": "0.1", + "className": "", + "x": 670, + "y": 140, + "wires": [["fb887036.12429"]] + }, + { + "id": "572a6daa.6004c4", + "type": "link in", + "z": "baa1e3d9.cb29d", + "name": "", + "links": ["559a8085.1d6b9"], + "x": 735, + "y": 60, + "wires": [["99b11fe4.2795d"]] + }, + { + "id": "8032ea50.1b57f", + "type": "ui_template", + "z": "baa1e3d9.cb29d", + "group": "b5d61bc7.54fe48", + "name": "progress header", + "order": 1, + "width": 0, + "height": 0, + "format": "

Capture progress

", + "storeOutMessages": false, + "fwdInMessages": false, + "resendOnRefresh": false, + "templateScope": "local", + "x": 1270, + "y": 820, + "wires": [[]] + }, + { + "id": "a4abb1ae.2ae418", + "type": "subflow:1c24ad9c.bebec2", + "z": "baa1e3d9.cb29d", + "name": "", + "env": [], + "x": 890, + "y": 480, + "wires": [[]] + }, + { + "id": "4be09c97f86897d9", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "get nb_frame", + "func": "msg.payload = msg.payload.nb_frame;\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 330, + "y": 220, + "wires": [["51b4d0df.d70a88"]] + }, + { + "id": "f573206abefa9518", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "get imaging_pump_volume", + "func": "msg.payload = msg.payload.imaging_pump_volume;\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 380, + "y": 260, + "wires": [["0df8d1d86af6455a"]] + }, + { + "id": "f948151ab4031df4", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "get sleep_before", + "func": "msg.payload = msg.payload.sleep_before;\nreturn msg;", + "outputs": 1, + "timeout": "", + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 340, + "y": 140, + "wires": [["49ea1123.ee1768"]] + }, + { + "id": "ad153212312f0347", + "type": "ui_ui_control", + "z": "baa1e3d9.cb29d", + "name": "onTab", + "events": "all", + "x": 310, + "y": 340, + "wires": [["9b69ea945b587192"]] + }, + { + "id": "9b69ea945b587192", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "check tab", + "func": "if (msg.name == \"Fluidic Acquisition\"){\n return { \"topic\": \"imager/ image\" }\n}", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 460, + "y": 340, + "wires": [["52ea7d01.711034"]], + "outputLabels": ["interface"] + }, + { + "id": "0df8d1d86af6455a", + "type": "ui_text_input", + "z": "baa1e3d9.cb29d", + "name": "imaging_pump_volume", + "label": "Pumped volume (mL)", + "tooltip": "between frames", + "group": "4322c187.e73e5", + "order": 3, + "width": 0, + "height": 0, + "passthru": true, + "mode": "number", + "delay": 300, + "topic": "imaging_pump_volume", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 630, + "y": 260, + "wires": [["fb887036.12429", "67091ac0.8f9f6c"]] + }, + { + "id": "37116281279b9b82", + "type": "ui_template", + "z": "baa1e3d9.cb29d", + "group": "4322c187.e73e5", + "name": "Start Acquisition", + "order": 12, + "width": "5", + "height": "1", + "format": "\n\n", + "storeOutMessages": false, + "fwdInMessages": false, + "resendOnRefresh": false, + "templateScope": "local", + "className": "", + "x": 420, + "y": 440, + "wires": [["c9f510c0.7d1328"]] + }, + { + "id": "9d6abe67.6bb3d", + "type": "ui_button", + "z": "cb95299c.2817c8", + "name": "", + "group": "64903b47.4034e4", + "order": 1, + "width": 0, + "height": 0, + "passthru": false, + "label": "Home", + "tooltip": "", + "color": "", + "bgcolor": "", + "icon": "home", + "payload": "{\"tab\":\"Home\"}", + "payloadType": "json", + "topic": "", + "x": 430, + "y": 600, + "wires": [["f0fb77cf.8f1c28"]] + }, + { + "id": "f0fb77cf.8f1c28", + "type": "ui_ui_control", + "z": "cb95299c.2817c8", + "name": "", + "events": "change", + "x": 740, + "y": 600, + "wires": [[]] + }, + { + "id": "8ec68b82.17e3d8", + "type": "ui_button", + "z": "cb95299c.2817c8", + "name": "Start segmentation", + "group": "abeb6dad.635a2", + "order": 10, + "width": 5, + "height": 1, + "passthru": false, + "label": "Start segmentation", + "tooltip": "", + "color": "", + "bgcolor": "", + "icon": "", + "payload": "{\"action\":\"segment\"}", + "payloadType": "json", + "topic": "segmenter/segment", + "x": 370, + "y": 460, + "wires": [["33c28dc1.238002", "c72a1064.1ec388"]] + }, + { + "id": "27be7971.b3fbce", + "type": "ui_button", + "z": "cb95299c.2817c8", + "d": true, + "name": "Stop segmentation", + "group": "abeb6dad.635a2", + "order": 12, + "width": 4, + "height": 1, + "passthru": true, + "label": "Stop segmentation", + "tooltip": "", + "color": "", + "bgcolor": "#AD1625", + "icon": "", + "payload": "{\"action\":\"stop\"}", + "payloadType": "json", + "topic": "segmenter/segment", + "x": 370, + "y": 520, + "wires": [["16f3cef4.0acac9"]] + }, + { + "id": "16f3cef4.0acac9", + "type": "mqtt out", + "z": "cb95299c.2817c8", + "name": "", + "topic": "", + "qos": "", + "retain": "", + "broker": "8dc3722c.06efa8", + "x": 850, + "y": 520, + "wires": [] + }, + { + "id": "8f3788f6.ddcf98", + "type": "function", + "z": "cb95299c.2817c8", + "name": "obj_counter", + "func": "obj_counter = flow.get('obj_counter')\nobj_counter = obj_counter + 1\nflow.set('obj_counter', obj_counter)\nmsg.payload = obj_counter\nmsg.topic = \"object count\"\nreturn msg", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 810, + "y": 800, + "wires": [["fa3b7929.ac7da8", "9d53dbe2.dbffe8"]] + }, + { + "id": "aa38dbbc.cf0a9", + "type": "switch", + "z": "cb95299c.2817c8", + "name": "Segmenter", + "property": "topic", + "propertyType": "msg", + "rules": [ + { + "t": "eq", + "v": "status/segmenter", + "vt": "str" + }, + { + "t": "eq", + "v": "status/segmenter/name", + "vt": "str" + }, + { + "t": "eq", + "v": "status/segmenter/object_id", + "vt": "str" + }, + { + "t": "eq", + "v": "status/segmenter/metric", + "vt": "str" + } + ], + "checkall": "true", + "repair": false, + "outputs": 4, + "x": 490, + "y": 740, + "wires": [ + ["b9a23b91.93638", "6919465f.332e5"], + ["49af3d24.1799e4"], + ["8f3788f6.ddcf98"], + [] + ] + }, + { + "id": "9d53dbe2.dbffe8", + "type": "ui_chart", + "z": "cb95299c.2817c8", + "name": "counter graph", + "group": "46be9c86.dea684", + "order": 7, + "width": 10, + "height": 2, + "label": "", + "chartType": "horizontalBar", + "legend": "false", + "xformat": "HH:mm:ss", + "interpolate": "linear", + "nodata": "Objects count will be shown here once the segmentation is started", + "dot": false, + "ymin": "", + "ymax": "", + "removeOlder": 1, + "removeOlderPoints": "", + "removeOlderUnit": "3600", + "cutout": 0, + "useOneColor": true, + "useUTC": false, + "colors": [ + "#1f77b4", + "#aec7e8", + "#ff7f0e", + "#2ca02c", + "#98df8a", + "#d62728", + "#ff9896", + "#9467bd", + "#c5b0d5" + ], + "outputs": 1, + "x": 1340, + "y": 840, + "wires": [[]] + }, + { + "id": "a4f0f0d1.3aca88", + "type": "ui_toast", + "z": "cb95299c.2817c8", + "position": "top right", + "displayTime": "5", + "highlight": "", + "sendall": true, + "outputs": 0, + "ok": "OK", + "cancel": "", + "raw": false, + "topic": "", + "name": "", + "x": 1350, + "y": 680, + "wires": [] + }, + { + "id": "49af3d24.1799e4", + "type": "debug", + "z": "cb95299c.2817c8", + "name": "segmentation name", + "active": true, + "tosidebar": true, + "console": false, + "tostatus": false, + "complete": "true", + "targetType": "full", + "statusVal": "", + "statusType": "auto", + "x": 840, + "y": 760, + "wires": [] + }, + { + "id": "7088a5be.0c79a4", + "type": "template", + "z": "cb95299c.2817c8", + "name": "Create sentence", + "field": "payload", + "fieldType": "msg", + "format": "handlebars", + "syntax": "mustache", + "template": "The {{topic}} is {{payload.status}}", + "output": "str", + "x": 1100, + "y": 680, + "wires": [["a4f0f0d1.3aca88"]] + }, + { + "id": "b9a23b91.93638", + "type": "change", + "z": "cb95299c.2817c8", + "name": "Remove high-level topic", + "rules": [ + { + "t": "change", + "p": "topic", + "pt": "msg", + "from": "status/", + "fromt": "str", "to": "", - "reg": false, - "x": 500, - "y": 720, - "wires": [ - [ - "6af85f0e0fc21b11" - ] - ] - }, - { - "id": "438439b4ae62444c", - "type": "ui_template", - "z": "eaae323a.31b3", - "group": "0035a03e1490cd8c", - "name": "Information", - "order": 1, - "width": "0", - "height": "0", - "format": "
\n

\n To start using your PlanktoScope, please indicate the version of your PlanktoScope hardware:\n

\n
\n", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": true, - "templateScope": "local", - "className": "", - "x": 710, - "y": 680, - "wires": [ - [] - ] - }, - { - "id": "a2f2a4c7cbae4446", - "type": "link in", - "z": "eaae323a.31b3", - "name": "Load hardware version", - "links": [ - "3973b999ee7b3b1d", - "56dd3f82c45717f0" - ], - "x": 185, - "y": 680, - "wires": [ - [ - "e954204b947a0c70" - ] - ] - }, - { - "id": "4557d689.a4fa88", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "sample_ship", - "label": "Name of the ship", - "tooltip": "", - "group": "3e1ba03d.f01d8", - "order": 2, - "width": 0, - "height": 0, - "passthru": true, - "mode": "text", - "delay": "300", - "topic": "sample_ship", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 670, - "y": 80, - "wires": [ - [ - "9f501f49.45645" - ] - ] - }, - { - "id": "fcfc31ae.af3af", - "type": "ui_dropdown", - "z": "b771c342.49603", - "name": "sample_sampling_gear", - "label": "Sampling gear*", - "tooltip": "", - "place": "Choose from list", - "group": "3e1ba03d.f01d8", - "order": 6, - "width": 0, - "height": 0, - "passthru": true, - "multiple": false, - "options": [ - { - "label": "High Speed Net", - "value": "net_hsn", - "type": "str" - }, - { - "label": "Tara Decknet", - "value": "net_decknet", - "type": "str" - }, - { - "label": "Plankton net", - "value": "net", - "type": "str" - }, - { - "label": "Niskin bottle 12L", - "value": "niskin_12L", - "type": "str" - }, - { - "label": "Niskin bottle 24L", - "value": "niskin_24L", - "type": "str" - }, - { - "label": "Pass Hull", - "value": "pass_hull", - "type": "str" - }, - { - "label": "Single location (with net or bucket)", - "value": "single_location", - "type": "str" - }, - { - "label": "Lab culture", - "value": "culture", - "type": "str" - }, - { - "label": "Test", - "value": "test", - "type": "str" - } - ], - "payload": "", - "topic": "sample_sampling_gear", - "topicType": "str", - "className": "", - "x": 630, - "y": 200, - "wires": [ - [ - "9f501f49.45645", - "46eb1bf8.3dc5f4", - "3ac7b631f5d8ef90" - ] - ] - }, - { - "id": "82c5fc77.59c97", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "sample_operator", - "label": "Name of the operator*", - "tooltip": "", - "group": "3e1ba03d.f01d8", - "order": 3, - "width": 0, - "height": 0, - "passthru": true, - "mode": "text", - "delay": "300", - "topic": "sample_operator", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 650, - "y": 160, - "wires": [ - [ - "9f501f49.45645" - ] - ] - }, - { - "id": "9c882b37.fde668", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "sample_project", - "label": "Name of the project*", - "tooltip": "", - "group": "3e1ba03d.f01d8", - "order": 1, - "width": 0, - "height": 0, - "passthru": true, - "mode": "text", - "delay": "300", - "topic": "sample_project", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 660, - "y": 40, - "wires": [ - [ - "9f501f49.45645" - ] - ] - }, - { - "id": "94eb4221.9b92c", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "sample_id", - "label": "Station ID*", - "tooltip": "", - "group": "3e1ba03d.f01d8", - "order": 4, - "width": 0, - "height": 0, - "passthru": true, - "mode": "text", - "delay": "300", - "topic": "sample_id", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 670, - "y": 120, - "wires": [ - [ - "9f501f49.45645" - ] - ] - }, - { - "id": "9f501f49.45645", - "type": "function", - "z": "b771c342.49603", - "name": "set global", - "func": "global.set(msg.topic,msg.payload);", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 1080, - "y": 200, - "wires": [ - [] - ] - }, - { - "id": "222c851d.5d0a3a", - "type": "ui_ui_control", - "z": "b771c342.49603", - "name": "", - "events": "change", - "x": 400, - "y": 880, - "wires": [ - [] - ] - }, - { - "id": "52f6b103.1efb6", - "type": "ui_toast", - "z": "b771c342.49603", - "position": "dialog", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 1, - "ok": "OK", - "cancel": "", - "raw": false, - "topic": "", - "name": "", - "x": 710, - "y": 980, - "wires": [ - [] - ] - }, - { - "id": "986d960a.c75908", - "type": "function", - "z": "b771c342.49603", - "name": "Check form", - "func": "var sample_project= global.get(\"sample_project\");\nvar sample_id= global.get(\"sample_id\");\nvar sample_operator= global.get(\"sample_operator\");\nvar sample_sampling_gear= global.get(\"sample_sampling_gear\");\nvar object_lat= global.get(\"object_lat\");\nvar object_lon= global.get(\"object_lon\");\nvar object_date= global.get(\"object_date\");\nvar object_time= global.get(\"object_time\");\nif (sample_project === undefined || sample_project === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Sample project\"\n return [null, msg];\n}\n\nelse if (sample_id === undefined || sample_id === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Sample ID\"\n return [null, msg];\n}\n\nelse if (sample_operator === undefined || sample_operator === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Sample operator\"\n return [null, msg];\n}\n\nelse if (sample_sampling_gear === undefined || sample_sampling_gear === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Sample sampling gear\"\n return [null, msg];\n}\n\nelse if (object_lat === undefined || object_lat === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Latitude of sample\"\n return [null, msg];\n}\n\nelse if (object_lon === undefined || object_lon === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Longitude of sample\"\n return [null, msg];\n}\n\nelse if (object_date === undefined || object_date === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Date of sample\"\n return [null, msg];\n}\n\nelse if (object_time === undefined || object_time === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Time of sample\"\n return [null, msg];\n}\nelse if (sample_sampling_gear.startsWith(\"net\")){\n var object_lat_end = global.get(\"object_lat_end\");\n var object_lon_end = global.get(\"object_lon_end\");\n var object_date_end = global.get(\"object_date_end\");\n var object_time_end = global.get(\"object_time_end\");\n var sample_gear_net_opening = global.get(\"sample_gear_net_opening\");\n\n if (object_lat_end === undefined || object_lat_end === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Latitude of retrieval\"\n return [null, msg];\n }\n \n else if (object_lon_end === undefined || object_lon_end === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Longitude of retrieval\"\n return [null, msg];\n }\n \n else if (object_date_end === undefined || object_date_end === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Date of retrieval\"\n return [null, msg];\n }\n \n else if (object_time_end === undefined || object_time_end === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Time of retrieval\"\n return [null, msg];\n }\n \n else if (sample_gear_net_opening === undefined || sample_gear_net_opening === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Net opening dimension\"\n return [null, msg];\n }\n \n if (sample_sampling_gear == \"net_decknet\"){\n var sample_total_volume = global.get(\"sample_total_volume\");\n if (sample_total_volume === undefined || sample_total_volume === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Decknet flowmeter readings\"\n return [null, msg];\n }\n }\n}\nmsg.topic = \"config_save\"\nmsg.payload={\"tab\":\"Optic Configuration\"};\n\nreturn [msg, null];", - "outputs": 2, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 470, - "y": 940, - "wires": [ - [ - "726a7822.cd6298", - "e2b277c1.07283" - ], - [ - "52f6b103.1efb6" - ] - ], - "outputLabels": [ - "message", - "error" - ] - }, - { - "id": "726a7822.cd6298", - "type": "ui_ui_control", - "z": "b771c342.49603", - "name": "", - "events": "change", - "x": 700, - "y": 900, - "wires": [ - [] - ] - }, - { - "id": "16de754c.cc969b", - "type": "ui_button", - "z": "b771c342.49603", - "name": "", - "group": "5517c651.b2f668", - "order": 1, - "width": 5, - "height": 1, - "passthru": false, - "label": "Previous", - "tooltip": "", - "color": "#097479", - "bgcolor": "white", - "icon": "keyboard_return", - "payload": "{\"tab\":\"Home\"}", - "payloadType": "json", - "topic": "", - "x": 240, - "y": 880, - "wires": [ - [ - "222c851d.5d0a3a" - ] - ] - }, - { - "id": "84f3d040.5f7ea", - "type": "ui_button", - "z": "b771c342.49603", - "name": "", - "group": "5517c651.b2f668", - "order": 2, - "width": 5, - "height": 1, - "passthru": false, - "label": "Continue", - "tooltip": "", - "color": "#097479", - "bgcolor": "white", - "icon": "keyboard_tab", - "payload": "{\"tab\":\"Home\"}", - "payloadType": "json", - "topic": "", - "x": 240, - "y": 940, - "wires": [ - [ - "986d960a.c75908" - ] - ] - }, - { - "id": "d027a6bf.7049e8", - "type": "function", - "z": "b771c342.49603", - "name": "get sample_projet", - "func": "msg.payload = msg.payload.sample_project;\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 310, - "y": 40, - "wires": [ - [ - "9c882b37.fde668" - ] - ] - }, - { - "id": "5a811caf.0f3144", - "type": "function", - "z": "b771c342.49603", - "name": "get sample_ship", - "func": "msg.payload = msg.payload.sample_ship;\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 300, - "y": 80, - "wires": [ - [ - "4557d689.a4fa88" - ] - ] - }, - { - "id": "45911c98.2bd83c", - "type": "function", - "z": "b771c342.49603", - "name": "get sample_id", - "func": "msg.payload = msg.payload.sample_id;\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 300, - "y": 120, - "wires": [ - [ - "94eb4221.9b92c" - ] - ] - }, - { - "id": "1e09a4ab.72996b", - "type": "function", - "z": "b771c342.49603", - "name": "get sample_operator", - "func": "msg.payload = msg.payload.sample_operator;\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 320, - "y": 160, - "wires": [ - [ - "82c5fc77.59c97" - ] - ] - }, - { - "id": "a3272681.f271c8", - "type": "function", - "z": "b771c342.49603", - "name": "get sample_sampling_gear", - "func": "msg.topic = \"sample_sampling_gear\"\nif (msg.payload.sample_sampling_gear === undefined){\n msg.payload = \"net\";\n}\nelse\n{\n msg.payload = msg.payload.sample_sampling_gear;\n}\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 340, - "y": 200, - "wires": [ - [ - "fcfc31ae.af3af" - ] - ] - }, - { - "id": "a6907a38.f6611", - "type": "subflow:1c24ad9c.bebec2", - "z": "b771c342.49603", - "name": "", - "env": [], - "x": 70, - "y": 220, - "wires": [ - [ - "d027a6bf.7049e8", - "5a811caf.0f3144", - "45911c98.2bd83c", - "1e09a4ab.72996b", - "8dff1648.82e42", - "9f04c5ec.75f3d8", - "f408a273.4fb538", - "e73fd87d.d24e4", - "489c8e06.cc7d6", - "a3272681.f271c8" - ] - ] - }, - { - "id": "e2b277c1.07283", - "type": "subflow:1c24ad9c.bebec2", - "z": "b771c342.49603", - "name": "", - "env": [], - "x": 690, - "y": 940, - "wires": [ - [] - ] - }, - { - "id": "9c7f7fc9.c8d3a", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "object_depth_max", - "label": "Max sampling depth (m)", - "tooltip": "in m", - "group": "3e1ba03d.f01d8", - "order": 10, - "width": 5, - "height": 1, - "passthru": true, - "mode": "number", - "delay": "300", - "topic": "object_depth_max", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 650, - "y": 240, - "wires": [ - [ - "9f501f49.45645" - ] - ] - }, - { - "id": "317eeeb7.8d3042", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "object_depth_min", - "label": "Min sampling depth (m)", - "tooltip": "in m", - "group": "3e1ba03d.f01d8", - "order": 9, - "width": 5, - "height": 1, - "passthru": true, - "mode": "number", - "delay": "300", - "topic": "object_depth_min", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 650, - "y": 280, - "wires": [ - [ - "9f501f49.45645" - ] - ] - }, - { - "id": "cbb123ab.fd3428", - "type": "ui_ui_control", - "z": "b771c342.49603", - "name": "show/hide net groups", - "events": "change", - "x": 1320, - "y": 300, - "wires": [ - [] - ] - }, - { - "id": "642ff403.1ed91c", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "sample_concentrated_sample_volume", - "label": "Concentrated sample volume (mL)", - "tooltip": "Volume extracted from the net codend (in mL)", - "group": "3e1ba03d.f01d8", - "order": 12, - "width": 10, - "height": 1, - "passthru": true, - "mode": "number", - "delay": "300", - "topic": "sample_concentrated_sample_volume", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 590, - "y": 440, - "wires": [ - [ - "9f501f49.45645" - ] - ] - }, - { - "id": "e967b844.46aa48", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "sample_gear_net_opening", - "label": "Net opening dimension (mm)", - "tooltip": "Size of the net mouth opening (in mm)", - "group": "cf5d9f0e.d57e7", - "order": 1, - "width": 10, - "height": 1, - "passthru": true, - "mode": "number", - "delay": "300", - "topic": "sample_gear_net_opening", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 620, - "y": 320, - "wires": [ - [ - "9f501f49.45645" - ] - ] - }, - { - "id": "c0ce5626.b6c5", - "type": "ui_toast", - "z": "b771c342.49603", - "position": "dialog", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 1, - "ok": "OK", - "cancel": "", - "raw": false, - "topic": "", - "name": "", - "x": 1230, - "y": 620, - "wires": [ - [] - ] - }, - { - "id": "c33f1124.af6688", - "type": "ui_form", - "z": "b771c342.49603", - "name": "sample_location", - "label": "Sample Location", - "group": "cef1e703.bcf3c8", - "order": 1, - "width": 0, - "height": 0, - "options": [ - { - "label": "Latitude (36.574439°N or 36°57.4439'N)", - "value": "object_lat", - "type": "text", - "required": true, - "rows": null - }, - { - "label": "Longitude (110.42100°W or 110°4.2100'W)", - "value": "object_lon", - "type": "text", - "required": true, - "rows": null - }, - { - "label": "Date (YYYY-MM-DD, UTC)", - "value": "object_date", - "type": "text", - "required": true, - "rows": null - }, - { - "label": "Time (HH:MM(:SS), UTC 24h)", - "value": "object_time", - "type": "text", - "required": true, - "rows": null - } - ], - "formValue": { - "object_lat": "", - "object_lon": "", - "object_date": "", - "object_time": "" - }, - "payload": "", - "submit": "Validate", - "cancel": "Reset", - "topic": "sample_location", - "x": 660, - "y": 580, - "wires": [ - [ - "14658615.47c862", - "a9fb1f4b83fc25a7" - ] - ] - }, - { - "id": "358908cd.416ab", - "type": "ui_form", - "z": "b771c342.49603", - "name": "net_throw_location", - "label": "Net Throw Location", - "group": "cf5d9f0e.d57e7", - "order": 3, - "width": 0, - "height": 0, - "options": [ - { - "label": "Latitude (36.574439°N or 36°57.4439'N)", - "value": "object_lat", - "type": "text", - "required": true, - "rows": null - }, - { - "label": "Longitude (110.42100°W or 110°4.2100'W)", - "value": "object_lon", - "type": "text", - "required": true, - "rows": null - }, - { - "label": "Date (YYYY-MM-DD UTC)", - "value": "object_date", - "type": "text", - "required": true, - "rows": null - }, - { - "label": "Time (HH:MM, UTC 24h)", - "value": "object_time", - "type": "text", - "required": true, - "rows": null - } - ], - "formValue": { - "object_lat": "", - "object_lon": "", - "object_date": "", - "object_time": "" - }, - "payload": "", - "submit": "Validate", - "cancel": "", - "topic": "net_throw_location", - "topicType": "str", - "splitLayout": false, - "className": "", - "x": 650, - "y": 620, - "wires": [ - [ - "14658615.47c862", - "ad54b89540460d27" - ] - ] - }, - { - "id": "56d40584.eff4e4", - "type": "ui_form", - "z": "b771c342.49603", - "name": "net_retrieval_location", - "label": "Net Retrieval Location", - "group": "cf5d9f0e.d57e7", - "order": 4, - "width": 0, - "height": 0, - "options": [ - { - "label": "Latitude (36.574439°N or 36°57.4439'N)", - "value": "object_lat_end", - "type": "text", - "required": true, - "rows": null - }, - { - "label": "Longitude (110.42100°W or 110°4.2100'W)", - "value": "object_lon_end", - "type": "text", - "required": true, - "rows": null - }, - { - "label": "Date (YYYY-MM-DD UTC)", - "value": "object_date_end", - "type": "text", - "required": true, - "rows": null - }, - { - "label": "Time (HH:MM, UTC 24h)", - "value": "object_time_end", - "type": "text", - "required": true, - "rows": null - } - ], - "formValue": { - "object_lat_end": "", - "object_lon_end": "", - "object_date_end": "", - "object_time_end": "" - }, - "payload": "", - "submit": "Validate", - "cancel": "", - "topic": "net_retrieval_location", - "topicType": "str", - "splitLayout": false, - "x": 640, - "y": 660, - "wires": [ - [ - "14658615.47c862", - "c21bf0244e67e40a" - ] - ] - }, - { - "id": "14658615.47c862", - "type": "function", - "z": "b771c342.49603", - "name": "Validate Location / Timestamp", - "func": "// Code added here will be run once\n// whenever the node is started.\nfunction ConvertDDMMToDD(input) {\n // Input Format 36°57.4439'N, 110°4.2100'W\n // From https://stackoverflow.com/questions/1140189/converting-latitude-and-longitude-to-decimal-values\n if (!input.match(/\\d+°\\d+\\.*\\d*\\'[NSEW]/)){\n \treturn \"parsing error\"\n }\n var parts = input.split(/[^\\d.\\w]+/)\n if (parts.length != 3){\n \treturn \"parsing error\"\n }\n var dd = Number(parts[0]) + Number(parts[1])/60\n return dd.toFixed(6) + parts[2]\n}\n\nfunction ValidateCoordinates(input, lat){\n // Input Format 36.574439°N, 110.42100°W\n // Or 36°57.4439'N, 110°4.2100'W\n if (input.match(\"'\")){\n input = ConvertDDMMToDD(input)\n }\n \n var error = {}\n\n if (input.startsWith(\"parsing error\")){\n error.topic = \"Error with the \"\n error.payload = \"You need to respect the format example, 36.574439°N or 36°57.4439'N\"\n return [null, error]\n }\n \n var direction = input.match(/[NSEW]/)\n var position = input.match(/[\\+\\-\\d\\.]+/)\n \n if (direction === null){\n error.topic = \"Error with the \"\n error.payload = \"You need to explicitely enter N/S/E/W\"\n return [null, error]\n }\n \n // Test that position is only made of digits!\n if(/^[\\+\\-]/.test(position)){\n error.topic = \"Error with the \"\n error.payload = \"Use of +/- sign is inconsistent with N/S/E/W letter! Please only use N/S/E/W!\"\n return [null, error]\n }\n \n var dd = Number(position)\n if (lat){\n // Check latitude\n if (direction == \"S\" || direction == \"N\") {\n if (dd>90.0){\n error.topic = \"Error with the \"\n error.payload = \"Latitude is more than 90°\"\n return [null, error]\n }\n }\n if (direction == \"W\" || direction == \"E\") {\n error.topic = \"Error with the \"\n error.payload = \"This is not a Latitude!\"\n return [null, error]\n }\n }\n else{\n // Check longitude\n if (direction == \"W\" || direction == \"E\") {\n if (dd>180.0){\n error.topic = \"Error with the \"\n error.payload = \"Longitude is more than 180°\"\n return [null, error]\n }\n }\n if (direction == \"N\" || direction == \"S\") {\n error.topic = \"Error with the \"\n error.payload = \"This is not a Longitude!\"\n return [null, error]\n }\n }\n \n if (direction == \"S\" || direction == \"W\") {\n dd = dd * -1\n } // Don't do anything for N or E\n return [dd.toFixed(4), null]\n \n}\n\nfunction ValidateDate(input){\n // Input Format 2020-12-25\n var error = {};\n \n if (! /20\\d{2}-[0-1]\\d-[0-3]\\d/.test(input)){\n error.topic = \"Error with the date\";\n error.payload = \"The date should respect the ISO format YYYY-MM-DD\";\n return [null, error];\n }\n else {\n var date = input.match(/\\d+/g);\n if (!((2000 < date[0]) && (date[0] < 2100))){\n error.topic = \"Error with the date\"\n error.payload = \"The year should be between 2000 and 2100\"\n return [null, error]\n }\n else if (!((0 < date[1]) && (date[1] <= 12))){\n error.topic = \"Error with the date\"\n error.payload = \"The month should be between 01 and 12\"\n return [null, error]\n }\n else if (!((0 < date[2]) && (date[2] <= 31))){\n error.topic = \"Error with the date\"\n error.payload = \"The day should be between 01 and 31\"\n return [null, error]\n }\n }\n return [input.replace(/-/g, ''), null]\n}\n\nfunction ValidateTime(input){\n // Input Format 12:00\n var error = {}\n \n if (! /[0-2]?\\d:[0-5]\\d/.test(input)){\n error.topic = \"Error with the time\"\n error.payload = \"The date should respect the ISO format HH:MM\"\n return [null, error]\n }\n else {\n var time = input.match(/\\d+/g)\n \n if (!((0 <= time[0]) && (time[0] < 24))){\n error.topic = \"Error with the time\"\n error.payload = \"The hours should be 0 and 23.\"\n return [null, error]\n }\n else if (!((0 <= time[1]) && (time[1] < 60))){\n error.topic = \"Error with the time\"\n error.payload = \"The minutes should be between 0 and 59\"\n return [null, error]\n }\n }\n return [input.replace(/:/g, ''), null]\n}\n\n\nvar ret\nvar payload_for_form = {payload:{}}\nmsg.valid = false\n\nif (msg.topic == \"culture_timestamp\"){\n ret = ValidateDate(msg.payload.object_date)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_date\", ret[0])\n \n ret = ValidateTime(msg.payload.object_time)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_time\", ret[0])\n return [{topic: \"Date and time format valid!\", payload: \"All good!\", valid: true}, payload_for_form]\n}\nelse if (msg.topic == \"net_retrieval_location\"){\n ret = ValidateCoordinates(msg.payload.object_lat_end, true);\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" Latitude\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_lat_end\", ret[0])\n ret = ValidateCoordinates(msg.payload.object_lon_end, false)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" Longitude\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_lon_end\", ret[0]);\n \n ret = ValidateDate(msg.payload.object_date_end)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample retrieval\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_date_end\", ret[0])\n \n ret = ValidateTime(msg.payload.object_time_end)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample retrieval\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_time_end\", ret[0])\n}\nelse{\n ret = ValidateCoordinates(msg.payload.object_lat, true);\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" Latitude\";\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_lat\", ret[0]);\n payload_for_form.payload[\"object_lat_end\"] = msg.payload.object_lat;\n \n ret = ValidateCoordinates(msg.payload.object_lon, false);\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" Longitude\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_lon\", ret[0])\n payload_for_form.payload[\"object_lon_end\"] = msg.payload.object_lon;\n\n ret = ValidateDate(msg.payload.object_date)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_date\", ret[0])\n payload_for_form.payload[\"object_date_end\"] = msg.payload.object_date;\n \n ret = ValidateTime(msg.payload.object_time)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_time\", ret[0])\n payload_for_form.payload[\"object_time_end\"] = msg.payload.object_time;\n}\nreturn [{topic: \"Coordinates valid!\", payload: \"All good!\", valid: true}, payload_for_form]\n", - "outputs": 2, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 930, - "y": 620, - "wires": [ - [ - "c0ce5626.b6c5", - "9a18a4b4.178448" - ], - [ - "56d40584.eff4e4" - ] - ], - "inputLabels": [ - "Location form data" - ], - "outputLabels": [ - "Message", - "Location validated" - ] - }, - { - "id": "46eb1bf8.3dc5f4", - "type": "function", - "z": "b771c342.49603", - "name": "Net check", - "func": "var decknet = {}\nvar activation_msg = {}\n\nif (msg.payload.startsWith(\"net_decknet\")){\n decknet.enabled = true;\n}\nelse {\n decknet.enabled = false;\n}\n\nif (msg.payload.startsWith(\"net\")){\n activation_msg.payload = {\"group\":{\"show\":[\"Sample_Net_Metadata\"],\"hide\":[\"Sample_Sample_Location\",\"Sample_Culture_Date_and_Time\"]}};\n}\nelse if (msg.payload != \"culture\" && msg.payload != \"test\"){\n activation_msg.payload = {\"group\":{\"show\":[\"Sample_Sample_Location\"], \"hide\":[\"Sample_Net_Metadata\",\"Sample_Culture_Date_and_Time\"]}};\n}\n\n\nreturn [decknet, activation_msg];", - "outputs": 2, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 1080, - "y": 240, - "wires": [ - [ - "516375fd.2ed61c", - "470e382a.25691", - "fbe32ac8.ff6a38" - ], - [ - "cbb123ab.fd3428" - ] - ], - "outputLabels": [ - "decknet activation", - "group display control" - ] - }, - { - "id": "516375fd.2ed61c", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "sample_total_flowmeter_start", - "label": "Decknet flowmeter start", - "tooltip": "in L", - "group": "cf5d9f0e.d57e7", - "order": 6, - "width": 5, - "height": 1, - "passthru": false, - "mode": "text", - "delay": "300", - "topic": "sample_total_flowmeter_start", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 1340, - "y": 220, - "wires": [ - [ - "e9bc112c.eb75f8" - ] - ] - }, - { - "id": "470e382a.25691", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "sample_total_flowmeter_end", - "label": "Decknet flowmeter end", - "tooltip": "in L", - "group": "cf5d9f0e.d57e7", - "order": 7, - "width": 5, - "height": 1, - "passthru": false, - "mode": "text", - "delay": "300", - "topic": "sample_total_flowmeter_end", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 1340, - "y": 260, - "wires": [ - [ - "e9bc112c.eb75f8" - ] - ] - }, - { - "id": "fbe32ac8.ff6a38", - "type": "ui_template", - "z": "b771c342.49603", - "group": "cf5d9f0e.d57e7", - "name": "Decknet flowmeter read", - "order": 5, - "width": 10, - "height": 1, - "format": "
\n

Decknet flowmeter readings

\n

Those values are used to calculate sample_total_volume. Values are in L.

\n
\n", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": true, - "templateScope": "local", - "x": 1330, - "y": 180, - "wires": [ - [] - ] - }, - { - "id": "f408a273.4fb538", - "type": "function", - "z": "b771c342.49603", - "name": "get sample_gear_net_opening", - "func": "if (msg.payload.sample_gear_net_opening === null){\n msg.payload = 0;\n global.set(\"sample_gear_net_opening\",msg.payload);\n}\nelse\n{\n msg.payload = msg.payload.sample_gear_net_opening;\n}\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 350, - "y": 320, - "wires": [ - [ - "e967b844.46aa48" - ] - ] - }, - { - "id": "8dff1648.82e42", - "type": "function", - "z": "b771c342.49603", - "name": "get object_depth_max", - "func": "if (msg.payload.object_depth_max === null){\n msg.payload = 0;\n global.set(\"object_depth_max\",msg.payload);\n}\nelse\n{\n msg.payload = msg.payload.object_depth_max;\n}\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 320, - "y": 240, - "wires": [ - [ - "9c7f7fc9.c8d3a" - ] - ] - }, - { - "id": "9f04c5ec.75f3d8", - "type": "function", - "z": "b771c342.49603", - "name": "get object_depth_min", - "func": "if (msg.payload.object_depth_min === null){\n msg.payload = 0;\n global.set(\"object_depth_min\",msg.payload);\n}\nelse\n{\n msg.payload = msg.payload.object_depth_min;\n}\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 320, - "y": 280, - "wires": [ - [ - "317eeeb7.8d3042" - ] - ] - }, - { - "id": "9a18a4b4.178448", - "type": "function", - "z": "b771c342.49603", - "name": "calculate sample_total_volume", - "func": "\n/*object_lat = 33.95 \nobject_lon = 118.4 \nobject_lat_end = 40.6333 \nobject_lon_end = 73.78333\nsample_gear_net_opening = 40*/\n\n// Copyright 1997 Ed Williams. All rights reserved\n// Adapted by Romain Bazile - Ocean Trotter - 01-2021\n\ndecpl=4 // Dec places of minutes output\n\nellipse = {\"name\":\"WSG84\", \"a\":6378.137/1.852, \"invf\":298.257223563}\n\nfunction ComputeDistance(lat1, lon1, lat2, lon2){\n var d,crs12,crs21\n var argacos\n var a,invf\n \n // lat and lon in radian\n lat1=(Math.PI/180)*lat1\n lat2=(Math.PI/180)*lat2\n lon1=(Math.PI/180)*lon1\n lon2=(Math.PI/180)*lon2\n \n //alert(\"lat1=\" + lat1 + \"lon1=\" + lon1 +\"\\nlat2=\" +lat2+ \"lon2=\"+lon2)\n \n /* get distance conversion factor */\n dc=1.852 //km\n //alert(\"dc=\" +dc)\n \n //showProps(ellipse,\"ellipse\")\n \n // elliptic code\n d=crsdist_ell(lat1,-lon1,lat2,-lon2,ellipse) // ellipse uses East negative\n d=d*dc // go to physical units\n \n //alert(\"d=\"+d+\" crs12=\"+crs12+\" crs21=\"+crs21)\n return d\n}\n\nfunction crsdist(lat1,lon1,lat2,lon2){ // radian args\n /* compute course and distance (spherical) */\n if ((lat1+lat2===0) && (Math.abs(lon1-lon2)==Math.PI) && \n (Math.abs(lat1) != (Math.PI/180)*90)){\t\n \talert(\"Course between antipodal points is undefined\")\n }\n \n d = Math.acos(Math.sin(lat1)*Math.sin(lat2)+Math.cos(lat1)*Math.cos(lat2)*Math.cos(lon1-lon2))\n return d\n}\n\nfunction crsdist_ell(glat1,glon1,glat2,glon2,ellipse){\n // glat1 initial geodetic latitude in radians N positive \n // glon1 initial geodetic longitude in radians E positive \n // glat2 final geodetic latitude in radians N positive \n // glon2 final geodetic longitude in radians E positive \n a=ellipse.a\n f=1/ellipse.invf\n //alert(\"a=\"+a+\" f=\"+f)\n var r, tu1, tu2, cu1, su1, cu2, s1, b1, f1\n var x, sx, cx, sy, cy,y, sa, c2a, cz, e, c, d\n var EPS= 0.00000000005\n var faz, baz, s\n var iter=1\n var MAXITER=100\n if ((glat1+glat2===0) && (Math.abs(glon1-glon2)==Math.PI)){\n alert(\"Course and distance between antipodal points is undefined\")\n glat1=glat1+0.00001 // allow algorithm to complete\n }\n if (glat1==glat2 && (glon1==glon2 || Math.abs(Math.abs(glon1-glon2)-2*Math.PI) < EPS)){\n alert(\"Points 1 and 2 are identical- course undefined\")\n out=new MakeArray(0)\n out.d=0\n out.crs12=0\n out.crs21=Math.PI\n return out\n }\n r = 1 - f\n tu1 = r * Math.tan (glat1)\n tu2 = r * Math.tan (glat2)\n cu1 = 1 / Math.sqrt (1 + tu1 * tu1)\n su1 = cu1 * tu1\n cu2 = 1 / Math.sqrt (1 + tu2 * tu2)\n s1 = cu1 * cu2\n b1 = s1 * tu2\n f1 = b1 * tu1\n x = glon2 - glon1\n d = x + 1 // force one pass\n while ((Math.abs(d - x) > EPS) && (iter < MAXITER))\n {\n iter=iter+1\n sx = Math.sin (x)\n // alert(\"sx=\"+sx)\n cx = Math.cos (x)\n tu1 = cu2 * sx\n tu2 = b1 - su1 * cu2 * cx\n sy = Math.sqrt(tu1 * tu1 + tu2 * tu2)\n cy = s1 * cx + f1\n y = atan2 (sy, cy)\n sa = s1 * sx / sy\n c2a = 1 - sa * sa\n cz = f1 + f1\n if (c2a > 0)\n cz = cy - cz / c2a\n e = cz * cz * 2 - 1\n c = ((-3 * c2a + 4) * f + 4) * c2a * f / 16\n d = x\n x = ((e * cy * c + cz) * sy * c + y) * sa\n x = (1 - c) * x * f + glon2 - glon1\n }\n x = Math.sqrt ((1 / (r * r) - 1) * c2a + 1)\n x +=1\n x = (x - 2) / x\n c = 1 - x\n c = (x * x / 4 + 1) / c\n d = (0.375 * x * x - 1) * x\n x = e * cy\n d = ((((sy*sy*4-3)*(1-e-e)*cz*d/6-x)*d/4+cz)*sy*d+y)*c*a*r\n if (Math.abs(iter-MAXITER)0) && (y>=0)){ out= Math.atan(y/x)}\n if ((x >0) && (y<0)) { out= Math.atan(y/x)+2*Math.PI}\n if ((x===0) && (y>0)) { out= Math.PI/2}\n if ((x===0) && (y<0)) { out= 3*Math.PI/2} \n if ((x===0) && (y===0)) {\n alert(\"atan2(0,0) undefined\")\n out= 0\n } \n return out\n}\n\nfunction showProps(obj,objName){\n var result=\"\"\n for (var i in obj){\n result +=objName + \".\" + i + \" = \" + obj[i] + \"\\n\"\n }\n alert(result)\n}\n\n\nif (msg.valid){\n msg.topic=\"sample_total_volume\"\n \n var object_lat_end = global.get(\"object_lat_end\")\n var object_lon_end = global.get(\"object_lon_end\")\n var sample_sampling_gear = global.get(\"sample_sampling_gear\")\n \n if (sample_sampling_gear.startsWith(\"net\") && sample_sampling_gear != \"net_decknet\") {\n if (!(isNaN(object_lat_end) && isNaN(object_lon_end))){\n var object_lat = global.get(\"object_lat\")\n var object_lon = global.get(\"object_lon\")\n var sample_gear_net_opening = global.get(\"sample_gear_net_opening\");\n\n distance_km = ComputeDistance(object_lat, object_lon, object_lat_end, object_lon_end)\n\n sample_total_volume = distance_km*(Math.PI*(sample_gear_net_opening/2)*(sample_gear_net_opening/2)) // liters\n sample_total_volume = Math.round(sample_total_volume + Number.EPSILON)\n msg.payload = sample_total_volume\n return msg\n }\n }\n}", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 930, - "y": 760, - "wires": [ - [ - "4f6afc5a.81e454" - ] - ] - }, - { - "id": "e73fd87d.d24e4", - "type": "function", - "z": "b771c342.49603", - "name": "get acq_minimum_mesh", - "func": "msg.payload = msg.payload.acq_minimum_mesh;\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 330, - "y": 360, - "wires": [ - [ - "1aad56b31b5647ce" - ] - ] - }, - { - "id": "489c8e06.cc7d6", - "type": "function", - "z": "b771c342.49603", - "name": "get acq_maximum_mesh", - "func": "msg.payload = msg.payload.acq_maximum_mesh;\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 330, - "y": 400, - "wires": [ - [ - "10eb31a2d7a6590c" - ] - ] - }, - { - "id": "58de1340.3cc354", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "sample_dilution_factor", - "label": "Concentration Factor", - "tooltip": "0.5 if diluted by two; 2 if concentrated by a factor 2", - "group": "3e1ba03d.f01d8", - "order": 13, - "width": 10, - "height": 1, - "passthru": true, - "mode": "number", - "delay": "300", - "topic": "sample_dilution_factor", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 640, - "y": 480, - "wires": [ - [ - "9f501f49.45645" - ] - ] - }, - { - "id": "4f6afc5a.81e454", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "sample_total_volume", - "label": "Filtered volume (in L)", - "tooltip": "Calculated or hand filled", - "group": "3e1ba03d.f01d8", - "order": 11, - "width": 0, - "height": 0, - "passthru": true, - "mode": "text", - "delay": "300", - "topic": "sample_total_volume", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 1220, - "y": 760, - "wires": [ - [ - "e1f2f6eb.fe1dd" - ] - ] - }, - { - "id": "e1f2f6eb.fe1dd", - "type": "function", - "z": "b771c342.49603", - "name": "set global", - "func": "global.set(msg.topic,msg.payload);", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 1420, - "y": 760, - "wires": [ - [] - ] - }, - { - "id": "e9bc112c.eb75f8", - "type": "function", - "z": "b771c342.49603", - "name": "Calculate volume", - "func": "if (msg.topic == \"sample_total_flowmeter_start\"){\n context.set(\"sample_total_flowmeter_start\", msg.payload);\n}\nif (msg.topic == \"sample_total_flowmeter_end\"){\n context.set(\"sample_total_flowmeter_end\", msg.payload);\n}\n\nif (context.keys().length == 2){\n sample_total_volume = context.get(\"sample_total_flowmeter_end\") - context.get(\"sample_total_flowmeter_start\");\n msg.topic=\"sample_total_volume\"\n msg.payload=sample_total_volume\n return msg\n}\n", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 1610, - "y": 240, - "wires": [ - [ - "4f6afc5a.81e454" - ] - ] - }, - { - "id": "cdd4181922eecf11", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "sample_speed_through_water", - "label": "Speed Through Water (kts)", - "tooltip": "in knots", - "group": "cf5d9f0e.d57e7", - "order": 2, - "width": 10, - "height": 1, - "passthru": true, - "mode": "number", - "delay": "300", - "topic": "sample_speed_through_water", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 610, - "y": 520, - "wires": [ - [ - "9f501f49.45645" - ] - ] - }, - { - "id": "1aad56b31b5647ce", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "acq_minimum_mesh", - "label": "Minimal fraction size (μm)", - "tooltip": "Net mesh pore size or minimal filtration mesh pore size", - "group": "3e1ba03d.f01d8", - "order": 7, - "width": 5, - "height": 1, - "passthru": true, - "mode": "number", - "delay": "300", - "topic": "acq_minimum_mesh", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 640, - "y": 360, - "wires": [ - [ - "9f501f49.45645" - ] - ] - }, - { - "id": "10eb31a2d7a6590c", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "acq_maximum_mesh", - "label": "Maximal fraction size (μm)", - "tooltip": "Maximal filtration mesh pore size", - "group": "3e1ba03d.f01d8", - "order": 8, - "width": 5, - "height": 1, - "passthru": true, - "mode": "number", - "delay": "300", - "topic": "acq_maximum_mesh", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 640, - "y": 400, - "wires": [ - [ - "9f501f49.45645" - ] - ] - }, - { - "id": "3ac7b631f5d8ef90", - "type": "function", - "z": "b771c342.49603", - "name": "Culture check", - "func": "var activation_msg = {}\nvar date_msg = {}\nvar timestamp=new Date().toISOString();\n\nif (msg.payload === \"culture\"){\n activation_msg.payload = {\"group\":{\"show\":[\"Sample_Culture_Date_and_Time\"],\"hide\":[\"Sample_Sample_Location\", \"Sample_Net_Metadata\"]}};\n global.set(\"object_lat\", \"-90.0000\")\n global.set(\"object_lon\", \"0.0000\")\n date_msg.payload = {\"object_date\": timestamp.split('T')[0],\n \"object_time\": timestamp.split('T')[1].split('.')[0]}\n return [activation_msg, date_msg];\n}\nelse if (msg.payload === \"test\"){\n activation_msg.payload = {\"group\":{\"hide\":[\"Sample_Culture_Date_and_Time\", \"Sample_Sample_Location\", \"Sample_Net_Metadata\"]}};\n global.set(\"object_lat\", \"-90.0000\")\n global.set(\"object_lon\", \"0.0000\")\n global.set(\"object_date\", timestamp.split('T')[0])\n global.set(\"object_time\", timestamp.split('T')[1].split('.')[0])\n return [activation_msg, null];\n}\nelse{\n return [null, null]\n}\n\n", - "outputs": 2, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 1100, - "y": 320, - "wires": [ - [ - "cbb123ab.fd3428" - ], - [ - "05c6aff2afbd69cf" - ] - ], - "outputLabels": [ - "decknet activation", - "" - ] - }, - { - "id": "05c6aff2afbd69cf", - "type": "ui_form", - "z": "b771c342.49603", - "name": "culture_timestamp", - "label": "Culture timestamp", - "group": "7bc0a4c416e4545c", - "order": 1, - "width": 0, - "height": 0, - "options": [ - { - "label": "Date (YYYY-MM-DD, UTC)", - "value": "object_date", - "type": "text", - "required": true, - "rows": null - }, - { - "label": "Time (HH:MM(:SS), UTC 24h)", - "value": "object_time", - "type": "text", - "required": true, - "rows": null - } - ], - "formValue": { - "object_date": "", - "object_time": "" - }, - "payload": "", - "submit": "Validate", - "cancel": "Reset", - "topic": "culture_timestamp", - "topicType": "str", - "splitLayout": false, - "className": "", - "x": 650, - "y": 700, - "wires": [ - [ - "14658615.47c862", - "f8044c35996322e6" - ] - ] - }, - { - "id": "a9fb1f4b83fc25a7", - "type": "change", - "z": "b771c342.49603", - "name": "Repopulate input fields", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 400, - "y": 580, - "wires": [ - [ - "c33f1124.af6688" - ] - ] - }, - { - "id": "ad54b89540460d27", - "type": "change", - "z": "b771c342.49603", - "name": "Repopulate input fields", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 400, - "y": 620, - "wires": [ - [ - "358908cd.416ab" - ] - ] - }, - { - "id": "c21bf0244e67e40a", - "type": "change", - "z": "b771c342.49603", - "name": "Repopulate input fields", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 400, - "y": 660, - "wires": [ - [ - "56d40584.eff4e4" - ] - ] - }, - { - "id": "f8044c35996322e6", - "type": "change", - "z": "b771c342.49603", - "name": "Repopulate input fields", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 400, - "y": 700, - "wires": [ - [ - "05c6aff2afbd69cf" - ] - ] - }, - { - "id": "8b48a02877b7b6d6", - "type": "inject", - "z": "b771c342.49603", - "name": "", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "", - "payload": "1", - "payloadType": "num", - "x": 270, - "y": 480, - "wires": [ - [ - "58de1340.3cc354" - ] - ] - }, - { - "id": "6a84252a.d52a0c", - "type": "ui_template", - "z": "bccd1f23.87219", - "group": "833bc5bb.217ba8", - "name": "Stream Pi Camera", - "order": 1, - "width": 18, - "height": 14, - "format": "
\n \"If\n
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "className": "", - "x": 610, - "y": 40, - "wires": [ - [] - ] - }, - { - "id": "dc48dc42.98d18", - "type": "function", - "z": "bccd1f23.87219", - "name": "set global", - "func": "global.set(msg.topic,msg.payload);", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 880, - "y": 440, - "wires": [ - [] - ] - }, - { - "id": "811cd88c.daf528", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "down", - "group": "fbd92986.1028c8", - "order": 8, - "width": 4, - "height": 1, - "passthru": true, + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 850, + "y": 680, + "wires": [["7088a5be.0c79a4"]] + }, + { + "id": "6919465f.332e5", + "type": "ui_text", + "z": "cb95299c.2817c8", + "group": "46be9c86.dea684", + "order": 1, + "width": 10, + "height": 1, + "name": "segmenter", + "label": "Segmenter status:", + "format": "{{msg.payload.status}}", + "layout": "row-spread", + "x": 810, + "y": 720, + "wires": [] + }, + { + "id": "fa3b7929.ac7da8", + "type": "ui_text", + "z": "cb95299c.2817c8", + "group": "46be9c86.dea684", + "order": 5, + "width": 4, + "height": 1, + "name": "counter", + "label": "", + "format": "{{msg.payload}}", + "layout": "col-center", + "x": 1320, + "y": 800, + "wires": [] + }, + { + "id": "640ece83.88cab", + "type": "inject", + "z": "cb95299c.2817c8", + "name": "Init graphs", + "props": [ + { + "p": "payload" + }, + { + "p": "topic", + "vt": "str" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "object count", + "payload": "0", + "payloadType": "num", + "x": 810, + "y": 880, + "wires": [["4f3f7c4a.cb21c4"]] + }, + { + "id": "25867454.a8e334", + "type": "link in", + "z": "cb95299c.2817c8", + "name": "Segmenter module status", + "links": ["dcf5bd45.16a8d"], + "x": 295, + "y": 740, + "wires": [["aa38dbbc.cf0a9"]] + }, + { + "id": "c8749cbb.55254", + "type": "function", + "z": "cb95299c.2817c8", + "name": "set global", + "func": "global.set(msg.topic, msg.payload);", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 960, + "y": 380, + "wires": [[]] + }, + { + "id": "d43c3ed9.e6cb1", + "type": "ui_template", + "z": "cb95299c.2817c8", + "group": "46be9c86.dea684", + "name": "Object counts", + "order": 3, + "width": 0, + "height": 0, + "format": "

Object counts

", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": true, + "templateScope": "local", + "x": 1340, + "y": 760, + "wires": [[]] + }, + { + "id": "33c28dc1.238002", + "type": "function", + "z": "cb95299c.2817c8", + "name": "prepare segmentation", + "func": "global.set('obj_counter', 0);\n\nvar segmentation_list = flow.get('segmentation_list')\nif (segmentation_list !== undefined && segmentation_list !== \"\") {\n msg.payload['path'] = segmentation_list\n}\n\n\nvar force = flow.get('force')\nif (force !== undefined && force !== \"\") {\n msg.payload['settings'] = {\"force\":Boolean(force)}\n}\n\n\nvar recursive = flow.get('recursive')\nif (recursive !== undefined && recursive !== \"\") {\n if (\"settings\" in msg.payload){\n msg.payload.settings[\"recursive\"] = Boolean(recursive)\n }\n else{\n msg.payload['settings'] = {\"recursive\": Boolean(recursive)}\n }\n}\n\nvar ecotaxa = flow.get('ecotaxa')\nif (ecotaxa !== undefined && ecotaxa !== \"\") {\n if (\"settings\" in msg.payload){\n msg.payload.settings[\"ecotaxa\"] = Boolean(ecotaxa)\n }\n else{\n msg.payload['settings'] = {\"ecotaxa\": Boolean(ecotaxa)}\n }\n}\n\nvar keep = flow.get('keep')\nif (keep !== undefined && keep !== \"\") {\n if (\"settings\" in msg.payload){\n msg.payload.settings[\"keep\"] = Boolean(keep)\n }\n else{\n msg.payload['settings'] = {\"keep\": Boolean(keep)}\n }\n}\n\nvar process_id = global.get('process_id')\nif (process_id !== undefined && process_id !== \"\") {\n if (\"settings\" in msg.payload){\n msg.payload.settings[\"process_id\"] = process_id\n }\n else{\n msg.payload['settings'] = {\"process_id\": process_id}\n }\n}\n\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 620, + "y": 460, + "wires": [["16f3cef4.0acac9"]] + }, + { + "id": "fa12f9f8.00cfa8", + "type": "subflow:1c24ad9c.bebec2", + "z": "cb95299c.2817c8", + "name": "", + "env": [], + "x": 430, + "y": 380, + "wires": [["3b72d11c.86e9e6"]] + }, + { + "id": "3b72d11c.86e9e6", + "type": "function", + "z": "cb95299c.2817c8", + "name": "get process_id", + "func": "msg.payload = msg.payload.process_id;\nmsg.topic = \"process_id\";\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 600, + "y": 380, + "wires": [["56971109c8be3b54"]] + }, + { + "id": "3ea12061.ce62c", + "type": "ui_list", + "z": "cb95299c.2817c8", + "group": "abeb6dad.635a2", + "name": "", + "order": 9, + "width": 10, + "height": 11, + "lineType": "one", + "actionType": "check", + "allowHTML": false, + "outputs": 1, + "topic": "", + "x": 770, + "y": 140, + "wires": [["cb3b87b5.63c4"]] + }, + { + "id": "8bd8fb2c.53fa4", + "type": "dir2files", + "z": "cb95299c.2817c8", + "name": "", + "dirname": "/home/pi/data/img/", + "pathRegex": "", + "isRecursive": true, + "findDir": true, + "isArray": true, + "x": 460, + "y": 140, + "wires": [["ba2947.c854deb8"]] + }, + { + "id": "127d4ee.f8ad1b1", + "type": "ui_button", + "z": "cb95299c.2817c8", + "name": "Refresh", + "group": "abeb6dad.635a2", + "order": 8, + "width": 0, + "height": 0, + "passthru": false, + "label": "Update acquisition's folder list", + "tooltip": "Refresh the list of previous acquisitions", + "color": "", + "bgcolor": "", + "icon": "mi-find_replace", + "payload": "", + "payloadType": "date", + "topic": "update", + "x": 260, + "y": 140, + "wires": [["8bd8fb2c.53fa4", "56f845f5.e7c054"]] + }, + { + "id": "946ce9ee.092cf", + "type": "inject", + "z": "cb95299c.2817c8", + "name": "Init", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "payload": "", + "payloadType": "date", + "x": 270, + "y": 100, + "wires": [["8bd8fb2c.53fa4", "56f845f5.e7c054"]] + }, + { + "id": "cb3b87b5.63c4", + "type": "function", + "z": "cb95299c.2817c8", + "name": "update segmentation_list", + "func": "var segmentation_list = flow.get('segmentation_list');\n\nif (segmentation_list === undefined || segmentation_list === \"\") {\n segmentation_list = []\n console.log(\"error\")\n}\n\npath = \"/home/pi/data/img/\" + msg.payload.title\n\nif (msg.payload.isChecked){\n if (segmentation_list.includes(path) === false){\n segmentation_list.push(path)\n }\n // Element already in list, don't push it more than once\n //segmentation_list.push(msg.payload[\"title\"])\n}\nelse {\n var pos = segmentation_list.indexOf(path)\n segmentation_list.splice(pos, 1)\n}\n\nflow.set('segmentation_list', segmentation_list)", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 950, + "y": 140, + "wires": [[]] + }, + { + "id": "56f845f5.e7c054", + "type": "change", + "z": "cb95299c.2817c8", + "name": "Reset segmentation_list", + "rules": [ + { + "t": "set", + "p": "segmentation_list", + "pt": "flow", + "to": "[]", + "tot": "json" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 510, + "y": 100, + "wires": [[]] + }, + { + "id": "7fc72364.8f038c", + "type": "ui_template", + "z": "cb95299c.2817c8", + "group": "abeb6dad.635a2", + "name": "Update message", + "order": 1, + "width": 10, + "height": 3, + "format": "
You can choose here in which folder(s) you want the segmentation script to run. A few details though:\n
The segmentation is run recursively in all folders. So if you select a top level folder, the segmentation will be run in all subfolders.\n
Also, you will be able to chose wether for force the segmentation for folders in which it has run already.
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": true, + "templateScope": "local", + "x": 270, + "y": 40, + "wires": [[]] + }, + { + "id": "ba2947.c854deb8", + "type": "function", + "z": "cb95299c.2817c8", + "name": "remove common", + "func": "function remove_path(item, index, array) {\n array[index] = item.replace(\"/home/pi/data/img/\", \"\")\n} \n\nmsg.payload.forEach(remove_path)\n\nreturn msg", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 620, + "y": 140, + "wires": [["3ea12061.ce62c"]] + }, + { + "id": "21af0db1.c2c182", + "type": "ui_multistate_switch", + "z": "cb95299c.2817c8", + "name": "recursive toggle", + "group": "abeb6dad.635a2", + "order": 4, + "width": 5, + "height": 1, + "label": "Recursive folder", + "stateField": "payload", + "enableField": "enable", + "rounded": true, + "useThemeColors": true, + "hideSelectedLabel": false, + "options": [ + { + "label": "No", + "value": "0", + "valueType": "num", + "color": "#009933" + }, + { + "label": "Yes", + "value": "1", + "valueType": "num", + "color": "#999999" + } + ], + "x": 480, + "y": 220, + "wires": [["880b192a.88e2d"]] + }, + { + "id": "dffb9881.feef8", + "type": "ui_multistate_switch", + "z": "cb95299c.2817c8", + "name": "force toggle", + "group": "abeb6dad.635a2", + "order": 3, + "width": 5, + "height": 1, + "label": "Force rework", + "stateField": "payload", + "enableField": "enable", + "rounded": true, + "useThemeColors": true, + "hideSelectedLabel": false, + "options": [ + { + "label": "No", + "value": "0", + "valueType": "num", + "color": "#009933" + }, + { + "label": "Yes", + "value": "1", + "valueType": "num", + "color": "#999999" + } + ], + "x": 470, + "y": 300, + "wires": [["a4f68fa6.5d77f8"]] + }, + { + "id": "880b192a.88e2d", + "type": "change", + "z": "cb95299c.2817c8", + "name": "", + "rules": [ + { + "t": "set", + "p": "recursive", + "pt": "flow", + "to": "payload", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 690, + "y": 240, + "wires": [[]] + }, + { + "id": "a4f68fa6.5d77f8", + "type": "change", + "z": "cb95299c.2817c8", + "name": "", + "rules": [ + { + "t": "set", + "p": "force", + "pt": "flow", + "to": "payload", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 670, + "y": 280, + "wires": [[]] + }, + { + "id": "1ef1b43b.b0f064", + "type": "inject", + "z": "cb95299c.2817c8", + "name": "0", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "payload": "0", + "payloadType": "num", + "x": 270, + "y": 280, + "wires": [["dffb9881.feef8", "a4f68fa6.5d77f8"]] + }, + { + "id": "f078c068.eacf58", + "type": "ui_template", + "z": "cb95299c.2817c8", + "group": "46be9c86.dea684", + "name": "Stream Segmented object", + "order": 2, + "width": 10, + "height": 8, + "format": "
\n Latest object segmented:
\n \"If\n
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "className": "", + "x": 1380, + "y": 600, + "wires": [[]] + }, + { + "id": "43f97b93.b76294", + "type": "inject", + "z": "cb95299c.2817c8", + "name": "1", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "payload": "1", + "payloadType": "num", + "x": 270, + "y": 240, + "wires": [["21af0db1.c2c182", "880b192a.88e2d"]] + }, + { + "id": "4f3f7c4a.cb21c4", + "type": "change", + "z": "cb95299c.2817c8", + "name": "", + "rules": [ + { + "t": "set", + "p": "obj_counter", + "pt": "flow", + "to": "0", + "tot": "num" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 1020, + "y": 840, + "wires": [["fa3b7929.ac7da8", "9d53dbe2.dbffe8"]] + }, + { + "id": "6bce0f60.f48998", + "type": "link in", + "z": "cb95299c.2817c8", + "name": "", + "links": ["596fc9d4.46c75"], + "x": 855, + "y": 840, + "wires": [["4f3f7c4a.cb21c4"]] + }, + { + "id": "596fc9d4.46c75", + "type": "link out", + "z": "cb95299c.2817c8", + "name": "", + "links": ["6bce0f60.f48998"], + "x": 715, + "y": 500, + "wires": [] + }, + { + "id": "c72a1064.1ec388", + "type": "change", + "z": "cb95299c.2817c8", + "name": "Reset counters", + "rules": [ + { + "t": "set", + "p": "topic", + "pt": "msg", + "to": "object count", + "tot": "str" + }, + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "0", + "tot": "num" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 600, + "y": 500, + "wires": [["596fc9d4.46c75"]] + }, + { + "id": "9367534a.fb8568", + "type": "ui_multistate_switch", + "z": "cb95299c.2817c8", + "name": "Ecotaxa archive", + "group": "abeb6dad.635a2", + "order": 6, + "width": 5, + "height": 1, + "label": "Ecotaxa archive", + "stateField": "payload", + "enableField": "enable", + "rounded": true, + "useThemeColors": true, + "hideSelectedLabel": false, + "options": [ + { + "label": "No", + "value": "0", + "valueType": "num", + "color": "#009933" + }, + { + "label": "Yes", + "value": "1", + "valueType": "num", + "color": "#999999" + } + ], + "x": 1080, + "y": 220, + "wires": [["25ac4f9a.5b05c8"]] + }, + { + "id": "25ac4f9a.5b05c8", + "type": "change", + "z": "cb95299c.2817c8", + "name": "", + "rules": [ + { + "t": "set", + "p": "ecotaxa", + "pt": "flow", + "to": "payload", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 1280, + "y": 240, + "wires": [[]] + }, + { + "id": "bef78886.8f0b98", + "type": "inject", + "z": "cb95299c.2817c8", + "name": "1", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "payload": "1", + "payloadType": "num", + "x": 910, + "y": 240, + "wires": [["9367534a.fb8568", "25ac4f9a.5b05c8"]] + }, + { + "id": "32465a4e.8fcac6", + "type": "ui_multistate_switch", + "z": "cb95299c.2817c8", + "name": "Keep objects", + "group": "abeb6dad.635a2", + "order": 5, + "width": 5, + "height": 1, + "label": "Keep objects", + "stateField": "payload", + "enableField": "enable", + "rounded": true, + "useThemeColors": true, + "hideSelectedLabel": false, + "options": [ + { + "label": "No", + "value": "0", + "valueType": "num", + "color": "#009933" + }, + { + "label": "Yes", + "value": "1", + "valueType": "num", + "color": "#999999" + } + ], + "x": 1070, + "y": 300, + "wires": [["8dd6f57f.b77f98"]] + }, + { + "id": "8dd6f57f.b77f98", + "type": "change", + "z": "cb95299c.2817c8", + "name": "", + "rules": [ + { + "t": "set", + "p": "keep", + "pt": "flow", + "to": "payload", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 1270, + "y": 280, + "wires": [[]] + }, + { + "id": "8090df89.c029e", + "type": "inject", + "z": "cb95299c.2817c8", + "name": "1", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "payload": "1", + "payloadType": "num", + "x": 910, + "y": 280, + "wires": [["32465a4e.8fcac6", "8dd6f57f.b77f98"]] + }, + { + "id": "56971109c8be3b54", + "type": "ui_text_input", + "z": "cb95299c.2817c8", + "name": "process_id", + "label": "Process unique ID*", + "tooltip": "", + "group": "abeb6dad.635a2", + "order": 2, + "width": 10, + "height": 1, + "passthru": true, + "mode": "text", + "delay": 300, + "topic": "process_id", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 790, + "y": 380, + "wires": [["c8749cbb.55254"]] + }, + { + "id": "2911fbc6.d28c24", + "type": "ui_template", + "z": "c1660bc.e7ff7f8", + "group": "c0ebfc57.42527", + "name": "Image browser", + "order": 1, + "width": "0", + "height": "0", + "format": "
\n\n
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "className": "", + "x": 400, + "y": 100, + "wires": [[]] + }, + { + "id": "4f02c726.de69b8", + "type": "ui_button", + "z": "9daf9e2b.019fc", + "name": "", + "group": "a7d64879.38298", + "order": 4, + "width": "6", + "height": 1, + "passthru": false, + "label": "Reboot", + "tooltip": "", + "color": "", + "bgcolor": "#AD1625", + "className": "", + "icon": "fa-repeat fa-2x", + "payload": "reboot", + "payloadType": "str", + "topic": "reboot", + "topicType": "str", + "x": 160, + "y": 240, + "wires": [["611a8b1c.a829b4"]] + }, + { + "id": "611a8b1c.a829b4", + "type": "exec", + "z": "9daf9e2b.019fc", + "command": "sudo", + "addpay": "payload", + "append": "now", + "useSpawn": "false", + "timer": "2", + "winHide": false, + "oldrc": false, + "name": "sudo cmd now", + "x": 480, + "y": 280, + "wires": [[], [], []] + }, + { + "id": "bc76c4d6.a7ad28", + "type": "ui_button", + "z": "9daf9e2b.019fc", + "name": "", + "group": "a7d64879.38298", + "order": 5, + "width": "6", + "height": 1, + "passthru": false, + "label": "Shutdown", + "tooltip": "", + "color": "", + "bgcolor": "#AD1625", + "className": "", + "icon": "fa-power-off fa-2x", + "payload": "shutdown", + "payloadType": "str", + "topic": "shutdown", + "topicType": "str", + "x": 160, + "y": 320, + "wires": [["611a8b1c.a829b4"]] + }, + { + "id": "b81b990a.d4dca", + "type": "link in", + "z": "9daf9e2b.019fc", + "name": "Shutdown", + "links": ["e08cfcb8.2a67e8"], + "x": 195, + "y": 280, + "wires": [["611a8b1c.a829b4"]] + }, + { + "id": "ea4fae012404854c", + "type": "ui_button", + "z": "9daf9e2b.019fc", + "name": "", + "group": "a7d64879.38298", + "order": 2, + "width": "6", + "height": 1, + "passthru": true, + "label": "Restart Hardware Controller", + "tooltip": "", + "color": "", + "bgcolor": "#AD1625", + "className": "", + "icon": "fa-refresh fa-2x", + "payload": "Restarting hardware controller...", + "payloadType": "str", + "topic": "", + "topicType": "str", + "x": 440, + "y": 420, + "wires": [["c54d948575dbcff8", "d10f3ffd98055447"]] + }, + { + "id": "438febd245a9f73c", + "type": "link in", + "z": "9daf9e2b.019fc", + "name": "Restart Hardware Controller", + "links": ["e41870d7.300eb8", "3973b999ee7b3b1d"], + "x": 195, + "y": 420, + "wires": [["ea4fae012404854c"]] + }, + { + "id": "c54d948575dbcff8", + "type": "exec", + "z": "9daf9e2b.019fc", + "command": "sudo systemctl restart planktoscope-org.device-backend.controller.service", + "addpay": false, + "append": "", + "useSpawn": "false", + "timer": "", + "winHide": false, + "oldrc": false, + "name": "Restart hardware controller", + "x": 780, + "y": 420, + "wires": [[], [], []] + }, + { + "id": "e2e5ce0351a6cc11", + "type": "ui_button", + "z": "9daf9e2b.019fc", + "name": "", + "group": "a7d64879.38298", + "order": 3, + "width": "6", + "height": 1, + "passthru": true, + "label": "Restart Segmenter", + "tooltip": "", + "color": "", + "bgcolor": "#AD1625", + "className": "", + "icon": "fa-refresh fa-2x", + "payload": "Restarting segmenter...", + "payloadType": "str", + "topic": "", + "topicType": "str", + "x": 410, + "y": 500, + "wires": [["2cdbadb65d0e1b20", "9c1629488b02fdba"]] + }, + { + "id": "2cdbadb65d0e1b20", + "type": "exec", + "z": "9daf9e2b.019fc", + "command": "docker restart apps_ps_backend_proc-segmenter-server-1", + "addpay": false, + "append": "", + "useSpawn": "false", + "timer": "", + "winHide": false, + "oldrc": false, + "name": "Restart segmenter", + "x": 750, + "y": 500, + "wires": [[], [], []] + }, + { + "id": "7b64209d734e4e2c", + "type": "ui_template", + "z": "9daf9e2b.019fc", + "group": "a7d64879.38298", + "name": "Logs", + "order": 1, + "width": "0", + "height": "0", + "format": "

\n The PlanktoScope software application consists of three components: a Node-RED dashboard which provides the user interface you're using; a Hardware Controller\n which executes commands sent from the Node-RED dashboard for hardware control and image acquisition; and a Segmenter which processes an acquired dataset of\n images and isolates objects from those images. Each component has its own independent log of messages, managed separately from the logs for the other components.\n

\n

\n All three components have live-updating logs which you can monitor. Additionally, the Hardware Controller and the Segmenter also save all of their log messages\n to files which you can browse and download. Those software components create a new log file each time they start, and the name of the log file includes the time\n in the PlanktoScope's clock when the software component started. However, if your PlanktoScope's clock is usually wrong, it makes the log files difficult to navigate.\n This will be fixed in a future version of the software.\n

\n

\n If you need to share your logs with other people (e.g. on Slack or GitHub), you should open the \"Downloadable Logs\" links, and then you can select one file or multiple\n log files for downloading as a zip archive.\n

\n", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": true, + "templateScope": "local", + "className": "", + "x": 630, + "y": 180, + "wires": [[]] + }, + { + "id": "d10f3ffd98055447", + "type": "ui_toast", + "z": "9daf9e2b.019fc", + "position": "top right", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 0, + "ok": "OK", + "cancel": "", + "raw": false, + "className": "", + "topic": "", + "name": "", + "x": 750, + "y": 380, + "wires": [] + }, + { + "id": "9c1629488b02fdba", + "type": "ui_toast", + "z": "9daf9e2b.019fc", + "position": "top right", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 0, + "ok": "OK", + "cancel": "", + "raw": false, + "className": "", + "topic": "", + "name": "", + "x": 750, + "y": 460, + "wires": [] + }, + { + "id": "3910d662.fa1f7a", + "type": "exec", + "z": "1371dec5.76e671", + "command": "df -h | grep /dev/root | awk -F ' ' '{print $5}' | tr -d % | tr \"\\n$\" \"\\ \" | sed 's/,/./' | tr -d \" \"", + "addpay": false, + "append": "", + "useSpawn": "", + "timer": "", + "name": "Disk Usage", + "x": 330, + "y": 120, + "wires": [["eaf74a43.fa27d"], [], []] + }, + { + "id": "1cd5b4c0.46af9b", + "type": "inject", + "z": "1371dec5.76e671", + "name": "update: 5s", + "props": [ + { + "p": "payload" + }, + { + "p": "topic", + "vt": "str" + } + ], + "repeat": "5", + "crontab": "", + "once": false, + "onceDelay": "", + "topic": "", + "payload": "", + "payloadType": "date", + "x": 110, + "y": 160, + "wires": [ + [ + "3910d662.fa1f7a", + "aa2e4cd182dbc776", + "797675a937dc1629", + "f6f570b10c675854" + ] + ] + }, + { + "id": "569154a.b53182c", + "type": "inject", + "z": "1371dec5.76e671", + "name": "once", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": "", + "topic": "", + "payload": "start", + "payloadType": "str", + "x": 130, + "y": 700, + "wires": [["5883e629f5d546ed"]] + }, + { + "id": "4828d2f4.7c712c", + "type": "function", + "z": "1371dec5.76e671", + "name": "set global", + "func": "global.set(\"acq_instrument_id\",msg.payload);\n", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 580, + "y": 720, + "wires": [[]] + }, + { + "id": "e2f39a35.f57298", + "type": "subflow:1c24ad9c.bebec2", + "z": "1371dec5.76e671", + "name": "", + "env": [], + "x": 130, + "y": 640, + "wires": [["9b64f397101c2762"]] + }, + { + "id": "3e64877a.9684b", + "type": "function", + "z": "1371dec5.76e671", + "name": "set global", + "func": "global.set(\"acq_software\", \"PlanktoScope \" + msg.payload);\n", + "outputs": 1, + "timeout": "", + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 820, + "y": 520, + "wires": [[]] + }, + { + "id": "bdc6718a.dd5d48", + "type": "ui_text", + "z": "1371dec5.76e671", + "group": "ce9e278.781eed8", + "order": 2, + "width": 0, + "height": 0, + "name": "", + "label": "Instrument Type", + "format": "{{msg.payload}}", + "layout": "row-spread", + "className": "", + "style": false, + "font": "", + "fontSize": "", + "color": "#000000", + "x": 600, + "y": 640, + "wires": [] + }, + { + "id": "a400a97e.e333a8", + "type": "ui_text", + "z": "1371dec5.76e671", + "group": "ce9e278.781eed8", + "order": 1, + "width": 0, + "height": 0, + "name": "", + "label": "Instrument Name", + "format": "{{msg.payload}}", + "layout": "row-spread", + "x": 610, + "y": 680, + "wires": [] + }, + { + "id": "8343fa69.49339", + "type": "ui_text", + "z": "1371dec5.76e671", + "group": "ce9e278.781eed8", + "order": 3, + "width": 0, + "height": 0, + "name": "", + "label": "Software Version", + "format": "{{msg.payload}}", + "layout": "row-spread", + "className": "", + "style": false, + "font": "", + "fontSize": "", + "color": "#000000", + "x": 850, + "y": 560, + "wires": [] + }, + { + "id": "f783aefd.c3bfd8", + "type": "ui_text", + "z": "1371dec5.76e671", + "group": "ce9e278.781eed8", + "order": 4, + "width": 0, + "height": 0, + "name": "", + "label": "Camera Name", + "format": "{{msg.payload}}", + "layout": "row-spread", + "x": 600, + "y": 760, + "wires": [] + }, + { + "id": "30067f35.532f2", + "type": "link in", + "z": "1371dec5.76e671", + "name": "Camera Name", + "links": ["559a8085.1d6b9"], + "x": 155, + "y": 760, + "wires": [["f783aefd.c3bfd8"]] + }, + { + "id": "eaf74a43.fa27d", + "type": "switch", + "z": "1371dec5.76e671", + "name": "if disk > 90%", + "property": "payload", + "propertyType": "msg", + "rules": [ + { + "t": "gte", + "v": "90", + "vt": "num" + } + ], + "checkall": "true", + "repair": false, + "outputs": 1, + "x": 590, + "y": 120, + "wires": [["6d09f428.930bcc"]] + }, + { + "id": "46d5e78b.15f998", + "type": "ui_toast", + "z": "1371dec5.76e671", + "position": "dialog", + "displayTime": "10", + "highlight": "", + "sendall": true, + "outputs": 1, + "ok": "OK", + "cancel": "", + "raw": false, + "topic": "", + "name": "", + "x": 1090, + "y": 120, + "wires": [[]] + }, + { + "id": "24df077a.cb252", + "type": "change", + "z": "1371dec5.76e671", + "name": "full disk msg", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "\"Your drive has reached 90% capacity, you should do a backup to an external drive and a purge.\"", + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 930, + "y": 120, + "wires": [["46d5e78b.15f998"]] + }, + { + "id": "6d09f428.930bcc", + "type": "delay", + "z": "1371dec5.76e671", + "name": "", + "pauseType": "rate", + "timeout": "5", + "timeoutUnits": "seconds", + "rate": "1", + "nbRateUnits": "5", + "rateUnits": "minute", + "randomFirst": "1", + "randomLast": "5", + "randomUnits": "seconds", + "drop": true, + "allowrate": false, + "outputs": 1, + "x": 760, + "y": 120, + "wires": [["24df077a.cb252"]] + }, + { + "id": "5883e629f5d546ed", + "type": "file in", + "z": "1371dec5.76e671", + "name": "Get machine name", + "filename": "/run/machine-name", + "filenameType": "str", + "format": "utf8", + "chunk": false, + "sendError": false, + "encoding": "none", + "allProps": false, + "x": 350, + "y": 700, + "wires": [["a400a97e.e333a8", "4828d2f4.7c712c"]] + }, + { + "id": "9b64f397101c2762", + "type": "change", + "z": "1371dec5.76e671", + "name": "Get acq_instrument", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.acq_instrument", + "tot": "msg" + }, + { + "t": "set", + "p": "topic", + "pt": "msg", + "to": "acq_instrument", + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 350, + "y": 640, + "wires": [["bdc6718a.dd5d48"]] + }, + { + "id": "99725e1437cc390b", + "type": "file in", + "z": "1371dec5.76e671", + "name": "Versioning File", + "filename": "/usr/share/planktoscope/installer-versioning.yml", + "filenameType": "str", + "format": "utf8", + "chunk": false, + "sendError": false, + "encoding": "none", + "allProps": false, + "x": 240, + "y": 540, + "wires": [["f4e21e28bd903f6d"]], + "info": "# PlanktoScope Help\nThis Node will read the content of the file named **config.txt** containing all the input placeholders.\n" + }, + { + "id": "6a0fa173874c3ddd", + "type": "inject", + "z": "1371dec5.76e671", + "name": "once", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": "", + "topic": "", + "payload": "start", + "payloadType": "str", + "x": 90, + "y": 540, + "wires": [["99725e1437cc390b"]] + }, + { + "id": "f4e21e28bd903f6d", + "type": "yaml", + "z": "1371dec5.76e671", + "property": "payload", + "name": "", + "x": 390, + "y": 540, + "wires": [["d6264e3e29b68c6e", "aa84b912c996c69e", "fba22dc2c16b3ec8"]] + }, + { + "id": "d6264e3e29b68c6e", + "type": "change", + "z": "1371dec5.76e671", + "name": "Get version", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.version", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 590, + "y": 540, + "wires": [["3e64877a.9684b", "8343fa69.49339"]] + }, + { + "id": "aa84b912c996c69e", + "type": "change", + "z": "1371dec5.76e671", + "name": "Get repo", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.repo", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 580, + "y": 500, + "wires": [["fd55e7a43d9bdbbb"]] + }, + { + "id": "fd55e7a43d9bdbbb", + "type": "function", + "z": "1371dec5.76e671", + "name": "set global", + "func": "global.set(\"process_source\", msg.payload);\n", + "outputs": 1, + "timeout": "", + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 820, + "y": 480, + "wires": [[]] + }, + { + "id": "fba22dc2c16b3ec8", + "type": "change", + "z": "1371dec5.76e671", + "name": "Get commit", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.commit", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 590, + "y": 580, + "wires": [["2ddc75a4ac38a17f"]] + }, + { + "id": "2ddc75a4ac38a17f", + "type": "function", + "z": "1371dec5.76e671", + "name": "set global", + "func": "global.set(\"process_commit\", msg.payload);\n", + "outputs": 1, + "timeout": "", + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 820, + "y": 600, + "wires": [[]] + }, + { + "id": "797675a937dc1629", + "type": "ui_template", + "z": "1371dec5.76e671", + "group": "3da7da8f.179606", + "name": "Metrics panel", + "order": 2, + "width": "0", + "height": "0", + "format": "
\n

\n The instrument's system time is different from your web browser's time by {{drift}}.\n As a result, timestamps in your datasets will be incorrect.\n Additionally, system metrics will not be recorded or shown correctly.\n Additionally, you will see incorrectly-aligned graphs in the metrics below.\n

\n

Please change the instrument's system time or your web browser's time to accurate values.

\n

\n \n

\n
\n\n
\n

Loading system metrics, please wait...

\n
\n\n
\n \n
\n\n\n", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "className": "", + "x": 330, + "y": 280, + "wires": [[]] + }, + { + "id": "aa2e4cd182dbc776", + "type": "function", + "z": "1371dec5.76e671", + "name": "Get system time", + "func": "var date = new Date();\ndate.setSeconds(0, 0);\nmsg.payload = (\n date.toISOString().replace('T', ' ').replace(/:\\d+\\.\\d+Z/,' UTC')\n);\nreturn msg", + "outputs": 1, + "timeout": "", + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 340, + "y": 240, + "wires": [["7c9ee522f6dbd3b0"]] + }, + { + "id": "7c9ee522f6dbd3b0", + "type": "ui_text", + "z": "1371dec5.76e671", + "group": "ce9e278.781eed8", + "order": 5, + "width": 0, + "height": 0, + "name": "", + "label": "System Time", + "format": "{{msg.payload}}", + "layout": "row-spread", + "className": "", + "style": false, + "font": "", + "fontSize": "", + "color": "#000000", + "x": 590, + "y": 240, + "wires": [] + }, + { + "id": "6dc9862f2eebe935", + "type": "http in", + "z": "1371dec5.76e671", + "name": "POST /api/system-time", + "url": "/api/system-time", + "method": "post", + "upload": false, + "swaggerDoc": "", + "x": 120, + "y": 360, + "wires": [["a7994a561866dc94", "dea222e9a6553cac"]] + }, + { + "id": "1c4113d4c933fd4b", + "type": "ui_toast", + "z": "1371dec5.76e671", + "position": "top right", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 0, + "ok": "OK", + "cancel": "", + "raw": false, + "className": "", + "topic": "Setting system time", + "name": "", + "x": 610, + "y": 340, + "wires": [] + }, + { + "id": "a7994a561866dc94", + "type": "function", + "z": "1371dec5.76e671", + "name": "Get system time", + "func": "var date = new Date(msg.payload.timestamp);\nmsg.payload = (\n date.toISOString().replace('T', ' ').replace(/:\\d+\\.\\d+Z/,' UTC')\n);\nreturn msg", + "outputs": 1, + "timeout": "", + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 340, + "y": 340, + "wires": [["1c4113d4c933fd4b", "423659c62bae0524"]] + }, + { + "id": "814ce40bfc413777", + "type": "exec", + "z": "1371dec5.76e671", + "command": "sudo date -s", + "addpay": "payload", + "append": "", + "useSpawn": "", + "timer": "", + "winHide": false, + "name": "Set system time", + "x": 600, + "y": 380, + "wires": [[], [], []] + }, + { + "id": "dea222e9a6553cac", + "type": "function", + "z": "1371dec5.76e671", + "name": "Prepare timestamp", + "func": "msg.payload = ('@' + msg.payload.timestamp).slice(0, -3);\nreturn msg;", + "outputs": 1, + "timeout": "", + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 350, + "y": 380, + "wires": [["814ce40bfc413777"]] + }, + { + "id": "f6f570b10c675854", + "type": "ui_template", + "z": "1371dec5.76e671", + "group": "ce9e278.781eed8", + "name": "Browser time", + "order": 6, + "width": "6", + "height": "1", + "format": "
\n

Browser Time

\n

{{time}}

\n
\n\n", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "className": "", + "x": 330, + "y": 200, + "wires": [[]] + }, + { + "id": "3822b843fda94733", + "type": "http in", + "z": "1371dec5.76e671", + "name": "GET /api/system-time", + "url": "/api/system-time", + "method": "get", + "upload": false, + "swaggerDoc": "", + "x": 120, + "y": 420, + "wires": [["5b0a65d3fe187424"]] + }, + { + "id": "5b0a65d3fe187424", + "type": "function", + "z": "1371dec5.76e671", + "name": "Get system time", + "func": "var date = new Date();\nmsg.payload = {'timestamp': date.getTime()};\nreturn msg", + "outputs": 1, + "timeout": "", + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 340, + "y": 420, + "wires": [["312a15407574b38e"]] + }, + { + "id": "423659c62bae0524", + "type": "http response", + "z": "1371dec5.76e671", + "name": "Send POST response", + "statusCode": "", + "headers": {}, + "x": 620, + "y": 300, + "wires": [] + }, + { + "id": "312a15407574b38e", + "type": "http response", + "z": "1371dec5.76e671", + "name": "Send GET response", + "statusCode": "", + "headers": { + "Content-Type": "application/json; charset=UTF-8" + }, + "x": 620, + "y": 420, + "wires": [] + }, + { + "id": "1fdf77b5.24e4e", + "type": "mqtt in", + "z": "9a22e67a.378818", + "name": "", + "topic": "status/#", + "qos": "0", + "datatype": "json", + "broker": "8dc3722c.06efa8", + "nl": false, + "rap": false, + "inputs": 0, + "x": 290, + "y": 340, + "wires": [["fa73983d.318188"]] + }, + { + "id": "4a1e9e3e.27506", + "type": "switch", + "z": "9a22e67a.378818", + "name": "Filter segmenter out", + "property": "topic", + "propertyType": "msg", + "rules": [ + { + "t": "else" + }, + { + "t": "cont", + "v": "status/segmenter", + "vt": "str" + } + ], + "checkall": "true", + "repair": false, + "outputs": 2, + "x": 620, + "y": 340, + "wires": [["58f2e0f.4e8b12"], ["dcf5bd45.16a8d"]] + }, + { + "id": "fa73983d.318188", + "type": "json", + "z": "9a22e67a.378818", + "name": "", + "property": "payload", + "action": "obj", + "pretty": true, + "x": 430, + "y": 340, + "wires": [["4a1e9e3e.27506"]] + }, + { + "id": "58f2e0f.4e8b12", + "type": "link out", + "z": "9a22e67a.378818", + "name": "Fluidic module status", + "links": ["bb628f8d.98f108"], + "x": 795, + "y": 320, + "wires": [] + }, + { + "id": "dcf5bd45.16a8d", + "type": "link out", + "z": "9a22e67a.378818", + "name": "Segmenter module status", + "links": ["25867454.a8e334"], + "x": 795, + "y": 360, + "wires": [] + }, + { + "id": "e41870d7.300eb8", + "type": "link out", + "z": "1eaf21c8.f7a21e", + "name": "Stepper config change", + "mode": "link", + "links": ["438febd245a9f73c"], + "x": 1495, + "y": 380, + "wires": [] + }, + { + "id": "2068e7f.f4efb18", + "type": "delay", + "z": "1eaf21c8.f7a21e", + "name": "", + "pauseType": "delay", + "timeout": "1", + "timeoutUnits": "seconds", + "rate": "1", + "nbRateUnits": "1", + "rateUnits": "second", + "randomFirst": "1", + "randomLast": "5", + "randomUnits": "seconds", + "drop": false, + "outputs": 1, + "x": 1180, + "y": 380, + "wires": [["e41870d7.300eb8"]] + }, + { + "id": "8e3b3d3c.955148", + "type": "subflow:4ed26b8b.253504", + "z": "1eaf21c8.f7a21e", + "name": "", + "env": [], + "x": 1220, + "y": 420, + "wires": [] + }, + { + "id": "54ba7f16.709ad8", + "type": "change", + "z": "1eaf21c8.f7a21e", + "name": "Get pump_steps_per_ml", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.pump_steps_per_ml", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 670, + "y": 400, + "wires": [["ee58b91c.396108"]] + }, + { + "id": "ee58b91c.396108", + "type": "ui_text_input", + "z": "1eaf21c8.f7a21e", + "name": "pump_steps_per_ml", + "label": "Pump: steps per mL", + "tooltip": "", + "group": "6be36295.0ab324", + "order": 6, + "width": 0, + "height": 0, + "passthru": false, + "mode": "number", + "delay": "2000", + "topic": "pump_steps_per_ml", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 940, + "y": 400, + "wires": [["2068e7f.f4efb18", "8e3b3d3c.955148"]] + }, + { + "id": "7534dfd9.8cf3e8", + "type": "ui_template", + "z": "1eaf21c8.f7a21e", + "group": "6be36295.0ab324", + "name": "Information", + "order": 1, + "width": "8", + "height": "3", + "format": "
\n

\n Changing one of these values will cause the Python hardware controller to restart, to reload the new hardware configuration.\n

\n

\n Warning: selecting a hardware version from the dropdown menu below will also overwrite all of your hardware settings, including your camera white balance settings.\n

\n

\n If you are not sure, you probably should not be touching anything here!\n

\n
\n", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": true, + "templateScope": "local", + "className": "", + "x": 610, + "y": 40, + "wires": [[]] + }, + { + "id": "a7e5c7f4.644678", + "type": "ui_dropdown", + "z": "1eaf21c8.f7a21e", + "name": "", + "label": "Hardware version", + "tooltip": "", + "place": "Select option", + "group": "6be36295.0ab324", + "order": 2, + "width": 0, + "height": 0, + "passthru": false, + "multiple": false, + "options": [ + { "label": "", - "tooltip": "", - "color": "", - "bgcolor": "", - "icon": "fa-angle-double-down fa-3x", - "payload": "DOWN", - "payloadType": "str", - "topic": "actuator/focus", - "x": 550, - "y": 800, - "wires": [ - [ - "65ad39d.b6d4d48" - ] - ] - }, - { - "id": "edda4df4.76de2", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "up", - "group": "fbd92986.1028c8", - "order": 1, - "width": 4, - "height": 1, - "passthru": false, + "value": "PlanktoScope v2.1", + "type": "str" + }, + { "label": "", - "tooltip": "", - "color": "", - "bgcolor": "", - "icon": "fa-angle-double-up fa-3x", - "payload": "UP", - "payloadType": "str", - "topic": "actuator/focus", - "x": 550, - "y": 760, - "wires": [ - [ - "65ad39d.b6d4d48" - ] - ] - }, - { - "id": "68962547.34a67c", - "type": "ui_text_input", - "z": "bccd1f23.87219", - "name": "pump_manual_volume", - "label": "Volume to pass (ml)", - "tooltip": "Tiny values are accepted down to 0.001mL", - "group": "707d9797.c8e798", - "order": 3, - "width": 2, - "height": 1, - "passthru": true, - "mode": "text", - "delay": "300", - "topic": "pump_manual_volume", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 600, - "y": 420, - "wires": [ - [ - "dc48dc42.98d18" - ] - ] - }, - { - "id": "6c792043.b6ff9", - "type": "ui_ui_control", - "z": "bccd1f23.87219", - "name": "", - "events": "change", - "x": 560, - "y": 1140, - "wires": [ - [] - ] - }, - { - "id": "902429eb.ceacb8", - "type": "ui_toast", - "z": "bccd1f23.87219", - "position": "dialog", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 1, - "ok": "OK", - "cancel": "", - "raw": false, - "topic": "", - "name": "", - "x": 570, - "y": 1220, - "wires": [ - [] - ] - }, - { - "id": "fe840e05.b46f3", - "type": "function", - "z": "bccd1f23.87219", - "name": "Check form", - "func": "var acq_fnumber_objective= global.get(\"acq_fnumber_objective\");\n\nif (acq_fnumber_objective === undefined || acq_fnumber_objective === \"\") {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Focal Length of the objective\";\n return [null, msg];\n}\n\nmsg.topic = \"Change Tab\";\nmsg.payload={\"tab\":\"Fluidic Acquisition\"};\nreturn [msg, null];", - "outputs": 2, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 330, - "y": 1180, - "wires": [ - [ - "6c792043.b6ff9", - "326a1d95.ca21aa" - ], - [ - "902429eb.ceacb8" - ] - ], - "outputLabels": [ - "message", - "error" - ] - }, - { - "id": "5846b1d4.7971b", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "Backward", - "group": "707d9797.c8e798", - "order": 2, - "width": 1, - "height": 1, - "passthru": false, + "value": "PlanktoScope v2.3", + "type": "str" + }, + { "label": "", - "tooltip": "", - "color": "", - "bgcolor": "", - "icon": "fa-rotate-left fa-2x", - "payload": "BACKWARD", - "payloadType": "str", - "topic": "actuator/pump", - "x": 560, - "y": 280, - "wires": [ - [ - "3cb96380.e575ec" - ] - ] - }, - { - "id": "2cab680b.baf888", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "Forward", - "group": "707d9797.c8e798", - "order": 4, - "width": 1, - "height": 1, - "passthru": true, + "value": "PlanktoScope v2.5", + "type": "str" + }, + { "label": "", - "tooltip": "", - "color": "", - "bgcolor": "", - "icon": "fa-rotate-right fa-2x", - "payload": "FORWARD", - "payloadType": "str", - "topic": "actuator/pump", - "x": 560, - "y": 320, - "wires": [ - [ - "3cb96380.e575ec" - ] - ] - }, - { - "id": "8038414a.34461", - "type": "function", - "z": "bccd1f23.87219", - "name": "Calculate optics", - "func": "var acq_fnumber_objective = String(global.get(\"acq_fnumber_objective\"));\nvar acq_camera = global.get(\"acq_camera\")\n\n// Those values needs to be recalculated, they are not good!\nif (acq_camera == \"HQ Camera\"){\n switch(acq_fnumber_objective) {\n case \"25\":\n acq_magnification= 0.6;\n process_pixel= 1.56;\n sug_min= 60;\n sug_max= 670;\n sug_flowrate= 3;\n break;\n case \"16\":\n acq_magnification= 1.6;\n process_pixel= 1.01;\n sug_min= 40;\n sug_max= 430;\n sug_flowrate= 2.4;\n break;\n case \"12\":\n acq_magnification= 1.20;\n process_pixel= 0.79;\n sug_min= 30;\n sug_max= 340;\n sug_flowrate= 1.25;\n break;\n case \"8\":\n acq_magnification= 1.78;\n process_pixel= 0.53;\n sug_min= 20;\n sug_max= 230;\n sug_flowrate= 0.42;\n break;\n case \"6\":\n acq_magnification= 2.36;\n process_pixel= 0.41;\n sug_min= 15;\n sug_max= 170;\n sug_flowrate= 0.32;\n break;\n }\n}\nelse if (acq_camera == \"Camera v2.1\"){\n switch(acq_fnumber_objective) {\n case \"25\":\n acq_magnification= 0.6;\n process_pixel= 1.86;\n sug_min= 60;\n sug_max= 670;\n sug_flowrate= 3;\n break;\n case \"16\":\n acq_magnification= 1.6;\n process_pixel= 0.7;\n sug_min= 40;\n sug_max= 430;\n sug_flowrate= 2.4;\n break;\n case \"12\":\n acq_magnification= 1.20;\n process_pixel= 0.94;\n sug_min= 30;\n sug_max= 340;\n sug_flowrate= 1.25;\n break;\n case \"8\":\n acq_magnification= 1.78;\n process_pixel= 0.63;\n sug_min= 20;\n sug_max= 230;\n sug_flowrate= 0.42;\n break;\n case \"6\":\n acq_magnification= 2.36;\n process_pixel= 0.48;\n sug_min= 15;\n sug_max= 170;\n sug_flowrate= 0.32;\n break;\n }\n}else {\n acq_magnification= \"ERROR\";\n process_pixel= \"ERROR\";\n sug_min= \"ERROR\";\n sug_max= \"ERROR\";\n sug_flowrate= \"ERROR\";\n}\n\nvar process_pixel_fixed = global.get(\"process_pixel_fixed\")\n\nif (process_pixel_fixed !== undefined && process_pixel_fixed !== \"\") {\n process_pixel = process_pixel_fixed\n}\n\nglobal.set(\"process_pixel\",process_pixel);\n\nglobal.set(\"acq_magnification\",acq_magnification);\n\n\nreturn [{payload: acq_fnumber_objective}, {payload: acq_magnification}, {payload: process_pixel}, {payload: sug_min}, {payload: sug_max}];", - "outputs": 5, - "timeout": "", - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 1080, - "y": 120, - "wires": [ - [], - [], - [], - [], - [] - ], - "inputLabels": [ - "acq_fnumber_objective" - ], - "outputLabels": [ - "acq_magnification", - "process_pixel", - "sug_min", - "sug_max", - "" - ] - }, - { - "id": "f61aaed5.1e64", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "", - "group": "7a0b4877.a5d268", - "order": 1, - "width": 2, - "height": 1, - "passthru": false, - "label": "Previous", - "tooltip": "", - "color": "#097479", - "bgcolor": "white", - "icon": "keyboard_return", - "payload": "{\"tab\":\"Sample\"}", - "payloadType": "json", - "topic": "", - "x": 140, - "y": 1140, - "wires": [ - [ - "6c792043.b6ff9" - ] - ] - }, - { - "id": "9ba6ec0a.22c96", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "", - "group": "7a0b4877.a5d268", - "order": 2, - "width": 2, - "height": 1, - "passthru": false, - "label": "Continue", - "tooltip": "", - "color": "#097479", - "bgcolor": "white", - "icon": "keyboard_tab", - "payload": "{\"tab\":\"Home\"}", - "payloadType": "json", - "topic": "", - "x": 140, - "y": 1180, - "wires": [ - [ - "fe840e05.b46f3" - ] - ] - }, - { - "id": "3cb96380.e575ec", - "type": "function", - "z": "bccd1f23.87219", - "name": "pump", - "func": "var manual_volume= global.get(\"pump_manual_volume\");\nvar flowrate= global.get(\"pump_flowrate\");\n\nif (manual_volume === undefined || manual_volume === \"\" || manual_volume === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Volume to pass\";\n return [null, msg];\n}\nelse if (flowrate === undefined || flowrate === \"\" || flowrate === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Flowrate\";\n return [null, msg];\n}\nelse {\n msg.topic = \"actuator/pump\";\n // msg.payload is FORWARD or BACKWARD here\n msg.payload={\"action\":\"move\", \n \"direction\":msg.payload,\n \"volume\":manual_volume,\n \"flowrate\":flowrate};\n}\nreturn [msg, null];", - "outputs": 2, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 750, - "y": 300, - "wires": [ - [ - "bdc8ce57.de1f08" - ], - [ - "8bcce348.efc1a" - ] - ], - "inputLabels": [ - "direction" - ], - "outputLabels": [ - "message", - "error" - ] - }, - { - "id": "8bcce348.efc1a", - "type": "ui_toast", - "z": "bccd1f23.87219", - "position": "dialog", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 1, - "ok": "OK", - "cancel": "", - "raw": false, - "topic": "", - "name": "", - "x": 1090, - "y": 300, - "wires": [ - [] - ] - }, - { - "id": "bdc8ce57.de1f08", - "type": "mqtt out", - "z": "bccd1f23.87219", - "name": "", - "topic": "", - "qos": "", - "retain": "", - "broker": "8dc3722c.06efa8", - "x": 1210, - "y": 260, - "wires": [] - }, - { - "id": "d71d224f.0585d8", - "type": "ui_toast", - "z": "bccd1f23.87219", - "position": "dialog", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 1, - "ok": "OK", - "cancel": "", - "raw": false, - "topic": "", - "name": "", - "x": 1090, - "y": 800, - "wires": [ - [] - ] - }, - { - "id": "65ad39d.b6d4d48", - "type": "function", - "z": "bccd1f23.87219", - "name": "focus", - "func": "var distance = global.get(\"focus_distance\");\nvar speed = global.get(\"focus_speed\");\n\nif (distance === undefined || distance === \"\" || distance === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Distance\";\n return [null, msg]\n}\nif (speed === undefined || speed === \"\" || speed === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Speed\";\n return [null, msg]\n}\n// msg.payload is UP or DOWN here\nmsg.payload={\"action\":\"move\", \n \"direction\":msg.payload,\n \"distance\":(distance/1000),\n \"speed\": (speed/1000)\n};\nreturn [msg, null];", - "outputs": 2, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 850, - "y": 780, - "wires": [ - [ - "62030521.88317c" - ], - [ - "d71d224f.0585d8" - ] - ], - "inputLabels": [ - "direction" - ], - "outputLabels": [ - "message", - "error" - ] - }, - { - "id": "1962d999.4a97e6", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "stop focus", - "group": "fbd92986.1028c8", - "order": 9, - "width": 0, - "height": 0, - "passthru": true, - "label": " STOP FOCUS", - "tooltip": "", - "color": "", - "bgcolor": "#AD1625", - "icon": "fa-pause fa-2x", - "payload": "{\"action\":\"stop\"}", - "payloadType": "json", - "topic": "actuator/focus", - "x": 570, - "y": 560, - "wires": [ - [ - "62030521.88317c" - ] - ] - }, - { - "id": "62030521.88317c", - "type": "mqtt out", - "z": "bccd1f23.87219", - "name": "", - "topic": "", - "qos": "", - "retain": "", - "broker": "8dc3722c.06efa8", - "x": 1210, - "y": 720, - "wires": [] - }, - { - "id": "3bd43039.bc5fb8", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "", - "group": "fbd92986.1028c8", - "order": 2, - "width": 4, - "height": 1, - "passthru": false, - "label": "UP 1mm", - "tooltip": "", - "color": "", - "bgcolor": "", - "icon": "fa-angle-up fa-3x", - "payload": "{\"action\":\"move\",\"direction\":\"UP\",\"distance\":1}", - "payloadType": "json", - "topic": "actuator/focus", - "topicType": "str", - "x": 560, - "y": 600, - "wires": [ - [ - "62030521.88317c" - ] - ] - }, - { - "id": "c0663029.2d03b", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "", - "group": "fbd92986.1028c8", - "order": 7, - "width": 4, - "height": 1, - "passthru": false, - "label": "DOWN 1mm", - "tooltip": "", - "color": "", - "bgcolor": "", - "icon": "fa-angle-down fa-3x", - "payload": "{\"action\":\"move\",\"direction\":\"DOWN\",\"distance\":1}", - "payloadType": "json", - "topic": "actuator/focus", - "topicType": "str", - "x": 570, - "y": 720, - "wires": [ - [ - "62030521.88317c" - ] - ] - }, - { - "id": "71f55a58.d7eaf4", - "type": "inject", - "z": "bccd1f23.87219", - "name": "Default: 500µm", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": "0.5", - "topic": "", - "payload": "500", - "payloadType": "num", - "x": 120, - "y": 460, - "wires": [ - [ - "be33e564.029358" - ] - ] - }, - { - "id": "9a1d0e7c.2d5a1", - "type": "inject", - "z": "bccd1f23.87219", - "name": "Default: OFF", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "", - "payload": "off", - "payloadType": "str", - "x": 130, - "y": 120, - "wires": [ - [ - "f0775525.cf806" - ] - ] - }, - { - "id": "f782a471.447748", - "type": "inject", - "z": "bccd1f23.87219", - "name": "Default: 2mL/min", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": "0.5", - "topic": "", - "payload": "2", - "payloadType": "num", - "x": 130, - "y": 380, - "wires": [ - [ - "cb2d5174.cfe9f" - ] - ] - }, - { - "id": "73b8252a.5ca754", - "type": "inject", - "z": "bccd1f23.87219", - "name": "Default: 2mL", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": "0.5", - "topic": "", - "payload": "2", - "payloadType": "num", - "x": 110, - "y": 420, - "wires": [ - [ - "68962547.34a67c" - ] - ] - }, - { - "id": "6451f991.aaac1", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "stop pump", - "group": "707d9797.c8e798", - "order": 5, - "width": 4, - "height": 1, - "passthru": true, - "label": " STOP PUMP", - "tooltip": "", - "color": "", - "bgcolor": "#AD1625", - "icon": "fa-pause fa-2x", - "payload": "{\"action\":\"stop\"}", - "payloadType": "json", - "topic": "actuator/pump", - "x": 570, - "y": 240, - "wires": [ - [ - "bdc8ce57.de1f08" - ] - ] - }, - { - "id": "cfc783d7.d6ceb", - "type": "link in", - "z": "bccd1f23.87219", - "name": "Optics recalculation", - "links": [ - "559a8085.1d6b9", - "5d5ad36d2c50dcc2" - ], - "x": 915, - "y": 120, - "wires": [ - [ - "8038414a.34461" - ] - ] - }, - { - "id": "326a1d95.ca21aa", - "type": "subflow:1c24ad9c.bebec2", - "z": "bccd1f23.87219", - "name": "", - "x": 550, - "y": 1180, - "wires": [ - [] - ] - }, - { - "id": "2d371e59.b0e50a", - "type": "inject", - "z": "bccd1f23.87219", - "name": "Default: 1000µm/s", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": "0.5", - "topic": "", - "payload": "1000", - "payloadType": "num", - "x": 130, - "y": 500, - "wires": [ - [ - "3a86de51.765b9a" - ] - ] - }, - { - "id": "167cda35.c9b6ae", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "", - "group": "fbd92986.1028c8", - "order": 3, - "width": 4, - "height": 1, - "passthru": false, - "label": "UP 100um", - "tooltip": "", - "color": "", - "bgcolor": "", - "icon": "fa-angle-up fa-3x", - "payload": "{\"action\":\"move\",\"direction\":\"UP\",\"distance\":0.1}", - "payloadType": "json", - "topic": "actuator/focus", - "topicType": "str", - "x": 570, - "y": 640, - "wires": [ - [ - "62030521.88317c" - ] - ] - }, - { - "id": "72a7c597.9374fc", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "", - "group": "fbd92986.1028c8", - "order": 6, - "width": 4, - "height": 1, - "passthru": false, - "label": "DOWN 100um", - "tooltip": "", - "color": "", - "bgcolor": "", - "icon": "fa-angle-down fa-3x", - "payload": "{\"action\":\"move\",\"direction\":\"DOWN\",\"distance\":0.1}", - "payloadType": "json", - "topic": "actuator/focus", - "topicType": "str", - "x": 580, - "y": 680, - "wires": [ - [ - "62030521.88317c" - ] - ] - }, - { - "id": "f0775525.cf806", - "type": "ui_multistate_switch", - "z": "bccd1f23.87219", - "name": "light_control", - "group": "4248342d.e55fac", - "order": 1, - "width": 6, - "height": 1, - "label": "Light ", - "stateField": "payload", - "enableField": "enable", - "passthroughField": "passthrough", - "inputMsgField": "inputmsg", - "rounded": true, - "useThemeColors": true, - "hideSelectedLabel": false, - "multilineLabel": false, - "passThrough": "never", - "inputMsg": "all", - "userInput": "enabled_show", - "options": [ - { - "label": "Off", - "value": "off", - "valueType": "str", - "color": "#009933" - }, - { - "label": "On", - "value": "on", - "valueType": "str", - "color": "#999999" - } - ], - "topic": "", - "x": 310, - "y": 120, - "wires": [ - [ - "99ae4886.8d43c" - ] - ] - }, - { - "id": "99ae4886.8d43c", - "type": "function", - "z": "bccd1f23.87219", - "name": "Prepare message", - "func": "msg.topic = \"light\"\nmsg.payload = {\"action\":msg.payload}\n\nreturn msg;", - "outputs": 1, - "timeout": "", - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 490, - "y": 120, - "wires": [ - [ - "d31fcead.7e2ef" - ] - ] - }, - { - "id": "d31fcead.7e2ef", - "type": "mqtt out", - "z": "bccd1f23.87219", - "name": "", - "topic": "", - "qos": "", - "retain": "", - "respTopic": "", - "contentType": "", - "userProps": "", - "correl": "", - "expiry": "", - "broker": "8dc3722c.06efa8", - "x": 650, - "y": 120, - "wires": [] - }, - { - "id": "8ea9dc9a.c7d87", - "type": "function", - "z": "bccd1f23.87219", - "name": "Encapsulate settings", - "func": "msg.payload = {\n \"action\":\"settings\", \n \"settings\":{[msg.topic]:msg.payload}\n}\n\nmsg.topic = \"imager/image\"\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 1120, - "y": 940, - "wires": [ - [ - "845e06e1.0d812" - ] - ] - }, - { - "id": "5765a825.a595c8", - "type": "ui_slider", - "z": "bccd1f23.87219", - "name": "Shutter speed slider", - "label": "Shutter Speed", - "tooltip": "In microseconds, up to 1000µs, 125µs by default", - "group": "8c38a81e.9897a8", - "order": 4, - "width": 0, - "height": 0, - "passthru": true, - "outs": "end", - "topic": "shutter_speed", - "topicType": "str", - "min": "125", - "max": "1000", - "step": "1", - "className": "", - "x": 600, - "y": 880, - "wires": [ - [ - "8ea9dc9a.c7d87" - ] - ] - }, - { - "id": "845e06e1.0d812", - "type": "mqtt out", - "z": "bccd1f23.87219", - "name": "", - "topic": "", - "qos": "", - "retain": "", - "broker": "8dc3722c.06efa8", - "x": 1390, - "y": 980, - "wires": [] - }, - { - "id": "2350e507.d4e302", - "type": "inject", - "z": "bccd1f23.87219", - "name": "Default: 125µs", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": "1", - "topic": "", - "payload": "125", - "payloadType": "num", - "x": 120, - "y": 880, - "wires": [ - [ - "5765a825.a595c8" - ] - ] - }, - { - "id": "5e147425.7666ec", - "type": "function", - "z": "bccd1f23.87219", - "name": "Encapsulate wb gain settings", - "func": "msg.payload = {\n \"action\":\"settings\", \n \"settings\":{\"white_balance_gain\":{\n [msg.topic]:Math.round(msg.payload*100)\n }\n }\n}\nmsg.topic = \"imager/image\"\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 1100, - "y": 1060, - "wires": [ - [ - "845e06e1.0d812" - ] - ] - }, - { - "id": "82722a3c.846b3", - "type": "inject", - "z": "bccd1f23.87219", - "name": "Default: OFF", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": "1", - "topic": "", - "payload": "false", - "payloadType": "bool", - "x": 110, - "y": 920, - "wires": [ - [ - "60e44330.50bdec" - ] - ] - }, - { - "id": "60e44330.50bdec", - "type": "ui_switch", - "z": "bccd1f23.87219", - "name": "AWB", - "label": "Auto White Balance", - "tooltip": "", - "group": "8c38a81e.9897a8", - "order": 5, - "width": 2, - "height": 2, - "passthru": true, - "decouple": "false", - "topic": "white_balance", - "topicType": "str", - "style": "", - "onvalue": "auto", - "onvalueType": "str", - "onicon": "", - "oncolor": "", - "offvalue": "off", - "offvalueType": "str", - "officon": "", - "offcolor": "", - "animate": true, - "className": "", - "x": 550, - "y": 920, - "wires": [ - [ - "8ea9dc9a.c7d87" - ] - ] - }, - { - "id": "6be64480.7e7e24", - "type": "change", - "z": "bccd1f23.87219", - "name": "Get red_gain", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.red_gain", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 370, - "y": 1040, - "wires": [ - [ - "d5415af6.e06cc" - ] - ] - }, - { - "id": "6d49d161.13628", - "type": "change", - "z": "bccd1f23.87219", - "name": "Get blue_gain", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.blue_gain", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 380, - "y": 1080, - "wires": [ - [ - "dba68c1f.e3144" - ] - ] - }, - { - "id": "56835fa1.2fe538", - "type": "subflow:4ed26b8b.253504", - "z": "bccd1f23.87219", - "name": "", - "env": [], - "x": 1160, - "y": 1020, - "wires": [] - }, - { - "id": "8ef294ba.12213", - "type": "change", - "z": "bccd1f23.87219", - "name": "Get analog_gain", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "1", - "tot": "num" - }, - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.analog_gain", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 380, - "y": 960, - "wires": [ - [ - "a6c7eec4.f7a918" - ] - ] - }, - { - "id": "8e336e58.14722", - "type": "change", - "z": "bccd1f23.87219", - "name": "Get digital_gain", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "1", - "tot": "num" - }, - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.digital_gain", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 380, - "y": 1000, - "wires": [ - [ - "66b37eef.f3f9e" - ] - ] - }, - { - "id": "a6c7eec4.f7a918", - "type": "ui_text_input", - "z": "bccd1f23.87219", - "d": true, - "name": "Analog gain field", - "label": "Analog Gain", - "tooltip": "From 1.0 to 12.0", - "group": "8c38a81e.9897a8", - "order": 2, - "width": 0, - "height": 0, - "passthru": true, - "mode": "number", - "delay": 300, - "topic": "analog", - "topicType": "str", - "x": 580, - "y": 960, - "wires": [ - [ - "44e02933.a66688", - "d361a2c4.0990f8" - ] - ] - }, - { - "id": "66b37eef.f3f9e", - "type": "ui_text_input", - "z": "bccd1f23.87219", - "d": true, - "name": "Digital gain field", - "label": "Digital Gain", - "tooltip": "From 1.0 to 64.0. Overexpose starting at 4.0", - "group": "8c38a81e.9897a8", - "order": 3, - "width": 0, - "height": 0, - "passthru": true, - "mode": "number", - "delay": 300, - "topic": "digital", - "topicType": "str", - "x": 580, - "y": 1000, - "wires": [ - [ - "44e02933.a66688", - "d361a2c4.0990f8" - ] - ] - }, - { - "id": "44e02933.a66688", - "type": "function", - "z": "bccd1f23.87219", - "name": "Encapsulate image gain settings", - "func": "msg.payload = {\n \"action\":\"settings\", \n \"settings\":{\"image_gain\":{\n [msg.topic]:Math.round(msg.payload*100)\n }\n }\n}\nmsg.topic = \"imager/image\"\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 1090, - "y": 980, - "wires": [ - [ - "845e06e1.0d812" - ] - ] - }, - { - "id": "d361a2c4.0990f8", - "type": "change", - "z": "bccd1f23.87219", - "name": "topic *_gain", - "rules": [ - { - "t": "set", - "p": "topic", - "pt": "msg", - "to": "topic&'_gain'", - "tot": "jsonata" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 970, - "y": 1020, - "wires": [ - [ - "56835fa1.2fe538" - ] - ] - }, - { - "id": "d8d006bf.2947f", - "type": "inject", - "z": "bccd1f23.87219", - "name": "Default: ISO 150", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": "1", - "topic": "", - "payload": "150", - "payloadType": "num", - "x": 130, - "y": 840, - "wires": [ - [ - "f62c3241bd753f24" - ] - ] - }, - { - "id": "eb9966de.cf13c8", - "type": "change", - "z": "bccd1f23.87219", - "name": "", - "rules": [ - { - "t": "set", - "p": "topic", - "pt": "msg", - "to": "iso", - "tot": "str" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 740, - "y": 840, - "wires": [ - [ - "8ea9dc9a.c7d87" - ] - ] - }, - { - "id": "be33e564.029358", - "type": "ui_text_input", - "z": "bccd1f23.87219", - "name": "focus_distance", - "label": "Focus Distance (in µm)", - "tooltip": "in µm, 25µm resolution", - "group": "fbd92986.1028c8", - "order": 4, - "width": 0, - "height": 0, - "passthru": true, - "mode": "number", - "delay": 300, - "topic": "focus_distance", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 580, - "y": 460, - "wires": [ - [ - "dc48dc42.98d18" - ] - ] - }, - { - "id": "3a86de51.765b9a", - "type": "ui_text_input", - "z": "bccd1f23.87219", - "name": "focus_speed", - "label": "Focus Speed (in µm/sec)", - "tooltip": "in µm/sec", - "group": "fbd92986.1028c8", - "order": 5, - "width": 0, - "height": 0, - "passthru": true, - "mode": "number", - "delay": 300, - "topic": "focus_speed", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 570, - "y": 500, - "wires": [ - [ - "dc48dc42.98d18" - ] - ] - }, - { - "id": "cb2d5174.cfe9f", - "type": "ui_text_input", - "z": "bccd1f23.87219", - "name": "pump_flowrate", - "label": "Flowrate (ml/min)*", - "tooltip": "", - "group": "707d9797.c8e798", - "order": 1, - "width": 0, - "height": 0, - "passthru": true, - "mode": "text", - "delay": 300, - "topic": "pump_flowrate", - "topicType": "str", - "x": 580, - "y": 380, - "wires": [ - [ - "dc48dc42.98d18" - ] - ] - }, - { - "id": "dba68c1f.e3144", - "type": "ui_text_input", - "z": "bccd1f23.87219", - "name": "WB Blue input", - "label": "WB: Blue", - "tooltip": "From 0.0 to 64.0", - "group": "8c38a81e.9897a8", - "order": 7, - "width": 4, - "height": 1, - "passthru": true, - "mode": "number", - "delay": "0", - "topic": "blue", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 580, - "y": 1080, - "wires": [ - [ - "3ece53716a02e09e" - ] - ] - }, - { - "id": "33ef60a6a80aa3a7", - "type": "subflow:b7861ce703215a01", - "z": "bccd1f23.87219", - "name": "", - "x": 160, - "y": 1020, - "wires": [ - [ - "8ef294ba.12213", - "8e336e58.14722", - "6be64480.7e7e24", - "6d49d161.13628" - ] - ] - }, - { - "id": "a3d034643b56796f", - "type": "inject", - "z": "bccd1f23.87219", - "name": "Once", - "props": [], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "", - "x": 70, - "y": 1080, - "wires": [ - [ - "33ef60a6a80aa3a7" - ] - ] - }, - { - "id": "5984b086eddc9311", - "type": "link in", - "z": "bccd1f23.87219", - "name": "Load hardware config", - "links": [ - "3973b999ee7b3b1d", - "5d3df1564b9af89c" - ], - "x": 25, - "y": 1000, - "wires": [ - [ - "33ef60a6a80aa3a7" - ] - ] - }, - { - "id": "d5415af6.e06cc", - "type": "ui_text_input", - "z": "bccd1f23.87219", - "name": "WB Red input", - "label": "WB: Red", - "tooltip": "From 0.0 to 32.0", - "group": "8c38a81e.9897a8", - "order": 6, - "width": 4, - "height": 1, - "passthru": true, - "mode": "number", - "delay": "0", - "topic": "red", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 580, - "y": 1040, - "wires": [ - [ - "01c2b633558b0b02" - ] - ] - }, - { - "id": "01c2b633558b0b02", - "type": "switch", - "z": "bccd1f23.87219", - "name": "Validate", - "property": "payload", - "propertyType": "msg", - "rules": [ - { - "t": "btwn", - "v": "0.0", - "vt": "num", - "v2": "32.0", - "v2t": "num" - }, - { - "t": "else" - } - ], - "checkall": "false", - "repair": false, - "outputs": 2, - "x": 740, - "y": 1040, - "wires": [ - [ - "d361a2c4.0990f8", - "5e147425.7666ec" - ], - [ - "cbfaf049d92be90e", - "5d3df1564b9af89c" - ] - ] - }, - { - "id": "3ece53716a02e09e", - "type": "switch", - "z": "bccd1f23.87219", - "name": "Validate", - "property": "payload", - "propertyType": "msg", - "rules": [ - { - "t": "btwn", - "v": "0.0", - "vt": "num", - "v2": "32.0", - "v2t": "num" - }, - { - "t": "else" - } - ], - "checkall": "false", - "repair": false, - "outputs": 2, - "x": 740, - "y": 1080, - "wires": [ - [ - "d361a2c4.0990f8", - "5e147425.7666ec" - ], - [ - "cbfaf049d92be90e", - "5d3df1564b9af89c" - ] - ] - }, - { - "id": "cbfaf049d92be90e", - "type": "ui_toast", - "z": "bccd1f23.87219", - "position": "top right", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 0, - "ok": "OK", - "cancel": "", - "raw": false, - "className": "", - "topic": "Invalid white balance value", - "name": "", - "x": 990, - "y": 1100, - "wires": [] - }, - { - "id": "5d3df1564b9af89c", - "type": "link out", - "z": "bccd1f23.87219", - "name": "Reload hardware config", - "mode": "link", - "links": [ - "5984b086eddc9311" - ], - "x": 915, - "y": 1140, - "wires": [] - }, - { - "id": "f62c3241bd753f24", - "type": "ui_slider", - "z": "bccd1f23.87219", - "name": "ISO selector", - "label": "ISO", - "tooltip": "", - "group": "8c38a81e.9897a8", - "order": 1, - "width": 0, - "height": 0, - "passthru": true, - "outs": "end", - "topic": "topic", - "topicType": "msg", - "min": "50", - "max": "650", - "step": "50", - "className": "", - "x": 570, - "y": 840, - "wires": [ - [ - "eb9966de.cf13c8" - ] - ] - }, - { - "id": "6b34c456.83178c", - "type": "ui_text_input", - "z": "baa1e3d9.cb29d", - "name": "acq_id", - "label": "Acquisition unique ID*", - "tooltip": "", - "group": "4322c187.e73e5", - "order": 1, - "width": 5, - "height": 1, - "passthru": true, - "mode": "text", - "delay": 300, - "topic": "acq_id", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 690, - "y": 180, - "wires": [ - [ - "fb887036.12429" - ] - ] - }, - { - "id": "cc0ca68b.4263a8", - "type": "ui_dropdown", - "z": "baa1e3d9.cb29d", - "name": "acq_celltype", - "label": "Flowcell thickness*", - "tooltip": "", - "place": "Select option", - "group": "4322c187.e73e5", - "order": 6, - "width": 5, - "height": 1, - "passthru": true, - "multiple": false, - "options": [ - { - "label": "200 μm µ-Slide I Luer", - "value": 200, - "type": "num" - }, - { - "label": "300 µm capillary", - "value": 300, - "type": "num" - }, - { - "label": "400 μm µ-Slide I Luer", - "value": 400, - "type": "num" - }, - { - "label": "600 μm µ-Slide I Luer", - "value": 600, - "type": "num" - }, - { - "label": "800 μm µ-Slide I Luer", - "value": 800, - "type": "num" - } - ], - "payload": "", - "topic": "acq_celltype", - "topicType": "str", - "className": "", - "x": 670, - "y": 100, - "wires": [ - [ - "fb887036.12429", - "99b11fe4.2795d" - ] - ] - }, - { - "id": "fb887036.12429", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "set global", - "func": "global.set(msg.topic, msg.payload);\nreturn msg", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 920, - "y": 180, - "wires": [ - [ - "52ea7d01.711034" - ] - ] - }, - { - "id": "bb2bb7ce.1d1458", - "type": "ui_template", - "z": "baa1e3d9.cb29d", - "group": "858a0e3c.987fe", - "name": "Stream Pi Camera", - "order": 1, - "width": 10, - "height": 8, - "format": "
\n \"If\n
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "className": "", - "x": 550, - "y": 40, - "wires": [ - [] - ] - }, - { - "id": "d0c5b57d.590818", - "type": "ui_ui_control", - "z": "baa1e3d9.cb29d", - "name": "", - "events": "change", - "x": 1280, - "y": 660, - "wires": [ - [] - ] - }, - { - "id": "c72f8fae.23bd4", - "type": "ui_button", - "z": "baa1e3d9.cb29d", - "name": "", - "group": "b7919ae2.c01788", - "order": 1, - "width": 5, - "height": 1, - "passthru": false, - "label": "Previous", - "tooltip": "", - "color": "#097479", - "bgcolor": "white", - "icon": "keyboard_return", - "payload": "{\"tab\":\"Optic Configuration\"}", - "payloadType": "json", - "topic": "", - "x": 1140, - "y": 660, - "wires": [ - [ - "d0c5b57d.590818" - ] - ] - }, - { - "id": "29be525e.0c87fe", - "type": "ui_template", - "z": "baa1e3d9.cb29d", - "group": "b5d61bc7.54fe48", - "name": "Show Metadata", - "order": 9, - "width": 0, - "height": 0, - "format": "
\n \n \n \n \n \n \n \n \n \n
\n

Sample

\n

id:

\n

project:\n

\n

ship:

\n

operator:\n

\n

sampling gear:\n

\n

concentrated volume:\n

\n

gear net opening:\n

\n

total volume filtered:\n

\n
\n

Acquisition

\n

id:

\n

instrument:\n

\n

instrument id:\n

\n

camera:

\n

celltype: \n

\n

minimum mesh:\n

\n

maximum mesh:\n

\n

min esd: \n

\n

max esd: \n

\n

volume:

\n

magnification:\n

\n

fnumber objective:\n

\n

software: \n

\n
\n

Object

\n

latitude: \n

\n

longitude: \n

\n

latitude end:\n

\n

longitude end:\n

\n

date:

\n

time:

\n

date end:\n

\n

time end:\n

\n

depth min:\n

\n

depth max:\n

\n
\n

Process

\n

pixel: \n

\n

id:

\n
\n
", - "storeOutMessages": false, - "fwdInMessages": false, - "resendOnRefresh": false, - "templateScope": "local", - "className": "", - "x": 1160, - "y": 380, - "wires": [ - [] - ] - }, - { - "id": "c9f510c0.7d1328", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "Image control", - "func": "// Reset the number of images taken\nflow.set('img_counter', 0);\n\nvar acq_celltype = global.get(\"acq_celltype\");\nvar acq_minimum_mesh = global.get(\"acq_minimum_mesh\");\nvar acq_maximum_mesh = global.get(\"acq_maximum_mesh\");\nvar imaging_pump_volume = global.get(\"imaging_pump_volume\");\nvar acq_id = global.get(\"acq_id\");\nvar nb_frame = global.get(\"nb_frame\");\nvar pump_direction = global.get(\"pump_direction\");\nvar sleep_before = global.get(\"sleep_before\");\nvar object_date = global.get(\"object_date\");\n\nif (acq_celltype === undefined || acq_celltype === \"\") {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Type of the flowcell\";\n return [null, msg];\n} else if (acq_minimum_mesh === undefined || acq_minimum_mesh === \"\") {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Lower fraction size\";\n return [null, msg];\n} else if (acq_maximum_mesh === undefined || acq_maximum_mesh === \"\") {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Upper fraction size\";\n return [null, msg];\n} else if (imaging_pump_volume === undefined || imaging_pump_volume === \"\" || imaging_pump_volume === null) {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Volume inbetween images\";\n return [null, msg];\n} else if (acq_id === undefined || acq_id === \"\") {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Acquisition ID\";\n return [null, msg];\n} else if (nb_frame === undefined || nb_frame === \"\" || nb_frame === null) {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Number of image to save\";\n return [null, msg];\n} else if (pump_direction === undefined || pump_direction === \"\" || pump_direction === null) {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Pump direction\";\n return [null, msg];\n} else if (sleep_before === undefined || sleep_before === \"\" || sleep_before === null) {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Delay before image\";\n return [null, msg];\n}else if (object_date === undefined || object_date === \"\" || object_date === null) {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Object date\";\n return [null, msg];\n}\n\nmsg.payload = {\n \"action\": \"image\",\n \"sleep\": sleep_before,\n \"pump_direction\": pump_direction,\n \"volume\": imaging_pump_volume,\n \"nb_frame\": nb_frame,\n}\nmsg.send = true\n\nreturn [msg, null];", - "outputs": 2, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 640, - "y": 440, - "wires": [ - [ - "52ea7d01.711034", - "40c12463.a1f84c", - "a4abb1ae.2ae418" - ], - [ - "20e0a8c8.edbeb" - ] - ] - }, - { - "id": "20e0a8c8.edbeb", - "type": "ui_toast", - "z": "baa1e3d9.cb29d", - "position": "dialog", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 1, - "ok": "OK", - "cancel": "", - "raw": false, - "topic": "", - "name": "", - "x": 890, - "y": 520, - "wires": [ - [] - ] - }, - { - "id": "c3e50240.82aa58", - "type": "mqtt out", - "z": "baa1e3d9.cb29d", - "name": "", - "topic": "", - "qos": "", - "retain": "", - "broker": "8dc3722c.06efa8", - "x": 1130, - "y": 420, - "wires": [] - }, - { - "id": "3a4450b1.4459a8", - "type": "ui_button", - "z": "baa1e3d9.cb29d", - "name": "Stop Acquisition", - "group": "4322c187.e73e5", - "order": 11, - "width": 5, - "height": 1, - "passthru": true, - "label": "STOP ACQUISITION", - "tooltip": "", - "color": "", - "bgcolor": "#AD1625", - "icon": "cancel", - "payload": "{\"action\":\"stop\"}", - "payloadType": "json", - "topic": "imager/image", - "x": 420, - "y": 480, - "wires": [ - [ - "d74210ef.edc15" - ] - ] - }, - { - "id": "d74210ef.edc15", - "type": "mqtt out", - "z": "baa1e3d9.cb29d", - "name": "", - "topic": "", - "qos": "", - "retain": "", - "broker": "8dc3722c.06efa8", - "x": 610, - "y": 480, - "wires": [] - }, - { - "id": "bb62da8a.ebc328", - "type": "ui_switch", - "z": "baa1e3d9.cb29d", - "name": "Pump direction", - "label": "Pump direction", - "tooltip": "BACKWARD / FORWARD", - "group": "4322c187.e73e5", - "order": 9, - "width": 5, - "height": 1, - "passthru": true, - "decouple": "false", - "topic": "pump_direction", - "style": "", - "onvalue": "FORWARD", - "onvalueType": "str", - "onicon": "", - "oncolor": "", - "offvalue": "BACKWARD", - "offvalueType": "str", - "officon": "", - "offcolor": "", - "x": 420, - "y": 520, - "wires": [ - [ - "6b2239f3.41fa3" - ] - ] - }, - { - "id": "52ea7d01.711034", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "Encapsulate config", - "func": "msg.payload = {\n\t\"action\": \"update_config\",\n\t\"config\": {\n \t\"description\": {\n \t\t\"sample_project\": \"Project's name\",\n \t\t\"sample_id\": \"Sample ID\",\n \t\t\"sample_uuid\": \"Sample UUID (Autogenerated)\",\n \t\t\"sample_ship\": \"Ship's name\",\n \t\t\"sample_operator\": \"Operator's name\",\n \t\t\"sample_sampling_gear\": \"Sampling gear used\",\n \t\t\"sample_concentrated_sample_volume\": \"Volume of concentrated sample, in mL\",\n \t\t\"sample_total_volume\": \"Total volume filtered by the net used, in L\",\n \t\t\"sample_dilution_factor\": \"Dilution factor of the sample, 0.5 if diluted by 2, 2 if concentrated by 2\",\n \t\t\"sample_speed_through_water\": \"Speed of the boat through water when sampling, in kts\",\n \t\t\"acq_id\": \"Acquisition ID\",\n \t\t\"acq_uuid\": \"Acquisition UUID (Autogenerated)\",\n \t\t\"acq_instrument\": \"Instrument type\",\n \t\t\"acq_instrument_id\": \"Instrument ID\",\n \t\t\"acq_celltype\": \"Flow cell dimension thickness, in µm\",\n \t\t\"acq_minimum_mesh\": \"Minimum filtration mesh size, in µm\",\n \t\t\"acq_maximum_mesh\": \"Maximum filtration mesh size, in µm\",\n \t\t\"acq_min_esd\": \"\",\n \t\t\"acq_max_esd\": \"\",\n \t\t\"acq_volume\": \"Pumped volume, in mL\",\n\t\t \"acq_imaged_volume\": \"Total imaged volume, in mL\",\n \t\t\"acq_magnification\": \"Optical magnification\",\n \t\t\"acq_fnumber_objective\": \"Focal length of the objective, in mm\",\n \t\t\"acq_camera_name\": \"Name of the camera used\",\n \t\t\"acq_nb_frame\": \"Number of picture taken\",\n \"acq_local_datetime\": \"Instrument local datetime\",\n \"acq_camera_resolution\": \"Resolution of the images\",\n \"acq_camera_iso\": \"ISO Number of the images\",\n \"acq_camera_shutter_speed\": \"Shutter speed of the images, in µs\",\n \"acq_software\": \"Software version number\",\n \t\t\"object_date\": \"Sample collection date (or beginning if using a net)\",\n \t\t\"object_time\": \"Sample collection time (or beginning if using a net)\",\n \t\t\"object_lat\": \"Sample collection latitude (or beginning if using a net)\",\n \t\t\"object_lon\": \"Sample collection longitude (or beginning if using a net)\",\n \t\t\"object_depth_min\": \"Sample collection minimal depth, in m\",\n \t\t\"object_depth_max\": \"Sample collection maximum depth, in m\",\n \t\t\"process_pixel\": \"Pixel imaging resolution, in µm/pixel\",\n \t\t\"process_datetime\": \"Segmentation timestamp\",\n \t\t\"process_id\": \"Segmentation ID\",\n \t\t\"process_uuid\": \"Segmentation UUID (Autogenerated)\",\n \t\t\"process_source\": \"Code source link of the executed code\",\n \t\t\"process_commit\": \"Version reference of the executed code\",\n \t\t\"sample_gear_net_opening\": \"Sample mouth opening dimension, in mm\",\n \t\t\"object_date_end\": \"Sample end collection date when using a net\",\n \t\t\"object_time_end\": \"Sample end collection time when using a net\",\n \t\t\"object_lat_end\": \"Sample end collection latitude when using a net\",\n \t\t\"object_lon_end\": \"Sample end collection longitude when using a net\",\n \t},\n\t\t\"sample_project\": global.get(\"sample_project\"),\n\t\t\"sample_id\": global.get(\"sample_project\") + \"_\" + global.get(\"sample_id\"),\n\t\t\"sample_ship\": global.get(\"sample_ship\"),\n\t\t\"sample_operator\": global.get(\"sample_operator\"),\n\t\t\"sample_sampling_gear\": global.get(\"sample_sampling_gear\"),\n\t\t\"sample_concentrated_sample_volume\": global.get(\"sample_concentrated_sample_volume\"),\n\t\t\"sample_total_volume\": global.get(\"sample_total_volume\"),\n\t\t\"sample_dilution_factor\": global.get(\"sample_dilution_factor\"),\n\t\t\"sample_speed_through_water\": global.get(\"sample_speed_through_water\"),\n\n\t\t\"acq_id\": global.get(\"sample_project\") + \"_\" + global.get(\"sample_id\")+ \"_\" + global.get(\"acq_id\"),\n\t\t\"acq_instrument\": global.get(\"acq_instrument\"),\n\t\t\"acq_instrument_id\": global.get(\"acq_instrument_id\"),\n\t\t\"acq_celltype\": global.get(\"acq_celltype\"),\n\t\t\"acq_minimum_mesh\": global.get(\"acq_minimum_mesh\"),\n\t\t\"acq_maximum_mesh\": global.get(\"acq_maximum_mesh\"),\n\t\t\"acq_min_esd\": global.get(\"acq_min_esd\"),\n\t\t\"acq_max_esd\": global.get(\"acq_max_esd\"),\n\t\t\"acq_volume\": global.get(\"acq_volume\"),\n\t\t\"acq_imaged_volume\": global.get(\"acq_imaged_volume\"),\n\t\t\"acq_magnification\": global.get(\"acq_magnification\"),\n\t\t\"acq_fnumber_objective\": global.get(\"acq_fnumber_objective\"),\n\t\t\"acq_camera\": global.get(\"acq_camera\"),\n\t\t\"acq_nb_frame\": global.get(\"nb_frame\"),\n\t\t\"acq_software\": global.get(\"acq_software\"),\n\n\t\t\"object_date\": global.get(\"object_date\"),\n\t\t\"object_time\": global.get(\"object_time\"),\n\t\t\"object_lat\": global.get(\"object_lat\"),\n\t\t\"object_lon\": global.get(\"object_lon\"),\n\t\t\"object_depth_min\": global.get(\"object_depth_min\"),\n\t\t\"object_depth_max\": global.get(\"object_depth_max\"),\n\n\t\t\"process_pixel\": global.get(\"process_pixel\"),\n\t\t\"process_source\": global.get(\"process_source\"),\n\t\t\"process_commit\": global.get(\"process_commit\")\n\t}\n};\n\nif (msg.payload.config.sample_sampling_gear.startsWith(\"net\")) {\n\tmsg.payload.config[\"sample_gear_net_opening\"] = global.get(\"sample_gear_net_opening\")\n\tmsg.payload.config[\"object_date_end\"] = global.get(\"object_date_end\")\n\tmsg.payload.config[\"object_time_end\"] = global.get(\"object_time_end\")\n\tmsg.payload.config[\"object_lat_end\"] = global.get(\"object_lat_end\")\n\tmsg.payload.config[\"object_lon_end\"] = global.get(\"object_lon_end\")\n}\n\nif ( msg.send == true){\n\treturn [msg, msg]\n}\nelse{\n\treturn [msg, null]\n}", - "outputs": 2, - "timeout": "", - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 870, - "y": 400, - "wires": [ - [ - "29be525e.0c87fe" - ], - [ - "c3e50240.82aa58" - ] - ] - }, - { - "id": "40c12463.a1f84c", - "type": "delay", - "z": "baa1e3d9.cb29d", - "name": "", - "pauseType": "delay", - "timeout": "1", - "timeoutUnits": "seconds", - "rate": "1", - "nbRateUnits": "1", - "rateUnits": "second", - "randomFirst": "1", - "randomLast": "5", - "randomUnits": "seconds", - "drop": false, - "outputs": 1, - "x": 900, - "y": 440, - "wires": [ - [ - "c3e50240.82aa58" - ] - ] - }, - { - "id": "4d1b02cb.83b51c", - "type": "ui_button", - "z": "baa1e3d9.cb29d", - "name": "", - "group": "4322c187.e73e5", - "order": 10, - "width": 5, - "height": 1, - "passthru": false, - "label": "Update config", - "tooltip": "", - "color": "", - "bgcolor": "", - "className": "", - "icon": "save", - "payload": "", - "payloadType": "str", - "topic": "imager/image", - "topicType": "str", - "x": 420, - "y": 400, - "wires": [ - [ - "52ea7d01.711034" - ] - ] - }, - { - "id": "5921d0d0.a3d568", - "type": "subflow:1c24ad9c.bebec2", - "z": "baa1e3d9.cb29d", - "name": "", - "env": [], - "x": 110, - "y": 180, - "wires": [ - [ - "f3658d30.b8448", - "de2c90cf.b73b08", - "4be09c97f86897d9", - "f573206abefa9518", - "f948151ab4031df4" - ] - ] - }, - { - "id": "f3658d30.b8448", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "get acq_id", - "func": "msg.payload = msg.payload.acq_id;\nreturn msg;", - "outputs": 1, - "timeout": "", - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 330, - "y": 180, - "wires": [ - [ - "6b34c456.83178c" - ] - ] - }, - { - "id": "de2c90cf.b73b08", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "get acq_celltype", - "func": "msg.topic = 'acq_celltype';\nmsg.payload = msg.payload.acq_celltype;\nreturn msg;", - "outputs": 1, - "timeout": "", - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 340, - "y": 100, - "wires": [ - [ - "cc0ca68b.4263a8" - ] - ] - }, - { - "id": "b402f719.55bc98", - "type": "inject", - "z": "baa1e3d9.cb29d", - "name": "Default: FORWARD", - "props": [ - { - "p": "payload" - }, - { - "p": "topic", - "vt": "str" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "pump_direction", - "payload": "FORWARD", - "payloadType": "str", - "x": 180, - "y": 520, - "wires": [ - [ - "bb62da8a.ebc328" - ] - ] - }, - { - "id": "6b2239f3.41fa3", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "set global", - "func": "global.set(msg.topic, msg.payload);", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 620, - "y": 520, - "wires": [ - [] - ] - }, - { - "id": "51b4d0df.d70a88", - "type": "ui_text_input", - "z": "baa1e3d9.cb29d", - "name": "nb_frame", - "label": "Number of images to acquire", - "tooltip": "", - "group": "4322c187.e73e5", - "order": 2, - "width": 5, - "height": 1, - "passthru": true, - "mode": "number", - "delay": 300, - "topic": "nb_frame", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 680, - "y": 220, - "wires": [ - [ - "fb887036.12429", - "67091ac0.8f9f6c", - "99b11fe4.2795d" - ] - ] - }, - { - "id": "999065ca.27edb8", - "type": "switch", - "z": "baa1e3d9.cb29d", - "name": "topic filter", - "property": "topic", - "propertyType": "msg", - "rules": [ - { - "t": "eq", - "v": "status/pump", - "vt": "str" - }, - { - "t": "eq", - "v": "status/focus", - "vt": "str" - }, - { - "t": "eq", - "v": "status/light", - "vt": "str" - }, - { - "t": "eq", - "v": "status/imager", - "vt": "str" - } - ], - "checkall": "true", - "repair": false, - "outputs": 4, - "x": 320, - "y": 800, - "wires": [ - [ - "a46a1e7f.88a92", - "6742014e.1bb238" - ], - [ - "c516d9ea.f7f6e", - "6742014e.1bb238" - ], - [ - "6742014e.1bb238" - ], - [ - "307c851e.fb0f7a", - "2b9d6988.d84836" - ] - ] - }, - { - "id": "2b009bd7.c07004", - "type": "ui_text", - "z": "baa1e3d9.cb29d", - "group": "70de8209.68416c", - "order": 3, - "width": 10, - "height": 2, - "name": "imager", - "label": "Imager status:", - "format": "{{msg.payload.status}}", - "layout": "col-center", - "x": 770, - "y": 740, - "wires": [] - }, - { - "id": "c516d9ea.f7f6e", - "type": "ui_text", - "z": "baa1e3d9.cb29d", - "group": "70de8209.68416c", - "order": 1, - "width": 5, - "height": 1, - "name": "focus", - "label": "Focus status:", - "format": "{{msg.payload.status}}", - "layout": "col-center", - "x": 770, - "y": 700, - "wires": [] - }, - { - "id": "a46a1e7f.88a92", - "type": "ui_text", - "z": "baa1e3d9.cb29d", - "group": "70de8209.68416c", - "order": 2, - "width": 5, - "height": 1, - "name": "pump", - "label": "Pump status:", - "format": "{{msg.payload.status}}", - "layout": "col-center", - "x": 770, - "y": 660, - "wires": [] - }, - { - "id": "bb628f8d.98f108", - "type": "link in", - "z": "baa1e3d9.cb29d", - "name": "Status for fluidic module", - "links": [ - "58f2e0f.4e8b12" - ], - "x": 175, - "y": 800, - "wires": [ - [ - "999065ca.27edb8" - ] - ] - }, - { - "id": "307c851e.fb0f7a", - "type": "switch", - "z": "baa1e3d9.cb29d", - "name": "Imaging state", - "property": "payload", - "propertyType": "msg", - "rules": [ - { - "t": "jsonata_exp", - "v": "$contains(msg.payload.status, \"jpg\")\t", - "vt": "jsonata" - }, - { - "t": "else" - } - ], - "checkall": "false", - "repair": false, - "outputs": 2, - "x": 540, - "y": 880, - "wires": [ - [ - "db8e3dde.44efb8" - ], - [ - "6742014e.1bb238" - ] - ] - }, - { - "id": "db8e3dde.44efb8", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "img_counter", - "func": "img_counter=flow.get('img_counter')\nif (img_counter === undefined || img_counter === \"\"){\n img_counter = 0\n}\nimg_counter=img_counter+1\nflow.set('img_counter',img_counter)\nmsg.payload = img_counter\nmsg.payload = (100 * img_counter/global.get('nb_frame')).toFixed(2)\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 770, - "y": 860, - "wires": [ - [ - "1a2e721a.f5e876" - ] - ] - }, - { - "id": "59164d65.e7993c", - "type": "ui_toast", - "z": "baa1e3d9.cb29d", - "position": "top right", - "displayTime": "5", - "highlight": "", - "sendall": true, - "outputs": 0, - "ok": "OK", - "cancel": "", - "raw": false, - "topic": "", - "name": "", - "x": 1270, - "y": 900, - "wires": [] - }, - { - "id": "8c7348aa.1962e8", - "type": "template", - "z": "baa1e3d9.cb29d", - "name": "Create sentence", - "field": "payload", - "fieldType": "msg", - "format": "handlebars", - "syntax": "mustache", - "template": "The {{topic}} is {{payload.status}}", - "output": "str", - "x": 1050, - "y": 900, - "wires": [ - [ - "59164d65.e7993c" - ] - ] - }, - { - "id": "6742014e.1bb238", - "type": "change", - "z": "baa1e3d9.cb29d", - "name": "Remove high-level topic", - "rules": [ - { - "t": "change", - "p": "topic", - "pt": "msg", - "from": "status/", - "fromt": "str", - "to": "", - "tot": "str" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 810, - "y": 900, - "wires": [ - [ - "8c7348aa.1962e8" - ] - ] - }, - { - "id": "1a2e721a.f5e876", - "type": "ui_gauge", - "z": "baa1e3d9.cb29d", - "name": "progress donut", - "group": "b5d61bc7.54fe48", - "order": 3, - "width": 6, - "height": 3, - "gtype": "donut", - "title": "", - "label": "%", - "format": "{{value}}", - "min": 0, - "max": "100", - "colors": [ - "#ffa83f", - "#e6ff02", - "#00dfe9" - ], - "seg1": "50", - "seg2": "75", - "x": 1260, - "y": 860, - "wires": [] - }, - { - "id": "9bd72495.a8a098", - "type": "ui_text", - "z": "baa1e3d9.cb29d", - "group": "4322c187.e73e5", - "order": 5, - "width": 5, - "height": 1, - "name": "Total imaged volume", - "label": "Total imaged volume", - "format": "{{msg.payload}}", - "layout": "col-center", - "x": 1200, - "y": 100, - "wires": [] - }, - { - "id": "99b11fe4.2795d", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "imaged volume calc", - "func": "camera = global.get(\"acq_camera\");\ncell = global.get(\"acq_celltype\");\nnb_frame = global.get(\"nb_frame\");\nprocess_pixel = global.get(\"process_pixel\");\n\nvar volume = 0\nif (camera == \"HQ Camera\"){\n volume = nb_frame * (process_pixel*4056*process_pixel*3040*cell/1000000000) / 1000;\n}\nelse if (camera == \"Camera v2.1\"){\n volume = nb_frame * (process_pixel*3280*process_pixel*2464*cell/1000000000) / 1000;\n}\nelse{\n msg.payload = \"The camera is not known to this system\";\n return msg;\n}\n\nglobal.set(\"acq_imaged_volume\", volume.toFixed(4))\n\nmsg.payload = volume.toFixed(2) + \" mL\"\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 960, - "y": 100, - "wires": [ - [ - "9bd72495.a8a098" - ] - ], - "info": "### Focusing\n##### focus.py `nb_step` `orientation`\n\n- `nb_step` : **integer** (from 1 to 100000) - number of step to perform by the stage (about 31um/step)\n- `orientation` : **string** - orientation of the focus either `up` or `down`\n\nExample:\n\n python3.7 $HOME/PlanktoScope/scripts/focus.py 650 up\n" - }, - { - "id": "8e16aa2f.e40398", - "type": "ui_text", - "z": "baa1e3d9.cb29d", - "group": "4322c187.e73e5", - "order": 7, - "width": 5, - "height": 1, - "name": "Total pumped volume", - "label": "Total pumped volume", - "format": "{{msg.payload}} mL", - "layout": "col-center", - "x": 1200, - "y": 260, - "wires": [] - }, - { - "id": "67091ac0.8f9f6c", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "acq_volume calc", - "func": "var imaging_pump_volume = global.get(\"imaging_pump_volume\");\nvar nb_frame = global.get(\"nb_frame\");\nvar acq_volume = 0\n\nacq_volume = (Number(nb_frame)*Number(imaging_pump_volume)).toFixed(2)\nglobal.set(\"acq_volume\", acq_volume)\n\nmsg.payload = acq_volume\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 950, - "y": 260, - "wires": [ - [ - "8e16aa2f.e40398" - ] - ], - "info": "### Focusing\n##### focus.py `nb_step` `orientation`\n\n- `nb_step` : **integer** (from 1 to 100000) - number of step to perform by the stage (about 31um/step)\n- `orientation` : **string** - orientation of the focus either `up` or `down`\n\nExample:\n\n python3.7 $HOME/PlanktoScope/scripts/focus.py 650 up\n" - }, - { - "id": "2b9d6988.d84836", - "type": "switch", - "z": "baa1e3d9.cb29d", - "name": "", - "property": "payload", - "propertyType": "msg", - "rules": [ - { - "t": "hask", - "v": "status", - "vt": "str" - }, - { - "t": "hask", - "v": "camera_name", - "vt": "str" - } - ], - "checkall": "true", - "repair": false, - "outputs": 2, - "x": 650, - "y": 760, - "wires": [ - [ - "2b009bd7.c07004" - ], - [ - "3bbb756a.84190a" - ] - ] - }, - { - "id": "3bbb756a.84190a", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "set camera name", - "func": "global.set(\"acq_camera\", msg.payload.camera_name);\n\nmsg.payload = msg.payload.camera_name;\n\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 810, - "y": 780, - "wires": [ - [ - "559a8085.1d6b9" - ] - ] - }, - { - "id": "559a8085.1d6b9", - "type": "link out", - "z": "baa1e3d9.cb29d", - "name": "Camera Name", - "links": [ - "30067f35.532f2", - "572a6daa.6004c4" - ], - "x": 965, - "y": 780, - "wires": [] - }, - { - "id": "49ea1123.ee1768", - "type": "ui_numeric", - "z": "baa1e3d9.cb29d", - "name": "sleep_before", - "label": "Delay to stabilize image (s)", - "tooltip": "Happens before every capture", - "group": "4322c187.e73e5", - "order": 4, - "width": 5, - "height": 1, - "wrap": false, - "passthru": true, - "topic": "sleep_before", - "topicType": "str", - "format": "{{value}}", - "min": "0.1", - "max": "5", - "step": "0.1", - "className": "", - "x": 670, - "y": 140, - "wires": [ - [ - "fb887036.12429" - ] - ] - }, - { - "id": "572a6daa.6004c4", - "type": "link in", - "z": "baa1e3d9.cb29d", - "name": "", - "links": [ - "559a8085.1d6b9" - ], - "x": 735, - "y": 60, - "wires": [ - [ - "99b11fe4.2795d" - ] - ] - }, - { - "id": "8032ea50.1b57f", - "type": "ui_template", - "z": "baa1e3d9.cb29d", - "group": "b5d61bc7.54fe48", - "name": "progress header", - "order": 1, - "width": 0, - "height": 0, - "format": "

Capture progress

", - "storeOutMessages": false, - "fwdInMessages": false, - "resendOnRefresh": false, - "templateScope": "local", - "x": 1270, - "y": 820, - "wires": [ - [] - ] - }, - { - "id": "a4abb1ae.2ae418", - "type": "subflow:1c24ad9c.bebec2", - "z": "baa1e3d9.cb29d", - "name": "", - "env": [], - "x": 890, - "y": 480, - "wires": [ - [] - ] - }, - { - "id": "4be09c97f86897d9", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "get nb_frame", - "func": "msg.payload = msg.payload.nb_frame;\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 330, - "y": 220, - "wires": [ - [ - "51b4d0df.d70a88" - ] - ] - }, - { - "id": "f573206abefa9518", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "get imaging_pump_volume", - "func": "msg.payload = msg.payload.imaging_pump_volume;\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 380, - "y": 260, - "wires": [ - [ - "0df8d1d86af6455a" - ] - ] - }, - { - "id": "f948151ab4031df4", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "get sleep_before", - "func": "msg.payload = msg.payload.sleep_before;\nreturn msg;", - "outputs": 1, - "timeout": "", - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 340, - "y": 140, - "wires": [ - [ - "49ea1123.ee1768" - ] - ] - }, - { - "id": "ad153212312f0347", - "type": "ui_ui_control", - "z": "baa1e3d9.cb29d", - "name": "onTab", - "events": "all", - "x": 310, - "y": 340, - "wires": [ - [ - "9b69ea945b587192" - ] - ] - }, - { - "id": "9b69ea945b587192", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "check tab", - "func": "if (msg.name == \"Fluidic Acquisition\"){\n return { \"topic\": \"imager/ image\" }\n}", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 460, - "y": 340, - "wires": [ - [ - "52ea7d01.711034" - ] - ], - "outputLabels": [ - "interface" - ] - }, - { - "id": "0df8d1d86af6455a", - "type": "ui_text_input", - "z": "baa1e3d9.cb29d", - "name": "imaging_pump_volume", - "label": "Pumped volume (mL)", - "tooltip": "between frames", - "group": "4322c187.e73e5", - "order": 3, - "width": 0, - "height": 0, - "passthru": true, - "mode": "number", - "delay": 300, - "topic": "imaging_pump_volume", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 630, - "y": 260, - "wires": [ - [ - "fb887036.12429", - "67091ac0.8f9f6c" - ] - ] - }, - { - "id": "37116281279b9b82", - "type": "ui_template", - "z": "baa1e3d9.cb29d", - "group": "4322c187.e73e5", - "name": "Start Acquisition", - "order": 12, - "width": "5", - "height": "1", - "format": "\n\n", - "storeOutMessages": false, - "fwdInMessages": false, - "resendOnRefresh": false, - "templateScope": "local", - "className": "", - "x": 420, - "y": 440, - "wires": [ - [ - "c9f510c0.7d1328" - ] - ] - }, - { - "id": "9d6abe67.6bb3d", - "type": "ui_button", - "z": "cb95299c.2817c8", - "name": "", - "group": "64903b47.4034e4", - "order": 1, - "width": 0, - "height": 0, - "passthru": false, - "label": "Home", - "tooltip": "", - "color": "", - "bgcolor": "", - "icon": "home", - "payload": "{\"tab\":\"Home\"}", - "payloadType": "json", - "topic": "", - "x": 430, - "y": 600, - "wires": [ - [ - "f0fb77cf.8f1c28" - ] - ] - }, - { - "id": "f0fb77cf.8f1c28", - "type": "ui_ui_control", - "z": "cb95299c.2817c8", - "name": "", - "events": "change", - "x": 740, - "y": 600, - "wires": [ - [] - ] - }, - { - "id": "8ec68b82.17e3d8", - "type": "ui_button", - "z": "cb95299c.2817c8", - "name": "Start segmentation", - "group": "abeb6dad.635a2", - "order": 10, - "width": 5, - "height": 1, - "passthru": false, - "label": "Start segmentation", - "tooltip": "", - "color": "", - "bgcolor": "", - "icon": "", - "payload": "{\"action\":\"segment\"}", - "payloadType": "json", - "topic": "segmenter/segment", - "x": 370, - "y": 460, - "wires": [ - [ - "33c28dc1.238002", - "c72a1064.1ec388" - ] - ] - }, - { - "id": "27be7971.b3fbce", - "type": "ui_button", - "z": "cb95299c.2817c8", - "d": true, - "name": "Stop segmentation", - "group": "abeb6dad.635a2", - "order": 12, - "width": 4, - "height": 1, - "passthru": true, - "label": "Stop segmentation", - "tooltip": "", - "color": "", - "bgcolor": "#AD1625", - "icon": "", - "payload": "{\"action\":\"stop\"}", - "payloadType": "json", - "topic": "segmenter/segment", - "x": 370, - "y": 520, - "wires": [ - [ - "16f3cef4.0acac9" - ] - ] - }, - { - "id": "16f3cef4.0acac9", - "type": "mqtt out", - "z": "cb95299c.2817c8", - "name": "", - "topic": "", - "qos": "", - "retain": "", - "broker": "8dc3722c.06efa8", - "x": 850, - "y": 520, - "wires": [] - }, - { - "id": "8f3788f6.ddcf98", - "type": "function", - "z": "cb95299c.2817c8", - "name": "obj_counter", - "func": "obj_counter = flow.get('obj_counter')\nobj_counter = obj_counter + 1\nflow.set('obj_counter', obj_counter)\nmsg.payload = obj_counter\nmsg.topic = \"object count\"\nreturn msg", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 810, - "y": 800, - "wires": [ - [ - "fa3b7929.ac7da8", - "9d53dbe2.dbffe8" - ] - ] - }, - { - "id": "aa38dbbc.cf0a9", - "type": "switch", - "z": "cb95299c.2817c8", - "name": "Segmenter", - "property": "topic", - "propertyType": "msg", - "rules": [ - { - "t": "eq", - "v": "status/segmenter", - "vt": "str" - }, - { - "t": "eq", - "v": "status/segmenter/name", - "vt": "str" - }, - { - "t": "eq", - "v": "status/segmenter/object_id", - "vt": "str" - }, - { - "t": "eq", - "v": "status/segmenter/metric", - "vt": "str" - } - ], - "checkall": "true", - "repair": false, - "outputs": 4, - "x": 490, - "y": 740, - "wires": [ - [ - "b9a23b91.93638", - "6919465f.332e5" - ], - [ - "49af3d24.1799e4" - ], - [ - "8f3788f6.ddcf98" - ], - [] - ] - }, - { - "id": "9d53dbe2.dbffe8", - "type": "ui_chart", - "z": "cb95299c.2817c8", - "name": "counter graph", - "group": "46be9c86.dea684", - "order": 7, - "width": 10, - "height": 2, - "label": "", - "chartType": "horizontalBar", - "legend": "false", - "xformat": "HH:mm:ss", - "interpolate": "linear", - "nodata": "Objects count will be shown here once the segmentation is started", - "dot": false, - "ymin": "", - "ymax": "", - "removeOlder": 1, - "removeOlderPoints": "", - "removeOlderUnit": "3600", - "cutout": 0, - "useOneColor": true, - "useUTC": false, - "colors": [ - "#1f77b4", - "#aec7e8", - "#ff7f0e", - "#2ca02c", - "#98df8a", - "#d62728", - "#ff9896", - "#9467bd", - "#c5b0d5" - ], - "outputs": 1, - "x": 1340, - "y": 840, - "wires": [ - [] - ] - }, - { - "id": "a4f0f0d1.3aca88", - "type": "ui_toast", - "z": "cb95299c.2817c8", - "position": "top right", - "displayTime": "5", - "highlight": "", - "sendall": true, - "outputs": 0, - "ok": "OK", - "cancel": "", - "raw": false, - "topic": "", - "name": "", - "x": 1350, - "y": 680, - "wires": [] - }, - { - "id": "49af3d24.1799e4", - "type": "debug", - "z": "cb95299c.2817c8", - "name": "segmentation name", - "active": true, - "tosidebar": true, - "console": false, - "tostatus": false, - "complete": "true", - "targetType": "full", - "statusVal": "", - "statusType": "auto", - "x": 840, - "y": 760, - "wires": [] - }, - { - "id": "7088a5be.0c79a4", - "type": "template", - "z": "cb95299c.2817c8", - "name": "Create sentence", - "field": "payload", - "fieldType": "msg", - "format": "handlebars", - "syntax": "mustache", - "template": "The {{topic}} is {{payload.status}}", - "output": "str", - "x": 1100, - "y": 680, - "wires": [ - [ - "a4f0f0d1.3aca88" - ] - ] - }, - { - "id": "b9a23b91.93638", - "type": "change", - "z": "cb95299c.2817c8", - "name": "Remove high-level topic", - "rules": [ - { - "t": "change", - "p": "topic", - "pt": "msg", - "from": "status/", - "fromt": "str", - "to": "", - "tot": "str" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 850, - "y": 680, - "wires": [ - [ - "7088a5be.0c79a4" - ] - ] - }, - { - "id": "6919465f.332e5", - "type": "ui_text", - "z": "cb95299c.2817c8", - "group": "46be9c86.dea684", - "order": 1, - "width": 10, - "height": 1, - "name": "segmenter", - "label": "Segmenter status:", - "format": "{{msg.payload.status}}", - "layout": "row-spread", - "x": 810, - "y": 720, - "wires": [] - }, - { - "id": "fa3b7929.ac7da8", - "type": "ui_text", - "z": "cb95299c.2817c8", - "group": "46be9c86.dea684", - "order": 5, - "width": 4, - "height": 1, - "name": "counter", + "value": "PlanktoScope v2.6", + "type": "str" + }, + { "label": "", - "format": "{{msg.payload}}", - "layout": "col-center", - "x": 1320, - "y": 800, - "wires": [] - }, - { - "id": "640ece83.88cab", - "type": "inject", - "z": "cb95299c.2817c8", - "name": "Init graphs", - "props": [ - { - "p": "payload" - }, - { - "p": "topic", - "vt": "str" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "object count", - "payload": "0", - "payloadType": "num", - "x": 810, - "y": 880, - "wires": [ - [ - "4f3f7c4a.cb21c4" - ] - ] - }, - { - "id": "25867454.a8e334", - "type": "link in", - "z": "cb95299c.2817c8", - "name": "Segmenter module status", - "links": [ - "dcf5bd45.16a8d" - ], - "x": 295, - "y": 740, - "wires": [ - [ - "aa38dbbc.cf0a9" - ] - ] - }, - { - "id": "c8749cbb.55254", - "type": "function", - "z": "cb95299c.2817c8", - "name": "set global", - "func": "global.set(msg.topic, msg.payload);", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 960, - "y": 380, - "wires": [ - [] - ] - }, - { - "id": "d43c3ed9.e6cb1", - "type": "ui_template", - "z": "cb95299c.2817c8", - "group": "46be9c86.dea684", - "name": "Object counts", - "order": 3, - "width": 0, - "height": 0, - "format": "

Object counts

", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": true, - "templateScope": "local", - "x": 1340, - "y": 760, - "wires": [ - [] - ] - }, - { - "id": "33c28dc1.238002", - "type": "function", - "z": "cb95299c.2817c8", - "name": "prepare segmentation", - "func": "global.set('obj_counter', 0);\n\nvar segmentation_list = flow.get('segmentation_list')\nif (segmentation_list !== undefined && segmentation_list !== \"\") {\n msg.payload['path'] = segmentation_list\n}\n\n\nvar force = flow.get('force')\nif (force !== undefined && force !== \"\") {\n msg.payload['settings'] = {\"force\":Boolean(force)}\n}\n\n\nvar recursive = flow.get('recursive')\nif (recursive !== undefined && recursive !== \"\") {\n if (\"settings\" in msg.payload){\n msg.payload.settings[\"recursive\"] = Boolean(recursive)\n }\n else{\n msg.payload['settings'] = {\"recursive\": Boolean(recursive)}\n }\n}\n\nvar ecotaxa = flow.get('ecotaxa')\nif (ecotaxa !== undefined && ecotaxa !== \"\") {\n if (\"settings\" in msg.payload){\n msg.payload.settings[\"ecotaxa\"] = Boolean(ecotaxa)\n }\n else{\n msg.payload['settings'] = {\"ecotaxa\": Boolean(ecotaxa)}\n }\n}\n\nvar keep = flow.get('keep')\nif (keep !== undefined && keep !== \"\") {\n if (\"settings\" in msg.payload){\n msg.payload.settings[\"keep\"] = Boolean(keep)\n }\n else{\n msg.payload['settings'] = {\"keep\": Boolean(keep)}\n }\n}\n\nvar process_id = global.get('process_id')\nif (process_id !== undefined && process_id !== \"\") {\n if (\"settings\" in msg.payload){\n msg.payload.settings[\"process_id\"] = process_id\n }\n else{\n msg.payload['settings'] = {\"process_id\": process_id}\n }\n}\n\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 620, - "y": 460, - "wires": [ - [ - "16f3cef4.0acac9" - ] - ] - }, - { - "id": "fa12f9f8.00cfa8", - "type": "subflow:1c24ad9c.bebec2", - "z": "cb95299c.2817c8", - "name": "", - "env": [], - "x": 430, - "y": 380, - "wires": [ - [ - "3b72d11c.86e9e6" - ] - ] - }, - { - "id": "3b72d11c.86e9e6", - "type": "function", - "z": "cb95299c.2817c8", - "name": "get process_id", - "func": "msg.payload = msg.payload.process_id;\nmsg.topic = \"process_id\";\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 600, - "y": 380, - "wires": [ - [ - "56971109c8be3b54" - ] - ] - }, - { - "id": "3ea12061.ce62c", - "type": "ui_list", - "z": "cb95299c.2817c8", - "group": "abeb6dad.635a2", - "name": "", - "order": 9, - "width": 10, - "height": 11, - "lineType": "one", - "actionType": "check", - "allowHTML": false, - "outputs": 1, - "topic": "", - "x": 770, - "y": 140, - "wires": [ - [ - "cb3b87b5.63c4" - ] - ] - }, - { - "id": "8bd8fb2c.53fa4", - "type": "dir2files", - "z": "cb95299c.2817c8", - "name": "", - "dirname": "/home/pi/data/img/", - "pathRegex": "", - "isRecursive": true, - "findDir": true, - "isArray": true, - "x": 460, - "y": 140, - "wires": [ - [ - "ba2947.c854deb8" - ] - ] - }, - { - "id": "127d4ee.f8ad1b1", - "type": "ui_button", - "z": "cb95299c.2817c8", - "name": "Refresh", - "group": "abeb6dad.635a2", - "order": 8, - "width": 0, - "height": 0, - "passthru": false, - "label": "Update acquisition's folder list", - "tooltip": "Refresh the list of previous acquisitions", - "color": "", - "bgcolor": "", - "icon": "mi-find_replace", - "payload": "", - "payloadType": "date", - "topic": "update", - "x": 260, - "y": 140, - "wires": [ - [ - "8bd8fb2c.53fa4", - "56f845f5.e7c054" - ] - ] - }, - { - "id": "946ce9ee.092cf", - "type": "inject", - "z": "cb95299c.2817c8", - "name": "Init", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "", - "payload": "", - "payloadType": "date", - "x": 270, - "y": 100, - "wires": [ - [ - "8bd8fb2c.53fa4", - "56f845f5.e7c054" - ] - ] - }, - { - "id": "cb3b87b5.63c4", - "type": "function", - "z": "cb95299c.2817c8", - "name": "update segmentation_list", - "func": "var segmentation_list = flow.get('segmentation_list');\n\nif (segmentation_list === undefined || segmentation_list === \"\") {\n segmentation_list = []\n console.log(\"error\")\n}\n\npath = \"/home/pi/data/img/\" + msg.payload.title\n\nif (msg.payload.isChecked){\n if (segmentation_list.includes(path) === false){\n segmentation_list.push(path)\n }\n // Element already in list, don't push it more than once\n //segmentation_list.push(msg.payload[\"title\"])\n}\nelse {\n var pos = segmentation_list.indexOf(path)\n segmentation_list.splice(pos, 1)\n}\n\nflow.set('segmentation_list', segmentation_list)", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 950, - "y": 140, - "wires": [ - [] - ] - }, - { - "id": "56f845f5.e7c054", - "type": "change", - "z": "cb95299c.2817c8", - "name": "Reset segmentation_list", - "rules": [ - { - "t": "set", - "p": "segmentation_list", - "pt": "flow", - "to": "[]", - "tot": "json" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 510, - "y": 100, - "wires": [ - [] - ] - }, - { - "id": "7fc72364.8f038c", - "type": "ui_template", - "z": "cb95299c.2817c8", - "group": "abeb6dad.635a2", - "name": "Update message", - "order": 1, - "width": 10, - "height": 3, - "format": "
You can choose here in which folder(s) you want the segmentation script to run. A few details though:\n
The segmentation is run recursively in all folders. So if you select a top level folder, the segmentation will be run in all subfolders.\n
Also, you will be able to chose wether for force the segmentation for folders in which it has run already.
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": true, - "templateScope": "local", - "x": 270, - "y": 40, - "wires": [ - [] - ] - }, - { - "id": "ba2947.c854deb8", - "type": "function", - "z": "cb95299c.2817c8", - "name": "remove common", - "func": "function remove_path(item, index, array) {\n array[index] = item.replace(\"/home/pi/data/img/\", \"\")\n} \n\nmsg.payload.forEach(remove_path)\n\nreturn msg", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 620, - "y": 140, - "wires": [ - [ - "3ea12061.ce62c" - ] - ] - }, - { - "id": "21af0db1.c2c182", - "type": "ui_multistate_switch", - "z": "cb95299c.2817c8", - "name": "recursive toggle", - "group": "abeb6dad.635a2", - "order": 4, - "width": 5, - "height": 1, - "label": "Recursive folder", - "stateField": "payload", - "enableField": "enable", - "rounded": true, - "useThemeColors": true, - "hideSelectedLabel": false, - "options": [ - { - "label": "No", - "value": "0", - "valueType": "num", - "color": "#009933" - }, - { - "label": "Yes", - "value": "1", - "valueType": "num", - "color": "#999999" - } - ], - "x": 480, - "y": 220, - "wires": [ - [ - "880b192a.88e2d" - ] - ] - }, - { - "id": "dffb9881.feef8", - "type": "ui_multistate_switch", - "z": "cb95299c.2817c8", - "name": "force toggle", - "group": "abeb6dad.635a2", - "order": 3, - "width": 5, - "height": 1, - "label": "Force rework", - "stateField": "payload", - "enableField": "enable", - "rounded": true, - "useThemeColors": true, - "hideSelectedLabel": false, - "options": [ - { - "label": "No", - "value": "0", - "valueType": "num", - "color": "#009933" - }, - { - "label": "Yes", - "value": "1", - "valueType": "num", - "color": "#999999" - } - ], - "x": 470, - "y": 300, - "wires": [ - [ - "a4f68fa6.5d77f8" - ] - ] - }, - { - "id": "880b192a.88e2d", - "type": "change", - "z": "cb95299c.2817c8", - "name": "", - "rules": [ - { - "t": "set", - "p": "recursive", - "pt": "flow", - "to": "payload", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 690, - "y": 240, - "wires": [ - [] - ] - }, - { - "id": "a4f68fa6.5d77f8", - "type": "change", - "z": "cb95299c.2817c8", - "name": "", - "rules": [ - { - "t": "set", - "p": "force", - "pt": "flow", - "to": "payload", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 670, - "y": 280, - "wires": [ - [] - ] - }, - { - "id": "1ef1b43b.b0f064", - "type": "inject", - "z": "cb95299c.2817c8", - "name": "0", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "", - "payload": "0", - "payloadType": "num", - "x": 270, - "y": 280, - "wires": [ - [ - "dffb9881.feef8", - "a4f68fa6.5d77f8" - ] - ] - }, - { - "id": "f078c068.eacf58", - "type": "ui_template", - "z": "cb95299c.2817c8", - "group": "46be9c86.dea684", - "name": "Stream Segmented object", - "order": 2, - "width": 10, - "height": 8, - "format": "
\n Latest object segmented:
\n \"If\n
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "className": "", - "x": 1380, - "y": 600, - "wires": [ - [] - ] - }, - { - "id": "43f97b93.b76294", - "type": "inject", - "z": "cb95299c.2817c8", - "name": "1", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "", - "payload": "1", - "payloadType": "num", - "x": 270, - "y": 240, - "wires": [ - [ - "21af0db1.c2c182", - "880b192a.88e2d" - ] - ] - }, - { - "id": "4f3f7c4a.cb21c4", - "type": "change", - "z": "cb95299c.2817c8", - "name": "", - "rules": [ - { - "t": "set", - "p": "obj_counter", - "pt": "flow", - "to": "0", - "tot": "num" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 1020, - "y": 840, - "wires": [ - [ - "fa3b7929.ac7da8", - "9d53dbe2.dbffe8" - ] - ] - }, - { - "id": "6bce0f60.f48998", - "type": "link in", - "z": "cb95299c.2817c8", - "name": "", - "links": [ - "596fc9d4.46c75" - ], - "x": 855, - "y": 840, - "wires": [ - [ - "4f3f7c4a.cb21c4" - ] - ] - }, - { - "id": "596fc9d4.46c75", - "type": "link out", - "z": "cb95299c.2817c8", - "name": "", - "links": [ - "6bce0f60.f48998" - ], - "x": 715, - "y": 500, - "wires": [] - }, - { - "id": "c72a1064.1ec388", - "type": "change", - "z": "cb95299c.2817c8", - "name": "Reset counters", - "rules": [ - { - "t": "set", - "p": "topic", - "pt": "msg", - "to": "object count", - "tot": "str" - }, - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "0", - "tot": "num" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 600, - "y": 500, - "wires": [ - [ - "596fc9d4.46c75" - ] - ] - }, - { - "id": "9367534a.fb8568", - "type": "ui_multistate_switch", - "z": "cb95299c.2817c8", - "name": "Ecotaxa archive", - "group": "abeb6dad.635a2", - "order": 6, - "width": 5, - "height": 1, - "label": "Ecotaxa archive", - "stateField": "payload", - "enableField": "enable", - "rounded": true, - "useThemeColors": true, - "hideSelectedLabel": false, - "options": [ - { - "label": "No", - "value": "0", - "valueType": "num", - "color": "#009933" - }, - { - "label": "Yes", - "value": "1", - "valueType": "num", - "color": "#999999" - } - ], - "x": 1080, - "y": 220, - "wires": [ - [ - "25ac4f9a.5b05c8" - ] - ] - }, - { - "id": "25ac4f9a.5b05c8", - "type": "change", - "z": "cb95299c.2817c8", - "name": "", - "rules": [ - { - "t": "set", - "p": "ecotaxa", - "pt": "flow", - "to": "payload", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 1280, - "y": 240, - "wires": [ - [] - ] - }, - { - "id": "bef78886.8f0b98", - "type": "inject", - "z": "cb95299c.2817c8", - "name": "1", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "", - "payload": "1", - "payloadType": "num", - "x": 910, - "y": 240, - "wires": [ - [ - "9367534a.fb8568", - "25ac4f9a.5b05c8" - ] - ] - }, - { - "id": "32465a4e.8fcac6", - "type": "ui_multistate_switch", - "z": "cb95299c.2817c8", - "name": "Keep objects", - "group": "abeb6dad.635a2", - "order": 5, - "width": 5, - "height": 1, - "label": "Keep objects", - "stateField": "payload", - "enableField": "enable", - "rounded": true, - "useThemeColors": true, - "hideSelectedLabel": false, - "options": [ - { - "label": "No", - "value": "0", - "valueType": "num", - "color": "#009933" - }, - { - "label": "Yes", - "value": "1", - "valueType": "num", - "color": "#999999" - } - ], - "x": 1070, - "y": 300, - "wires": [ - [ - "8dd6f57f.b77f98" - ] - ] - }, - { - "id": "8dd6f57f.b77f98", - "type": "change", - "z": "cb95299c.2817c8", - "name": "", - "rules": [ - { - "t": "set", - "p": "keep", - "pt": "flow", - "to": "payload", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 1270, - "y": 280, - "wires": [ - [] - ] - }, - { - "id": "8090df89.c029e", - "type": "inject", - "z": "cb95299c.2817c8", - "name": "1", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "", - "payload": "1", - "payloadType": "num", - "x": 910, - "y": 280, - "wires": [ - [ - "32465a4e.8fcac6", - "8dd6f57f.b77f98" - ] - ] - }, - { - "id": "56971109c8be3b54", - "type": "ui_text_input", - "z": "cb95299c.2817c8", - "name": "process_id", - "label": "Process unique ID*", - "tooltip": "", - "group": "abeb6dad.635a2", - "order": 2, - "width": 10, - "height": 1, - "passthru": true, - "mode": "text", - "delay": 300, - "topic": "process_id", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 790, - "y": 380, - "wires": [ - [ - "c8749cbb.55254" - ] - ] - }, - { - "id": "2911fbc6.d28c24", - "type": "ui_template", - "z": "c1660bc.e7ff7f8", - "group": "c0ebfc57.42527", - "name": "Image browser", - "order": 1, - "width": "0", - "height": "0", - "format": "
\n\n
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "className": "", - "x": 400, - "y": 100, - "wires": [ - [] - ] - }, - { - "id": "4f02c726.de69b8", - "type": "ui_button", - "z": "9daf9e2b.019fc", - "name": "", - "group": "a7d64879.38298", - "order": 4, - "width": "6", - "height": 1, - "passthru": false, - "label": "Reboot", - "tooltip": "", - "color": "", - "bgcolor": "#AD1625", - "className": "", - "icon": "fa-repeat fa-2x", - "payload": "reboot", - "payloadType": "str", - "topic": "reboot", - "topicType": "str", - "x": 160, - "y": 240, - "wires": [ - [ - "611a8b1c.a829b4" - ] - ] - }, - { - "id": "611a8b1c.a829b4", - "type": "exec", - "z": "9daf9e2b.019fc", - "command": "sudo", - "addpay": "payload", - "append": "now", - "useSpawn": "false", - "timer": "2", - "winHide": false, - "oldrc": false, - "name": "sudo cmd now", - "x": 480, - "y": 280, - "wires": [ - [], - [], - [] - ] - }, - { - "id": "bc76c4d6.a7ad28", - "type": "ui_button", - "z": "9daf9e2b.019fc", - "name": "", - "group": "a7d64879.38298", - "order": 5, - "width": "6", - "height": 1, - "passthru": false, - "label": "Shutdown", - "tooltip": "", - "color": "", - "bgcolor": "#AD1625", - "className": "", - "icon": "fa-power-off fa-2x", - "payload": "shutdown", - "payloadType": "str", - "topic": "shutdown", - "topicType": "str", - "x": 160, - "y": 320, - "wires": [ - [ - "611a8b1c.a829b4" - ] - ] - }, - { - "id": "b81b990a.d4dca", - "type": "link in", - "z": "9daf9e2b.019fc", - "name": "Shutdown", - "links": [ - "e08cfcb8.2a67e8" - ], - "x": 195, - "y": 280, - "wires": [ - [ - "611a8b1c.a829b4" - ] - ] - }, - { - "id": "ea4fae012404854c", - "type": "ui_button", - "z": "9daf9e2b.019fc", - "name": "", - "group": "a7d64879.38298", - "order": 2, - "width": "6", - "height": 1, - "passthru": true, - "label": "Restart Hardware Controller", - "tooltip": "", - "color": "", - "bgcolor": "#AD1625", - "className": "", - "icon": "fa-refresh fa-2x", - "payload": "Restarting hardware controller...", - "payloadType": "str", - "topic": "", - "topicType": "str", - "x": 440, - "y": 420, - "wires": [ - [ - "c54d948575dbcff8", - "d10f3ffd98055447" - ] - ] - }, - { - "id": "438febd245a9f73c", - "type": "link in", - "z": "9daf9e2b.019fc", - "name": "Restart Hardware Controller", - "links": [ - "e41870d7.300eb8", - "3973b999ee7b3b1d" - ], - "x": 195, - "y": 420, - "wires": [ - [ - "ea4fae012404854c" - ] - ] - }, - { - "id": "c54d948575dbcff8", - "type": "exec", - "z": "9daf9e2b.019fc", - "command": "sudo systemctl restart planktoscope-org.device-backend.controller.service", - "addpay": false, - "append": "", - "useSpawn": "false", - "timer": "", - "winHide": false, - "oldrc": false, - "name": "Restart hardware controller", - "x": 780, - "y": 420, - "wires": [ - [], - [], - [] - ] - }, - { - "id": "e2e5ce0351a6cc11", - "type": "ui_button", - "z": "9daf9e2b.019fc", - "name": "", - "group": "a7d64879.38298", - "order": 3, - "width": "6", - "height": 1, - "passthru": true, - "label": "Restart Segmenter", - "tooltip": "", - "color": "", - "bgcolor": "#AD1625", - "className": "", - "icon": "fa-refresh fa-2x", - "payload": "Restarting segmenter...", - "payloadType": "str", - "topic": "", - "topicType": "str", - "x": 410, - "y": 500, - "wires": [ - [ - "2cdbadb65d0e1b20", - "9c1629488b02fdba" - ] - ] - }, - { - "id": "2cdbadb65d0e1b20", - "type": "exec", - "z": "9daf9e2b.019fc", - "command": "docker restart apps_ps_backend_proc-segmenter-server-1", - "addpay": false, - "append": "", - "useSpawn": "false", - "timer": "", - "winHide": false, - "oldrc": false, - "name": "Restart segmenter", - "x": 750, - "y": 500, - "wires": [ - [], - [], - [] - ] - }, - { - "id": "7b64209d734e4e2c", - "type": "ui_template", - "z": "9daf9e2b.019fc", - "group": "a7d64879.38298", - "name": "Logs", - "order": 1, - "width": "0", - "height": "0", - "format": "

\n The PlanktoScope software application consists of three components: a Node-RED dashboard which provides the user interface you're using; a Hardware Controller\n which executes commands sent from the Node-RED dashboard for hardware control and image acquisition; and a Segmenter which processes an acquired dataset of\n images and isolates objects from those images. Each component has its own independent log of messages, managed separately from the logs for the other components.\n

\n

\n All three components have live-updating logs which you can monitor. Additionally, the Hardware Controller and the Segmenter also save all of their log messages\n to files which you can browse and download. Those software components create a new log file each time they start, and the name of the log file includes the time\n in the PlanktoScope's clock when the software component started. However, if your PlanktoScope's clock is usually wrong, it makes the log files difficult to navigate.\n This will be fixed in a future version of the software.\n

\n

\n If you need to share your logs with other people (e.g. on Slack or GitHub), you should open the \"Downloadable Logs\" links, and then you can select one file or multiple\n log files for downloading as a zip archive.\n

\n", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": true, - "templateScope": "local", - "className": "", - "x": 630, - "y": 180, - "wires": [ - [] - ] - }, - { - "id": "d10f3ffd98055447", - "type": "ui_toast", - "z": "9daf9e2b.019fc", - "position": "top right", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 0, - "ok": "OK", - "cancel": "", - "raw": false, - "className": "", - "topic": "", - "name": "", - "x": 750, - "y": 380, - "wires": [] - }, - { - "id": "9c1629488b02fdba", - "type": "ui_toast", - "z": "9daf9e2b.019fc", - "position": "top right", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 0, - "ok": "OK", - "cancel": "", - "raw": false, - "className": "", - "topic": "", - "name": "", - "x": 750, - "y": 460, - "wires": [] - }, - { - "id": "3910d662.fa1f7a", - "type": "exec", - "z": "1371dec5.76e671", - "command": "df -h | grep /dev/root | awk -F ' ' '{print $5}' | tr -d % | tr \"\\n$\" \"\\ \" | sed 's/,/./' | tr -d \" \"", - "addpay": false, - "append": "", - "useSpawn": "", - "timer": "", - "name": "Disk Usage", - "x": 330, - "y": 120, - "wires": [ - [ - "eaf74a43.fa27d" - ], - [], - [] - ] - }, - { - "id": "1cd5b4c0.46af9b", - "type": "inject", - "z": "1371dec5.76e671", - "name": "update: 5s", - "props": [ - { - "p": "payload" - }, - { - "p": "topic", - "vt": "str" - } - ], - "repeat": "5", - "crontab": "", - "once": false, - "onceDelay": "", - "topic": "", - "payload": "", - "payloadType": "date", - "x": 110, - "y": 160, - "wires": [ - [ - "3910d662.fa1f7a", - "aa2e4cd182dbc776", - "797675a937dc1629", - "f6f570b10c675854" - ] - ] - }, - { - "id": "569154a.b53182c", - "type": "inject", - "z": "1371dec5.76e671", - "name": "once", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": "", - "topic": "", - "payload": "start", - "payloadType": "str", - "x": 130, - "y": 700, - "wires": [ - [ - "5883e629f5d546ed" - ] - ] - }, - { - "id": "4828d2f4.7c712c", - "type": "function", - "z": "1371dec5.76e671", - "name": "set global", - "func": "global.set(\"acq_instrument_id\",msg.payload);\n", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 580, - "y": 720, - "wires": [ - [] - ] - }, - { - "id": "e2f39a35.f57298", - "type": "subflow:1c24ad9c.bebec2", - "z": "1371dec5.76e671", - "name": "", - "env": [], - "x": 130, - "y": 640, - "wires": [ - [ - "9b64f397101c2762" - ] - ] - }, - { - "id": "3e64877a.9684b", - "type": "function", - "z": "1371dec5.76e671", - "name": "set global", - "func": "global.set(\"acq_software\", \"PlanktoScope \" + msg.payload);\n", - "outputs": 1, - "timeout": "", - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 820, - "y": 520, - "wires": [ - [] - ] - }, - { - "id": "bdc6718a.dd5d48", - "type": "ui_text", - "z": "1371dec5.76e671", - "group": "ce9e278.781eed8", - "order": 2, - "width": 0, - "height": 0, - "name": "", - "label": "Instrument Type", - "format": "{{msg.payload}}", - "layout": "row-spread", - "className": "", - "style": false, - "font": "", - "fontSize": "", - "color": "#000000", - "x": 600, - "y": 640, - "wires": [] - }, - { - "id": "a400a97e.e333a8", - "type": "ui_text", - "z": "1371dec5.76e671", - "group": "ce9e278.781eed8", - "order": 1, - "width": 0, - "height": 0, - "name": "", - "label": "Instrument Name", - "format": "{{msg.payload}}", - "layout": "row-spread", - "x": 610, - "y": 680, - "wires": [] - }, - { - "id": "8343fa69.49339", - "type": "ui_text", - "z": "1371dec5.76e671", - "group": "ce9e278.781eed8", - "order": 3, - "width": 0, - "height": 0, - "name": "", - "label": "Software Version", - "format": "{{msg.payload}}", - "layout": "row-spread", - "className": "", - "style": false, - "font": "", - "fontSize": "", - "color": "#000000", - "x": 850, - "y": 560, - "wires": [] - }, - { - "id": "f783aefd.c3bfd8", - "type": "ui_text", - "z": "1371dec5.76e671", - "group": "ce9e278.781eed8", - "order": 4, - "width": 0, - "height": 0, - "name": "", - "label": "Camera Name", - "format": "{{msg.payload}}", - "layout": "row-spread", - "x": 600, - "y": 760, - "wires": [] - }, - { - "id": "30067f35.532f2", - "type": "link in", - "z": "1371dec5.76e671", - "name": "Camera Name", - "links": [ - "559a8085.1d6b9" - ], - "x": 155, - "y": 760, - "wires": [ - [ - "f783aefd.c3bfd8" - ] - ] - }, - { - "id": "eaf74a43.fa27d", - "type": "switch", - "z": "1371dec5.76e671", - "name": "if disk > 90%", - "property": "payload", - "propertyType": "msg", - "rules": [ - { - "t": "gte", - "v": "90", - "vt": "num" - } - ], - "checkall": "true", - "repair": false, - "outputs": 1, - "x": 590, - "y": 120, - "wires": [ - [ - "6d09f428.930bcc" - ] - ] - }, - { - "id": "46d5e78b.15f998", - "type": "ui_toast", - "z": "1371dec5.76e671", - "position": "dialog", - "displayTime": "10", - "highlight": "", - "sendall": true, - "outputs": 1, - "ok": "OK", - "cancel": "", - "raw": false, - "topic": "", - "name": "", - "x": 1090, - "y": 120, - "wires": [ - [] - ] - }, - { - "id": "24df077a.cb252", - "type": "change", - "z": "1371dec5.76e671", - "name": "full disk msg", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "\"Your drive has reached 90% capacity, you should do a backup to an external drive and a purge.\"", - "tot": "str" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 930, - "y": 120, - "wires": [ - [ - "46d5e78b.15f998" - ] - ] - }, - { - "id": "6d09f428.930bcc", - "type": "delay", - "z": "1371dec5.76e671", - "name": "", - "pauseType": "rate", - "timeout": "5", - "timeoutUnits": "seconds", - "rate": "1", - "nbRateUnits": "5", - "rateUnits": "minute", - "randomFirst": "1", - "randomLast": "5", - "randomUnits": "seconds", - "drop": true, - "allowrate": false, - "outputs": 1, - "x": 760, - "y": 120, - "wires": [ - [ - "24df077a.cb252" - ] - ] - }, - { - "id": "5883e629f5d546ed", - "type": "file in", - "z": "1371dec5.76e671", - "name": "Get machine name", - "filename": "/run/machine-name", - "filenameType": "str", - "format": "utf8", - "chunk": false, - "sendError": false, - "encoding": "none", - "allProps": false, - "x": 350, - "y": 700, - "wires": [ - [ - "a400a97e.e333a8", - "4828d2f4.7c712c" - ] - ] - }, - { - "id": "9b64f397101c2762", - "type": "change", - "z": "1371dec5.76e671", - "name": "Get acq_instrument", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.acq_instrument", - "tot": "msg" - }, - { - "t": "set", - "p": "topic", - "pt": "msg", - "to": "acq_instrument", - "tot": "str" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 350, - "y": 640, - "wires": [ - [ - "bdc6718a.dd5d48" - ] - ] - }, - { - "id": "99725e1437cc390b", - "type": "file in", - "z": "1371dec5.76e671", - "name": "Versioning File", - "filename": "/usr/share/planktoscope/installer-versioning.yml", - "filenameType": "str", - "format": "utf8", - "chunk": false, - "sendError": false, - "encoding": "none", - "allProps": false, - "x": 240, - "y": 540, - "wires": [ - [ - "f4e21e28bd903f6d" - ] - ], - "info": "# PlanktoScope Help\nThis Node will read the content of the file named **config.txt** containing all the input placeholders.\n" - }, - { - "id": "6a0fa173874c3ddd", - "type": "inject", - "z": "1371dec5.76e671", - "name": "once", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": "", - "topic": "", - "payload": "start", - "payloadType": "str", - "x": 90, - "y": 540, - "wires": [ - [ - "99725e1437cc390b" - ] - ] - }, - { - "id": "f4e21e28bd903f6d", - "type": "yaml", - "z": "1371dec5.76e671", - "property": "payload", - "name": "", - "x": 390, - "y": 540, - "wires": [ - [ - "d6264e3e29b68c6e", - "aa84b912c996c69e", - "fba22dc2c16b3ec8" - ] - ] - }, - { - "id": "d6264e3e29b68c6e", - "type": "change", - "z": "1371dec5.76e671", - "name": "Get version", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.version", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 590, - "y": 540, - "wires": [ - [ - "3e64877a.9684b", - "8343fa69.49339" - ] - ] - }, - { - "id": "aa84b912c996c69e", - "type": "change", - "z": "1371dec5.76e671", - "name": "Get repo", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.repo", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 580, - "y": 500, - "wires": [ - [ - "fd55e7a43d9bdbbb" - ] - ] - }, - { - "id": "fd55e7a43d9bdbbb", - "type": "function", - "z": "1371dec5.76e671", - "name": "set global", - "func": "global.set(\"process_source\", msg.payload);\n", - "outputs": 1, - "timeout": "", - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 820, - "y": 480, - "wires": [ - [] - ] - }, - { - "id": "fba22dc2c16b3ec8", - "type": "change", - "z": "1371dec5.76e671", - "name": "Get commit", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.commit", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 590, - "y": 580, - "wires": [ - [ - "2ddc75a4ac38a17f" - ] - ] - }, - { - "id": "2ddc75a4ac38a17f", - "type": "function", - "z": "1371dec5.76e671", - "name": "set global", - "func": "global.set(\"process_commit\", msg.payload);\n", - "outputs": 1, - "timeout": "", - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 820, - "y": 600, - "wires": [ - [] - ] - }, - { - "id": "797675a937dc1629", - "type": "ui_template", - "z": "1371dec5.76e671", - "group": "3da7da8f.179606", - "name": "Metrics panel", - "order": 2, - "width": "0", - "height": "0", - "format": "
\n

\n The instrument's system time is different from your web browser's time by {{drift}}.\n As a result, timestamps in your datasets will be incorrect.\n Additionally, system metrics will not be recorded or shown correctly.\n Additionally, you will see incorrectly-aligned graphs in the metrics below.\n

\n

Please change the instrument's system time or your web browser's time to accurate values.

\n

\n \n

\n
\n\n
\n

Loading system metrics, please wait...

\n
\n\n
\n \n
\n\n\n", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "className": "", - "x": 330, - "y": 280, - "wires": [ - [] - ] - }, - { - "id": "aa2e4cd182dbc776", - "type": "function", - "z": "1371dec5.76e671", - "name": "Get system time", - "func": "var date = new Date();\ndate.setSeconds(0, 0);\nmsg.payload = (\n date.toISOString().replace('T', ' ').replace(/:\\d+\\.\\d+Z/,' UTC')\n);\nreturn msg", - "outputs": 1, - "timeout": "", - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 340, - "y": 240, - "wires": [ - [ - "7c9ee522f6dbd3b0" - ] - ] - }, - { - "id": "7c9ee522f6dbd3b0", - "type": "ui_text", - "z": "1371dec5.76e671", - "group": "ce9e278.781eed8", - "order": 5, - "width": 0, - "height": 0, - "name": "", - "label": "System Time", - "format": "{{msg.payload}}", - "layout": "row-spread", - "className": "", - "style": false, - "font": "", - "fontSize": "", - "color": "#000000", - "x": 590, - "y": 240, - "wires": [] - }, - { - "id": "6dc9862f2eebe935", - "type": "http in", - "z": "1371dec5.76e671", - "name": "POST /api/system-time", - "url": "/api/system-time", - "method": "post", - "upload": false, - "swaggerDoc": "", - "x": 120, - "y": 360, - "wires": [ - [ - "a7994a561866dc94", - "dea222e9a6553cac" - ] - ] - }, - { - "id": "1c4113d4c933fd4b", - "type": "ui_toast", - "z": "1371dec5.76e671", - "position": "top right", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 0, - "ok": "OK", - "cancel": "", - "raw": false, - "className": "", - "topic": "Setting system time", - "name": "", - "x": 610, - "y": 340, - "wires": [] - }, - { - "id": "a7994a561866dc94", - "type": "function", - "z": "1371dec5.76e671", - "name": "Get system time", - "func": "var date = new Date(msg.payload.timestamp);\nmsg.payload = (\n date.toISOString().replace('T', ' ').replace(/:\\d+\\.\\d+Z/,' UTC')\n);\nreturn msg", - "outputs": 1, - "timeout": "", - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 340, - "y": 340, - "wires": [ - [ - "1c4113d4c933fd4b", - "423659c62bae0524" - ] - ] - }, - { - "id": "814ce40bfc413777", - "type": "exec", - "z": "1371dec5.76e671", - "command": "sudo date -s", - "addpay": "payload", - "append": "", - "useSpawn": "", - "timer": "", - "winHide": false, - "name": "Set system time", - "x": 600, - "y": 380, - "wires": [ - [], - [], - [] - ] - }, - { - "id": "dea222e9a6553cac", - "type": "function", - "z": "1371dec5.76e671", - "name": "Prepare timestamp", - "func": "msg.payload = ('@' + msg.payload.timestamp).slice(0, -3);\nreturn msg;", - "outputs": 1, - "timeout": "", - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 350, - "y": 380, - "wires": [ - [ - "814ce40bfc413777" - ] - ] - }, - { - "id": "f6f570b10c675854", - "type": "ui_template", - "z": "1371dec5.76e671", - "group": "ce9e278.781eed8", - "name": "Browser time", - "order": 6, - "width": "6", - "height": "1", - "format": "
\n

Browser Time

\n

{{time}}

\n
\n\n", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "className": "", - "x": 330, - "y": 200, - "wires": [ - [] - ] - }, - { - "id": "3822b843fda94733", - "type": "http in", - "z": "1371dec5.76e671", - "name": "GET /api/system-time", - "url": "/api/system-time", - "method": "get", - "upload": false, - "swaggerDoc": "", - "x": 120, - "y": 420, - "wires": [ - [ - "5b0a65d3fe187424" - ] - ] - }, - { - "id": "5b0a65d3fe187424", - "type": "function", - "z": "1371dec5.76e671", - "name": "Get system time", - "func": "var date = new Date();\nmsg.payload = {'timestamp': date.getTime()};\nreturn msg", - "outputs": 1, - "timeout": "", - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 340, - "y": 420, - "wires": [ - [ - "312a15407574b38e" - ] - ] - }, - { - "id": "423659c62bae0524", - "type": "http response", - "z": "1371dec5.76e671", - "name": "Send POST response", - "statusCode": "", - "headers": {}, - "x": 620, - "y": 300, - "wires": [] - }, - { - "id": "312a15407574b38e", - "type": "http response", - "z": "1371dec5.76e671", - "name": "Send GET response", - "statusCode": "", - "headers": { - "Content-Type": "application/json; charset=UTF-8" - }, - "x": 620, - "y": 420, - "wires": [] - }, - { - "id": "1fdf77b5.24e4e", - "type": "mqtt in", - "z": "9a22e67a.378818", - "name": "", - "topic": "status/#", - "qos": "0", - "datatype": "json", - "broker": "8dc3722c.06efa8", - "nl": false, - "rap": false, - "inputs": 0, - "x": 290, - "y": 340, - "wires": [ - [ - "fa73983d.318188" - ] - ] - }, - { - "id": "4a1e9e3e.27506", - "type": "switch", - "z": "9a22e67a.378818", - "name": "Filter segmenter out", - "property": "topic", - "propertyType": "msg", - "rules": [ - { - "t": "else" - }, - { - "t": "cont", - "v": "status/segmenter", - "vt": "str" - } - ], - "checkall": "true", - "repair": false, - "outputs": 2, - "x": 620, - "y": 340, - "wires": [ - [ - "58f2e0f.4e8b12" - ], - [ - "dcf5bd45.16a8d" - ] - ] - }, - { - "id": "fa73983d.318188", - "type": "json", - "z": "9a22e67a.378818", - "name": "", - "property": "payload", - "action": "obj", - "pretty": true, - "x": 430, - "y": 340, - "wires": [ - [ - "4a1e9e3e.27506" - ] - ] - }, - { - "id": "58f2e0f.4e8b12", - "type": "link out", - "z": "9a22e67a.378818", - "name": "Fluidic module status", - "links": [ - "bb628f8d.98f108" - ], - "x": 795, - "y": 320, - "wires": [] - }, - { - "id": "dcf5bd45.16a8d", - "type": "link out", - "z": "9a22e67a.378818", - "name": "Segmenter module status", - "links": [ - "25867454.a8e334" - ], - "x": 795, - "y": 360, - "wires": [] - }, - { - "id": "e41870d7.300eb8", - "type": "link out", - "z": "1eaf21c8.f7a21e", - "name": "Stepper config change", - "mode": "link", - "links": [ - "438febd245a9f73c" - ], - "x": 1495, - "y": 380, - "wires": [] - }, - { - "id": "2068e7f.f4efb18", - "type": "delay", - "z": "1eaf21c8.f7a21e", - "name": "", - "pauseType": "delay", - "timeout": "1", - "timeoutUnits": "seconds", - "rate": "1", - "nbRateUnits": "1", - "rateUnits": "second", - "randomFirst": "1", - "randomLast": "5", - "randomUnits": "seconds", - "drop": false, - "outputs": 1, - "x": 1180, - "y": 380, - "wires": [ - [ - "e41870d7.300eb8" - ] - ] - }, - { - "id": "8e3b3d3c.955148", - "type": "subflow:4ed26b8b.253504", - "z": "1eaf21c8.f7a21e", - "name": "", - "env": [], - "x": 1220, - "y": 420, - "wires": [] - }, - { - "id": "54ba7f16.709ad8", - "type": "change", - "z": "1eaf21c8.f7a21e", - "name": "Get pump_steps_per_ml", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.pump_steps_per_ml", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 670, - "y": 400, - "wires": [ - [ - "ee58b91c.396108" - ] - ] - }, - { - "id": "ee58b91c.396108", - "type": "ui_text_input", - "z": "1eaf21c8.f7a21e", - "name": "pump_steps_per_ml", - "label": "Pump: steps per mL", - "tooltip": "", - "group": "6be36295.0ab324", - "order": 6, - "width": 0, - "height": 0, - "passthru": false, - "mode": "number", - "delay": "2000", - "topic": "pump_steps_per_ml", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 940, - "y": 400, - "wires": [ - [ - "2068e7f.f4efb18", - "8e3b3d3c.955148" - ] - ] - }, - { - "id": "7534dfd9.8cf3e8", - "type": "ui_template", - "z": "1eaf21c8.f7a21e", - "group": "6be36295.0ab324", - "name": "Information", - "order": 1, - "width": "8", - "height": "3", - "format": "
\n

\n Changing one of these values will cause the Python hardware controller to restart, to reload the new hardware configuration.\n

\n

\n Warning: selecting a hardware version from the dropdown menu below will also overwrite all of your hardware settings, including your camera white balance settings.\n

\n

\n If you are not sure, you probably should not be touching anything here!\n

\n
\n", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": true, - "templateScope": "local", - "className": "", - "x": 610, - "y": 40, - "wires": [ - [] - ] - }, - { - "id": "a7e5c7f4.644678", - "type": "ui_dropdown", - "z": "1eaf21c8.f7a21e", - "name": "", - "label": "Hardware version", - "tooltip": "", - "place": "Select option", - "group": "6be36295.0ab324", - "order": 2, - "width": 0, - "height": 0, - "passthru": false, - "multiple": false, - "options": [ - { - "label": "", - "value": "PlanktoScope v2.1", - "type": "str" - }, - { - "label": "", - "value": "PlanktoScope v2.3", - "type": "str" - }, - { - "label": "", - "value": "PlanktoScope v2.5", - "type": "str" - }, - { - "label": "", - "value": "PlanktoScope v2.6", - "type": "str" - }, - { - "label": "", - "value": "PlanktoScope v3.0", - "type": "str" - } - ], - "payload": "", - "topic": "acq_instrument", - "topicType": "str", - "className": "", - "x": 670, - "y": 160, - "wires": [ - [ - "08d177136bd18281", - "56dd3f82c45717f0" - ] - ] - }, - { - "id": "1cfadc66.3cde8c", - "type": "subflow:1c24ad9c.bebec2", - "z": "1eaf21c8.f7a21e", - "name": "", - "env": [], - "x": 510, - "y": 300, - "wires": [ - [] - ] - }, - { - "id": "3e2c5c1c.4c57b4", - "type": "function", - "z": "1eaf21c8.f7a21e", - "name": "Save global", - "func": "global.set(msg.topic,msg.payload);\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 350, - "y": 300, - "wires": [ - [ - "1cfadc66.3cde8c" - ] - ] - }, - { - "id": "427c312.fc5e65", - "type": "subflow:1c24ad9c.bebec2", - "z": "1eaf21c8.f7a21e", - "name": "", - "env": [], - "x": 170, - "y": 140, - "wires": [ - [ - "c00c6732b9f36adb" - ] - ] - }, - { - "id": "c67c305004f87e39", - "type": "change", - "z": "1eaf21c8.f7a21e", - "name": "Get process_pixel_fixed", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.process_pixel_fixed", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 670, - "y": 480, - "wires": [ - [ - "244ca5dd62df2bcd" - ] - ] - }, - { - "id": "244ca5dd62df2bcd", - "type": "ui_text_input", - "z": "1eaf21c8.f7a21e", - "name": "process_pixel_fixed", - "label": "Pixel size calibration: um per pixel", - "tooltip": "Object size in µm / pixel. 0 will remove this calibration.", - "group": "6be36295.0ab324", - "order": 8, - "width": 0, - "height": 0, - "passthru": true, - "mode": "number", - "delay": "1000", - "topic": "process_pixel_fixed", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 940, - "y": 480, - "wires": [ - [ - "8e3b3d3c.955148", - "f9b47f4b1da15778" - ] - ] - }, - { - "id": "f9b47f4b1da15778", - "type": "function", - "z": "1eaf21c8.f7a21e", - "name": "Set or remove if null", - "func": "if (msg.payload == 0){\n global.set(msg.topic,undefined)\n}\nelse {\n global.set(msg.topic,msg.payload);\n}\n\nreturn msg", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 1220, - "y": 480, - "wires": [ - [ - "5d5ad36d2c50dcc2" - ] - ] - }, - { - "id": "5d5ad36d2c50dcc2", - "type": "link out", - "z": "1eaf21c8.f7a21e", - "name": "Process_pixel calibration", - "links": [], - "x": 1495, - "y": 500, - "wires": [] - }, - { - "id": "6146ba22df928516", - "type": "ui_dropdown", - "z": "1eaf21c8.f7a21e", - "name": "acq_fnumber_objective", - "label": "M12 Lens", - "tooltip": "", - "place": "Select option", - "group": "6be36295.0ab324", - "order": 7, - "width": 0, - "height": 0, - "passthru": true, - "multiple": false, - "options": [ - { - "label": "f 25mm 1/2\" 5MP IR", - "value": 25, - "type": "num" - }, - { - "label": "f 16mm 1/2.5\" 5MP IR", - "value": 16, - "type": "num" - }, - { - "label": "f 12mm 1/2.5\" 5MP IR", - "value": 12, - "type": "num" - }, - { - "label": "f 8mm 1/2.5\" 5MP IR", - "value": 8, - "type": "num" - }, - { - "label": "f 6mm 1/2.5\" 5MP IR", - "value": 6, - "type": "num" - } - ], - "payload": "", - "topic": "acq_fnumber_objective", - "topicType": "str", - "x": 930, - "y": 520, - "wires": [ - [ - "a6983d3232b570a7", - "8e3b3d3c.955148" - ] - ] - }, - { - "id": "a6983d3232b570a7", - "type": "change", - "z": "1eaf21c8.f7a21e", - "name": "", - "rules": [ - { - "t": "set", - "p": "acq_fnumber_objective", - "pt": "global", - "to": "payload", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 1260, - "y": 520, - "wires": [ - [ - "5d5ad36d2c50dcc2" - ] - ] - }, - { - "id": "11955bbeefc29ab4", - "type": "change", - "z": "1eaf21c8.f7a21e", - "name": "Get acq_fnumber_objective", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.acq_fnumber_objective", - "tot": "msg" - }, - { - "t": "set", - "p": "topic", - "pt": "msg", - "to": "acq_fnumber_objective", - "tot": "str" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 680, - "y": 520, - "wires": [ - [ - "6146ba22df928516" - ] - ] - }, - { - "id": "d276ce894f483bcf", - "type": "ui_toast", - "z": "1eaf21c8.f7a21e", - "position": "top right", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 0, - "ok": "OK", - "cancel": "", - "raw": false, - "className": "", - "topic": "Resetting hardware configuration to version-specific default", - "name": "", - "x": 370, - "y": 260, - "wires": [] - }, - { - "id": "68703ef63da2f081", - "type": "change", - "z": "1eaf21c8.f7a21e", - "name": "Choose default hardware config", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "$join([\"/home/pi/PlanktoScope/device-backend/default-configs/\", $substringAfter(msg.payload, \"PlanktoScope \"), \".hardware.json\"])", - "tot": "jsonata" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 410, - "y": 220, - "wires": [ - [ - "e3ba6ac89221b17b" - ] - ] - }, - { - "id": "e3ba6ac89221b17b", - "type": "exec", - "z": "1eaf21c8.f7a21e", - "command": "cp", - "addpay": "payload", - "append": "/home/pi/PlanktoScope/hardware.json", - "useSpawn": "false", - "timer": "", - "winHide": false, - "oldrc": false, - "name": "Copy default hardware config", - "x": 700, - "y": 220, - "wires": [ - [ - "97e582080deae888" - ], - [], - [] - ] - }, - { - "id": "97e582080deae888", - "type": "delay", - "z": "1eaf21c8.f7a21e", - "name": "", - "pauseType": "delay", - "timeout": "500", - "timeoutUnits": "milliseconds", - "rate": "1", - "nbRateUnits": "1", - "rateUnits": "second", - "randomFirst": "1", - "randomLast": "5", - "randomUnits": "seconds", - "drop": false, - "allowrate": false, - "outputs": 1, - "x": 930, - "y": 220, - "wires": [ - [ - "3973b999ee7b3b1d" - ] - ] - }, - { - "id": "3973b999ee7b3b1d", - "type": "link out", - "z": "1eaf21c8.f7a21e", - "name": "Reload hardware config", - "mode": "link", - "links": [ - "438febd245a9f73c", - "4ebc0345e63a78e9", - "5984b086eddc9311", - "a2f2a4c7cbae4446" - ], - "x": 1095, - "y": 220, - "wires": [] - }, - { - "id": "3bcaf757cbc77fbe", - "type": "subflow:b7861ce703215a01", - "z": "1eaf21c8.f7a21e", - "name": "", - "x": 380, - "y": 440, - "wires": [ - [ - "54ba7f16.709ad8", - "c67c305004f87e39", - "11955bbeefc29ab4" - ] - ] - }, - { - "id": "862235d10aae5b83", - "type": "inject", - "z": "1eaf21c8.f7a21e", - "name": "Once", - "props": [], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "", - "x": 170, - "y": 460, - "wires": [ - [ - "3bcaf757cbc77fbe" - ] - ] - }, - { - "id": "c00c6732b9f36adb", - "type": "change", - "z": "1eaf21c8.f7a21e", - "name": "Get acq_instrument", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.acq_instrument", - "tot": "msg" - }, - { - "t": "set", - "p": "topic", - "pt": "msg", - "to": "acq_instrument", - "tot": "str" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 370, - "y": 140, - "wires": [ - [ - "a7e5c7f4.644678", - "56dd3f82c45717f0" - ] - ] - }, - { - "id": "4ebc0345e63a78e9", - "type": "link in", - "z": "1eaf21c8.f7a21e", - "name": "Load hardware config", - "links": [ - "3973b999ee7b3b1d" - ], - "x": 205, - "y": 420, - "wires": [ - [ - "3bcaf757cbc77fbe" - ] - ] - }, - { - "id": "cb9009e8a49e93cc", - "type": "link in", - "z": "1eaf21c8.f7a21e", - "name": "Set hardware version", - "links": [ - "08d177136bd18281", - "9f34e4a2f33c4022" - ], - "x": 205, - "y": 260, - "wires": [ - [ - "68703ef63da2f081", - "d276ce894f483bcf", - "3e2c5c1c.4c57b4", - "a7e5c7f4.644678" - ] - ] - }, - { - "id": "08d177136bd18281", - "type": "link out", - "z": "1eaf21c8.f7a21e", - "name": "Set hardware version", - "mode": "link", - "links": [ - "cb9009e8a49e93cc" - ], - "x": 875, - "y": 160, - "wires": [] - }, - { - "id": "56dd3f82c45717f0", - "type": "link out", - "z": "1eaf21c8.f7a21e", - "name": "Hardware version loaded", - "mode": "link", - "links": [ - "a2f2a4c7cbae4446" - ], - "x": 875, - "y": 120, - "wires": [] - } + "value": "PlanktoScope v3.0", + "type": "str" + } + ], + "payload": "", + "topic": "acq_instrument", + "topicType": "str", + "className": "", + "x": 670, + "y": 160, + "wires": [["08d177136bd18281", "56dd3f82c45717f0"]] + }, + { + "id": "1cfadc66.3cde8c", + "type": "subflow:1c24ad9c.bebec2", + "z": "1eaf21c8.f7a21e", + "name": "", + "env": [], + "x": 510, + "y": 300, + "wires": [[]] + }, + { + "id": "3e2c5c1c.4c57b4", + "type": "function", + "z": "1eaf21c8.f7a21e", + "name": "Save global", + "func": "global.set(msg.topic,msg.payload);\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 350, + "y": 300, + "wires": [["1cfadc66.3cde8c"]] + }, + { + "id": "427c312.fc5e65", + "type": "subflow:1c24ad9c.bebec2", + "z": "1eaf21c8.f7a21e", + "name": "", + "env": [], + "x": 170, + "y": 140, + "wires": [["c00c6732b9f36adb"]] + }, + { + "id": "c67c305004f87e39", + "type": "change", + "z": "1eaf21c8.f7a21e", + "name": "Get process_pixel_fixed", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.process_pixel_fixed", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 670, + "y": 480, + "wires": [["244ca5dd62df2bcd"]] + }, + { + "id": "244ca5dd62df2bcd", + "type": "ui_text_input", + "z": "1eaf21c8.f7a21e", + "name": "process_pixel_fixed", + "label": "Pixel size calibration: um per pixel", + "tooltip": "Object size in µm / pixel. 0 will remove this calibration.", + "group": "6be36295.0ab324", + "order": 8, + "width": 0, + "height": 0, + "passthru": true, + "mode": "number", + "delay": "1000", + "topic": "process_pixel_fixed", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 940, + "y": 480, + "wires": [["8e3b3d3c.955148", "f9b47f4b1da15778"]] + }, + { + "id": "f9b47f4b1da15778", + "type": "function", + "z": "1eaf21c8.f7a21e", + "name": "Set or remove if null", + "func": "if (msg.payload == 0){\n global.set(msg.topic,undefined)\n}\nelse {\n global.set(msg.topic,msg.payload);\n}\n\nreturn msg", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 1220, + "y": 480, + "wires": [["5d5ad36d2c50dcc2"]] + }, + { + "id": "5d5ad36d2c50dcc2", + "type": "link out", + "z": "1eaf21c8.f7a21e", + "name": "Process_pixel calibration", + "links": [], + "x": 1495, + "y": 500, + "wires": [] + }, + { + "id": "6146ba22df928516", + "type": "ui_dropdown", + "z": "1eaf21c8.f7a21e", + "name": "acq_fnumber_objective", + "label": "M12 Lens", + "tooltip": "", + "place": "Select option", + "group": "6be36295.0ab324", + "order": 7, + "width": 0, + "height": 0, + "passthru": true, + "multiple": false, + "options": [ + { + "label": "f 25mm 1/2\" 5MP IR", + "value": 25, + "type": "num" + }, + { + "label": "f 16mm 1/2.5\" 5MP IR", + "value": 16, + "type": "num" + }, + { + "label": "f 12mm 1/2.5\" 5MP IR", + "value": 12, + "type": "num" + }, + { + "label": "f 8mm 1/2.5\" 5MP IR", + "value": 8, + "type": "num" + }, + { + "label": "f 6mm 1/2.5\" 5MP IR", + "value": 6, + "type": "num" + } + ], + "payload": "", + "topic": "acq_fnumber_objective", + "topicType": "str", + "x": 930, + "y": 520, + "wires": [["a6983d3232b570a7", "8e3b3d3c.955148"]] + }, + { + "id": "a6983d3232b570a7", + "type": "change", + "z": "1eaf21c8.f7a21e", + "name": "", + "rules": [ + { + "t": "set", + "p": "acq_fnumber_objective", + "pt": "global", + "to": "payload", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 1260, + "y": 520, + "wires": [["5d5ad36d2c50dcc2"]] + }, + { + "id": "11955bbeefc29ab4", + "type": "change", + "z": "1eaf21c8.f7a21e", + "name": "Get acq_fnumber_objective", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.acq_fnumber_objective", + "tot": "msg" + }, + { + "t": "set", + "p": "topic", + "pt": "msg", + "to": "acq_fnumber_objective", + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 680, + "y": 520, + "wires": [["6146ba22df928516"]] + }, + { + "id": "d276ce894f483bcf", + "type": "ui_toast", + "z": "1eaf21c8.f7a21e", + "position": "top right", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 0, + "ok": "OK", + "cancel": "", + "raw": false, + "className": "", + "topic": "Resetting hardware configuration to version-specific default", + "name": "", + "x": 370, + "y": 260, + "wires": [] + }, + { + "id": "68703ef63da2f081", + "type": "change", + "z": "1eaf21c8.f7a21e", + "name": "Choose default hardware config", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "$join([\"/home/pi/PlanktoScope/device-backend/default-configs/\", $substringAfter(msg.payload, \"PlanktoScope \"), \".hardware.json\"])", + "tot": "jsonata" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 410, + "y": 220, + "wires": [["e3ba6ac89221b17b"]] + }, + { + "id": "e3ba6ac89221b17b", + "type": "exec", + "z": "1eaf21c8.f7a21e", + "command": "cp", + "addpay": "payload", + "append": "/home/pi/PlanktoScope/hardware.json", + "useSpawn": "false", + "timer": "", + "winHide": false, + "oldrc": false, + "name": "Copy default hardware config", + "x": 700, + "y": 220, + "wires": [["97e582080deae888"], [], []] + }, + { + "id": "97e582080deae888", + "type": "delay", + "z": "1eaf21c8.f7a21e", + "name": "", + "pauseType": "delay", + "timeout": "500", + "timeoutUnits": "milliseconds", + "rate": "1", + "nbRateUnits": "1", + "rateUnits": "second", + "randomFirst": "1", + "randomLast": "5", + "randomUnits": "seconds", + "drop": false, + "allowrate": false, + "outputs": 1, + "x": 930, + "y": 220, + "wires": [["3973b999ee7b3b1d"]] + }, + { + "id": "3973b999ee7b3b1d", + "type": "link out", + "z": "1eaf21c8.f7a21e", + "name": "Reload hardware config", + "mode": "link", + "links": [ + "438febd245a9f73c", + "4ebc0345e63a78e9", + "5984b086eddc9311", + "a2f2a4c7cbae4446" + ], + "x": 1095, + "y": 220, + "wires": [] + }, + { + "id": "3bcaf757cbc77fbe", + "type": "subflow:b7861ce703215a01", + "z": "1eaf21c8.f7a21e", + "name": "", + "x": 380, + "y": 440, + "wires": [["54ba7f16.709ad8", "c67c305004f87e39", "11955bbeefc29ab4"]] + }, + { + "id": "862235d10aae5b83", + "type": "inject", + "z": "1eaf21c8.f7a21e", + "name": "Once", + "props": [], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "x": 170, + "y": 460, + "wires": [["3bcaf757cbc77fbe"]] + }, + { + "id": "c00c6732b9f36adb", + "type": "change", + "z": "1eaf21c8.f7a21e", + "name": "Get acq_instrument", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.acq_instrument", + "tot": "msg" + }, + { + "t": "set", + "p": "topic", + "pt": "msg", + "to": "acq_instrument", + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 370, + "y": 140, + "wires": [["a7e5c7f4.644678", "56dd3f82c45717f0"]] + }, + { + "id": "4ebc0345e63a78e9", + "type": "link in", + "z": "1eaf21c8.f7a21e", + "name": "Load hardware config", + "links": ["3973b999ee7b3b1d"], + "x": 205, + "y": 420, + "wires": [["3bcaf757cbc77fbe"]] + }, + { + "id": "cb9009e8a49e93cc", + "type": "link in", + "z": "1eaf21c8.f7a21e", + "name": "Set hardware version", + "links": ["08d177136bd18281", "9f34e4a2f33c4022"], + "x": 205, + "y": 260, + "wires": [ + [ + "68703ef63da2f081", + "d276ce894f483bcf", + "3e2c5c1c.4c57b4", + "a7e5c7f4.644678" + ] + ] + }, + { + "id": "08d177136bd18281", + "type": "link out", + "z": "1eaf21c8.f7a21e", + "name": "Set hardware version", + "mode": "link", + "links": ["cb9009e8a49e93cc"], + "x": 875, + "y": 160, + "wires": [] + }, + { + "id": "56dd3f82c45717f0", + "type": "link out", + "z": "1eaf21c8.f7a21e", + "name": "Hardware version loaded", + "mode": "link", + "links": ["a2f2a4c7cbae4446"], + "x": 875, + "y": 120, + "wires": [] + } ] From f4a5acbf6c3c7d4b5d73c4c430e8ab9881f88dcd Mon Sep 17 00:00:00 2001 From: Sonny Piers Date: Wed, 21 May 2025 11:07:44 +0200 Subject: [PATCH 2/3] f --- .../node-red-dashboard/adafruithat/flows.json | 16876 +++++++++------- .../planktoscopehat/flows.json | 16209 ++++++++------- 2 files changed, 17815 insertions(+), 15270 deletions(-) diff --git a/software/node-red-dashboard/adafruithat/flows.json b/software/node-red-dashboard/adafruithat/flows.json index f7ea326ce..2271db36d 100644 --- a/software/node-red-dashboard/adafruithat/flows.json +++ b/software/node-red-dashboard/adafruithat/flows.json @@ -1,7811 +1,9099 @@ [ - { - "id": "eaae323a.31b3", - "type": "tab", - "label": "Home", - "disabled": false, - "info": "" - }, - { - "id": "b771c342.49603", - "type": "tab", - "label": "Sample", - "disabled": false, - "info": "" - }, - { - "id": "bccd1f23.87219", - "type": "tab", - "label": "Optic Configuration", - "disabled": false, - "info": "" - }, - { - "id": "baa1e3d9.cb29d", - "type": "tab", - "label": "Fluidic Acquisition", - "disabled": false, - "info": "" - }, - { - "id": "cb95299c.2817c8", - "type": "tab", - "label": "Segmentation", - "disabled": false, - "info": "" - }, - { - "id": "c1660bc.e7ff7f8", - "type": "tab", - "label": "Gallery", - "disabled": false, - "info": "" - }, - { - "id": "9daf9e2b.019fc", - "type": "tab", - "label": "Administration", - "disabled": false, - "info": "" - }, - { - "id": "1371dec5.76e671", - "type": "tab", - "label": "System Monitoring", - "disabled": false, - "info": "" - }, - { - "id": "9a22e67a.378818", - "type": "tab", - "label": "MQTT Receive", - "disabled": false, - "info": "" - }, - { - "id": "1eaf21c8.f7a21e", - "type": "tab", - "label": "Hardware Settings", - "disabled": false, - "info": "" - }, - { - "id": "1c24ad9c.bebec2", - "type": "subflow", - "name": "Config", - "info": "An input to this subflow will get the configuration to be saved to disk.\n\nOn startup, this node outputs the loaded configuration", - "category": "", - "in": [ - { + { + "id": "eaae323a.31b3", + "type": "tab", + "label": "Home", + "disabled": false, + "info": "" + }, + { + "id": "b771c342.49603", + "type": "tab", + "label": "Sample", + "disabled": false, + "info": "" + }, + { + "id": "bccd1f23.87219", + "type": "tab", + "label": "Optic Configuration", + "disabled": false, + "info": "" + }, + { + "id": "baa1e3d9.cb29d", + "type": "tab", + "label": "Fluidic Acquisition", + "disabled": false, + "info": "" + }, + { + "id": "cb95299c.2817c8", + "type": "tab", + "label": "Segmentation", + "disabled": false, + "info": "" + }, + { + "id": "c1660bc.e7ff7f8", + "type": "tab", + "label": "Gallery", + "disabled": false, + "info": "" + }, + { + "id": "9daf9e2b.019fc", + "type": "tab", + "label": "Administration", + "disabled": false, + "info": "" + }, + { + "id": "1371dec5.76e671", + "type": "tab", + "label": "System Monitoring", + "disabled": false, + "info": "" + }, + { + "id": "9a22e67a.378818", + "type": "tab", + "label": "MQTT Receive", + "disabled": false, + "info": "" + }, + { + "id": "1eaf21c8.f7a21e", + "type": "tab", + "label": "Hardware Settings", + "disabled": false, + "info": "" + }, + { + "id": "1c24ad9c.bebec2", + "type": "subflow", + "name": "Config", + "info": "An input to this subflow will get the configuration to be saved to disk.\n\nOn startup, this node outputs the loaded configuration", + "category": "", + "in": [ + { + "x": 220, + "y": 160, + "wires": [ + { + "id": "3ad9835.08c937c" + } + ] + } + ], + "out": [ + { + "x": 1040, + "y": 60, + "wires": [ + { + "id": "ad541674.4791c8", + "port": 0 + } + ] + } + ], + "env": [], + "color": "#DDAA99" + }, + { + "id": "4ed26b8b.253504", + "type": "subflow", + "name": "Save hardware config", + "info": "", + "category": "", + "in": [ + { + "x": 40, + "y": 40, + "wires": [ + { + "id": "53d163be.47cf24" + } + ] + } + ], + "out": [], + "env": [], + "meta": {}, + "color": "#DDAA99" + }, + { + "id": "e6665421f66ea4c8", + "type": "subflow", + "name": "Load hardware config", + "info": "", + "category": "", + "in": [ + { + "x": 40, + "y": 40, + "wires": [ + { + "id": "48ceeda454438cb7" + } + ] + } + ], + "out": [ + { + "x": 900, + "y": 40, + "wires": [ + { + "id": "2b1a67ac127f3fe7", + "port": 0 + } + ] + } + ], + "env": [], + "meta": {}, + "color": "#DDAA99" + }, + { + "id": "3a6bb13f.c9703e", + "type": "ui_tab", + "name": "Home", + "icon": "home", + "order": 1, + "disabled": false, + "hidden": false + }, + { + "id": "181bb236.1e94be", + "type": "ui_tab", + "name": "Optic Configuration", + "icon": "fa-eye", + "order": 3, + "disabled": false, + "hidden": false + }, + { + "id": "c9194f02.9d5e9", + "type": "ui_tab", + "name": "Fluidic Acquisition", + "icon": "fa-flask", + "order": 4, + "disabled": false, + "hidden": false + }, + { + "id": "8d16beb8.9b3fb", + "type": "ui_tab", + "name": "Segmentation", + "icon": "fa-crop", + "order": 5, + "disabled": false, + "hidden": false + }, + { + "id": "d9cd733b.ab73d", + "type": "ui_tab", + "name": "System Monitoring", + "icon": "fa-thermometer-full", + "order": 7, + "disabled": false, + "hidden": false + }, + { + "id": "4248342d.e55fac", + "type": "ui_group", + "name": "Optic Characterization", + "tab": "181bb236.1e94be", + "order": 4, + "disp": true, + "width": "6", + "collapse": false + }, + { + "id": "858a0e3c.987fe", + "type": "ui_group", + "name": "Preview", + "tab": "c9194f02.9d5e9", + "order": 1, + "disp": true, + "width": 10, + "collapse": false + }, + { + "id": "64903b47.4034e4", + "type": "ui_group", + "name": "Navigation", + "tab": "8d16beb8.9b3fb", + "order": 3, + "disp": false, + "width": "6", + "collapse": false + }, + { + "id": "3da7da8f.179606", + "type": "ui_group", + "name": "Metrics", + "tab": "d9cd733b.ab73d", + "order": 1, + "disp": true, + "width": "24", + "collapse": true, + "className": "" + }, + { + "id": "cc8bc4eb.651868", + "type": "ui_base", + "theme": { + "name": "theme-dark", + "lightTheme": { + "default": "#0094CE", + "baseColor": "#5900ce", + "baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif", + "edited": false, + "reset": false + }, + "darkTheme": { + "default": "#097479", + "baseColor": "#097479", + "baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif", + "edited": true, + "reset": false + }, + "customTheme": { + "name": "Untitled Theme 1", + "default": "#4B7930", + "baseColor": "#4B7930", + "baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif" + }, + "themeState": { + "base-color": { + "default": "#097479", + "value": "#097479", + "edited": true + }, + "page-titlebar-backgroundColor": { + "value": "#097479", + "edited": false + }, + "page-backgroundColor": { + "value": "#111111", + "edited": false + }, + "page-sidebar-backgroundColor": { + "value": "#333333", + "edited": false + }, + "group-textColor": { + "value": "#0eb8c0", + "edited": false + }, + "group-borderColor": { + "value": "#555555", + "edited": false + }, + "group-backgroundColor": { + "value": "#333333", + "edited": false + }, + "widget-textColor": { + "value": "#eeeeee", + "edited": false + }, + "widget-backgroundColor": { + "value": "#097479", + "edited": false + }, + "widget-borderColor": { + "value": "#333333", + "edited": false + }, + "base-font": { + "value": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif" + } + }, + "angularTheme": { + "primary": "indigo", + "accents": "blue", + "warn": "red", + "background": "grey", + "palette": "light" + } + }, + "site": { + "name": "PlanktoScope", + "hideToolbar": "false", + "allowSwipe": "false", + "lockMenu": "false", + "allowTempTheme": "true", + "dateFormat": "Y-MM-DD", + "sizes": { + "sx": 55, + "sy": 55, + "gx": 4, + "gy": 4, + "cx": 4, + "cy": 4, + "px": 4, + "py": 4 + } + } + }, + { + "id": "36739a35.7cce36", + "type": "ui_tab", + "name": "Gallery", + "icon": "fa-file-image-o", + "order": 6, + "disabled": false, + "hidden": false + }, + { + "id": "c0ebfc57.42527", + "type": "ui_group", + "name": "Group 1", + "tab": "36739a35.7cce36", + "order": 1, + "disp": false, + "width": "24", + "collapse": false + }, + { + "id": "737ec584.2eea2c", + "type": "ui_tab", + "name": "Sample", + "icon": "fa-eyedropper", + "order": 2, + "disabled": false, + "hidden": false + }, + { + "id": "6f97e7ae.270c48", + "type": "ui_group", + "name": "Group 1", + "tab": "3a6bb13f.c9703e", + "order": 1, + "disp": false, + "width": "4", + "collapse": false + }, + { + "id": "3e1ba03d.f01d8", + "type": "ui_group", + "name": "Sample Identification", + "tab": "737ec584.2eea2c", + "order": 1, + "disp": true, + "width": "10", + "collapse": false + }, + { + "id": "4e0cd5ea.17e59c", + "type": "ui_group", + "name": "Group 2", + "tab": "3a6bb13f.c9703e", + "order": 2, + "disp": false, + "width": "4", + "collapse": false + }, + { + "id": "ef590206.24f6", + "type": "ui_group", + "name": "Group 3", + "tab": "3a6bb13f.c9703e", + "order": 3, + "disp": false, + "width": "4", + "collapse": false + }, + { + "id": "ae8f6620.073358", + "type": "ui_group", + "name": "Group 4", + "tab": "3a6bb13f.c9703e", + "order": 4, + "disp": false, + "width": "4", + "collapse": false + }, + { + "id": "196518b2.4d53b7", + "type": "ui_group", + "name": "Group 5", + "tab": "3a6bb13f.c9703e", + "order": 5, + "disp": false, + "width": "4", + "collapse": false + }, + { + "id": "777a7c33.fcd804", + "type": "ui_group", + "name": "Group 6", + "tab": "3a6bb13f.c9703e", + "order": 6, + "disp": false, + "width": "4", + "collapse": false + }, + { + "id": "cef1e703.bcf3c8", + "type": "ui_group", + "name": "Sample Location", + "tab": "737ec584.2eea2c", + "order": 3, + "disp": false, + "width": "10", + "collapse": false + }, + { + "id": "5517c651.b2f668", + "type": "ui_group", + "name": "Validation", + "tab": "737ec584.2eea2c", + "order": 5, + "disp": false, + "width": 10, + "collapse": false + }, + { + "id": "fbd92986.1028c8", + "type": "ui_group", + "name": "Focus Adjustment", + "tab": "181bb236.1e94be", + "order": 2, + "disp": true, + "width": 4, + "collapse": false + }, + { + "id": "707d9797.c8e798", + "type": "ui_group", + "name": "Fluidic Manual Manipulation", + "tab": "181bb236.1e94be", + "order": 5, + "disp": true, + "width": 4, + "collapse": false + }, + { + "id": "7a0b4877.a5d268", + "type": "ui_group", + "name": "Navigation", + "tab": "181bb236.1e94be", + "order": 6, + "disp": false, + "width": 4, + "collapse": false + }, + { + "id": "404c301a.19c4e", + "type": "ui_group", + "name": "Fraction size", + "tab": "c9194f02.9d5e9", + "order": 2, + "disp": true, + "width": "10", + "collapse": false + }, + { + "id": "4322c187.e73e5", + "type": "ui_group", + "name": "Acquisition", + "tab": "c9194f02.9d5e9", + "order": 3, + "disp": true, + "width": 10, + "collapse": false + }, + { + "id": "b7919ae2.c01788", + "type": "ui_group", + "name": "Navigation", + "tab": "c9194f02.9d5e9", + "order": 6, + "disp": false, + "width": "10", + "collapse": false + }, + { + "id": "b5d61bc7.54fe48", + "type": "ui_group", + "name": "Statistics", + "tab": "c9194f02.9d5e9", + "order": 4, + "disp": true, + "width": "10", + "collapse": false + }, + { + "id": "8dc3722c.06efa8", + "type": "mqtt-broker", + "name": "", + "broker": "0.0.0.0", + "port": "1883", + "clientid": "Client_node", + "autoConnect": true, + "usetls": false, + "compatmode": false, + "protocolVersion": "4", + "keepalive": "60", + "cleansession": true, + "birthTopic": "", + "birthQos": "0", + "birthPayload": "", + "birthMsg": {}, + "closeTopic": "", + "closeQos": "0", + "closePayload": "", + "closeMsg": {}, + "willTopic": "", + "willQos": "0", + "willPayload": "", + "willMsg": {}, + "userProps": "", + "sessionExpiry": "" + }, + { + "id": "abeb6dad.635a2", + "type": "ui_group", + "name": "Control", + "tab": "8d16beb8.9b3fb", + "order": 1, + "disp": true, + "width": 10, + "collapse": false + }, + { + "id": "cf5d9f0e.d57e7", + "type": "ui_group", + "name": "Net Metadata", + "tab": "737ec584.2eea2c", + "order": 4, + "disp": false, + "width": "10", + "collapse": false + }, + { + "id": "ce9e278.781eed8", + "type": "ui_group", + "name": "Information", + "tab": "d9cd733b.ab73d", + "order": 5, + "disp": true, + "width": 6, + "collapse": false + }, + { + "id": "70de8209.68416c", + "type": "ui_group", + "name": "Status", + "tab": "c9194f02.9d5e9", + "order": 5, + "disp": true, + "width": 10, + "collapse": false + }, + { + "id": "46be9c86.dea684", + "type": "ui_group", + "name": "Status", + "tab": "8d16beb8.9b3fb", + "order": 2, + "disp": true, + "width": 10, + "collapse": false + }, + { + "id": "8c38a81e.9897a8", + "type": "ui_group", + "name": "Camera Settings", + "tab": "181bb236.1e94be", + "order": 3, + "disp": true, + "width": 6, + "collapse": false + }, + { + "id": "2489e51c.eed77a", + "type": "ui_tab", + "name": "Administration", + "icon": "dashboard", + "order": 9, + "disabled": false, + "hidden": false + }, + { + "id": "b0fb559a.6966a8", + "type": "ui_tab", + "name": "Hardware Settings", + "icon": "fa-cogs", + "disabled": false, + "hidden": false + }, + { + "id": "6be36295.0ab324", + "type": "ui_group", + "name": "Settings", + "tab": "b0fb559a.6966a8", + "order": 1, + "disp": false, + "width": "8", + "collapse": false, + "className": "" + }, + { + "id": "fc5e4e6f.5b1c8", + "type": "ui_group", + "name": "GPS Status", + "tab": "737ec584.2eea2c", + "order": 6, + "disp": true, + "width": 10, + "collapse": false + }, + { + "id": "f3ca28ef.4df0a8", + "type": "ui_group", + "name": "Shutdown", + "tab": "3a6bb13f.c9703e", + "order": 7, + "disp": true, + "width": 4, + "collapse": false + }, + { + "id": "3dfd8a69.69ed56", + "type": "ui_spacer", + "name": "spacer", + "group": "3e1ba03d.f01d8", + "order": 5, + "width": 10, + "height": 1 + }, + { + "id": "72a9216.2ff48e", + "type": "ui_spacer", + "name": "spacer", + "group": "4322c187.e73e5", + "order": 8, + "width": 10, + "height": 1 + }, + { + "id": "1b664927.c91d1f", + "type": "ui_spacer", + "name": "spacer", + "group": "b5d61bc7.54fe48", + "order": 2, + "width": 2, + "height": 1 + }, + { + "id": "1a663b6a.ab5805", + "type": "ui_spacer", + "name": "spacer", + "group": "b5d61bc7.54fe48", + "order": 4, + "width": 2, + "height": 1 + }, + { + "id": "8eeed8d8.ad9098", + "type": "ui_spacer", + "name": "spacer", + "group": "b5d61bc7.54fe48", + "order": 5, + "width": 2, + "height": 1 + }, + { + "id": "be1c5ce7.004e", + "type": "ui_spacer", + "name": "spacer", + "group": "b5d61bc7.54fe48", + "order": 6, + "width": 2, + "height": 1 + }, + { + "id": "c2fe38e9.555e3", + "type": "ui_spacer", + "name": "spacer", + "group": "b5d61bc7.54fe48", + "order": 7, + "width": 2, + "height": 1 + }, + { + "id": "89bd18b7.c779a8", + "type": "ui_spacer", + "name": "spacer", + "group": "b5d61bc7.54fe48", + "order": 8, + "width": 2, + "height": 1 + }, + { + "id": "3cbbfa5d.efa636", + "type": "ui_spacer", + "name": "spacer", + "group": "b7919ae2.c01788", + "order": 2, + "width": 5, + "height": 1 + }, + { + "id": "97148e8d8e298f1a", + "type": "ui_spacer", + "z": "cb95299c.2817c8", + "name": "spacer", + "group": "abeb6dad.635a2", + "order": 7, + "width": 10, + "height": 1 + }, + { + "id": "3b2eccc574e6a9ae", + "type": "ui_spacer", + "z": "cb95299c.2817c8", + "name": "spacer", + "group": "abeb6dad.635a2", + "order": 11, + "width": 1, + "height": 1 + }, + { + "id": "bbd6431d97c86f97", + "type": "ui_spacer", + "z": "cb95299c.2817c8", + "name": "spacer", + "group": "46be9c86.dea684", + "order": 4, + "width": 3, + "height": 1 + }, + { + "id": "5f98f5f140f0ecde", + "type": "ui_spacer", + "z": "cb95299c.2817c8", + "name": "spacer", + "group": "46be9c86.dea684", + "order": 6, + "width": 3, + "height": 1 + }, + { + "id": "7bc0a4c416e4545c", + "type": "ui_group", + "name": "Culture Date and Time", + "tab": "737ec584.2eea2c", + "order": 2, + "disp": true, + "width": "10", + "collapse": false, + "className": "" + }, + { + "id": "6c31ad948a9d62fd", + "type": "ui_spacer", + "name": "spacer", + "group": "4248342d.e55fac", + "order": 2, + "width": 1, + "height": 1 + }, + { + "id": "833bc5bb.217ba8", + "type": "ui_group", + "name": "Preview", + "tab": "181bb236.1e94be", + "order": 1, + "disp": true, + "width": 18, + "collapse": false + }, + { + "id": "a7d64879.38298", + "type": "ui_group", + "name": "Logs", + "tab": "2489e51c.eed77a", + "order": 1, + "disp": true, + "width": "12", + "collapse": true, + "className": "" + }, + { + "id": "6465bdd5.15eb8c", + "type": "file in", + "z": "1c24ad9c.bebec2", + "name": "", + "filename": "/home/pi/PlanktoScope/config.json", + "filenameType": "str", + "format": "utf8", + "chunk": false, + "sendError": false, + "encoding": "none", + "x": 560, + "y": 60, + "wires": [ + [ + "15ceb135.6628bf" + ] + ], + "info": "# PlanktoScope Help\nThis Node will read the content of the file named **config.txt** containing all the input placeholders.\n" + }, + { + "id": "15ceb135.6628bf", + "type": "json", + "z": "1c24ad9c.bebec2", + "name": "config.json", + "property": "payload", + "action": "", + "pretty": false, + "x": 730, + "y": 60, + "wires": [ + [ + "ad541674.4791c8" + ] + ] + }, + { + "id": "7205d267.36adcc", + "type": "file", + "z": "1c24ad9c.bebec2", + "name": "", + "filename": "/home/pi/PlanktoScope/config.json", + "appendNewline": true, + "createDir": true, + "overwriteFile": "true", + "encoding": "none", + "x": 990, + "y": 160, + "wires": [ + [] + ] + }, + { + "id": "2e6ddf51.c0dba", + "type": "json", + "z": "1c24ad9c.bebec2", + "name": "config.json", + "property": "payload", + "action": "str", + "pretty": true, + "x": 730, + "y": 160, + "wires": [ + [ + "7205d267.36adcc" + ] + ] + }, + { + "id": "ad541674.4791c8", + "type": "function", + "z": "1c24ad9c.bebec2", + "name": "Global Set", + "func": "global.set(\"config_keys\", Object.keys(msg.payload));\n\nfor (const key in msg.payload) {\n global.set(key, msg.payload[key]);\n}\n\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 910, + "y": 60, + "wires": [ + [] + ] + }, + { + "id": "3e9a33c.141384c", + "type": "inject", + "z": "1c24ad9c.bebec2", + "name": "Load config", + "props": [ + { + "p": "topic", + "vt": "str" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "payloadType": "str", + "x": 230, + "y": 60, + "wires": [ + [ + "6465bdd5.15eb8c" + ] + ] + }, + { + "id": "3ad9835.08c937c", + "type": "function", + "z": "1c24ad9c.bebec2", + "name": "get config payload", + "func": "keys = global.get(\"config_keys\")\n\nvar payload = {}\n\nkeys.forEach(function(item, index, array) {\n payload[item] = global.get(item);\n})\n\nreturn {\"payload\": payload};", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 410, + "y": 160, + "wires": [ + [ + "2e6ddf51.c0dba" + ] + ] + }, + { + "id": "f439663c.8abd3", + "type": "ui_ui_control", + "z": "1c24ad9c.bebec2", + "name": "Connect Event", + "events": "connect", + "x": 220, + "y": 100, + "wires": [ + [ + "6465bdd5.15eb8c" + ] + ] + }, + { + "id": "82099021.9ceb08", + "type": "file", + "z": "4ed26b8b.253504", + "name": "", + "filename": "/home/pi/PlanktoScope/hardware.json", + "appendNewline": true, + "createDir": true, + "overwriteFile": "true", + "encoding": "none", + "x": 660, + "y": 40, + "wires": [ + [] + ] + }, + { + "id": "bb0a8725.a1849", + "type": "json", + "z": "4ed26b8b.253504", + "name": "Create JSON", + "property": "payload", + "action": "str", + "pretty": true, + "x": 490, + "y": 40, + "wires": [ + [ + "82099021.9ceb08" + ] + ] + }, + { + "id": "53d163be.47cf24", + "type": "function", + "z": "4ed26b8b.253504", + "name": "Update and retrieve hardware_conf", + "func": "// change global\nhardware_conf = global.get(\"hardware_conf\");\n\nif (msg.topic == \"process_pixel_fixed\" && msg.payload == 0){\n delete hardware_conf[msg.topic]\n delete msg.topic\n}\n\nif (msg.topic !== null && msg.topic !== undefined){\n hardware_conf[msg.topic] = msg.payload;\n global.set(\"hardware_conf\", hardware_conf);\n}\n\nreturn {\"payload\": hardware_conf};", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 240, + "y": 40, + "wires": [ + [ + "bb0a8725.a1849" + ] + ] + }, + { + "id": "48ceeda454438cb7", + "type": "file in", + "z": "e6665421f66ea4c8", + "name": "", + "filename": "/home/pi/PlanktoScope/hardware.json", + "filenameType": "str", + "format": "utf8", + "chunk": false, + "sendError": false, + "encoding": "none", + "x": 250, + "y": 40, + "wires": [ + [ + "853c938a270fd85e" + ] + ], + "info": "# PlanktoScope Help\nThis Node will read the content of the file named **config.txt** containing all the input placeholders.\n" + }, + { + "id": "853c938a270fd85e", + "type": "json", + "z": "e6665421f66ea4c8", + "name": "Parse JSON", + "property": "payload", + "action": "", + "pretty": false, + "x": 510, + "y": 40, + "wires": [ + [ + "2b1a67ac127f3fe7" + ] + ] + }, + { + "id": "2b1a67ac127f3fe7", + "type": "change", + "z": "e6665421f66ea4c8", + "name": "", + "rules": [ + { + "t": "set", + "p": "hardware_conf", + "pt": "global", + "to": "payload", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 730, + "y": 40, + "wires": [ + [] + ] + }, + { + "id": "2f30a6ee99587899", + "type": "comment", + "z": "eaae323a.31b3", + "name": "LICENSE", + "info": "Copyright 2022 Thibaut Pollina and Romain Bazile\nLicensed under GPL v3.0", + "x": 140, + "y": 600, + "wires": [] + }, + { + "id": "4e78af2d.90be7", + "type": "ui_ui_control", + "z": "eaae323a.31b3", + "name": "", + "events": "change", + "x": 440, + "y": 160, + "wires": [ + [] + ] + }, + { + "id": "7789839d.69b48c", + "type": "ui_template", + "z": "eaae323a.31b3", + "group": "4e0cd5ea.17e59c", + "name": "Optic Configuration", + "order": 1, + "width": 4, + "height": 4, + "format": "\n \n
Optic Configuration
\n
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "x": 130, + "y": 100, + "wires": [ + [ + "4e78af2d.90be7" + ] + ] + }, + { + "id": "6ea6c306.f9c12c", + "type": "ui_template", + "z": "eaae323a.31b3", + "group": "ef590206.24f6", + "name": "Fluidic Acquisition", + "order": 1, + "width": 4, + "height": 4, + "format": "\n \n
Fluidic Acquisition
\n
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "x": 130, + "y": 140, + "wires": [ + [ + "4e78af2d.90be7" + ] + ] + }, + { + "id": "bb9eb153.9e36c", + "type": "ui_template", + "z": "eaae323a.31b3", + "group": "ae8f6620.073358", + "name": "Segmentation", + "order": 1, + "width": 4, + "height": 4, + "format": "\n \n
Segmentation
\n
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "x": 140, + "y": 180, + "wires": [ + [ + "4e78af2d.90be7" + ] + ] + }, + { + "id": "eaf8ee7f.96f44", + "type": "ui_template", + "z": "eaae323a.31b3", + "group": "196518b2.4d53b7", + "name": "Gallery", + "order": 1, + "width": 4, + "height": 4, + "format": "\n \n
Gallery
\n
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "x": 160, + "y": 220, + "wires": [ + [ + "4e78af2d.90be7" + ] + ] + }, + { + "id": "c1b1469.9650eb8", + "type": "ui_template", + "z": "eaae323a.31b3", + "group": "777a7c33.fcd804", + "name": "System Monitoring", + "order": 1, + "width": 4, + "height": 4, + "format": "\n \n
System Monitoring
\n
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "x": 130, + "y": 260, + "wires": [ + [ + "4e78af2d.90be7" + ] + ] + }, + { + "id": "abafd6e6.04a5f8", + "type": "ui_template", + "z": "eaae323a.31b3", + "group": "6f97e7ae.270c48", + "name": "Sample", + "order": 1, + "width": 4, + "height": 4, + "format": "\n \n
Sample
\n
\n In doubt? Start Here!\n
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "x": 160, + "y": 60, + "wires": [ + [ + "4e78af2d.90be7" + ] + ] + }, + { + "id": "dab82064.26a8d", + "type": "ui_button", + "z": "eaae323a.31b3", + "name": "Unlock button", + "group": "f3ca28ef.4df0a8", + "order": 2, + "width": 0, + "height": 0, + "passthru": false, + "label": "Unlock button", + "tooltip": "", + "color": "", + "bgcolor": "", + "icon": "", + "payload": "shutdown", + "payloadType": "flow", + "topic": "", + "x": 120, + "y": 380, + "wires": [ + [ + "6c3a3b4.78cad44" + ] + ] + }, + { + "id": "1c658761.b852a1", + "type": "ui_toast", + "z": "eaae323a.31b3", + "position": "dialog", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 1, + "ok": "YES PLEASE", + "cancel": "NO!", + "raw": false, + "topic": "Are you sure?", + "name": "Confirmation message", + "x": 800, + "y": 380, + "wires": [ + [ + "8f1b8e23.daafe" + ] + ] + }, + { + "id": "a48ff63f.db5e18", + "type": "inject", + "z": "eaae323a.31b3", + "name": "disabled", + "props": [ + { + "p": "enabled", + "v": "false", + "vt": "bool" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "x": 140, + "y": 420, + "wires": [ + [ + "d58039a9.6e7928" + ] + ] + }, + { + "id": "b67a7147.65fcd8", + "type": "ui_button", + "z": "eaae323a.31b3", + "name": "Shutdown button", + "group": "f3ca28ef.4df0a8", + "order": 4, + "width": 0, + "height": 0, + "passthru": false, + "label": "Shutdown", + "tooltip": "", + "color": "", + "bgcolor": "#AD1625", + "icon": "fa-power-off fa-2x", + "payload": "Do you want to turn the machine off now?", + "payloadType": "str", + "topic": "", + "x": 550, + "y": 380, + "wires": [ + [ + "1c658761.b852a1" + ] + ] + }, + { + "id": "d58039a9.6e7928", + "type": "change", + "z": "eaae323a.31b3", + "name": "", + "rules": [ + { + "t": "set", + "p": "shutdown", + "pt": "flow", + "to": "false", + "tot": "bool" + }, + { + "t": "set", + "p": "enabled", + "pt": "msg", + "to": "shutdown", + "tot": "flow" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 320, + "y": 420, + "wires": [ + [ + "b67a7147.65fcd8" + ] + ] + }, + { + "id": "6c3a3b4.78cad44", + "type": "function", + "z": "eaae323a.31b3", + "name": "Toggle", + "func": "flow.set(\"shutdown\", !flow.get(\"shutdown\"))\nmsg.enabled = flow.get(\"shutdown\")\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 290, + "y": 380, + "wires": [ + [ + "b67a7147.65fcd8" + ] + ] + }, + { + "id": "d1153ad6.40d738", + "type": "ui_template", + "z": "eaae323a.31b3", + "group": "f3ca28ef.4df0a8", + "name": "Shutdown information", + "order": 1, + "width": 0, + "height": 0, + "format": "
To prevent data corruption, please always shutdown the machine before unplugging the unit.\n

\nRemember to first unlock the shutdown button.\n
", + "storeOutMessages": true, + "fwdInMessages": false, + "resendOnRefresh": true, + "templateScope": "local", + "x": 120, + "y": 320, + "wires": [ + [] + ] + }, + { + "id": "e08cfcb8.2a67e8", + "type": "link out", + "z": "eaae323a.31b3", + "name": "Home shutdown button", + "links": [ + "b81b990a.d4dca" + ], + "x": 715, + "y": 500, + "wires": [] + }, + { + "id": "ce7087fc.dcc9e8", + "type": "ui_toast", + "z": "eaae323a.31b3", + "position": "dialog", + "displayTime": "10", + "highlight": "", + "sendall": true, + "outputs": 1, + "ok": "OK", + "cancel": "", + "raw": false, + "topic": "Turning off now!", + "name": "Shutdown message", + "x": 570, + "y": 540, + "wires": [ + [] + ] + }, + { + "id": "7d1626a0.deb85", + "type": "change", + "z": "eaae323a.31b3", + "name": "shutdown!", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "shutdown", + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 300, + "y": 500, + "wires": [ + [ + "e08cfcb8.2a67e8" + ] + ] + }, + { + "id": "8f1b8e23.daafe", + "type": "switch", + "z": "eaae323a.31b3", + "name": "", + "property": "payload", + "propertyType": "msg", + "rules": [ + { + "t": "eq", + "v": "NO!", + "vt": "str" + }, + { + "t": "else" + } + ], + "checkall": "true", + "repair": false, + "outputs": 2, + "x": 150, + "y": 500, + "wires": [ + [ + "d58039a9.6e7928" + ], + [ + "7d1626a0.deb85", + "281a56c9.ec7902" + ] + ] + }, + { + "id": "281a56c9.ec7902", + "type": "change", + "z": "eaae323a.31b3", + "name": "Shutdown message", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "Please wait a minute before disconnecting the machine from its power supply!", + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 330, + "y": 540, + "wires": [ + [ + "ce7087fc.dcc9e8" + ] + ] + }, + { + "id": "4557d689.a4fa88", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "sample_ship", + "label": "Name of the ship", + "tooltip": "", + "group": "3e1ba03d.f01d8", + "order": 2, + "width": 0, + "height": 0, + "passthru": true, + "mode": "text", + "delay": "300", + "topic": "sample_ship", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 670, + "y": 80, + "wires": [ + [ + "9f501f49.45645" + ] + ] + }, + { + "id": "fcfc31ae.af3af", + "type": "ui_dropdown", + "z": "b771c342.49603", + "name": "sample_sampling_gear", + "label": "Sampling gear*", + "tooltip": "", + "place": "Choose from list", + "group": "3e1ba03d.f01d8", + "order": 6, + "width": 0, + "height": 0, + "passthru": true, + "multiple": false, + "options": [ + { + "label": "High Speed Net", + "value": "net_hsn", + "type": "str" + }, + { + "label": "Tara Decknet", + "value": "net_decknet", + "type": "str" + }, + { + "label": "Plankton net", + "value": "net", + "type": "str" + }, + { + "label": "Niskin bottle 12L", + "value": "niskin_12L", + "type": "str" + }, + { + "label": "Niskin bottle 24L", + "value": "niskin_24L", + "type": "str" + }, + { + "label": "Pass Hull", + "value": "pass_hull", + "type": "str" + }, + { + "label": "Single location (with net or bucket)", + "value": "single_location", + "type": "str" + }, + { + "label": "Lab culture", + "value": "culture", + "type": "str" + }, + { + "label": "Test", + "value": "test", + "type": "str" + } + ], + "payload": "", + "topic": "sample_sampling_gear", + "topicType": "str", + "className": "", + "x": 630, + "y": 200, + "wires": [ + [ + "9f501f49.45645", + "46eb1bf8.3dc5f4", + "3ac7b631f5d8ef90" + ] + ] + }, + { + "id": "82c5fc77.59c97", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "sample_operator", + "label": "Name of the operator*", + "tooltip": "", + "group": "3e1ba03d.f01d8", + "order": 3, + "width": 0, + "height": 0, + "passthru": true, + "mode": "text", + "delay": "300", + "topic": "sample_operator", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 650, + "y": 160, + "wires": [ + [ + "9f501f49.45645" + ] + ] + }, + { + "id": "9c882b37.fde668", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "sample_project", + "label": "Name of the project*", + "tooltip": "", + "group": "3e1ba03d.f01d8", + "order": 1, + "width": 0, + "height": 0, + "passthru": true, + "mode": "text", + "delay": "300", + "topic": "sample_project", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 660, + "y": 40, + "wires": [ + [ + "9f501f49.45645" + ] + ] + }, + { + "id": "94eb4221.9b92c", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "sample_id", + "label": "Station ID*", + "tooltip": "", + "group": "3e1ba03d.f01d8", + "order": 4, + "width": 0, + "height": 0, + "passthru": true, + "mode": "text", + "delay": "300", + "topic": "sample_id", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 670, + "y": 120, + "wires": [ + [ + "9f501f49.45645" + ] + ] + }, + { + "id": "9f501f49.45645", + "type": "function", + "z": "b771c342.49603", + "name": "set global", + "func": "global.set(msg.topic,msg.payload);", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 1080, + "y": 200, + "wires": [ + [] + ] + }, + { + "id": "222c851d.5d0a3a", + "type": "ui_ui_control", + "z": "b771c342.49603", + "name": "", + "events": "change", + "x": 400, + "y": 880, + "wires": [ + [] + ] + }, + { + "id": "52f6b103.1efb6", + "type": "ui_toast", + "z": "b771c342.49603", + "position": "dialog", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 1, + "ok": "OK", + "cancel": "", + "raw": false, + "topic": "", + "name": "", + "x": 710, + "y": 980, + "wires": [ + [] + ] + }, + { + "id": "986d960a.c75908", + "type": "function", + "z": "b771c342.49603", + "name": "Check form", + "func": "var sample_project= global.get(\"sample_project\");\nvar sample_id= global.get(\"sample_id\");\nvar sample_operator= global.get(\"sample_operator\");\nvar sample_sampling_gear= global.get(\"sample_sampling_gear\");\nvar object_lat= global.get(\"object_lat\");\nvar object_lon= global.get(\"object_lon\");\nvar object_date= global.get(\"object_date\");\nvar object_time= global.get(\"object_time\");\nif (sample_project === undefined || sample_project === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Sample project\"\n return [null, msg];\n}\n\nelse if (sample_id === undefined || sample_id === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Sample ID\"\n return [null, msg];\n}\n\nelse if (sample_operator === undefined || sample_operator === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Sample operator\"\n return [null, msg];\n}\n\nelse if (sample_sampling_gear === undefined || sample_sampling_gear === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Sample sampling gear\"\n return [null, msg];\n}\n\nelse if (object_lat === undefined || object_lat === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Latitude of sample\"\n return [null, msg];\n}\n\nelse if (object_lon === undefined || object_lon === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Longitude of sample\"\n return [null, msg];\n}\n\nelse if (object_date === undefined || object_date === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Date of sample\"\n return [null, msg];\n}\n\nelse if (object_time === undefined || object_time === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Time of sample\"\n return [null, msg];\n}\nelse if (sample_sampling_gear.startsWith(\"net\")){\n var object_lat_end = global.get(\"object_lat_end\");\n var object_lon_end = global.get(\"object_lon_end\");\n var object_date_end = global.get(\"object_date_end\");\n var object_time_end = global.get(\"object_time_end\");\n var sample_gear_net_opening = global.get(\"sample_gear_net_opening\");\n\n if (object_lat_end === undefined || object_lat_end === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Latitude of retrieval\"\n return [null, msg];\n }\n \n else if (object_lon_end === undefined || object_lon_end === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Longitude of retrieval\"\n return [null, msg];\n }\n \n else if (object_date_end === undefined || object_date_end === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Date of retrieval\"\n return [null, msg];\n }\n \n else if (object_time_end === undefined || object_time_end === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Time of retrieval\"\n return [null, msg];\n }\n \n else if (sample_gear_net_opening === undefined || sample_gear_net_opening === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Net opening dimension\"\n return [null, msg];\n }\n \n if (sample_sampling_gear == \"net_decknet\"){\n var sample_total_volume = global.get(\"sample_total_volume\");\n if (sample_total_volume === undefined || sample_total_volume === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Decknet flowmeter readings\"\n return [null, msg];\n }\n }\n}\nmsg.topic = \"config_save\"\nmsg.payload={\"tab\":\"Optic Configuration\"};\n\nreturn [msg, null];", + "outputs": 2, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 470, + "y": 940, + "wires": [ + [ + "726a7822.cd6298", + "e2b277c1.07283" + ], + [ + "52f6b103.1efb6" + ] + ], + "outputLabels": [ + "message", + "error" + ] + }, + { + "id": "18f44504.cac66b", + "type": "gpsd", + "z": "b771c342.49603", + "name": "", + "hostname": "localhost", + "port": "2947", + "tpv": true, + "sky": false, + "info": false, + "device": false, + "gst": false, + "att": false, + "x": 250, + "y": 1240, + "wires": [ + [ + "258b4562.9f778a", + "54e37580.fdc31c", + "cc21ca16.b92928", + "4a4de52c.cf2884", + "73c4a14a.9b93c8" + ] + ] + }, + { + "id": "726a7822.cd6298", + "type": "ui_ui_control", + "z": "b771c342.49603", + "name": "", + "events": "change", + "x": 700, + "y": 900, + "wires": [ + [] + ] + }, + { + "id": "16de754c.cc969b", + "type": "ui_button", + "z": "b771c342.49603", + "name": "", + "group": "5517c651.b2f668", + "order": 1, + "width": 5, + "height": 1, + "passthru": false, + "label": "Previous", + "tooltip": "", + "color": "#097479", + "bgcolor": "white", + "icon": "keyboard_return", + "payload": "{\"tab\":\"Home\"}", + "payloadType": "json", + "topic": "", + "x": 240, + "y": 880, + "wires": [ + [ + "222c851d.5d0a3a" + ] + ] + }, + { + "id": "84f3d040.5f7ea", + "type": "ui_button", + "z": "b771c342.49603", + "name": "", + "group": "5517c651.b2f668", + "order": 2, + "width": 5, + "height": 1, + "passthru": false, + "label": "Continue", + "tooltip": "", + "color": "#097479", + "bgcolor": "white", + "icon": "keyboard_tab", + "payload": "{\"tab\":\"Home\"}", + "payloadType": "json", + "topic": "", + "x": 240, + "y": 940, + "wires": [ + [ + "986d960a.c75908" + ] + ] + }, + { + "id": "d027a6bf.7049e8", + "type": "function", + "z": "b771c342.49603", + "name": "get sample_projet", + "func": "msg.payload = msg.payload.sample_project;\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 310, + "y": 40, + "wires": [ + [ + "9c882b37.fde668" + ] + ] + }, + { + "id": "5a811caf.0f3144", + "type": "function", + "z": "b771c342.49603", + "name": "get sample_ship", + "func": "msg.payload = msg.payload.sample_ship;\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 300, + "y": 80, + "wires": [ + [ + "4557d689.a4fa88" + ] + ] + }, + { + "id": "45911c98.2bd83c", + "type": "function", + "z": "b771c342.49603", + "name": "get sample_id", + "func": "msg.payload = msg.payload.sample_id;\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 300, + "y": 120, + "wires": [ + [ + "94eb4221.9b92c" + ] + ] + }, + { + "id": "1e09a4ab.72996b", + "type": "function", + "z": "b771c342.49603", + "name": "get sample_operator", + "func": "msg.payload = msg.payload.sample_operator;\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 320, + "y": 160, + "wires": [ + [ + "82c5fc77.59c97" + ] + ] + }, + { + "id": "a3272681.f271c8", + "type": "function", + "z": "b771c342.49603", + "name": "get sample_sampling_gear", + "func": "msg.topic = \"sample_sampling_gear\"\nif (msg.payload.sample_sampling_gear === undefined){\n msg.payload = \"net\";\n}\nelse\n{\n msg.payload = msg.payload.sample_sampling_gear;\n}\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 340, + "y": 200, + "wires": [ + [ + "fcfc31ae.af3af" + ] + ] + }, + { + "id": "a6907a38.f6611", + "type": "subflow:1c24ad9c.bebec2", + "z": "b771c342.49603", + "name": "", + "env": [], + "x": 70, + "y": 220, + "wires": [ + [ + "d027a6bf.7049e8", + "5a811caf.0f3144", + "45911c98.2bd83c", + "1e09a4ab.72996b", + "8dff1648.82e42", + "9f04c5ec.75f3d8", + "f408a273.4fb538", + "e73fd87d.d24e4", + "489c8e06.cc7d6", + "a3272681.f271c8" + ] + ] + }, + { + "id": "e2b277c1.07283", + "type": "subflow:1c24ad9c.bebec2", + "z": "b771c342.49603", + "name": "", + "env": [], + "x": 690, + "y": 940, + "wires": [ + [] + ] + }, + { + "id": "7116e906.9f50f", + "type": "ui_text", + "z": "b771c342.49603", + "group": "fc5e4e6f.5b1c8", + "order": 1, + "width": 10, + "height": 1, + "name": "GPS Status Display", + "label": "GPS Status:", + "format": "{{msg.payload}}", + "layout": "row-center", + "x": 730, + "y": 1080, + "wires": [] + }, + { + "id": "9c7f7fc9.c8d3a", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "object_depth_max", + "label": "Max sampling depth (m)", + "tooltip": "in m", + "group": "3e1ba03d.f01d8", + "order": 10, + "width": 5, + "height": 1, + "passthru": true, + "mode": "number", + "delay": "300", + "topic": "object_depth_max", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 650, + "y": 240, + "wires": [ + [ + "9f501f49.45645" + ] + ] + }, + { + "id": "317eeeb7.8d3042", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "object_depth_min", + "label": "Min sampling depth (m)", + "tooltip": "in m", + "group": "3e1ba03d.f01d8", + "order": 9, + "width": 5, + "height": 1, + "passthru": true, + "mode": "number", + "delay": "300", + "topic": "object_depth_min", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 650, + "y": 280, + "wires": [ + [ + "9f501f49.45645" + ] + ] + }, + { + "id": "cbb123ab.fd3428", + "type": "ui_ui_control", + "z": "b771c342.49603", + "name": "show/hide net groups", + "events": "change", + "x": 1320, + "y": 300, + "wires": [ + [] + ] + }, + { + "id": "642ff403.1ed91c", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "sample_concentrated_sample_volume", + "label": "Concentrated sample volume (mL)", + "tooltip": "Volume extracted from the net codend (in mL)", + "group": "3e1ba03d.f01d8", + "order": 12, + "width": 10, + "height": 1, + "passthru": true, + "mode": "number", + "delay": "300", + "topic": "sample_concentrated_sample_volume", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 590, + "y": 440, + "wires": [ + [ + "9f501f49.45645" + ] + ] + }, + { + "id": "e967b844.46aa48", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "sample_gear_net_opening", + "label": "Net opening dimension (mm)", + "tooltip": "Size of the net mouth opening (in mm)", + "group": "cf5d9f0e.d57e7", + "order": 1, + "width": 10, + "height": 1, + "passthru": true, + "mode": "number", + "delay": "300", + "topic": "sample_gear_net_opening", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 620, + "y": 320, + "wires": [ + [ + "9f501f49.45645" + ] + ] + }, + { + "id": "c0ce5626.b6c5", + "type": "ui_toast", + "z": "b771c342.49603", + "position": "dialog", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 1, + "ok": "OK", + "cancel": "", + "raw": false, + "topic": "", + "name": "", + "x": 1230, + "y": 620, + "wires": [ + [] + ] + }, + { + "id": "c33f1124.af6688", + "type": "ui_form", + "z": "b771c342.49603", + "name": "sample_location", + "label": "Sample Location", + "group": "cef1e703.bcf3c8", + "order": 1, + "width": 0, + "height": 0, + "options": [ + { + "label": "Latitude (36.574439°N or 36°57.4439'N)", + "value": "object_lat", + "type": "text", + "required": true, + "rows": null + }, + { + "label": "Longitude (110.42100°W or 110°4.2100'W)", + "value": "object_lon", + "type": "text", + "required": true, + "rows": null + }, + { + "label": "Date (YYYY-MM-DD, UTC)", + "value": "object_date", + "type": "text", + "required": true, + "rows": null + }, + { + "label": "Time (HH:MM(:SS), UTC 24h)", + "value": "object_time", + "type": "text", + "required": true, + "rows": null + } + ], + "formValue": { + "object_lat": "", + "object_lon": "", + "object_date": "", + "object_time": "" + }, + "payload": "", + "submit": "Validate", + "cancel": "Reset", + "topic": "sample_location", + "x": 660, + "y": 580, + "wires": [ + [ + "14658615.47c862", + "3318a1aaa70fc2ee" + ] + ] + }, + { + "id": "358908cd.416ab", + "type": "ui_form", + "z": "b771c342.49603", + "name": "net_throw_location", + "label": "Net Throw Location", + "group": "cf5d9f0e.d57e7", + "order": 3, + "width": 0, + "height": 0, + "options": [ + { + "label": "Latitude (36.574439°N or 36°57.4439'N)", + "value": "object_lat", + "type": "text", + "required": true, + "rows": null + }, + { + "label": "Longitude (110.42100°W or 110°4.2100'W)", + "value": "object_lon", + "type": "text", + "required": true, + "rows": null + }, + { + "label": "Date (YYYY-MM-DD UTC)", + "value": "object_date", + "type": "text", + "required": true, + "rows": null + }, + { + "label": "Time (HH:MM, UTC 24h)", + "value": "object_time", + "type": "text", + "required": true, + "rows": null + } + ], + "formValue": { + "object_lat": "", + "object_lon": "", + "object_date": "", + "object_time": "" + }, + "payload": "", + "submit": "Validate", + "cancel": "", + "topic": "net_throw_location", + "topicType": "str", + "splitLayout": false, + "className": "", + "x": 650, + "y": 620, + "wires": [ + [ + "14658615.47c862", + "cc67c97f55a340d3" + ] + ] + }, + { + "id": "56d40584.eff4e4", + "type": "ui_form", + "z": "b771c342.49603", + "name": "net_retrieval_location", + "label": "Net Retrieval Location", + "group": "cf5d9f0e.d57e7", + "order": 4, + "width": 0, + "height": 0, + "options": [ + { + "label": "Latitude (36.574439°N or 36°57.4439'N)", + "value": "object_lat_end", + "type": "text", + "required": true, + "rows": null + }, + { + "label": "Longitude (110.42100°W or 110°4.2100'W)", + "value": "object_lon_end", + "type": "text", + "required": true, + "rows": null + }, + { + "label": "Date (YYYY-MM-DD UTC)", + "value": "object_date_end", + "type": "text", + "required": true, + "rows": null + }, + { + "label": "Time (HH:MM, UTC 24h)", + "value": "object_time_end", + "type": "text", + "required": true, + "rows": null + } + ], + "formValue": { + "object_lat_end": "", + "object_lon_end": "", + "object_date_end": "", + "object_time_end": "" + }, + "payload": "", + "submit": "Validate", + "cancel": "", + "topic": "net_retrieval_location", + "topicType": "str", + "splitLayout": false, + "x": 640, + "y": 660, + "wires": [ + [ + "14658615.47c862", + "9c8f370d124a55e4" + ] + ] + }, + { + "id": "14658615.47c862", + "type": "function", + "z": "b771c342.49603", + "name": "Validate Location / Timestamp", + "func": "// Code added here will be run once\n// whenever the node is started.\nfunction ConvertDDMMToDD(input) {\n // Input Format 36°57.4439'N, 110°4.2100'W\n // From https://stackoverflow.com/questions/1140189/converting-latitude-and-longitude-to-decimal-values\n if (!input.match(/\\d+°\\d+\\.*\\d*\\'[NSEW]/)){\n \treturn \"parsing error\"\n }\n var parts = input.split(/[^\\d.\\w]+/)\n if (parts.length != 3){\n \treturn \"parsing error\"\n }\n var dd = Number(parts[0]) + Number(parts[1])/60\n return dd.toFixed(6) + parts[2]\n}\n\nfunction ValidateCoordinates(input, lat){\n // Input Format 36.574439°N, 110.42100°W\n // Or 36°57.4439'N, 110°4.2100'W\n if (input.match(\"'\")){\n input = ConvertDDMMToDD(input)\n }\n \n var error = {}\n\n if (input.startsWith(\"parsing error\")){\n error.topic = \"Error with the \"\n error.payload = \"You need to respect the format example, 36.574439°N or 36°57.4439'N\"\n return [null, error]\n }\n \n var direction = input.match(/[NSEW]/)\n var position = input.match(/[\\+\\-\\d\\.]+/)\n \n if (direction === null){\n error.topic = \"Error with the \"\n error.payload = \"You need to explicitely enter N/S/E/W\"\n return [null, error]\n }\n \n // Test that position is only made of digits!\n if(/^[\\+\\-]/.test(position)){\n error.topic = \"Error with the \"\n error.payload = \"Use of +/- sign is inconsistent with N/S/E/W letter! Please only use N/S/E/W!\"\n return [null, error]\n }\n \n var dd = Number(position)\n if (lat){\n // Check latitude\n if (direction == \"S\" || direction == \"N\") {\n if (dd>90.0){\n error.topic = \"Error with the \"\n error.payload = \"Latitude is more than 90°\"\n return [null, error]\n }\n }\n if (direction == \"W\" || direction == \"E\") {\n error.topic = \"Error with the \"\n error.payload = \"This is not a Latitude!\"\n return [null, error]\n }\n }\n else{\n // Check longitude\n if (direction == \"W\" || direction == \"E\") {\n if (dd>180.0){\n error.topic = \"Error with the \"\n error.payload = \"Longitude is more than 180°\"\n return [null, error]\n }\n }\n if (direction == \"N\" || direction == \"S\") {\n error.topic = \"Error with the \"\n error.payload = \"This is not a Longitude!\"\n return [null, error]\n }\n }\n \n if (direction == \"S\" || direction == \"W\") {\n dd = dd * -1\n } // Don't do anything for N or E\n return [dd.toFixed(4), null]\n \n}\n\nfunction ValidateDate(input){\n // Input Format 2020-12-25\n var error = {};\n \n if (! /20\\d{2}-[0-1]\\d-[0-3]\\d/.test(input)){\n error.topic = \"Error with the date\";\n error.payload = \"The date should respect the ISO format YYYY-MM-DD\";\n return [null, error];\n }\n else {\n var date = input.match(/\\d+/g);\n if (!((2000 < date[0]) && (date[0] < 2100))){\n error.topic = \"Error with the date\"\n error.payload = \"The year should be between 2000 and 2100\"\n return [null, error]\n }\n else if (!((0 < date[1]) && (date[1] <= 12))){\n error.topic = \"Error with the date\"\n error.payload = \"The month should be between 01 and 12\"\n return [null, error]\n }\n else if (!((0 < date[2]) && (date[2] <= 31))){\n error.topic = \"Error with the date\"\n error.payload = \"The day should be between 01 and 31\"\n return [null, error]\n }\n }\n return [input.replace(/-/g, ''), null]\n}\n\nfunction ValidateTime(input){\n // Input Format 12:00\n var error = {}\n \n if (! /[0-2]?\\d:[0-5]\\d/.test(input)){\n error.topic = \"Error with the time\"\n error.payload = \"The date should respect the ISO format HH:MM\"\n return [null, error]\n }\n else {\n var time = input.match(/\\d+/g)\n \n if (!((0 <= time[0]) && (time[0] < 24))){\n error.topic = \"Error with the time\"\n error.payload = \"The hours should be 0 and 23.\"\n return [null, error]\n }\n else if (!((0 <= time[1]) && (time[1] < 60))){\n error.topic = \"Error with the time\"\n error.payload = \"The minutes should be between 0 and 59\"\n return [null, error]\n }\n }\n return [input.replace(/:/g, ''), null]\n}\n\n\nvar ret\nvar payload_for_form = {payload:{}}\nmsg.valid = false\n\nif (msg.topic == \"culture_timestamp\"){\n ret = ValidateDate(msg.payload.object_date)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_date\", ret[0])\n \n ret = ValidateTime(msg.payload.object_time)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_time\", ret[0])\n return [{topic: \"Date and time format valid!\", payload: \"All good!\", valid: true}, payload_for_form]\n}\nelse if (msg.topic == \"net_retrieval_location\"){\n ret = ValidateCoordinates(msg.payload.object_lat_end, true);\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" Latitude\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_lat_end\", ret[0])\n ret = ValidateCoordinates(msg.payload.object_lon_end, false)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" Longitude\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_lon_end\", ret[0]);\n \n ret = ValidateDate(msg.payload.object_date_end)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample retrieval\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_date_end\", ret[0])\n \n ret = ValidateTime(msg.payload.object_time_end)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample retrieval\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_time_end\", ret[0])\n}\nelse{\n ret = ValidateCoordinates(msg.payload.object_lat, true);\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" Latitude\";\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_lat\", ret[0]);\n payload_for_form.payload[\"object_lat_end\"] = msg.payload.object_lat;\n \n ret = ValidateCoordinates(msg.payload.object_lon, false);\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" Longitude\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_lon\", ret[0])\n payload_for_form.payload[\"object_lon_end\"] = msg.payload.object_lon;\n\n ret = ValidateDate(msg.payload.object_date)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_date\", ret[0])\n payload_for_form.payload[\"object_date_end\"] = msg.payload.object_date;\n \n ret = ValidateTime(msg.payload.object_time)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_time\", ret[0])\n payload_for_form.payload[\"object_time_end\"] = msg.payload.object_time;\n}\nreturn [{topic: \"Coordinates valid!\", payload: \"All good!\", valid: true}, payload_for_form]\n", + "outputs": 2, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 930, + "y": 620, + "wires": [ + [ + "c0ce5626.b6c5", + "9a18a4b4.178448" + ], + [ + "56d40584.eff4e4" + ] + ], + "inputLabels": [ + "Location form data" + ], + "outputLabels": [ + "Message", + "Location validated" + ] + }, + { + "id": "46eb1bf8.3dc5f4", + "type": "function", + "z": "b771c342.49603", + "name": "Net check", + "func": "var decknet = {}\nvar activation_msg = {}\n\nif (msg.payload.startsWith(\"net_decknet\")){\n decknet.enabled = true;\n}\nelse {\n decknet.enabled = false;\n}\n\nif (msg.payload.startsWith(\"net\")){\n activation_msg.payload = {\"group\":{\"show\":[\"Sample_Net_Metadata\"],\"hide\":[\"Sample_Sample_Location\",\"Sample_Culture_Date_and_Time\"]}};\n}\nelse if (msg.payload != \"culture\" && msg.payload != \"test\"){\n activation_msg.payload = {\"group\":{\"show\":[\"Sample_Sample_Location\"], \"hide\":[\"Sample_Net_Metadata\",\"Sample_Culture_Date_and_Time\"]}};\n}\n\n\nreturn [decknet, activation_msg];", + "outputs": 2, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 1080, + "y": 240, + "wires": [ + [ + "516375fd.2ed61c", + "470e382a.25691", + "fbe32ac8.ff6a38" + ], + [ + "cbb123ab.fd3428" + ] + ], + "outputLabels": [ + "decknet activation", + "group display control" + ] + }, + { + "id": "516375fd.2ed61c", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "sample_total_flowmeter_start", + "label": "Decknet flowmeter start", + "tooltip": "in L", + "group": "cf5d9f0e.d57e7", + "order": 6, + "width": 5, + "height": 1, + "passthru": false, + "mode": "text", + "delay": "300", + "topic": "sample_total_flowmeter_start", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 1340, + "y": 220, + "wires": [ + [ + "e9bc112c.eb75f8" + ] + ] + }, + { + "id": "470e382a.25691", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "sample_total_flowmeter_end", + "label": "Decknet flowmeter end", + "tooltip": "in L", + "group": "cf5d9f0e.d57e7", + "order": 7, + "width": 5, + "height": 1, + "passthru": false, + "mode": "text", + "delay": "300", + "topic": "sample_total_flowmeter_end", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 1340, + "y": 260, + "wires": [ + [ + "e9bc112c.eb75f8" + ] + ] + }, + { + "id": "fbe32ac8.ff6a38", + "type": "ui_template", + "z": "b771c342.49603", + "group": "cf5d9f0e.d57e7", + "name": "Decknet flowmeter read", + "order": 5, + "width": 10, + "height": 1, + "format": "
\n

Decknet flowmeter readings

\n

Those values are used to calculate sample_total_volume. Values are in L.

\n
\n", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": true, + "templateScope": "local", + "x": 1330, + "y": 180, + "wires": [ + [] + ] + }, + { + "id": "f408a273.4fb538", + "type": "function", + "z": "b771c342.49603", + "name": "get sample_gear_net_opening", + "func": "if (msg.payload.sample_gear_net_opening === null){\n msg.payload = 0;\n global.set(\"sample_gear_net_opening\",msg.payload);\n}\nelse\n{\n msg.payload = msg.payload.sample_gear_net_opening;\n}\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 350, + "y": 320, + "wires": [ + [ + "e967b844.46aa48" + ] + ] + }, + { + "id": "8dff1648.82e42", + "type": "function", + "z": "b771c342.49603", + "name": "get object_depth_max", + "func": "if (msg.payload.object_depth_max === null){\n msg.payload = 0;\n global.set(\"object_depth_max\",msg.payload);\n}\nelse\n{\n msg.payload = msg.payload.object_depth_max;\n}\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 320, + "y": 240, + "wires": [ + [ + "9c7f7fc9.c8d3a" + ] + ] + }, + { + "id": "9f04c5ec.75f3d8", + "type": "function", + "z": "b771c342.49603", + "name": "get object_depth_min", + "func": "if (msg.payload.object_depth_min === null){\n msg.payload = 0;\n global.set(\"object_depth_min\",msg.payload);\n}\nelse\n{\n msg.payload = msg.payload.object_depth_min;\n}\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 320, + "y": 280, + "wires": [ + [ + "317eeeb7.8d3042" + ] + ] + }, + { + "id": "9a18a4b4.178448", + "type": "function", + "z": "b771c342.49603", + "name": "calculate sample_total_volume", + "func": "\n/*object_lat = 33.95 \nobject_lon = 118.4 \nobject_lat_end = 40.6333 \nobject_lon_end = 73.78333\nsample_gear_net_opening = 40*/\n\n// Copyright 1997 Ed Williams. All rights reserved\n// Adapted by Romain Bazile - Ocean Trotter - 01-2021\n\ndecpl=4 // Dec places of minutes output\n\nellipse = {\"name\":\"WSG84\", \"a\":6378.137/1.852, \"invf\":298.257223563}\n\nfunction ComputeDistance(lat1, lon1, lat2, lon2){\n var d,crs12,crs21\n var argacos\n var a,invf\n \n // lat and lon in radian\n lat1=(Math.PI/180)*lat1\n lat2=(Math.PI/180)*lat2\n lon1=(Math.PI/180)*lon1\n lon2=(Math.PI/180)*lon2\n \n //alert(\"lat1=\" + lat1 + \"lon1=\" + lon1 +\"\\nlat2=\" +lat2+ \"lon2=\"+lon2)\n \n /* get distance conversion factor */\n dc=1.852 //km\n //alert(\"dc=\" +dc)\n \n //showProps(ellipse,\"ellipse\")\n \n // elliptic code\n d=crsdist_ell(lat1,-lon1,lat2,-lon2,ellipse) // ellipse uses East negative\n d=d*dc // go to physical units\n \n //alert(\"d=\"+d+\" crs12=\"+crs12+\" crs21=\"+crs21)\n return d\n}\n\nfunction crsdist(lat1,lon1,lat2,lon2){ // radian args\n /* compute course and distance (spherical) */\n if ((lat1+lat2===0) && (Math.abs(lon1-lon2)==Math.PI) && \n (Math.abs(lat1) != (Math.PI/180)*90)){\t\n \talert(\"Course between antipodal points is undefined\")\n }\n \n d = Math.acos(Math.sin(lat1)*Math.sin(lat2)+Math.cos(lat1)*Math.cos(lat2)*Math.cos(lon1-lon2))\n return d\n}\n\nfunction crsdist_ell(glat1,glon1,glat2,glon2,ellipse){\n // glat1 initial geodetic latitude in radians N positive \n // glon1 initial geodetic longitude in radians E positive \n // glat2 final geodetic latitude in radians N positive \n // glon2 final geodetic longitude in radians E positive \n a=ellipse.a\n f=1/ellipse.invf\n //alert(\"a=\"+a+\" f=\"+f)\n var r, tu1, tu2, cu1, su1, cu2, s1, b1, f1\n var x, sx, cx, sy, cy,y, sa, c2a, cz, e, c, d\n var EPS= 0.00000000005\n var faz, baz, s\n var iter=1\n var MAXITER=100\n if ((glat1+glat2===0) && (Math.abs(glon1-glon2)==Math.PI)){\n alert(\"Course and distance between antipodal points is undefined\")\n glat1=glat1+0.00001 // allow algorithm to complete\n }\n if (glat1==glat2 && (glon1==glon2 || Math.abs(Math.abs(glon1-glon2)-2*Math.PI) < EPS)){\n alert(\"Points 1 and 2 are identical- course undefined\")\n out=new MakeArray(0)\n out.d=0\n out.crs12=0\n out.crs21=Math.PI\n return out\n }\n r = 1 - f\n tu1 = r * Math.tan (glat1)\n tu2 = r * Math.tan (glat2)\n cu1 = 1 / Math.sqrt (1 + tu1 * tu1)\n su1 = cu1 * tu1\n cu2 = 1 / Math.sqrt (1 + tu2 * tu2)\n s1 = cu1 * cu2\n b1 = s1 * tu2\n f1 = b1 * tu1\n x = glon2 - glon1\n d = x + 1 // force one pass\n while ((Math.abs(d - x) > EPS) && (iter < MAXITER))\n {\n iter=iter+1\n sx = Math.sin (x)\n // alert(\"sx=\"+sx)\n cx = Math.cos (x)\n tu1 = cu2 * sx\n tu2 = b1 - su1 * cu2 * cx\n sy = Math.sqrt(tu1 * tu1 + tu2 * tu2)\n cy = s1 * cx + f1\n y = atan2 (sy, cy)\n sa = s1 * sx / sy\n c2a = 1 - sa * sa\n cz = f1 + f1\n if (c2a > 0)\n cz = cy - cz / c2a\n e = cz * cz * 2 - 1\n c = ((-3 * c2a + 4) * f + 4) * c2a * f / 16\n d = x\n x = ((e * cy * c + cz) * sy * c + y) * sa\n x = (1 - c) * x * f + glon2 - glon1\n }\n x = Math.sqrt ((1 / (r * r) - 1) * c2a + 1)\n x +=1\n x = (x - 2) / x\n c = 1 - x\n c = (x * x / 4 + 1) / c\n d = (0.375 * x * x - 1) * x\n x = e * cy\n d = ((((sy*sy*4-3)*(1-e-e)*cz*d/6-x)*d/4+cz)*sy*d+y)*c*a*r\n if (Math.abs(iter-MAXITER)0) && (y>=0)){ out= Math.atan(y/x)}\n if ((x >0) && (y<0)) { out= Math.atan(y/x)+2*Math.PI}\n if ((x===0) && (y>0)) { out= Math.PI/2}\n if ((x===0) && (y<0)) { out= 3*Math.PI/2} \n if ((x===0) && (y===0)) {\n alert(\"atan2(0,0) undefined\")\n out= 0\n } \n return out\n}\n\nfunction showProps(obj,objName){\n var result=\"\"\n for (var i in obj){\n result +=objName + \".\" + i + \" = \" + obj[i] + \"\\n\"\n }\n alert(result)\n}\n\n\nif (msg.valid){\n msg.topic=\"sample_total_volume\"\n \n var object_lat_end = global.get(\"object_lat_end\")\n var object_lon_end = global.get(\"object_lon_end\")\n var sample_sampling_gear = global.get(\"sample_sampling_gear\")\n \n if (sample_sampling_gear.startsWith(\"net\") && sample_sampling_gear != \"net_decknet\") {\n if (!(isNaN(object_lat_end) && isNaN(object_lon_end))){\n var object_lat = global.get(\"object_lat\")\n var object_lon = global.get(\"object_lon\")\n var sample_gear_net_opening = global.get(\"sample_gear_net_opening\");\n\n distance_km = ComputeDistance(object_lat, object_lon, object_lat_end, object_lon_end)\n\n sample_total_volume = distance_km*(Math.PI*(sample_gear_net_opening/2)*(sample_gear_net_opening/2)) // liters\n sample_total_volume = Math.round(sample_total_volume + Number.EPSILON)\n msg.payload = sample_total_volume\n return msg\n }\n }\n}", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 930, + "y": 760, + "wires": [ + [ + "4f6afc5a.81e454" + ] + ] + }, + { + "id": "4fb4e0ad.c417c", + "type": "ui_text", + "z": "b771c342.49603", + "group": "fc5e4e6f.5b1c8", + "order": 6, + "width": 5, + "height": 1, + "name": "Latitude", + "label": "Latitude", + "format": "{{msg.payload.lat.deg}}°{{msg.payload.lat.min}}'{{msg.payload.lat.sec}}{{msg.payload.lat.dir}}", + "layout": "col-center", + "x": 700, + "y": 1120, + "wires": [] + }, + { + "id": "8d2b5026.13e6e8", + "type": "ui_text", + "z": "b771c342.49603", + "group": "fc5e4e6f.5b1c8", + "order": 7, + "width": 5, + "height": 1, + "name": "Longitude", + "label": "Longitude", + "format": "{{msg.payload.lon.deg}}°{{msg.payload.lon.min}}'{{msg.payload.lon.sec}}{{msg.payload.lon.dir}}", + "layout": "col-center", + "x": 700, + "y": 1160, + "wires": [] + }, + { + "id": "258b4562.9f778a", + "type": "function", + "z": "b771c342.49603", + "name": "Convert DD to DMS", + "func": "function ConvertDDToDMS(D, lng){\n // from https://stackoverflow.com/a/5786281/2108279\n return {\n dir : D<0?lng?'W':'S':lng?'E':'N',\n deg : 0|(D<0?D=-D:D),\n min : 0|D%1*60,\n sec :(0|D*60%1*6000)/100\n };\n}\n\nmsg.payload = {\n \"lat\":ConvertDDToDMS(msg.payload.lat, false),\n \"lon\":ConvertDDToDMS(msg.payload.lon, true)\n};\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 490, + "y": 1140, + "wires": [ + [ + "4fb4e0ad.c417c", + "8d2b5026.13e6e8" + ] + ] + }, + { + "id": "7c4ce5f3.62dd5c", + "type": "ui_text", + "z": "b771c342.49603", + "group": "fc5e4e6f.5b1c8", + "order": 4, + "width": 2, + "height": 1, + "name": "Speed", + "label": "Speed", + "format": "{{msg.payload}} kts", + "layout": "col-center", + "x": 690, + "y": 1200, + "wires": [] + }, + { + "id": "54e37580.fdc31c", + "type": "ui_text", + "z": "b771c342.49603", + "group": "fc5e4e6f.5b1c8", + "order": 5, + "width": 2, + "height": 1, + "name": "Direction", + "label": "Direction", + "format": "{{msg.payload.track}} °", + "layout": "col-center", + "x": 700, + "y": 1240, + "wires": [] + }, + { + "id": "cc21ca16.b92928", + "type": "function", + "z": "b771c342.49603", + "name": "GPS Mode", + "func": "switch (msg.payload.mode){\n case 1:msg.payload = \"No Fix\"; break\n case 2:msg.payload = \"2D Fix\"; break\n case 3:msg.payload = \"3D Fix\"; break\n default: msg.payload = \"No info\"\n}\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 470, + "y": 1080, + "wires": [ + [ + "7116e906.9f50f" + ] + ] + }, + { + "id": "4a4de52c.cf2884", + "type": "function", + "z": "b771c342.49603", + "name": "Speed conversion", + "func": "msg.payload = (0|msg.payload.speed) * 1.9438\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 490, + "y": 1200, + "wires": [ + [ + "7c4ce5f3.62dd5c" + ] + ] + }, + { + "id": "35ad311f.344c76", + "type": "ui_text", + "z": "b771c342.49603", + "group": "fc5e4e6f.5b1c8", + "order": 2, + "width": 5, + "height": 1, + "name": "Time", + "label": "Time", + "format": "{{msg.payload.time}}", + "layout": "col-center", + "x": 690, + "y": 1280, + "wires": [] + }, + { + "id": "e73fd87d.d24e4", + "type": "function", + "z": "b771c342.49603", + "name": "get acq_minimum_mesh", + "func": "msg.payload = msg.payload.acq_minimum_mesh;\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 330, + "y": 360, + "wires": [ + [ + "1aad56b31b5647ce" + ] + ] + }, + { + "id": "489c8e06.cc7d6", + "type": "function", + "z": "b771c342.49603", + "name": "get acq_maximum_mesh", + "func": "msg.payload = msg.payload.acq_maximum_mesh;\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 330, + "y": 400, + "wires": [ + [ + "10eb31a2d7a6590c" + ] + ] + }, + { + "id": "73c4a14a.9b93c8", + "type": "function", + "z": "b771c342.49603", + "name": "Convert time", + "func": "msg.payload.time = msg.payload.time.replace('T', ' ');\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 470, + "y": 1280, + "wires": [ + [ + "35ad311f.344c76" + ] + ] + }, + { + "id": "58de1340.3cc354", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "sample_dilution_factor", + "label": "Concentration Factor", + "tooltip": "0.5 if diluted by two; 2 if concentrated by a factor 2", + "group": "3e1ba03d.f01d8", + "order": 13, + "width": 10, + "height": 1, + "passthru": true, + "mode": "number", + "delay": "300", + "topic": "sample_dilution_factor", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 640, + "y": 480, + "wires": [ + [ + "9f501f49.45645" + ] + ] + }, + { + "id": "4f6afc5a.81e454", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "sample_total_volume", + "label": "Filtered volume (in L)", + "tooltip": "Calculated or hand filled", + "group": "3e1ba03d.f01d8", + "order": 11, + "width": 0, + "height": 0, + "passthru": true, + "mode": "text", + "delay": "300", + "topic": "sample_total_volume", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 1220, + "y": 760, + "wires": [ + [ + "e1f2f6eb.fe1dd" + ] + ] + }, + { + "id": "e1f2f6eb.fe1dd", + "type": "function", + "z": "b771c342.49603", + "name": "set global", + "func": "global.set(msg.topic,msg.payload);", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 1420, + "y": 760, + "wires": [ + [] + ] + }, + { + "id": "e9bc112c.eb75f8", + "type": "function", + "z": "b771c342.49603", + "name": "Calculate volume", + "func": "if (msg.topic == \"sample_total_flowmeter_start\"){\n context.set(\"sample_total_flowmeter_start\", msg.payload);\n}\nif (msg.topic == \"sample_total_flowmeter_end\"){\n context.set(\"sample_total_flowmeter_end\", msg.payload);\n}\n\nif (context.keys().length == 2){\n sample_total_volume = context.get(\"sample_total_flowmeter_end\") - context.get(\"sample_total_flowmeter_start\");\n msg.topic=\"sample_total_volume\"\n msg.payload=sample_total_volume\n return msg\n}\n", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 1610, + "y": 240, + "wires": [ + [ + "4f6afc5a.81e454" + ] + ] + }, + { + "id": "cdd4181922eecf11", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "sample_speed_through_water", + "label": "Speed Through Water (kts)", + "tooltip": "in knots", + "group": "cf5d9f0e.d57e7", + "order": 2, + "width": 10, + "height": 1, + "passthru": true, + "mode": "number", + "delay": "300", + "topic": "sample_speed_through_water", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 610, + "y": 520, + "wires": [ + [ + "9f501f49.45645" + ] + ] + }, + { + "id": "1aad56b31b5647ce", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "acq_minimum_mesh", + "label": "Minimal fraction size (μm)", + "tooltip": "Net mesh pore size or minimal filtration mesh pore size", + "group": "3e1ba03d.f01d8", + "order": 7, + "width": 5, + "height": 1, + "passthru": true, + "mode": "number", + "delay": "300", + "topic": "acq_minimum_mesh", + "topicType": "str", + "x": 640, + "y": 360, + "wires": [ + [ + "9f501f49.45645" + ] + ] + }, + { + "id": "10eb31a2d7a6590c", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "acq_maximum_mesh", + "label": "Maximal fraction size (μm)", + "tooltip": "Maximal filtration mesh pore size", + "group": "3e1ba03d.f01d8", + "order": 8, + "width": 5, + "height": 1, + "passthru": true, + "mode": "number", + "delay": "300", + "topic": "acq_maximum_mesh", + "topicType": "str", + "x": 640, + "y": 400, + "wires": [ + [ + "9f501f49.45645" + ] + ] + }, + { + "id": "3ac7b631f5d8ef90", + "type": "function", + "z": "b771c342.49603", + "name": "Culture check", + "func": "var activation_msg = {}\nvar date_msg = {}\nvar timestamp=new Date().toISOString();\n\nif (msg.payload === \"culture\"){\n activation_msg.payload = {\"group\":{\"show\":[\"Sample_Culture_Date_and_Time\"],\"hide\":[\"Sample_Sample_Location\", \"Sample_Net_Metadata\"]}};\n global.set(\"object_lat\", \"-90.0000\")\n global.set(\"object_lon\", \"0.0000\")\n date_msg.payload = {\"object_date\": timestamp.split('T')[0],\n \"object_time\": timestamp.split('T')[1].split('.')[0]}\n return [activation_msg, date_msg];\n}\nelse if (msg.payload === \"test\"){\n activation_msg.payload = {\"group\":{\"hide\":[\"Sample_Culture_Date_and_Time\", \"Sample_Sample_Location\", \"Sample_Net_Metadata\"]}};\n global.set(\"object_lat\", \"-90.0000\")\n global.set(\"object_lon\", \"0.0000\")\n global.set(\"object_date\", timestamp.split('T')[0])\n global.set(\"object_time\", timestamp.split('T')[1].split('.')[0])\n return [activation_msg, null];\n}\nelse{\n return [null, null]\n}\n\n", + "outputs": 2, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 1100, + "y": 320, + "wires": [ + [ + "cbb123ab.fd3428" + ], + [ + "05c6aff2afbd69cf" + ] + ], + "outputLabels": [ + "decknet activation", + "" + ] + }, + { + "id": "05c6aff2afbd69cf", + "type": "ui_form", + "z": "b771c342.49603", + "name": "culture_timestamp", + "label": "Culture timestamp", + "group": "7bc0a4c416e4545c", + "order": 1, + "width": 0, + "height": 0, + "options": [ + { + "label": "Date (YYYY-MM-DD, UTC)", + "value": "object_date", + "type": "text", + "required": true, + "rows": null + }, + { + "label": "Time (HH:MM(:SS), UTC 24h)", + "value": "object_time", + "type": "text", + "required": true, + "rows": null + } + ], + "formValue": { + "object_date": "", + "object_time": "" + }, + "payload": "", + "submit": "Validate", + "cancel": "Reset", + "topic": "culture_timestamp", + "topicType": "str", + "splitLayout": false, + "className": "", + "x": 650, + "y": 700, + "wires": [ + [ + "14658615.47c862", + "38616e738f4f615b" + ] + ] + }, + { + "id": "3318a1aaa70fc2ee", + "type": "change", + "z": "b771c342.49603", + "name": "Repopulate input fields", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 400, + "y": 580, + "wires": [ + [ + "c33f1124.af6688" + ] + ] + }, + { + "id": "cc67c97f55a340d3", + "type": "change", + "z": "b771c342.49603", + "name": "Repopulate input fields", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 400, + "y": 620, + "wires": [ + [ + "358908cd.416ab" + ] + ] + }, + { + "id": "9c8f370d124a55e4", + "type": "change", + "z": "b771c342.49603", + "name": "Repopulate input fields", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 400, + "y": 660, + "wires": [ + [ + "56d40584.eff4e4" + ] + ] + }, + { + "id": "38616e738f4f615b", + "type": "change", + "z": "b771c342.49603", + "name": "Repopulate input fields", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 400, + "y": 700, + "wires": [ + [ + "05c6aff2afbd69cf" + ] + ] + }, + { + "id": "577be9c22c739ca0", + "type": "inject", + "z": "b771c342.49603", + "name": "", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "payload": "1", + "payloadType": "num", + "x": 270, + "y": 480, + "wires": [ + [ + "58de1340.3cc354" + ] + ] + }, + { + "id": "6a84252a.d52a0c", + "type": "ui_template", + "z": "bccd1f23.87219", + "group": "833bc5bb.217ba8", + "name": "Stream Pi Camera", + "order": 1, + "width": 18, + "height": 14, + "format": "
\n \"If\n
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "className": "", + "x": 610, + "y": 40, + "wires": [ + [] + ] + }, + { + "id": "dc48dc42.98d18", + "type": "function", + "z": "bccd1f23.87219", + "name": "set global", + "func": "global.set(msg.topic,msg.payload);", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 880, + "y": 440, + "wires": [ + [] + ] + }, + { + "id": "811cd88c.daf528", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "down", + "group": "fbd92986.1028c8", + "order": 6, + "width": 4, + "height": 1, + "passthru": true, + "label": "", + "tooltip": "", + "color": "", + "bgcolor": "", + "icon": "fa-angle-double-down fa-3x", + "payload": "DOWN", + "payloadType": "str", + "topic": "actuator/focus", + "x": 550, + "y": 800, + "wires": [ + [ + "65ad39d.b6d4d48" + ] + ] + }, + { + "id": "edda4df4.76de2", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "up", + "group": "fbd92986.1028c8", + "order": 3, + "width": 4, + "height": 1, + "passthru": false, + "label": "", + "tooltip": "", + "color": "", + "bgcolor": "", + "icon": "fa-angle-double-up fa-3x", + "payload": "UP", + "payloadType": "str", + "topic": "actuator/focus", + "x": 550, + "y": 760, + "wires": [ + [ + "65ad39d.b6d4d48" + ] + ] + }, + { + "id": "68962547.34a67c", + "type": "ui_text_input", + "z": "bccd1f23.87219", + "name": "pump_manual_volume", + "label": "Volume to pass (ml)", + "tooltip": "Tiny values are accepted down to 0.001mL", + "group": "707d9797.c8e798", + "order": 3, + "width": 2, + "height": 1, + "passthru": true, + "mode": "text", + "delay": "300", + "topic": "pump_manual_volume", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 600, + "y": 420, + "wires": [ + [ + "dc48dc42.98d18" + ] + ] + }, + { + "id": "6c792043.b6ff9", + "type": "ui_ui_control", + "z": "bccd1f23.87219", + "name": "", + "events": "change", + "x": 560, + "y": 1140, + "wires": [ + [] + ] + }, + { + "id": "902429eb.ceacb8", + "type": "ui_toast", + "z": "bccd1f23.87219", + "position": "dialog", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 1, + "ok": "OK", + "cancel": "", + "raw": false, + "topic": "", + "name": "", + "x": 570, + "y": 1220, + "wires": [ + [] + ] + }, + { + "id": "fe840e05.b46f3", + "type": "function", + "z": "bccd1f23.87219", + "name": "Check form", + "func": "var acq_fnumber_objective= global.get(\"acq_fnumber_objective\");\n\nif (acq_fnumber_objective === undefined || acq_fnumber_objective === \"\") {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Focal Length of the objective\";\n return [null, msg];\n}\n\nmsg.topic = \"Change Tab\";\nmsg.payload={\"tab\":\"Fluidic Acquisition\"};\nreturn [msg, null];", + "outputs": 2, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 330, + "y": 1180, + "wires": [ + [ + "6c792043.b6ff9", + "326a1d95.ca21aa" + ], + [ + "902429eb.ceacb8" + ] + ], + "outputLabels": [ + "message", + "error" + ] + }, + { + "id": "5846b1d4.7971b", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "Backward", + "group": "707d9797.c8e798", + "order": 2, + "width": 1, + "height": 1, + "passthru": false, + "label": "", + "tooltip": "", + "color": "", + "bgcolor": "", + "icon": "fa-rotate-left fa-2x", + "payload": "BACKWARD", + "payloadType": "str", + "topic": "actuator/pump", + "x": 560, + "y": 280, + "wires": [ + [ + "3cb96380.e575ec" + ] + ] + }, + { + "id": "2cab680b.baf888", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "Forward", + "group": "707d9797.c8e798", + "order": 4, + "width": 1, + "height": 1, + "passthru": true, + "label": "", + "tooltip": "", + "color": "", + "bgcolor": "", + "icon": "fa-rotate-right fa-2x", + "payload": "FORWARD", + "payloadType": "str", + "topic": "actuator/pump", + "x": 560, + "y": 320, + "wires": [ + [ + "3cb96380.e575ec" + ] + ] + }, + { + "id": "8038414a.34461", + "type": "function", + "z": "bccd1f23.87219", + "name": "Calculate optics", + "func": "var acq_fnumber_objective = String(global.get(\"acq_fnumber_objective\"));\nvar acq_camera = global.get(\"acq_camera\")\n\n// Those values needs to be recalculated, they are not good!\nif (acq_camera == \"HQ Camera\"){\n switch(acq_fnumber_objective) {\n case \"25\":\n acq_magnification= 0.6;\n process_pixel= 1.56;\n sug_min= 60;\n sug_max= 670;\n sug_flowrate= 3;\n break;\n case \"16\":\n acq_magnification= 1.6;\n process_pixel= 1.01;\n sug_min= 40;\n sug_max= 430;\n sug_flowrate= 2.4;\n break;\n case \"12\":\n acq_magnification= 1.20;\n process_pixel= 0.79;\n sug_min= 30;\n sug_max= 340;\n sug_flowrate= 1.25;\n break;\n case \"8\":\n acq_magnification= 1.78;\n process_pixel= 0.53;\n sug_min= 20;\n sug_max= 230;\n sug_flowrate= 0.42;\n break;\n case \"6\":\n acq_magnification= 2.36;\n process_pixel= 0.41;\n sug_min= 15;\n sug_max= 170;\n sug_flowrate= 0.32;\n break;\n }\n}\nelse if (acq_camera == \"Camera v2.1\"){\n switch(acq_fnumber_objective) {\n case \"25\":\n acq_magnification= 0.6;\n process_pixel= 1.86;\n sug_min= 60;\n sug_max= 670;\n sug_flowrate= 3;\n break;\n case \"16\":\n acq_magnification= 1.6;\n process_pixel= 0.7;\n sug_min= 40;\n sug_max= 430;\n sug_flowrate= 2.4;\n break;\n case \"12\":\n acq_magnification= 1.20;\n process_pixel= 0.94;\n sug_min= 30;\n sug_max= 340;\n sug_flowrate= 1.25;\n break;\n case \"8\":\n acq_magnification= 1.78;\n process_pixel= 0.63;\n sug_min= 20;\n sug_max= 230;\n sug_flowrate= 0.42;\n break;\n case \"6\":\n acq_magnification= 2.36;\n process_pixel= 0.48;\n sug_min= 15;\n sug_max= 170;\n sug_flowrate= 0.32;\n break;\n }\n}else {\n acq_magnification= \"ERROR\";\n process_pixel= \"ERROR\";\n sug_min= \"ERROR\";\n sug_max= \"ERROR\";\n sug_flowrate= \"ERROR\";\n}\n\nvar process_pixel_fixed = global.get(\"process_pixel_fixed\")\n\nif (process_pixel_fixed !== undefined && process_pixel_fixed !== \"\") {\n process_pixel = process_pixel_fixed\n}\n\nglobal.set(\"process_pixel\",process_pixel);\n\nglobal.set(\"acq_magnification\",acq_magnification);\n\n\nreturn [{payload: acq_fnumber_objective}, {payload: acq_magnification}, {payload: process_pixel}, {payload: sug_min}, {payload: sug_max}];", + "outputs": 5, + "timeout": "", + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 1080, + "y": 120, + "wires": [ + [], + [], + [], + [], + [] + ], + "inputLabels": [ + "acq_fnumber_objective" + ], + "outputLabels": [ + "acq_magnification", + "process_pixel", + "sug_min", + "sug_max", + "" + ] + }, + { + "id": "f61aaed5.1e64", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "", + "group": "7a0b4877.a5d268", + "order": 1, + "width": 2, + "height": 1, + "passthru": false, + "label": "Previous", + "tooltip": "", + "color": "#097479", + "bgcolor": "white", + "icon": "keyboard_return", + "payload": "{\"tab\":\"Sample\"}", + "payloadType": "json", + "topic": "", + "x": 140, + "y": 1140, + "wires": [ + [ + "6c792043.b6ff9" + ] + ] + }, + { + "id": "9ba6ec0a.22c96", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "", + "group": "7a0b4877.a5d268", + "order": 2, + "width": 2, + "height": 1, + "passthru": false, + "label": "Continue", + "tooltip": "", + "color": "#097479", + "bgcolor": "white", + "icon": "keyboard_tab", + "payload": "{\"tab\":\"Home\"}", + "payloadType": "json", + "topic": "", + "x": 140, + "y": 1180, + "wires": [ + [ + "fe840e05.b46f3" + ] + ] + }, + { + "id": "cbb8afed.0a026", + "type": "rpi-gpio out", + "z": "bccd1f23.87219", + "name": "LED Output", + "pin": "21", + "set": true, + "level": "0", + "freq": "", + "out": "out", + "bcm": true, + "x": 550, + "y": 120, + "wires": [] + }, + { + "id": "3cb96380.e575ec", + "type": "function", + "z": "bccd1f23.87219", + "name": "pump", + "func": "var manual_volume= global.get(\"pump_manual_volume\");\nvar flowrate= global.get(\"pump_flowrate\");\n\nif (manual_volume === undefined || manual_volume === \"\" || manual_volume === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Volume to pass\";\n return [null, msg];\n}\nelse if (flowrate === undefined || flowrate === \"\" || flowrate === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Flowrate\";\n return [null, msg];\n}\nelse {\n msg.topic = \"actuator/pump\";\n // msg.payload is FORWARD or BACKWARD here\n msg.payload={\"action\":\"move\", \n \"direction\":msg.payload,\n \"volume\":manual_volume,\n \"flowrate\":flowrate};\n}\nreturn [msg, null];", + "outputs": 2, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 750, + "y": 300, + "wires": [ + [ + "bdc8ce57.de1f08" + ], + [ + "8bcce348.efc1a" + ] + ], + "inputLabels": [ + "direction" + ], + "outputLabels": [ + "message", + "error" + ] + }, + { + "id": "8bcce348.efc1a", + "type": "ui_toast", + "z": "bccd1f23.87219", + "position": "dialog", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 1, + "ok": "OK", + "cancel": "", + "raw": false, + "topic": "", + "name": "", + "x": 1090, + "y": 300, + "wires": [ + [] + ] + }, + { + "id": "bdc8ce57.de1f08", + "type": "mqtt out", + "z": "bccd1f23.87219", + "name": "", + "topic": "", + "qos": "", + "retain": "", + "broker": "8dc3722c.06efa8", + "x": 1210, + "y": 260, + "wires": [] + }, + { + "id": "d71d224f.0585d8", + "type": "ui_toast", + "z": "bccd1f23.87219", + "position": "dialog", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 1, + "ok": "OK", + "cancel": "", + "raw": false, + "topic": "", + "name": "", + "x": 1090, + "y": 800, + "wires": [ + [] + ] + }, + { + "id": "65ad39d.b6d4d48", + "type": "function", + "z": "bccd1f23.87219", + "name": "focus", + "func": "var distance = global.get(\"focus_distance\");\n\nif (distance === undefined || distance === \"\" || distance === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Distance\";\n return [null, msg]\n}else {\n distance = global.get(\"focus_distance\");\n // msg.payload is UP or DOWN here\n msg.payload={\"action\":\"move\", \n \"direction\":msg.payload,\n \"distance\":(distance/1000)};\n}\nreturn [msg, null];", + "outputs": 2, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 850, + "y": 780, + "wires": [ + [ + "62030521.88317c" + ], + [ + "d71d224f.0585d8" + ] + ], + "inputLabels": [ + "direction" + ], + "outputLabels": [ + "message", + "error" + ] + }, + { + "id": "1962d999.4a97e6", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "stop focus", + "group": "fbd92986.1028c8", + "order": 9, + "width": 0, + "height": 0, + "passthru": true, + "label": " STOP FOCUS", + "tooltip": "", + "color": "", + "bgcolor": "#AD1625", + "icon": "fa-pause fa-2x", + "payload": "{\"action\":\"stop\"}", + "payloadType": "json", + "topic": "actuator/focus", + "x": 570, + "y": 560, + "wires": [ + [ + "62030521.88317c" + ] + ] + }, + { + "id": "62030521.88317c", + "type": "mqtt out", + "z": "bccd1f23.87219", + "name": "", + "topic": "", + "qos": "", + "retain": "", + "broker": "8dc3722c.06efa8", + "x": 1210, + "y": 720, + "wires": [] + }, + { + "id": "3bd43039.bc5fb8", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "", + "group": "fbd92986.1028c8", + "order": 1, + "width": 4, + "height": 1, + "passthru": false, + "label": "UP 1mm", + "tooltip": "", + "color": "", + "bgcolor": "", + "icon": "fa-angle-up fa-3x", + "payload": "{\"action\":\"move\",\"direction\":\"UP\",\"distance\":1}", + "payloadType": "json", + "topic": "actuator/focus", + "topicType": "str", + "x": 560, + "y": 600, + "wires": [ + [ + "62030521.88317c" + ] + ] + }, + { + "id": "c0663029.2d03b", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "", + "group": "fbd92986.1028c8", + "order": 8, + "width": 4, + "height": 1, + "passthru": false, + "label": "DOWN 1mm", + "tooltip": "", + "color": "", + "bgcolor": "", + "icon": "fa-angle-down fa-3x", + "payload": "{\"action\":\"move\",\"direction\":\"DOWN\",\"distance\":1}", + "payloadType": "json", + "topic": "actuator/focus", + "topicType": "str", + "x": 570, + "y": 720, + "wires": [ + [ + "62030521.88317c" + ] + ] + }, + { + "id": "71f55a58.d7eaf4", + "type": "inject", + "z": "bccd1f23.87219", + "name": "Default: 500µm", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": "0.5", + "topic": "", + "payload": "500", + "payloadType": "num", + "x": 120, + "y": 460, + "wires": [ + [ + "be33e564.029358" + ] + ] + }, + { + "id": "9a1d0e7c.2d5a1", + "type": "inject", + "z": "bccd1f23.87219", + "name": "Default: OFF", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "payload": "off", + "payloadType": "str", + "x": 130, + "y": 120, + "wires": [ + [ + "f0775525.cf806" + ] + ] + }, + { + "id": "f782a471.447748", + "type": "inject", + "z": "bccd1f23.87219", + "name": "Default: 2mL/min", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": "0.5", + "topic": "", + "payload": "2", + "payloadType": "num", + "x": 130, + "y": 380, + "wires": [ + [ + "cb2d5174.cfe9f" + ] + ] + }, + { + "id": "73b8252a.5ca754", + "type": "inject", + "z": "bccd1f23.87219", + "name": "Default: 2mL", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": "0.5", + "topic": "", + "payload": "2", + "payloadType": "num", + "x": 110, + "y": 420, + "wires": [ + [ + "68962547.34a67c" + ] + ] + }, + { + "id": "6451f991.aaac1", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "stop pump", + "group": "707d9797.c8e798", + "order": 5, + "width": 4, + "height": 1, + "passthru": true, + "label": " STOP PUMP", + "tooltip": "", + "color": "", + "bgcolor": "#AD1625", + "icon": "fa-pause fa-2x", + "payload": "{\"action\":\"stop\"}", + "payloadType": "json", + "topic": "actuator/pump", + "x": 570, + "y": 240, + "wires": [ + [ + "bdc8ce57.de1f08" + ] + ] + }, + { + "id": "cfc783d7.d6ceb", + "type": "link in", + "z": "bccd1f23.87219", + "name": "Optics recalculation", + "links": [ + "559a8085.1d6b9", + "5d5ad36d2c50dcc2" + ], + "x": 915, + "y": 120, + "wires": [ + [ + "8038414a.34461" + ] + ] + }, + { + "id": "326a1d95.ca21aa", + "type": "subflow:1c24ad9c.bebec2", + "z": "bccd1f23.87219", + "name": "", + "x": 550, + "y": 1180, + "wires": [ + [] + ] + }, + { + "id": "2d371e59.b0e50a", + "type": "inject", + "z": "bccd1f23.87219", + "name": "Default: 1000µm/s", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": "0.5", + "topic": "", + "payload": "1000", + "payloadType": "num", + "x": 130, + "y": 500, + "wires": [ + [ + "3a86de51.765b9a" + ] + ] + }, + { + "id": "167cda35.c9b6ae", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "", + "group": "fbd92986.1028c8", + "order": 2, + "width": 4, + "height": 1, + "passthru": false, + "label": "UP 100um", + "tooltip": "", + "color": "", + "bgcolor": "", + "icon": "fa-angle-up fa-3x", + "payload": "{\"action\":\"move\",\"direction\":\"UP\",\"distance\":0.1}", + "payloadType": "json", + "topic": "actuator/focus", + "topicType": "str", + "x": 570, + "y": 640, + "wires": [ + [ + "62030521.88317c" + ] + ] + }, + { + "id": "72a7c597.9374fc", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "", + "group": "fbd92986.1028c8", + "order": 7, + "width": 4, + "height": 1, + "passthru": false, + "label": "DOWN 100um", + "tooltip": "", + "color": "", + "bgcolor": "", + "icon": "fa-angle-down fa-3x", + "payload": "{\"action\":\"move\",\"direction\":\"DOWN\",\"distance\":0.1}", + "payloadType": "json", + "topic": "actuator/focus", + "topicType": "str", + "x": 580, + "y": 680, + "wires": [ + [ + "62030521.88317c" + ] + ] + }, + { + "id": "f0775525.cf806", + "type": "ui_multistate_switch", + "z": "bccd1f23.87219", + "name": "light_control", + "group": "4248342d.e55fac", + "order": 1, + "width": 5, + "height": 1, + "label": "Light ", + "stateField": "payload", + "enableField": "enable", + "rounded": true, + "useThemeColors": true, + "hideSelectedLabel": false, + "options": [ + { + "label": "Off", + "value": "0", + "valueType": "num", + "color": "#009933" + }, + { + "label": "On", + "value": "1", + "valueType": "num", + "color": "#999999" + } + ], + "x": 350, + "y": 120, + "wires": [ + [ + "cbb8afed.0a026" + ] + ] + }, + { + "id": "8ea9dc9a.c7d87", + "type": "function", + "z": "bccd1f23.87219", + "name": "Encapsulate settings", + "func": "msg.payload = {\n \"action\":\"settings\", \n \"settings\":{[msg.topic]:msg.payload}\n}\n\nmsg.topic = \"imager/image\"\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 1120, + "y": 940, + "wires": [ + [ + "845e06e1.0d812" + ] + ] + }, + { + "id": "5765a825.a595c8", + "type": "ui_slider", + "z": "bccd1f23.87219", + "name": "Shutter speed slider", + "label": "Shutter Speed", + "tooltip": "In microseconds, up to 1000µs, 125µs by default", + "group": "8c38a81e.9897a8", + "order": 4, + "width": 0, + "height": 0, + "passthru": true, + "outs": "end", + "topic": "shutter_speed", + "topicType": "str", + "min": "125", + "max": "1000", + "step": "1", + "className": "", + "x": 600, + "y": 880, + "wires": [ + [ + "8ea9dc9a.c7d87" + ] + ] + }, + { + "id": "845e06e1.0d812", + "type": "mqtt out", + "z": "bccd1f23.87219", + "name": "", + "topic": "", + "qos": "", + "retain": "", + "broker": "8dc3722c.06efa8", + "x": 1390, + "y": 980, + "wires": [] + }, + { + "id": "2350e507.d4e302", + "type": "inject", + "z": "bccd1f23.87219", + "name": "Default: 125µs", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": "1", + "topic": "", + "payload": "125", + "payloadType": "num", + "x": 120, + "y": 880, + "wires": [ + [ + "5765a825.a595c8" + ] + ] + }, + { + "id": "5e147425.7666ec", + "type": "function", + "z": "bccd1f23.87219", + "name": "Encapsulate wb gain settings", + "func": "msg.payload = {\n \"action\":\"settings\", \n \"settings\":{\"white_balance_gain\":{\n [msg.topic]:Math.round(msg.payload*100)\n }\n }\n}\nmsg.topic = \"imager/image\"\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 1100, + "y": 1060, + "wires": [ + [ + "845e06e1.0d812" + ] + ] + }, + { + "id": "82722a3c.846b3", + "type": "inject", + "z": "bccd1f23.87219", + "name": "Default: OFF", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": "1", + "topic": "", + "payload": "false", + "payloadType": "bool", + "x": 110, + "y": 920, + "wires": [ + [ + "60e44330.50bdec" + ] + ] + }, + { + "id": "60e44330.50bdec", + "type": "ui_switch", + "z": "bccd1f23.87219", + "name": "AWB", + "label": "Auto White Balance", + "tooltip": "", + "group": "8c38a81e.9897a8", + "order": 5, + "width": 2, + "height": 2, + "passthru": true, + "decouple": "false", + "topic": "white_balance", + "topicType": "str", + "style": "", + "onvalue": "auto", + "onvalueType": "str", + "onicon": "", + "oncolor": "", + "offvalue": "off", + "offvalueType": "str", + "officon": "", + "offcolor": "", + "animate": true, + "className": "", + "x": 550, + "y": 920, + "wires": [ + [ + "8ea9dc9a.c7d87" + ] + ] + }, + { + "id": "6be64480.7e7e24", + "type": "change", + "z": "bccd1f23.87219", + "name": "Get red_gain", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.red_gain", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 370, + "y": 1040, + "wires": [ + [ + "d5415af6.e06cc" + ] + ] + }, + { + "id": "6d49d161.13628", + "type": "change", + "z": "bccd1f23.87219", + "name": "Get blue_gain", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.blue_gain", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 380, + "y": 1080, + "wires": [ + [ + "dba68c1f.e3144" + ] + ] + }, + { + "id": "56835fa1.2fe538", + "type": "subflow:4ed26b8b.253504", + "z": "bccd1f23.87219", + "name": "", + "env": [], + "x": 1160, + "y": 1020, + "wires": [] + }, + { + "id": "8ef294ba.12213", + "type": "change", + "z": "bccd1f23.87219", + "name": "Get analog_gain", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "1", + "tot": "num" + }, + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.analog_gain", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 380, + "y": 960, + "wires": [ + [ + "a6c7eec4.f7a918" + ] + ] + }, + { + "id": "8e336e58.14722", + "type": "change", + "z": "bccd1f23.87219", + "name": "Get digital_gain", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "1", + "tot": "num" + }, + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.digital_gain", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 380, + "y": 1000, + "wires": [ + [ + "66b37eef.f3f9e" + ] + ] + }, + { + "id": "a6c7eec4.f7a918", + "type": "ui_text_input", + "z": "bccd1f23.87219", + "d": true, + "name": "Analog gain field", + "label": "Analog Gain", + "tooltip": "From 1.0 to 12.0", + "group": "8c38a81e.9897a8", + "order": 2, + "width": 0, + "height": 0, + "passthru": true, + "mode": "number", + "delay": 300, + "topic": "analog", + "topicType": "str", + "x": 580, + "y": 960, + "wires": [ + [ + "44e02933.a66688", + "d361a2c4.0990f8" + ] + ] + }, + { + "id": "66b37eef.f3f9e", + "type": "ui_text_input", + "z": "bccd1f23.87219", + "d": true, + "name": "Digital gain field", + "label": "Digital Gain", + "tooltip": "From 1.0 to 64.0. Overexpose starting at 4.0", + "group": "8c38a81e.9897a8", + "order": 3, + "width": 0, + "height": 0, + "passthru": true, + "mode": "number", + "delay": 300, + "topic": "digital", + "topicType": "str", + "x": 580, + "y": 1000, + "wires": [ + [ + "44e02933.a66688", + "d361a2c4.0990f8" + ] + ] + }, + { + "id": "44e02933.a66688", + "type": "function", + "z": "bccd1f23.87219", + "name": "Encapsulate image gain settings", + "func": "msg.payload = {\n \"action\":\"settings\", \n \"settings\":{\"image_gain\":{\n [msg.topic]:Math.round(msg.payload*100)\n }\n }\n}\nmsg.topic = \"imager/image\"\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 1090, + "y": 980, + "wires": [ + [ + "845e06e1.0d812" + ] + ] + }, + { + "id": "d361a2c4.0990f8", + "type": "change", + "z": "bccd1f23.87219", + "name": "topic *_gain", + "rules": [ + { + "t": "set", + "p": "topic", + "pt": "msg", + "to": "topic&'_gain'", + "tot": "jsonata" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 970, + "y": 1020, + "wires": [ + [ + "56835fa1.2fe538" + ] + ] + }, + { + "id": "d8d006bf.2947f", + "type": "inject", + "z": "bccd1f23.87219", + "name": "Default: ISO 150", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": "1", + "topic": "", + "payload": "150", + "payloadType": "num", + "x": 130, + "y": 840, + "wires": [ + [ + "37f412d1454deb64" + ] + ] + }, + { + "id": "eb9966de.cf13c8", + "type": "change", + "z": "bccd1f23.87219", + "name": "", + "rules": [ + { + "t": "set", + "p": "topic", + "pt": "msg", + "to": "iso", + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 740, + "y": 840, + "wires": [ + [ + "8ea9dc9a.c7d87" + ] + ] + }, + { + "id": "be33e564.029358", + "type": "ui_text_input", + "z": "bccd1f23.87219", + "name": "focus_distance", + "label": "Focus Distance (in µm)", + "tooltip": "in µm, 25µm resolution", + "group": "fbd92986.1028c8", + "order": 4, + "width": 0, + "height": 0, + "passthru": true, + "mode": "number", + "delay": 300, + "topic": "focus_distance", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 580, + "y": 460, + "wires": [ + [ + "dc48dc42.98d18" + ] + ] + }, + { + "id": "3a86de51.765b9a", + "type": "ui_text_input", + "z": "bccd1f23.87219", + "name": "focus_speed", + "label": "Focus Speed (in µm/sec)", + "tooltip": "in µm/sec", + "group": "fbd92986.1028c8", + "order": 5, + "width": 0, + "height": 0, + "passthru": true, + "mode": "number", + "delay": 300, + "topic": "focus_speed", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 570, + "y": 500, + "wires": [ + [ + "dc48dc42.98d18" + ] + ] + }, + { + "id": "cb2d5174.cfe9f", + "type": "ui_text_input", + "z": "bccd1f23.87219", + "name": "pump_flowrate", + "label": "Flowrate (ml/min)*", + "tooltip": "", + "group": "707d9797.c8e798", + "order": 1, + "width": 0, + "height": 0, + "passthru": true, + "mode": "text", + "delay": 300, + "topic": "pump_flowrate", + "topicType": "str", + "x": 580, + "y": 380, + "wires": [ + [ + "dc48dc42.98d18" + ] + ] + }, + { + "id": "d5415af6.e06cc", + "type": "ui_text_input", + "z": "bccd1f23.87219", + "name": "WB Red input", + "label": "WB: Red", + "tooltip": "From 0.0 to 32.0", + "group": "8c38a81e.9897a8", + "order": 6, + "width": 4, + "height": 1, + "passthru": true, + "mode": "number", + "delay": "0", + "topic": "red", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 580, + "y": 1040, + "wires": [ + [ + "f7a7398fd6ce4a4f" + ] + ] + }, + { + "id": "dba68c1f.e3144", + "type": "ui_text_input", + "z": "bccd1f23.87219", + "name": "WB Blue input", + "label": "WB: Blue", + "tooltip": "From 0.0 to 64.0", + "group": "8c38a81e.9897a8", + "order": 7, + "width": 4, + "height": 1, + "passthru": true, + "mode": "number", + "delay": "0", + "topic": "blue", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 580, + "y": 1080, + "wires": [ + [ + "df8a7667c9d133b1" + ] + ] + }, + { + "id": "d91550e8b15ed3b8", + "type": "subflow:e6665421f66ea4c8", + "z": "bccd1f23.87219", + "name": "", + "x": 160, + "y": 1020, + "wires": [ + [ + "8ef294ba.12213", + "8e336e58.14722", + "6be64480.7e7e24", + "6d49d161.13628" + ] + ] + }, + { + "id": "04920f50bbbf6a2a", + "type": "link in", + "z": "bccd1f23.87219", + "name": "Load hardware config", + "links": [ + "e4ead350b3d07578", + "4a1f303f0b6f7f42" + ], + "x": 25, + "y": 1000, + "wires": [ + [ + "d91550e8b15ed3b8" + ] + ] + }, + { + "id": "7386eaf7ca9d8bfa", + "type": "inject", + "z": "bccd1f23.87219", + "name": "Once", + "props": [], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "x": 50, + "y": 1080, + "wires": [ + [ + "d91550e8b15ed3b8" + ] + ] + }, + { + "id": "f7a7398fd6ce4a4f", + "type": "switch", + "z": "bccd1f23.87219", + "name": "Validate", + "property": "payload", + "propertyType": "msg", + "rules": [ + { + "t": "btwn", + "v": "0.0", + "vt": "num", + "v2": "32.0", + "v2t": "num" + }, + { + "t": "else" + } + ], + "checkall": "false", + "repair": false, + "outputs": 2, + "x": 740, + "y": 1040, + "wires": [ + [ + "d361a2c4.0990f8", + "5e147425.7666ec" + ], + [ + "64b05eea4c5469be", + "4a1f303f0b6f7f42" + ] + ] + }, + { + "id": "df8a7667c9d133b1", + "type": "switch", + "z": "bccd1f23.87219", + "name": "Validate", + "property": "payload", + "propertyType": "msg", + "rules": [ + { + "t": "btwn", + "v": "0.0", + "vt": "num", + "v2": "32.0", + "v2t": "num" + }, + { + "t": "else" + } + ], + "checkall": "false", + "repair": false, + "outputs": 2, + "x": 740, + "y": 1080, + "wires": [ + [ + "d361a2c4.0990f8", + "5e147425.7666ec" + ], + [ + "64b05eea4c5469be", + "4a1f303f0b6f7f42" + ] + ] + }, + { + "id": "64b05eea4c5469be", + "type": "ui_toast", + "z": "bccd1f23.87219", + "position": "top right", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 0, + "ok": "OK", + "cancel": "", + "raw": false, + "className": "", + "topic": "Invalid white balance value", + "name": "", + "x": 990, + "y": 1100, + "wires": [] + }, + { + "id": "4a1f303f0b6f7f42", + "type": "link out", + "z": "bccd1f23.87219", + "name": "Reload hardware config", + "mode": "link", + "links": [ + "04920f50bbbf6a2a" + ], + "x": 915, + "y": 1140, + "wires": [] + }, + { + "id": "37f412d1454deb64", + "type": "ui_slider", + "z": "bccd1f23.87219", + "name": "ISO selector", + "label": "ISO", + "tooltip": "", + "group": "8c38a81e.9897a8", + "order": 1, + "width": 0, + "height": 0, + "passthru": true, + "outs": "end", + "topic": "topic", + "topicType": "msg", + "min": "50", + "max": "800", + "step": "50", + "className": "", + "x": 570, + "y": 840, + "wires": [ + [ + "eb9966de.cf13c8" + ] + ] + }, + { + "id": "f59a2f0d.5e9af", + "type": "ui_numeric", + "z": "baa1e3d9.cb29d", + "name": "acq_minimum_mesh", + "label": "Min fraction size (μm)", + "tooltip": "", + "group": "404c301a.19c4e", + "order": 1, + "width": 5, + "height": 1, + "wrap": false, + "passthru": true, + "topic": "acq_minimum_mesh", + "format": "{{value}}", + "min": 0, + "max": "300", + "step": "10", + "x": 640, + "y": 160, + "wires": [ + [ + "fb887036.12429" + ] + ] + }, + { + "id": "6008a8bb.259f08", + "type": "ui_numeric", + "z": "baa1e3d9.cb29d", + "name": "acq_maximum_mesh", + "label": "Max fraction size (μm)", + "tooltip": "", + "group": "404c301a.19c4e", + "order": 2, + "width": 5, + "height": 1, + "wrap": false, + "passthru": true, + "topic": "acq_maximum_mesh", + "format": "{{value}}", + "min": "200", + "max": "2000", + "step": "100", + "x": 640, + "y": 200, + "wires": [ + [ + "fb887036.12429" + ] + ] + }, + { + "id": "6b34c456.83178c", + "type": "ui_text_input", + "z": "baa1e3d9.cb29d", + "name": "acq_id", + "label": "Acquisition unique ID*", + "tooltip": "", + "group": "4322c187.e73e5", + "order": 1, + "width": 5, + "height": 1, + "passthru": true, + "mode": "text", + "delay": 300, + "topic": "acq_id", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 690, + "y": 240, + "wires": [ + [ + "fb887036.12429" + ] + ] + }, + { + "id": "cc0ca68b.4263a8", + "type": "ui_dropdown", + "z": "baa1e3d9.cb29d", + "name": "acq_celltype", + "label": "Flowcell thickness*", + "tooltip": "", + "place": "Select option", + "group": "4322c187.e73e5", + "order": 6, + "width": 5, + "height": 1, + "passthru": true, + "multiple": false, + "options": [ + { + "label": "200 μm µ-Slide I Luer", + "value": 200, + "type": "num" + }, + { + "label": "300 µm capillary", + "value": 300, + "type": "num" + }, + { + "label": "400 μm µ-Slide I Luer", + "value": 400, + "type": "num" + }, + { + "label": "600 μm µ-Slide I Luer", + "value": 600, + "type": "num" + }, + { + "label": "800 μm µ-Slide I Luer", + "value": 800, + "type": "num" + } + ], + "payload": "", + "topic": "acq_celltype", + "topicType": "str", + "className": "", + "x": 670, + "y": 80, + "wires": [ + [ + "fb887036.12429", + "99b11fe4.2795d" + ] + ] + }, + { + "id": "fb887036.12429", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "set global", + "func": "global.set(msg.topic, msg.payload);\nreturn msg", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 920, + "y": 220, + "wires": [ + [ + "52ea7d01.711034" + ] + ] + }, + { + "id": "bb2bb7ce.1d1458", + "type": "ui_template", + "z": "baa1e3d9.cb29d", + "group": "858a0e3c.987fe", + "name": "Stream Pi Camera", + "order": 1, + "width": 10, + "height": 8, + "format": "
\n \"If\n
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "className": "", + "x": 650, + "y": 20, + "wires": [ + [] + ] + }, + { + "id": "d0c5b57d.590818", + "type": "ui_ui_control", + "z": "baa1e3d9.cb29d", + "name": "", + "events": "change", + "x": 1280, + "y": 660, + "wires": [ + [] + ] + }, + { + "id": "c72f8fae.23bd4", + "type": "ui_button", + "z": "baa1e3d9.cb29d", + "name": "", + "group": "b7919ae2.c01788", + "order": 1, + "width": 5, + "height": 1, + "passthru": false, + "label": "Previous", + "tooltip": "", + "color": "#097479", + "bgcolor": "white", + "icon": "keyboard_return", + "payload": "{\"tab\":\"Optic Configuration\"}", + "payloadType": "json", + "topic": "", + "x": 1140, + "y": 660, + "wires": [ + [ + "d0c5b57d.590818" + ] + ] + }, + { + "id": "29be525e.0c87fe", + "type": "ui_template", + "z": "baa1e3d9.cb29d", + "group": "b5d61bc7.54fe48", + "name": "Show Metadata", + "order": 9, + "width": 0, + "height": 0, + "format": "
\n \n \n \n \n \n \n \n \n \n
\n

Sample

\n

id:

\n

project:\n

\n

ship:

\n

operator:\n

\n

sampling gear:\n

\n

concentrated volume:\n

\n

gear net opening:\n

\n

total volume filtered:\n

\n
\n

Acquisition

\n

id:

\n

instrument:\n

\n

instrument id:\n

\n

camera:

\n

celltype: \n

\n

minimum mesh:\n

\n

maximum mesh:\n

\n

min esd: \n

\n

max esd: \n

\n

volume:

\n

magnification:\n

\n

fnumber objective:\n

\n

software: \n

\n
\n

Object

\n

latitude: \n

\n

longitude: \n

\n

latitude end:\n

\n

longitude end:\n

\n

date:

\n

time:

\n

date end:\n

\n

time end:\n

\n

depth min:\n

\n

depth max:\n

\n
\n

Process

\n

pixel: \n

\n

id:

\n
\n
", + "storeOutMessages": false, + "fwdInMessages": false, + "resendOnRefresh": false, + "templateScope": "local", + "className": "", + "x": 1180, + "y": 380, + "wires": [ + [] + ] + }, + { + "id": "c9f510c0.7d1328", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "Image control", + "func": "// Reset the number of images taken\nflow.set('img_counter', 0);\n\nvar acq_celltype = global.get(\"acq_celltype\");\nvar acq_minimum_mesh = global.get(\"acq_minimum_mesh\");\nvar acq_maximum_mesh = global.get(\"acq_maximum_mesh\");\nvar imaging_pump_volume = global.get(\"imaging_pump_volume\");\nvar acq_id = global.get(\"acq_id\");\nvar nb_frame = global.get(\"nb_frame\");\nvar pump_direction = global.get(\"pump_direction\");\nvar sleep_before = global.get(\"sleep_before\");\nvar object_date = global.get(\"object_date\");\n\nif (acq_celltype === undefined || acq_celltype === \"\") {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Type of the flowcell\";\n return [null, msg];\n} else if (acq_minimum_mesh === undefined || acq_minimum_mesh === \"\") {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Lower fraction size\";\n return [null, msg];\n} else if (acq_maximum_mesh === undefined || acq_maximum_mesh === \"\") {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Upper fraction size\";\n return [null, msg];\n} else if (imaging_pump_volume === undefined || imaging_pump_volume === \"\" || imaging_pump_volume === null) {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Volume inbetween images\";\n return [null, msg];\n} else if (acq_id === undefined || acq_id === \"\") {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Acquisition ID\";\n return [null, msg];\n} else if (nb_frame === undefined || nb_frame === \"\" || nb_frame === null) {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Number of image to save\";\n return [null, msg];\n} else if (pump_direction === undefined || pump_direction === \"\" || pump_direction === null) {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Pump direction\";\n return [null, msg];\n} else if (sleep_before === undefined || sleep_before === \"\" || sleep_before === null) {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Delay before image\";\n return [null, msg];\n}else if (object_date === undefined || object_date === \"\" || object_date === null) {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Object date\";\n return [null, msg];\n}\n\nmsg.payload = {\n \"action\": \"image\",\n \"sleep\": sleep_before,\n \"pump_direction\": pump_direction,\n \"volume\": imaging_pump_volume,\n \"nb_frame\": nb_frame,\n}\nmsg.send = true\n\nreturn [msg, null];", + "outputs": 2, + "timeout": "", + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 680, + "y": 480, + "wires": [ + [ + "52ea7d01.711034", + "40c12463.a1f84c", + "a4abb1ae.2ae418" + ], + [ + "20e0a8c8.edbeb" + ] + ] + }, + { + "id": "20e0a8c8.edbeb", + "type": "ui_toast", + "z": "baa1e3d9.cb29d", + "position": "dialog", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 1, + "ok": "OK", + "cancel": "", + "raw": false, + "className": "", + "topic": "", + "name": "", + "x": 950, + "y": 560, + "wires": [ + [] + ] + }, + { + "id": "c3e50240.82aa58", + "type": "mqtt out", + "z": "baa1e3d9.cb29d", + "name": "", + "topic": "", + "qos": "", + "retain": "", + "respTopic": "", + "contentType": "", + "userProps": "", + "correl": "", + "expiry": "", + "broker": "8dc3722c.06efa8", + "x": 1150, + "y": 440, + "wires": [] + }, + { + "id": "3a4450b1.4459a8", + "type": "ui_button", + "z": "baa1e3d9.cb29d", + "name": "Stop Acquisition", + "group": "4322c187.e73e5", + "order": 11, + "width": 5, + "height": 1, + "passthru": true, + "label": "STOP ACQUISITION", + "tooltip": "", + "color": "", + "bgcolor": "#AD1625", + "className": "", + "icon": "cancel", + "payload": "{\"action\":\"stop\"}", + "payloadType": "json", + "topic": "imager/image", + "topicType": "str", + "x": 460, + "y": 520, + "wires": [ + [ + "d74210ef.edc15" + ] + ] + }, + { + "id": "d74210ef.edc15", + "type": "mqtt out", + "z": "baa1e3d9.cb29d", + "name": "", + "topic": "", + "qos": "", + "retain": "", + "broker": "8dc3722c.06efa8", + "x": 650, + "y": 520, + "wires": [] + }, + { + "id": "bb62da8a.ebc328", + "type": "ui_switch", + "z": "baa1e3d9.cb29d", + "name": "Pump direction", + "label": "Pump direction", + "tooltip": "BACKWARD / FORWARD", + "group": "4322c187.e73e5", + "order": 9, + "width": 5, + "height": 1, + "passthru": true, + "decouple": "false", + "topic": "pump_direction", + "style": "", + "onvalue": "FORWARD", + "onvalueType": "str", + "onicon": "", + "oncolor": "", + "offvalue": "BACKWARD", + "offvalueType": "str", + "officon": "", + "offcolor": "", + "x": 460, + "y": 560, + "wires": [ + [ + "6b2239f3.41fa3" + ] + ] + }, + { + "id": "52ea7d01.711034", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "Encapsulate config", + "func": "msg.payload = {\n\t\"action\": \"update_config\",\n\t\"config\": {\n \t\"description\": {\n \t\t\"sample_project\": \"Project's name\",\n \t\t\"sample_id\": \"Sample ID\",\n \t\t\"sample_uuid\": \"Sample UUID (Autogenerated)\",\n \t\t\"sample_ship\": \"Ship's name\",\n \t\t\"sample_operator\": \"Operator's name\",\n \t\t\"sample_sampling_gear\": \"Sampling gear used\",\n \t\t\"sample_concentrated_sample_volume\": \"Volume of concentrated sample, in mL\",\n \t\t\"sample_total_volume\": \"Total volume filtered by the net used, in L\",\n \t\t\"sample_dilution_factor\": \"Dilution factor of the sample, 0.5 if diluted by 2, 2 if concentrated by 2\",\n \t\t\"sample_speed_through_water\": \"Speed of the boat through water when sampling, in kts\",\n \t\t\"acq_id\": \"Acquisition ID\",\n \t\t\"acq_uuid\": \"Acquisition UUID (Autogenerated)\",\n \t\t\"acq_instrument\": \"Instrument type\",\n \t\t\"acq_instrument_id\": \"Instrument ID\",\n \t\t\"acq_celltype\": \"Flow cell dimension thickness, in µm\",\n \t\t\"acq_minimum_mesh\": \"Minimum filtration mesh size, in µm\",\n \t\t\"acq_maximum_mesh\": \"Maximum filtration mesh size, in µm\",\n \t\t\"acq_min_esd\": \"\",\n \t\t\"acq_max_esd\": \"\",\n \t\t\"acq_volume\": \"Pumped volume, in mL\",\n\t\t \"acq_imaged_volume\": \"Total imaged volume, in mL\",\n \t\t\"acq_magnification\": \"Optical magnification\",\n \t\t\"acq_fnumber_objective\": \"Focal length of the objective, in mm\",\n \t\t\"acq_camera_name\": \"Name of the camera used\",\n \t\t\"acq_nb_frame\": \"Number of picture taken\",\n \"acq_local_datetime\": \"Instrument local datetime\",\n \"acq_camera_resolution\": \"Resolution of the images\",\n \"acq_camera_iso\": \"ISO Number of the images\",\n \"acq_camera_shutter_speed\": \"Shutter speed of the images, in µs\",\n \"acq_software\": \"Software version number\",\n \t\t\"object_date\": \"Sample collection date (or beginning if using a net)\",\n \t\t\"object_time\": \"Sample collection time (or beginning if using a net)\",\n \t\t\"object_lat\": \"Sample collection latitude (or beginning if using a net)\",\n \t\t\"object_lon\": \"Sample collection longitude (or beginning if using a net)\",\n \t\t\"object_depth_min\": \"Sample collection minimal depth, in m\",\n \t\t\"object_depth_max\": \"Sample collection maximum depth, in m\",\n \t\t\"process_pixel\": \"Pixel imaging resolution, in µm/pixel\",\n \t\t\"process_datetime\": \"Segmentation timestamp\",\n \t\t\"process_id\": \"Segmentation ID\",\n \t\t\"process_uuid\": \"Segmentation UUID (Autogenerated)\",\n \t\t\"process_source\": \"Code source link of the executed code\",\n \t\t\"process_commit\": \"Version reference of the executed code\",\n \t\t\"sample_gear_net_opening\": \"Sample mouth opening dimension, in mm\",\n \t\t\"object_date_end\": \"Sample end collection date when using a net\",\n \t\t\"object_time_end\": \"Sample end collection time when using a net\",\n \t\t\"object_lat_end\": \"Sample end collection latitude when using a net\",\n \t\t\"object_lon_end\": \"Sample end collection longitude when using a net\",\n \t},\n\t\t\"sample_project\": global.get(\"sample_project\"),\n\t\t\"sample_id\": global.get(\"sample_project\") + \"_\" + global.get(\"sample_id\"),\n\t\t\"sample_ship\": global.get(\"sample_ship\"),\n\t\t\"sample_operator\": global.get(\"sample_operator\"),\n\t\t\"sample_sampling_gear\": global.get(\"sample_sampling_gear\"),\n\t\t\"sample_concentrated_sample_volume\": global.get(\"sample_concentrated_sample_volume\"),\n\t\t\"sample_total_volume\": global.get(\"sample_total_volume\"),\n\t\t\"sample_dilution_factor\": global.get(\"sample_dilution_factor\"),\n\t\t\"sample_speed_through_water\": global.get(\"sample_speed_through_water\"),\n\n\t\t\"acq_id\": global.get(\"sample_project\") + \"_\" + global.get(\"sample_id\")+ \"_\" + global.get(\"acq_id\"),\n\t\t\"acq_instrument\": global.get(\"acq_instrument\"),\n\t\t\"acq_instrument_id\": global.get(\"acq_instrument_id\"),\n\t\t\"acq_celltype\": global.get(\"acq_celltype\"),\n\t\t\"acq_minimum_mesh\": global.get(\"acq_minimum_mesh\"),\n\t\t\"acq_maximum_mesh\": global.get(\"acq_maximum_mesh\"),\n\t\t\"acq_min_esd\": global.get(\"acq_min_esd\"),\n\t\t\"acq_max_esd\": global.get(\"acq_max_esd\"),\n\t\t\"acq_volume\": global.get(\"acq_volume\"),\n\t\t\"acq_imaged_volume\": global.get(\"acq_imaged_volume\"),\n\t\t\"acq_magnification\": global.get(\"acq_magnification\"),\n\t\t\"acq_fnumber_objective\": global.get(\"acq_fnumber_objective\"),\n\t\t\"acq_camera\": global.get(\"acq_camera\"),\n\t\t\"acq_nb_frame\": global.get(\"nb_frame\"),\n\t\t\"acq_software\": global.get(\"acq_software\"),\n\n\t\t\"object_date\": global.get(\"object_date\"),\n\t\t\"object_time\": global.get(\"object_time\"),\n\t\t\"object_lat\": global.get(\"object_lat\"),\n\t\t\"object_lon\": global.get(\"object_lon\"),\n\t\t\"object_depth_min\": global.get(\"object_depth_min\"),\n\t\t\"object_depth_max\": global.get(\"object_depth_max\"),\n\n\t\t\"process_pixel\": global.get(\"process_pixel\"),\n\t\t\"process_source\": global.get(\"process_source\"),\n\t\t\"process_commit\": global.get(\"process_commit\")\n\t}\n};\n\nif (msg.payload.config.sample_sampling_gear.startsWith(\"net\")) {\n\tmsg.payload.config[\"sample_gear_net_opening\"] = global.get(\"sample_gear_net_opening\")\n\tmsg.payload.config[\"object_date_end\"] = global.get(\"object_date_end\")\n\tmsg.payload.config[\"object_time_end\"] = global.get(\"object_time_end\")\n\tmsg.payload.config[\"object_lat_end\"] = global.get(\"object_lat_end\")\n\tmsg.payload.config[\"object_lon_end\"] = global.get(\"object_lon_end\")\n}\n\nif ( msg.send == true){\n\treturn [msg, msg]\n}\nelse{\n\treturn [msg, null]\n}", + "outputs": 2, + "timeout": "", + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 910, + "y": 440, + "wires": [ + [ + "29be525e.0c87fe" + ], + [ + "c3e50240.82aa58" + ] + ] + }, + { + "id": "40c12463.a1f84c", + "type": "delay", + "z": "baa1e3d9.cb29d", + "name": "", + "pauseType": "delay", + "timeout": "1", + "timeoutUnits": "seconds", + "rate": "1", + "nbRateUnits": "1", + "rateUnits": "second", + "randomFirst": "1", + "randomLast": "5", + "randomUnits": "seconds", + "drop": false, + "outputs": 1, + "x": 940, + "y": 480, + "wires": [ + [ + "c3e50240.82aa58" + ] + ] + }, + { + "id": "4d1b02cb.83b51c", + "type": "ui_button", + "z": "baa1e3d9.cb29d", + "name": "", + "group": "4322c187.e73e5", + "order": 10, + "width": 5, + "height": 1, + "passthru": false, + "label": "Update config", + "tooltip": "", + "color": "", + "bgcolor": "", + "className": "", + "icon": "save", + "payload": "", + "payloadType": "str", + "topic": "imager/image", + "topicType": "str", + "x": 680, + "y": 440, + "wires": [ + [ + "52ea7d01.711034" + ] + ] + }, + { + "id": "5921d0d0.a3d568", + "type": "subflow:1c24ad9c.bebec2", + "z": "baa1e3d9.cb29d", + "name": "", + "env": [], + "x": 110, + "y": 220, + "wires": [ + [ + "f3658d30.b8448", + "de2c90cf.b73b08", + "4be09c97f86897d9", + "f573206abefa9518", + "f948151ab4031df4", + "5e3dec55.881074", + "d3ca8847.4d1ae" + ] + ] + }, + { + "id": "f3658d30.b8448", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "get acq_id", + "func": "msg.payload = msg.payload.acq_id;\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 330, + "y": 240, + "wires": [ + [ + "6b34c456.83178c" + ] + ] + }, + { + "id": "de2c90cf.b73b08", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "get acq_celltype", + "func": "msg.topic = 'acq_celltype';\nmsg.payload = msg.payload.acq_celltype;\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 340, + "y": 80, + "wires": [ + [ + "cc0ca68b.4263a8" + ] + ] + }, + { + "id": "5e3dec55.881074", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "get acq_minimum_mesh", + "func": "msg.payload = msg.payload.acq_minimum_mesh;\nreturn msg;", + "outputs": 1, + "noerr": 0, + "x": 370, + "y": 160, + "wires": [ + [ + "f59a2f0d.5e9af" + ] + ] + }, + { + "id": "d3ca8847.4d1ae", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "get acq_maximum_mesh", + "func": "msg.payload = msg.payload.acq_maximum_mesh;\nreturn msg;", + "outputs": 1, + "noerr": 0, + "x": 370, + "y": 200, + "wires": [ + [ + "6008a8bb.259f08" + ] + ] + }, + { + "id": "b402f719.55bc98", + "type": "inject", + "z": "baa1e3d9.cb29d", + "name": "Default: FORWARD", + "props": [ + { + "p": "payload" + }, + { + "p": "topic", + "vt": "str" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "pump_direction", + "payload": "FORWARD", + "payloadType": "str", "x": 220, + "y": 560, + "wires": [ + [ + "bb62da8a.ebc328" + ] + ] + }, + { + "id": "6b2239f3.41fa3", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "set global", + "func": "global.set(msg.topic, msg.payload);", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 660, + "y": 560, + "wires": [ + [] + ] + }, + { + "id": "51b4d0df.d70a88", + "type": "ui_text_input", + "z": "baa1e3d9.cb29d", + "name": "nb_frame", + "label": "Number of images to acquire", + "tooltip": "", + "group": "4322c187.e73e5", + "order": 2, + "width": 5, + "height": 1, + "passthru": true, + "mode": "number", + "delay": 300, + "topic": "nb_frame", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 680, + "y": 280, + "wires": [ + [ + "fb887036.12429", + "67091ac0.8f9f6c", + "99b11fe4.2795d" + ] + ] + }, + { + "id": "999065ca.27edb8", + "type": "switch", + "z": "baa1e3d9.cb29d", + "name": "topic filter", + "property": "topic", + "propertyType": "msg", + "rules": [ + { + "t": "eq", + "v": "status/pump", + "vt": "str" + }, + { + "t": "eq", + "v": "status/focus", + "vt": "str" + }, + { + "t": "eq", + "v": "status/imager", + "vt": "str" + } + ], + "checkall": "true", + "repair": false, + "outputs": 3, + "x": 320, + "y": 800, + "wires": [ + [ + "a46a1e7f.88a92", + "6742014e.1bb238" + ], + [ + "c516d9ea.f7f6e", + "6742014e.1bb238" + ], + [ + "307c851e.fb0f7a", + "2b9d6988.d84836" + ] + ] + }, + { + "id": "2b009bd7.c07004", + "type": "ui_text", + "z": "baa1e3d9.cb29d", + "group": "70de8209.68416c", + "order": 3, + "width": 10, + "height": 2, + "name": "imager", + "label": "Imager status:", + "format": "{{msg.payload.status}}", + "layout": "col-center", + "x": 770, + "y": 740, + "wires": [] + }, + { + "id": "c516d9ea.f7f6e", + "type": "ui_text", + "z": "baa1e3d9.cb29d", + "group": "70de8209.68416c", + "order": 1, + "width": 5, + "height": 1, + "name": "focus", + "label": "Focus status:", + "format": "{{msg.payload.status}}", + "layout": "col-center", + "x": 770, + "y": 700, + "wires": [] + }, + { + "id": "a46a1e7f.88a92", + "type": "ui_text", + "z": "baa1e3d9.cb29d", + "group": "70de8209.68416c", + "order": 2, + "width": 5, + "height": 1, + "name": "pump", + "label": "Pump status:", + "format": "{{msg.payload.status}}", + "layout": "col-center", + "x": 770, + "y": 660, + "wires": [] + }, + { + "id": "bb628f8d.98f108", + "type": "link in", + "z": "baa1e3d9.cb29d", + "name": "Status for fluidic module", + "links": [ + "58f2e0f.4e8b12" + ], + "x": 175, + "y": 800, + "wires": [ + [ + "999065ca.27edb8" + ] + ] + }, + { + "id": "307c851e.fb0f7a", + "type": "switch", + "z": "baa1e3d9.cb29d", + "name": "Imaging state", + "property": "payload", + "propertyType": "msg", + "rules": [ + { + "t": "jsonata_exp", + "v": "$contains(msg.payload.status, \"jpg\")\t", + "vt": "jsonata" + }, + { + "t": "else" + } + ], + "checkall": "false", + "repair": false, + "outputs": 2, + "x": 540, + "y": 880, + "wires": [ + [ + "db8e3dde.44efb8" + ], + [ + "6742014e.1bb238" + ] + ] + }, + { + "id": "db8e3dde.44efb8", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "img_counter", + "func": "img_counter=flow.get('img_counter')\nif (img_counter === undefined || img_counter === \"\"){\n img_counter = 0\n}\nimg_counter=img_counter+1\nflow.set('img_counter',img_counter)\nmsg.payload = img_counter\nmsg.payload = (100 * img_counter/global.get('nb_frame')).toFixed(2)\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 770, + "y": 860, + "wires": [ + [ + "1a2e721a.f5e876" + ] + ] + }, + { + "id": "59164d65.e7993c", + "type": "ui_toast", + "z": "baa1e3d9.cb29d", + "position": "top right", + "displayTime": "5", + "highlight": "", + "sendall": true, + "outputs": 0, + "ok": "OK", + "cancel": "", + "raw": false, + "topic": "", + "name": "", + "x": 1260, + "y": 900, + "wires": [] + }, + { + "id": "8c7348aa.1962e8", + "type": "template", + "z": "baa1e3d9.cb29d", + "name": "Create sentence", + "field": "payload", + "fieldType": "msg", + "format": "handlebars", + "syntax": "mustache", + "template": "The {{topic}} is {{payload.status}}", + "output": "str", + "x": 1050, + "y": 900, + "wires": [ + [ + "59164d65.e7993c" + ] + ] + }, + { + "id": "6742014e.1bb238", + "type": "change", + "z": "baa1e3d9.cb29d", + "name": "Remove high-level topic", + "rules": [ + { + "t": "change", + "p": "topic", + "pt": "msg", + "from": "status/", + "fromt": "str", + "to": "", + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 810, + "y": 900, + "wires": [ + [ + "8c7348aa.1962e8" + ] + ] + }, + { + "id": "1a2e721a.f5e876", + "type": "ui_gauge", + "z": "baa1e3d9.cb29d", + "name": "progress donut", + "group": "b5d61bc7.54fe48", + "order": 3, + "width": 6, + "height": 3, + "gtype": "donut", + "title": "", + "label": "%", + "format": "{{value}}", + "min": 0, + "max": "100", + "colors": [ + "#ffa83f", + "#e6ff02", + "#00dfe9" + ], + "seg1": "50", + "seg2": "75", + "x": 1260, + "y": 860, + "wires": [] + }, + { + "id": "9bd72495.a8a098", + "type": "ui_text", + "z": "baa1e3d9.cb29d", + "group": "4322c187.e73e5", + "order": 5, + "width": 5, + "height": 1, + "name": "Total imaged volume", + "label": "Total imaged volume", + "format": "{{msg.payload}}", + "layout": "col-center", + "x": 1200, + "y": 140, + "wires": [] + }, + { + "id": "99b11fe4.2795d", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "imaged volume calc", + "func": "camera = global.get(\"acq_camera\");\ncell = global.get(\"acq_celltype\");\nnb_frame = global.get(\"nb_frame\");\nprocess_pixel = global.get(\"process_pixel\");\n\nvar volume = 0\nif (camera == \"HQ Camera\"){\n volume = nb_frame * (process_pixel*4056*process_pixel*3040*cell/1000000000) / 1000;\n}\nelse if (camera == \"Camera v2.1\"){\n volume = nb_frame * (process_pixel*3280*process_pixel*2464*cell/1000000000) / 1000;\n}\nelse{\n msg.payload = \"The camera is not known to this system\";\n return msg;\n}\n\nglobal.set(\"acq_imaged_volume\", volume.toFixed(4))\n\nmsg.payload = volume.toFixed(2) + \" mL\"\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 960, + "y": 140, + "wires": [ + [ + "9bd72495.a8a098" + ] + ], + "info": "### Focusing\n##### focus.py `nb_step` `orientation`\n\n- `nb_step` : **integer** (from 1 to 100000) - number of step to perform by the stage (about 31um/step)\n- `orientation` : **string** - orientation of the focus either `up` or `down`\n\nExample:\n\n python3.7 $HOME/PlanktoScope/scripts/focus.py 650 up\n" + }, + { + "id": "8e16aa2f.e40398", + "type": "ui_text", + "z": "baa1e3d9.cb29d", + "group": "4322c187.e73e5", + "order": 7, + "width": 5, + "height": 1, + "name": "Total pumped volume", + "label": "Total pumped volume", + "format": "{{msg.payload}} mL", + "layout": "col-center", + "x": 1200, + "y": 300, + "wires": [] + }, + { + "id": "67091ac0.8f9f6c", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "acq_volume calc", + "func": "var imaging_pump_volume = global.get(\"imaging_pump_volume\");\nvar nb_frame = global.get(\"nb_frame\");\nvar acq_volume = 0\n\nacq_volume = (Number(nb_frame)*Number(imaging_pump_volume)).toFixed(2)\nglobal.set(\"acq_volume\", acq_volume)\n\nmsg.payload = acq_volume\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 950, + "y": 300, + "wires": [ + [ + "8e16aa2f.e40398" + ] + ], + "info": "### Focusing\n##### focus.py `nb_step` `orientation`\n\n- `nb_step` : **integer** (from 1 to 100000) - number of step to perform by the stage (about 31um/step)\n- `orientation` : **string** - orientation of the focus either `up` or `down`\n\nExample:\n\n python3.7 $HOME/PlanktoScope/scripts/focus.py 650 up\n" + }, + { + "id": "2b9d6988.d84836", + "type": "switch", + "z": "baa1e3d9.cb29d", + "name": "", + "property": "payload", + "propertyType": "msg", + "rules": [ + { + "t": "hask", + "v": "status", + "vt": "str" + }, + { + "t": "hask", + "v": "camera_name", + "vt": "str" + } + ], + "checkall": "true", + "repair": false, + "outputs": 2, + "x": 650, + "y": 760, + "wires": [ + [ + "2b009bd7.c07004" + ], + [ + "3bbb756a.84190a" + ] + ] + }, + { + "id": "3bbb756a.84190a", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "set camera name", + "func": "global.set(\"acq_camera\", msg.payload.camera_name);\n\nmsg.payload = msg.payload.camera_name;\n\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 810, + "y": 780, + "wires": [ + [ + "559a8085.1d6b9" + ] + ] + }, + { + "id": "559a8085.1d6b9", + "type": "link out", + "z": "baa1e3d9.cb29d", + "name": "Camera Name", + "links": [ + "30067f35.532f2", + "572a6daa.6004c4" + ], + "x": 965, + "y": 780, + "wires": [] + }, + { + "id": "49ea1123.ee1768", + "type": "ui_numeric", + "z": "baa1e3d9.cb29d", + "name": "sleep_before", + "label": "Delay to stabilize image (s)", + "tooltip": "Happens before every capture", + "group": "4322c187.e73e5", + "order": 4, + "width": 5, + "height": 1, + "wrap": false, + "passthru": true, + "topic": "sleep_before", + "topicType": "str", + "format": "{{value}}", + "min": "0.1", + "max": "5", + "step": "0.1", + "className": "", + "x": 670, + "y": 120, + "wires": [ + [ + "fb887036.12429" + ] + ] + }, + { + "id": "572a6daa.6004c4", + "type": "link in", + "z": "baa1e3d9.cb29d", + "name": "", + "links": [ + "559a8085.1d6b9" + ], + "x": 795, + "y": 140, + "wires": [ + [ + "99b11fe4.2795d" + ] + ] + }, + { + "id": "8032ea50.1b57f", + "type": "ui_template", + "z": "baa1e3d9.cb29d", + "group": "b5d61bc7.54fe48", + "name": "progress header", + "order": 1, + "width": 0, + "height": 0, + "format": "

Capture progress

", + "storeOutMessages": false, + "fwdInMessages": false, + "resendOnRefresh": false, + "templateScope": "local", + "x": 1260, + "y": 820, + "wires": [ + [] + ] + }, + { + "id": "a4abb1ae.2ae418", + "type": "subflow:1c24ad9c.bebec2", + "z": "baa1e3d9.cb29d", + "name": "", + "env": [], + "x": 930, + "y": 520, + "wires": [ + [] + ] + }, + { + "id": "4be09c97f86897d9", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "get nb_frame", + "func": "msg.payload = msg.payload.nb_frame;\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 330, + "y": 280, + "wires": [ + [ + "51b4d0df.d70a88" + ] + ] + }, + { + "id": "f573206abefa9518", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "get imaging_pump_volume", + "func": "msg.payload = msg.payload.imaging_pump_volume;\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 380, + "y": 320, + "wires": [ + [ + "e1acc6c599033114" + ] + ] + }, + { + "id": "f948151ab4031df4", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "get sleep_before", + "func": "msg.payload = msg.payload.sleep_before;\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 340, + "y": 120, + "wires": [ + [ + "49ea1123.ee1768" + ] + ] + }, + { + "id": "ad153212312f0347", + "type": "ui_ui_control", + "z": "baa1e3d9.cb29d", + "name": "onTab", + "events": "all", + "x": 330, + "y": 380, + "wires": [ + [ + "9b69ea945b587192" + ] + ] + }, + { + "id": "9b69ea945b587192", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "check tab", + "func": "if (msg.name == \"Fluidic Acquisition\"){\n return { \"topic\": \"imager/ image\" }\n}", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 480, + "y": 380, + "wires": [ + [ + "52ea7d01.711034" + ] + ], + "outputLabels": [ + "interface" + ] + }, + { + "id": "e1acc6c599033114", + "type": "ui_text_input", + "z": "baa1e3d9.cb29d", + "name": "imaging_pump_volume", + "label": "Pumped volume (mL)", + "tooltip": "between frames", + "group": "4322c187.e73e5", + "order": 3, + "width": 0, + "height": 0, + "passthru": true, + "mode": "text", + "delay": 300, + "topic": "imaging_pump_volume", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 630, + "y": 320, + "wires": [ + [ + "fb887036.12429", + "67091ac0.8f9f6c" + ] + ] + }, + { + "id": "f4caa15e2bbfd6e7", + "type": "ui_template", + "z": "baa1e3d9.cb29d", + "group": "4322c187.e73e5", + "name": "Start Acquisition", + "order": 13, + "width": "5", + "height": "1", + "format": "\n\n", + "storeOutMessages": false, + "fwdInMessages": false, + "resendOnRefresh": false, + "templateScope": "local", + "className": "", + "x": 460, + "y": 480, + "wires": [ + [ + "c9f510c0.7d1328" + ] + ] + }, + { + "id": "9d6abe67.6bb3d", + "type": "ui_button", + "z": "cb95299c.2817c8", + "name": "", + "group": "64903b47.4034e4", + "order": 1, + "width": 0, + "height": 0, + "passthru": false, + "label": "Home", + "tooltip": "", + "color": "", + "bgcolor": "", + "icon": "home", + "payload": "{\"tab\":\"Home\"}", + "payloadType": "json", + "topic": "", + "x": 430, + "y": 600, + "wires": [ + [ + "f0fb77cf.8f1c28" + ] + ] + }, + { + "id": "f0fb77cf.8f1c28", + "type": "ui_ui_control", + "z": "cb95299c.2817c8", + "name": "", + "events": "change", + "x": 740, + "y": 600, + "wires": [ + [] + ] + }, + { + "id": "8ec68b82.17e3d8", + "type": "ui_button", + "z": "cb95299c.2817c8", + "name": "Start segmentation", + "group": "abeb6dad.635a2", + "order": 10, + "width": 5, + "height": 1, + "passthru": false, + "label": "Start segmentation", + "tooltip": "", + "color": "", + "bgcolor": "", + "icon": "", + "payload": "{\"action\":\"segment\"}", + "payloadType": "json", + "topic": "segmenter/segment", + "x": 370, + "y": 460, + "wires": [ + [ + "33c28dc1.238002", + "c72a1064.1ec388" + ] + ] + }, + { + "id": "27be7971.b3fbce", + "type": "ui_button", + "z": "cb95299c.2817c8", + "d": true, + "name": "Stop segmentation", + "group": "abeb6dad.635a2", + "order": 12, + "width": 4, + "height": 1, + "passthru": true, + "label": "Stop segmentation", + "tooltip": "", + "color": "", + "bgcolor": "#AD1625", + "icon": "", + "payload": "{\"action\":\"stop\"}", + "payloadType": "json", + "topic": "segmenter/segment", + "x": 370, + "y": 520, + "wires": [ + [ + "16f3cef4.0acac9" + ] + ] + }, + { + "id": "16f3cef4.0acac9", + "type": "mqtt out", + "z": "cb95299c.2817c8", + "name": "", + "topic": "", + "qos": "", + "retain": "", + "broker": "8dc3722c.06efa8", + "x": 850, + "y": 520, + "wires": [] + }, + { + "id": "8f3788f6.ddcf98", + "type": "function", + "z": "cb95299c.2817c8", + "name": "obj_counter", + "func": "obj_counter = flow.get('obj_counter')\nobj_counter = obj_counter + 1\nflow.set('obj_counter', obj_counter)\nmsg.payload = obj_counter\nmsg.topic = \"object count\"\nreturn msg", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 810, + "y": 800, + "wires": [ + [ + "fa3b7929.ac7da8", + "9d53dbe2.dbffe8" + ] + ] + }, + { + "id": "aa38dbbc.cf0a9", + "type": "switch", + "z": "cb95299c.2817c8", + "name": "Segmenter", + "property": "topic", + "propertyType": "msg", + "rules": [ + { + "t": "eq", + "v": "status/segmenter", + "vt": "str" + }, + { + "t": "eq", + "v": "status/segmenter/name", + "vt": "str" + }, + { + "t": "eq", + "v": "status/segmenter/object_id", + "vt": "str" + }, + { + "t": "eq", + "v": "status/segmenter/metric", + "vt": "str" + } + ], + "checkall": "true", + "repair": false, + "outputs": 4, + "x": 490, + "y": 740, + "wires": [ + [ + "b9a23b91.93638", + "6919465f.332e5" + ], + [ + "49af3d24.1799e4" + ], + [ + "8f3788f6.ddcf98" + ], + [] + ] + }, + { + "id": "9d53dbe2.dbffe8", + "type": "ui_chart", + "z": "cb95299c.2817c8", + "name": "counter graph", + "group": "46be9c86.dea684", + "order": 7, + "width": 10, + "height": 2, + "label": "", + "chartType": "horizontalBar", + "legend": "false", + "xformat": "HH:mm:ss", + "interpolate": "linear", + "nodata": "Objects count will be shown here once the segmentation is started", + "dot": false, + "ymin": "", + "ymax": "", + "removeOlder": 1, + "removeOlderPoints": "", + "removeOlderUnit": "3600", + "cutout": 0, + "useOneColor": true, + "useUTC": false, + "colors": [ + "#1f77b4", + "#aec7e8", + "#ff7f0e", + "#2ca02c", + "#98df8a", + "#d62728", + "#ff9896", + "#9467bd", + "#c5b0d5" + ], + "outputs": 1, + "x": 1340, + "y": 840, + "wires": [ + [] + ] + }, + { + "id": "a4f0f0d1.3aca88", + "type": "ui_toast", + "z": "cb95299c.2817c8", + "position": "top right", + "displayTime": "5", + "highlight": "", + "sendall": true, + "outputs": 0, + "ok": "OK", + "cancel": "", + "raw": false, + "topic": "", + "name": "", + "x": 1340, + "y": 680, + "wires": [] + }, + { + "id": "49af3d24.1799e4", + "type": "debug", + "z": "cb95299c.2817c8", + "name": "segmentation name", + "active": true, + "tosidebar": true, + "console": false, + "tostatus": false, + "complete": "true", + "targetType": "full", + "statusVal": "", + "statusType": "auto", + "x": 830, + "y": 760, + "wires": [] + }, + { + "id": "7088a5be.0c79a4", + "type": "template", + "z": "cb95299c.2817c8", + "name": "Create sentence", + "field": "payload", + "fieldType": "msg", + "format": "handlebars", + "syntax": "mustache", + "template": "The {{topic}} is {{payload.status}}", + "output": "str", + "x": 1100, + "y": 680, + "wires": [ + [ + "a4f0f0d1.3aca88" + ] + ] + }, + { + "id": "b9a23b91.93638", + "type": "change", + "z": "cb95299c.2817c8", + "name": "Remove high-level topic", + "rules": [ + { + "t": "change", + "p": "topic", + "pt": "msg", + "from": "status/", + "fromt": "str", + "to": "", + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 850, + "y": 680, + "wires": [ + [ + "7088a5be.0c79a4" + ] + ] + }, + { + "id": "6919465f.332e5", + "type": "ui_text", + "z": "cb95299c.2817c8", + "group": "46be9c86.dea684", + "order": 1, + "width": 10, + "height": 1, + "name": "segmenter", + "label": "Segmenter status:", + "format": "{{msg.payload.status}}", + "layout": "row-spread", + "x": 810, + "y": 720, + "wires": [] + }, + { + "id": "fa3b7929.ac7da8", + "type": "ui_text", + "z": "cb95299c.2817c8", + "group": "46be9c86.dea684", + "order": 5, + "width": 4, + "height": 1, + "name": "counter", + "label": "", + "format": "{{msg.payload}}", + "layout": "col-center", + "x": 1320, + "y": 800, + "wires": [] + }, + { + "id": "640ece83.88cab", + "type": "inject", + "z": "cb95299c.2817c8", + "name": "Init graphs", + "props": [ + { + "p": "payload" + }, + { + "p": "topic", + "vt": "str" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "object count", + "payload": "0", + "payloadType": "num", + "x": 810, + "y": 880, + "wires": [ + [ + "4f3f7c4a.cb21c4" + ] + ] + }, + { + "id": "25867454.a8e334", + "type": "link in", + "z": "cb95299c.2817c8", + "name": "Segmenter module status", + "links": [ + "dcf5bd45.16a8d" + ], + "x": 295, + "y": 740, + "wires": [ + [ + "aa38dbbc.cf0a9" + ] + ] + }, + { + "id": "c8749cbb.55254", + "type": "function", + "z": "cb95299c.2817c8", + "name": "set global", + "func": "global.set(msg.topic, msg.payload);", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 960, + "y": 380, + "wires": [ + [] + ] + }, + { + "id": "d43c3ed9.e6cb1", + "type": "ui_template", + "z": "cb95299c.2817c8", + "group": "46be9c86.dea684", + "name": "Object counts", + "order": 3, + "width": 0, + "height": 0, + "format": "

Object counts

", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": true, + "templateScope": "local", + "className": "", + "x": 1340, + "y": 760, + "wires": [ + [] + ] + }, + { + "id": "33c28dc1.238002", + "type": "function", + "z": "cb95299c.2817c8", + "name": "prepare segmentation", + "func": "global.set('obj_counter', 0);\n\nvar segmentation_list = flow.get('segmentation_list')\nif (segmentation_list !== undefined && segmentation_list !== \"\") {\n msg.payload['path'] = segmentation_list\n}\n\n\nvar force = flow.get('force')\nif (force !== undefined && force !== \"\") {\n msg.payload['settings'] = {\"force\":Boolean(force)}\n}\n\n\nvar recursive = flow.get('recursive')\nif (recursive !== undefined && recursive !== \"\") {\n if (\"settings\" in msg.payload){\n msg.payload.settings[\"recursive\"] = Boolean(recursive)\n }\n else{\n msg.payload['settings'] = {\"recursive\": Boolean(recursive)}\n }\n}\n\nvar ecotaxa = flow.get('ecotaxa')\nif (ecotaxa !== undefined && ecotaxa !== \"\") {\n if (\"settings\" in msg.payload){\n msg.payload.settings[\"ecotaxa\"] = Boolean(ecotaxa)\n }\n else{\n msg.payload['settings'] = {\"ecotaxa\": Boolean(ecotaxa)}\n }\n}\n\nvar keep = flow.get('keep')\nif (keep !== undefined && keep !== \"\") {\n if (\"settings\" in msg.payload){\n msg.payload.settings[\"keep\"] = Boolean(keep)\n }\n else{\n msg.payload['settings'] = {\"keep\": Boolean(keep)}\n }\n}\n\nvar process_id = global.get('process_id')\nif (process_id !== undefined && process_id !== \"\") {\n if (\"settings\" in msg.payload){\n msg.payload.settings[\"process_id\"] = process_id\n }\n else{\n msg.payload['settings'] = {\"process_id\": process_id}\n }\n}\n\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 620, + "y": 460, + "wires": [ + [ + "16f3cef4.0acac9" + ] + ] + }, + { + "id": "fa12f9f8.00cfa8", + "type": "subflow:1c24ad9c.bebec2", + "z": "cb95299c.2817c8", + "name": "", + "env": [], + "x": 430, + "y": 380, + "wires": [ + [ + "3b72d11c.86e9e6" + ] + ] + }, + { + "id": "3b72d11c.86e9e6", + "type": "function", + "z": "cb95299c.2817c8", + "name": "get process_id", + "func": "msg.payload = msg.payload.process_id;\nmsg.topic = \"process_id\";\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 600, + "y": 380, + "wires": [ + [ + "56971109c8be3b54" + ] + ] + }, + { + "id": "3ea12061.ce62c", + "type": "ui_list", + "z": "cb95299c.2817c8", + "group": "abeb6dad.635a2", + "name": "", + "order": 9, + "width": 10, + "height": 11, + "lineType": "one", + "actionType": "check", + "allowHTML": false, + "outputs": 1, + "topic": "", + "x": 790, + "y": 140, + "wires": [ + [ + "cb3b87b5.63c4" + ] + ] + }, + { + "id": "8bd8fb2c.53fa4", + "type": "dir2files", + "z": "cb95299c.2817c8", + "name": "", + "dirname": "/home/pi/data/img/", + "pathRegex": "", + "isRecursive": true, + "findDir": true, + "isArray": true, + "x": 460, + "y": 140, + "wires": [ + [ + "ba2947.c854deb8" + ] + ] + }, + { + "id": "127d4ee.f8ad1b1", + "type": "ui_button", + "z": "cb95299c.2817c8", + "name": "Refresh", + "group": "abeb6dad.635a2", + "order": 8, + "width": 0, + "height": 0, + "passthru": false, + "label": "Update acquisition's folder list", + "tooltip": "Refresh the list of previous acquisitions", + "color": "", + "bgcolor": "", + "icon": "mi-find_replace", + "payload": "", + "payloadType": "date", + "topic": "update", + "x": 260, + "y": 140, + "wires": [ + [ + "8bd8fb2c.53fa4", + "56f845f5.e7c054" + ] + ] + }, + { + "id": "946ce9ee.092cf", + "type": "inject", + "z": "cb95299c.2817c8", + "name": "Init", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "payload": "", + "payloadType": "date", + "x": 270, + "y": 100, + "wires": [ + [ + "8bd8fb2c.53fa4", + "56f845f5.e7c054" + ] + ] + }, + { + "id": "cb3b87b5.63c4", + "type": "function", + "z": "cb95299c.2817c8", + "name": "update segmentation_list", + "func": "var segmentation_list = flow.get('segmentation_list');\n\nif (segmentation_list === undefined || segmentation_list === \"\") {\n segmentation_list = []\n console.log(\"error\")\n}\n\npath = \"/home/pi/data/img/\" + msg.payload.title\n\nif (msg.payload.isChecked){\n if (segmentation_list.includes(path) === false){\n segmentation_list.push(path)\n }\n // Element already in list, don't push it more than once\n //segmentation_list.push(msg.payload[\"title\"])\n}\nelse {\n var pos = segmentation_list.indexOf(path)\n segmentation_list.splice(pos, 1)\n}\n\nflow.set('segmentation_list', segmentation_list)", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 990, + "y": 140, + "wires": [ + [] + ] + }, + { + "id": "56f845f5.e7c054", + "type": "change", + "z": "cb95299c.2817c8", + "name": "Reset segmentation_list", + "rules": [ + { + "t": "set", + "p": "segmentation_list", + "pt": "flow", + "to": "[]", + "tot": "json" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 510, + "y": 100, + "wires": [ + [] + ] + }, + { + "id": "7fc72364.8f038c", + "type": "ui_template", + "z": "cb95299c.2817c8", + "group": "abeb6dad.635a2", + "name": "Update message", + "order": 1, + "width": 10, + "height": 3, + "format": "
You can choose here in which folder(s) you want the segmentation script to run. A few details though:\n
The segmentation is run recursively in all folders. So if you select a top level folder, the segmentation will be run in all subfolders.\n
Also, you will be able to chose wether for force the segmentation for folders in which it has run already.
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": true, + "templateScope": "local", + "x": 270, + "y": 40, + "wires": [ + [] + ] + }, + { + "id": "ba2947.c854deb8", + "type": "function", + "z": "cb95299c.2817c8", + "name": "remove common", + "func": "function remove_path(item, index, array) {\n array[index] = item.replace(\"/home/pi/data/img/\", \"\")\n} \n\nmsg.payload.forEach(remove_path)\n\nreturn msg", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 630, + "y": 140, + "wires": [ + [ + "3ea12061.ce62c" + ] + ] + }, + { + "id": "21af0db1.c2c182", + "type": "ui_multistate_switch", + "z": "cb95299c.2817c8", + "name": "recursive toggle", + "group": "abeb6dad.635a2", + "order": 4, + "width": 5, + "height": 1, + "label": "Recursive folder", + "stateField": "payload", + "enableField": "enable", + "rounded": true, + "useThemeColors": true, + "hideSelectedLabel": false, + "options": [ + { + "label": "No", + "value": "0", + "valueType": "num", + "color": "#009933" + }, + { + "label": "Yes", + "value": "1", + "valueType": "num", + "color": "#999999" + } + ], + "x": 480, + "y": 220, + "wires": [ + [ + "880b192a.88e2d" + ] + ] + }, + { + "id": "dffb9881.feef8", + "type": "ui_multistate_switch", + "z": "cb95299c.2817c8", + "name": "force toggle", + "group": "abeb6dad.635a2", + "order": 3, + "width": 5, + "height": 1, + "label": "Force rework", + "stateField": "payload", + "enableField": "enable", + "rounded": true, + "useThemeColors": true, + "hideSelectedLabel": false, + "options": [ + { + "label": "No", + "value": "0", + "valueType": "num", + "color": "#009933" + }, + { + "label": "Yes", + "value": "1", + "valueType": "num", + "color": "#999999" + } + ], + "x": 470, + "y": 300, + "wires": [ + [ + "a4f68fa6.5d77f8" + ] + ] + }, + { + "id": "880b192a.88e2d", + "type": "change", + "z": "cb95299c.2817c8", + "name": "", + "rules": [ + { + "t": "set", + "p": "recursive", + "pt": "flow", + "to": "payload", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 690, + "y": 240, + "wires": [ + [] + ] + }, + { + "id": "a4f68fa6.5d77f8", + "type": "change", + "z": "cb95299c.2817c8", + "name": "", + "rules": [ + { + "t": "set", + "p": "force", + "pt": "flow", + "to": "payload", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 670, + "y": 280, + "wires": [ + [] + ] + }, + { + "id": "1ef1b43b.b0f064", + "type": "inject", + "z": "cb95299c.2817c8", + "name": "0", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "payload": "0", + "payloadType": "num", + "x": 270, + "y": 280, + "wires": [ + [ + "dffb9881.feef8", + "a4f68fa6.5d77f8" + ] + ] + }, + { + "id": "f078c068.eacf58", + "type": "ui_template", + "z": "cb95299c.2817c8", + "group": "46be9c86.dea684", + "name": "Stream Segmented object", + "order": 2, + "width": 10, + "height": 8, + "format": "
\n Latest object segmented:
\n \"If\n
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "className": "", + "x": 1370, + "y": 600, + "wires": [ + [] + ] + }, + { + "id": "43f97b93.b76294", + "type": "inject", + "z": "cb95299c.2817c8", + "name": "1", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "payload": "1", + "payloadType": "num", + "x": 270, + "y": 240, + "wires": [ + [ + "21af0db1.c2c182", + "880b192a.88e2d" + ] + ] + }, + { + "id": "4f3f7c4a.cb21c4", + "type": "change", + "z": "cb95299c.2817c8", + "name": "", + "rules": [ + { + "t": "set", + "p": "obj_counter", + "pt": "flow", + "to": "0", + "tot": "num" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 1010, + "y": 840, + "wires": [ + [ + "fa3b7929.ac7da8", + "9d53dbe2.dbffe8" + ] + ] + }, + { + "id": "6bce0f60.f48998", + "type": "link in", + "z": "cb95299c.2817c8", + "name": "", + "links": [ + "596fc9d4.46c75" + ], + "x": 855, + "y": 840, + "wires": [ + [ + "4f3f7c4a.cb21c4" + ] + ] + }, + { + "id": "596fc9d4.46c75", + "type": "link out", + "z": "cb95299c.2817c8", + "name": "", + "links": [ + "6bce0f60.f48998" + ], + "x": 715, + "y": 500, + "wires": [] + }, + { + "id": "c72a1064.1ec388", + "type": "change", + "z": "cb95299c.2817c8", + "name": "Reset counters", + "rules": [ + { + "t": "set", + "p": "topic", + "pt": "msg", + "to": "object count", + "tot": "str" + }, + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "0", + "tot": "num" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 600, + "y": 500, + "wires": [ + [ + "596fc9d4.46c75" + ] + ] + }, + { + "id": "9367534a.fb8568", + "type": "ui_multistate_switch", + "z": "cb95299c.2817c8", + "name": "Ecotaxa archive", + "group": "abeb6dad.635a2", + "order": 6, + "width": 5, + "height": 1, + "label": "Ecotaxa archive", + "stateField": "payload", + "enableField": "enable", + "rounded": true, + "useThemeColors": true, + "hideSelectedLabel": false, + "options": [ + { + "label": "No", + "value": "0", + "valueType": "num", + "color": "#009933" + }, + { + "label": "Yes", + "value": "1", + "valueType": "num", + "color": "#999999" + } + ], + "x": 1080, + "y": 220, + "wires": [ + [ + "25ac4f9a.5b05c8" + ] + ] + }, + { + "id": "25ac4f9a.5b05c8", + "type": "change", + "z": "cb95299c.2817c8", + "name": "", + "rules": [ + { + "t": "set", + "p": "ecotaxa", + "pt": "flow", + "to": "payload", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 1280, + "y": 240, + "wires": [ + [] + ] + }, + { + "id": "bef78886.8f0b98", + "type": "inject", + "z": "cb95299c.2817c8", + "name": "1", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "payload": "1", + "payloadType": "num", + "x": 910, + "y": 240, + "wires": [ + [ + "9367534a.fb8568", + "25ac4f9a.5b05c8" + ] + ] + }, + { + "id": "32465a4e.8fcac6", + "type": "ui_multistate_switch", + "z": "cb95299c.2817c8", + "name": "Keep objects", + "group": "abeb6dad.635a2", + "order": 5, + "width": 5, + "height": 1, + "label": "Keep objects", + "stateField": "payload", + "enableField": "enable", + "rounded": true, + "useThemeColors": true, + "hideSelectedLabel": false, + "options": [ + { + "label": "No", + "value": "0", + "valueType": "num", + "color": "#009933" + }, + { + "label": "Yes", + "value": "1", + "valueType": "num", + "color": "#999999" + } + ], + "x": 1070, + "y": 300, + "wires": [ + [ + "8dd6f57f.b77f98" + ] + ] + }, + { + "id": "8dd6f57f.b77f98", + "type": "change", + "z": "cb95299c.2817c8", + "name": "", + "rules": [ + { + "t": "set", + "p": "keep", + "pt": "flow", + "to": "payload", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 1270, + "y": 280, + "wires": [ + [] + ] + }, + { + "id": "8090df89.c029e", + "type": "inject", + "z": "cb95299c.2817c8", + "name": "1", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "payload": "1", + "payloadType": "num", + "x": 910, + "y": 280, + "wires": [ + [ + "32465a4e.8fcac6", + "8dd6f57f.b77f98" + ] + ] + }, + { + "id": "56971109c8be3b54", + "type": "ui_text_input", + "z": "cb95299c.2817c8", + "name": "process_id", + "label": "Process unique ID*", + "tooltip": "", + "group": "abeb6dad.635a2", + "order": 2, + "width": 10, + "height": 1, + "passthru": true, + "mode": "text", + "delay": 300, + "topic": "process_id", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 790, + "y": 380, + "wires": [ + [ + "c8749cbb.55254" + ] + ] + }, + { + "id": "2911fbc6.d28c24", + "type": "ui_template", + "z": "c1660bc.e7ff7f8", + "group": "c0ebfc57.42527", + "name": "Image browser", + "order": 1, + "width": "0", + "height": "0", + "format": "
\n\n
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "className": "", + "x": 400, + "y": 100, + "wires": [ + [] + ] + }, + { + "id": "4f02c726.de69b8", + "type": "ui_button", + "z": "9daf9e2b.019fc", + "name": "", + "group": "a7d64879.38298", + "order": 4, + "width": 6, + "height": 1, + "passthru": false, + "label": "Reboot", + "tooltip": "", + "color": "", + "bgcolor": "#AD1625", + "className": "", + "icon": "fa-repeat fa-2x", + "payload": "reboot", + "payloadType": "str", + "topic": "reboot", + "topicType": "str", + "x": 160, + "y": 240, + "wires": [ + [ + "4af9112d.87767" + ] + ] + }, + { + "id": "611a8b1c.a829b4", + "type": "exec", + "z": "9daf9e2b.019fc", + "command": "sudo", + "addpay": "payload", + "append": "now", + "useSpawn": "false", + "timer": "2", + "winHide": false, + "oldrc": false, + "name": "sudo cmd now", + "x": 480, + "y": 280, + "wires": [ + [], + [], + [] + ] + }, + { + "id": "bc76c4d6.a7ad28", + "type": "ui_button", + "z": "9daf9e2b.019fc", + "name": "", + "group": "a7d64879.38298", + "order": 5, + "width": 6, + "height": 1, + "passthru": false, + "label": "Shutdown", + "tooltip": "", + "color": "", + "bgcolor": "#AD1625", + "className": "", + "icon": "fa-power-off fa-2x", + "payload": "shutdown", + "payloadType": "str", + "topic": "shutdown", + "topicType": "str", + "x": 160, + "y": 320, + "wires": [ + [ + "4af9112d.87767" + ] + ] + }, + { + "id": "4af9112d.87767", + "type": "python3-function", + "z": "9daf9e2b.019fc", + "name": "action", + "func": "#!/usr/bin/python3\nimport smbus2 as smbus\n\nbus = smbus.SMBus(1)\n#turn off LED\nbus.write_byte_data(0x0d, 0x07, 0x00)\n#turn off Fan\nbus.write_byte_data(0x0d, 0x08, 0x00)\n\n#msg[\"payload\"] = str(msg[\"topic\"])+' now'\nreturn msg", + "outputs": 1, + "x": 330, + "y": 280, + "wires": [ + [ + "611a8b1c.a829b4" + ] + ] + }, + { + "id": "466eb611.4da048", + "type": "ui_button", + "z": "9daf9e2b.019fc", + "name": "", + "group": "a7d64879.38298", + "order": 2, + "width": 6, + "height": 1, + "passthru": true, + "label": "Restart Hardware Controller", + "tooltip": "", + "color": "", + "bgcolor": "#AD1625", + "className": "", + "icon": "fa-refresh fa-2x", + "payload": "Restarting hardware controller...", + "payloadType": "str", + "topic": "", + "topicType": "str", + "x": 460, + "y": 420, + "wires": [ + [ + "bd5cceef.b17ad", + "414353cde6a62346" + ] + ] + }, + { + "id": "bd5cceef.b17ad", + "type": "exec", + "z": "9daf9e2b.019fc", + "command": "sudo systemctl restart planktoscope-org.device-backend.controller.service", + "addpay": false, + "append": "", + "useSpawn": "false", + "timer": "", + "winHide": false, + "oldrc": false, + "name": "Restart hardware controller", + "x": 800, + "y": 420, + "wires": [ + [], + [], + [] + ] + }, + { + "id": "43cf8ff7.75231", + "type": "rpi-gpio out", + "z": "9daf9e2b.019fc", + "name": "Pump Enable", + "pin": "4", + "set": true, + "level": "1", + "freq": "", + "out": "out", + "bcm": true, + "x": 420, + "y": 80, + "wires": [] + }, + { + "id": "4bca8a25.15be3c", + "type": "rpi-gpio out", + "z": "9daf9e2b.019fc", + "name": "Focus Enable", + "pin": "12", + "set": true, + "level": "1", + "freq": "", + "out": "out", + "bcm": true, + "x": 420, + "y": 120, + "wires": [] + }, + { + "id": "50f9b5b.a84bccc", + "type": "inject", + "z": "9daf9e2b.019fc", + "name": "Default: ON", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": "0.01", + "topic": "", + "payload": "true", + "payloadType": "bool", + "x": 150, + "y": 100, + "wires": [ + [ + "43cf8ff7.75231", + "4bca8a25.15be3c", + "6db0fcf5.f0effc", + "5fc4ede4.72516c" + ] + ] + }, + { + "id": "45a7b5aa.2ed20c", + "type": "link in", + "z": "9daf9e2b.019fc", + "name": "Restart Hardware Controller", + "links": [ + "e41870d7.300eb8", + "e4ead350b3d07578" + ], + "x": 195, + "y": 420, + "wires": [ + [ + "466eb611.4da048" + ] + ] + }, + { + "id": "b81b990a.d4dca", + "type": "link in", + "z": "9daf9e2b.019fc", + "name": "Shutdown", + "links": [ + "e08cfcb8.2a67e8" + ], + "x": 195, + "y": 280, + "wires": [ + [ + "4af9112d.87767" + ] + ] + }, + { + "id": "5fc4ede4.72516c", + "type": "rpi-gpio out", + "z": "9daf9e2b.019fc", + "name": "HAT Pump Enable", + "pin": "23", + "set": true, + "level": "1", + "freq": "", + "out": "out", + "bcm": true, + "x": 430, + "y": 40, + "wires": [] + }, + { + "id": "6db0fcf5.f0effc", + "type": "rpi-gpio out", + "z": "9daf9e2b.019fc", + "name": "HAT Focus Enable", + "pin": "5", + "set": true, + "level": "1", + "freq": "", + "out": "out", + "bcm": true, + "x": 430, "y": 160, + "wires": [] + }, + { + "id": "38c05fcb891c82bf", + "type": "exec", + "z": "9daf9e2b.019fc", + "command": "docker restart apps_ps_backend_proc-segmenter-server-1", + "addpay": false, + "append": "", + "useSpawn": "false", + "timer": "", + "winHide": false, + "oldrc": false, + "name": "Restart segmenter", + "x": 770, + "y": 500, "wires": [ - { - "id": "3ad9835.08c937c" - } + [], + [], + [] ] - } - ], - "out": [ - { - "x": 1040, - "y": 60, + }, + { + "id": "631b8626185addfc", + "type": "ui_button", + "z": "9daf9e2b.019fc", + "name": "", + "group": "a7d64879.38298", + "order": 3, + "width": 6, + "height": 1, + "passthru": true, + "label": "Restart Segmenter", + "tooltip": "", + "color": "", + "bgcolor": "#AD1625", + "className": "", + "icon": "fa-refresh fa-2x", + "payload": "Restarting segmenter...", + "payloadType": "str", + "topic": "", + "topicType": "str", + "x": 430, + "y": 500, "wires": [ - { - "id": "ad541674.4791c8", - "port": 0 - } - ] - } - ], - "env": [], - "color": "#DDAA99" - }, - { - "id": "4ed26b8b.253504", - "type": "subflow", - "name": "Save hardware config", - "info": "", - "category": "", - "in": [ - { - "x": 40, + [ + "38c05fcb891c82bf", + "e036d07cf78fde85" + ] + ] + }, + { + "id": "cec5bd6f962f6903", + "type": "ui_template", + "z": "9daf9e2b.019fc", + "group": "a7d64879.38298", + "name": "Logs", + "order": 1, + "width": 0, + "height": 0, + "format": "

\n The PlanktoScope software application consists of three components: a Node-RED dashboard which provides the user interface you're using; a Hardware Controller\n which executes commands sent from the Node-RED dashboard for hardware control and image acquisition; and a Segmenter which processes an acquired dataset of\n images and isolates objects from those images. Each component has its own independent log of messages, managed separately from the logs for the other components.\n

\n

\n All three components have live-updating logs which you can monitor. Additionally, the Hardware Controller and the Segmenter also save all of their log messages\n to files which you can browse and download. Those software components create a new log file each time they start, and the name of the log file includes the time\n in the PlanktoScope's clock when the software component started. However, if your PlanktoScope's clock is usually wrong, it makes the log files difficult to navigate.\n This will be fixed in a future version of the software.\n

\n

\n If you need to share your logs with other people (e.g. on Slack or GitHub), you should open the \"Downloadable Logs\" links, and then you can select one file or multiple\n log files for downloading as a zip archive.\n

\n", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": true, + "templateScope": "local", + "className": "", + "x": 650, + "y": 180, + "wires": [ + [] + ] + }, + { + "id": "414353cde6a62346", + "type": "ui_toast", + "z": "9daf9e2b.019fc", + "position": "top right", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 0, + "ok": "OK", + "cancel": "", + "raw": false, + "className": "", + "topic": "", + "name": "", + "x": 770, + "y": 380, + "wires": [] + }, + { + "id": "e036d07cf78fde85", + "type": "ui_toast", + "z": "9daf9e2b.019fc", + "position": "top right", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 0, + "ok": "OK", + "cancel": "", + "raw": false, + "className": "", + "topic": "", + "name": "", + "x": 770, + "y": 460, + "wires": [] + }, + { + "id": "ddcbbfa5.cd158", + "type": "exec", + "z": "1371dec5.76e671", + "command": "vcgencmd measure_temp | tr -d \"temp=\" | tr -d \"'C\" | tr -d \"\\n\"", + "addpay": false, + "append": "", + "useSpawn": "", + "timer": "", + "name": "RPi Temp.", + "x": 330, "y": 40, "wires": [ - { - "id": "53d163be.47cf24" - } - ] - } - ], - "out": [], - "env": [], - "meta": {}, - "color": "#DDAA99" - }, - { - "id": "e6665421f66ea4c8", - "type": "subflow", - "name": "Load hardware config", - "info": "", - "category": "", - "in": [ - { - "x": 40, + [ + "bc503fa5.f46dd" + ], + [], + [] + ] + }, + { + "id": "3910d662.fa1f7a", + "type": "exec", + "z": "1371dec5.76e671", + "command": "df -h | grep /dev/root | awk -F ' ' '{print $5}' | tr -d % | tr \"\\n$\" \"\\ \" | sed 's/,/./' | tr -d \" \"", + "addpay": false, + "append": "", + "useSpawn": "", + "timer": "", + "name": "Disk Usage", + "x": 330, + "y": 120, + "wires": [ + [ + "eaf74a43.fa27d" + ], + [], + [] + ] + }, + { + "id": "1cd5b4c0.46af9b", + "type": "inject", + "z": "1371dec5.76e671", + "name": "update: 5s", + "props": [ + { + "p": "payload" + }, + { + "p": "topic", + "vt": "str" + } + ], + "repeat": "5", + "crontab": "", + "once": false, + "onceDelay": "", + "topic": "", + "payload": "", + "payloadType": "date", + "x": 110, + "y": 160, + "wires": [ + [ + "3910d662.fa1f7a", + "ddcbbfa5.cd158", + "23a84a3856fb68bd", + "4ed64bd91fa9fbdf", + "ed5f2d963d85478b" + ] + ] + }, + { + "id": "2549f778.4eb828", + "type": "python3-function", + "z": "1371dec5.76e671", + "name": "fan control", + "func": "import smbus2 as smbus\n\nstate = msg[\"payload\"]\nbus = smbus.SMBus(1)\n\nDEVICE_ADDRESS = 0x0d\n# command happens twice, for reasons\nif state == \"off\":\n with smbus.SMBus(1) as bus:\n bus.write_byte_data(DEVICE_ADDRESS, 0x08, 0x00)\n bus.write_byte_data(DEVICE_ADDRESS, 0x08, 0x00)\n return msg\nif state == \"on\":\n with smbus.SMBus(1) as bus:\n bus.write_byte_data(DEVICE_ADDRESS, 0x08, 0x01)\n bus.write_byte_data(DEVICE_ADDRESS, 0x08, 0x01)\n return msg\n", + "outputs": 1, + "x": 1150, "y": 40, "wires": [ - { - "id": "48ceeda454438cb7" - } + [ + "e640ebb5c397f424" + ] ] - } - ], - "out": [ - { - "x": 900, + }, + { + "id": "b7ab1ada.1f4158", + "type": "exec", + "z": "1371dec5.76e671", + "command": "i2cdetect -y 1", + "addpay": false, + "append": "", + "useSpawn": "false", + "timer": "1", + "winHide": false, + "oldrc": false, + "name": "i2c update", + "x": 1440, "y": 40, "wires": [ - { - "id": "2b1a67ac127f3fe7", - "port": 0 - } - ] - } - ], - "env": [], - "meta": {}, - "color": "#DDAA99" - }, - { - "id": "3a6bb13f.c9703e", - "type": "ui_tab", - "name": "Home", - "icon": "home", - "order": 1, - "disabled": false, - "hidden": false - }, - { - "id": "181bb236.1e94be", - "type": "ui_tab", - "name": "Optic Configuration", - "icon": "fa-eye", - "order": 3, - "disabled": false, - "hidden": false - }, - { - "id": "c9194f02.9d5e9", - "type": "ui_tab", - "name": "Fluidic Acquisition", - "icon": "fa-flask", - "order": 4, - "disabled": false, - "hidden": false - }, - { - "id": "8d16beb8.9b3fb", - "type": "ui_tab", - "name": "Segmentation", - "icon": "fa-crop", - "order": 5, - "disabled": false, - "hidden": false - }, - { - "id": "d9cd733b.ab73d", - "type": "ui_tab", - "name": "System Monitoring", - "icon": "fa-thermometer-full", - "order": 7, - "disabled": false, - "hidden": false - }, - { - "id": "4248342d.e55fac", - "type": "ui_group", - "name": "Optic Characterization", - "tab": "181bb236.1e94be", - "order": 4, - "disp": true, - "width": "6", - "collapse": false - }, - { - "id": "858a0e3c.987fe", - "type": "ui_group", - "name": "Preview", - "tab": "c9194f02.9d5e9", - "order": 1, - "disp": true, - "width": 10, - "collapse": false - }, - { - "id": "64903b47.4034e4", - "type": "ui_group", - "name": "Navigation", - "tab": "8d16beb8.9b3fb", - "order": 3, - "disp": false, - "width": "6", - "collapse": false - }, - { - "id": "3da7da8f.179606", - "type": "ui_group", - "name": "Metrics", - "tab": "d9cd733b.ab73d", - "order": 1, - "disp": true, - "width": "24", - "collapse": true, - "className": "" - }, - { - "id": "cc8bc4eb.651868", - "type": "ui_base", - "theme": { - "name": "theme-dark", - "lightTheme": { - "default": "#0094CE", - "baseColor": "#5900ce", - "baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif", - "edited": false, - "reset": false - }, - "darkTheme": { - "default": "#097479", - "baseColor": "#097479", - "baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif", - "edited": true, - "reset": false - }, - "customTheme": { - "name": "Untitled Theme 1", - "default": "#4B7930", - "baseColor": "#4B7930", - "baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif" - }, - "themeState": { - "base-color": { - "default": "#097479", - "value": "#097479", - "edited": true - }, - "page-titlebar-backgroundColor": { - "value": "#097479", - "edited": false - }, - "page-backgroundColor": { - "value": "#111111", - "edited": false - }, - "page-sidebar-backgroundColor": { - "value": "#333333", - "edited": false - }, - "group-textColor": { - "value": "#0eb8c0", - "edited": false - }, - "group-borderColor": { - "value": "#555555", - "edited": false - }, - "group-backgroundColor": { - "value": "#333333", - "edited": false - }, - "widget-textColor": { - "value": "#eeeeee", - "edited": false - }, - "widget-backgroundColor": { - "value": "#097479", - "edited": false - }, - "widget-borderColor": { - "value": "#333333", - "edited": false + [], + [], + [] + ] + }, + { + "id": "bc503fa5.f46dd", + "type": "switch", + "z": "1371dec5.76e671", + "name": "", + "property": "payload", + "propertyType": "msg", + "rules": [ + { + "t": "gt", + "v": "40", + "vt": "num" + }, + { + "t": "lte", + "v": "35", + "vt": "num" + } + ], + "checkall": "true", + "repair": false, + "outputs": 2, + "x": 570, + "y": 40, + "wires": [ + [ + "a25d6486.e1ce28" + ], + [ + "5d4f3e71.1bad4" + ] + ] + }, + { + "id": "5d4f3e71.1bad4", + "type": "change", + "z": "1371dec5.76e671", + "name": "Set OFF", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "off", + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 720, + "y": 60, + "wires": [ + [ + "7fb13a4a53b612a0" + ] + ] + }, + { + "id": "a25d6486.e1ce28", + "type": "change", + "z": "1371dec5.76e671", + "name": "Set ON", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "on", + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 720, + "y": 20, + "wires": [ + [ + "7fb13a4a53b612a0" + ] + ] + }, + { + "id": "569154a.b53182c", + "type": "inject", + "z": "1371dec5.76e671", + "name": "once", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": "", + "topic": "", + "payload": "start", + "payloadType": "str", + "x": 170, + "y": 680, + "wires": [ + [ + "ccb5172d10c1ccaf" + ] + ] + }, + { + "id": "4828d2f4.7c712c", + "type": "function", + "z": "1371dec5.76e671", + "name": "set global", + "func": "global.set(\"acq_instrument_id\",msg.payload);\n", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 580, + "y": 700, + "wires": [ + [] + ] + }, + { + "id": "e2f39a35.f57298", + "type": "subflow:1c24ad9c.bebec2", + "z": "1371dec5.76e671", + "name": "", + "env": [], + "x": 170, + "y": 620, + "wires": [ + [ + "950b773ad4c0fdfe" + ] + ] + }, + { + "id": "3e64877a.9684b", + "type": "function", + "z": "1371dec5.76e671", + "name": "set global", + "func": "global.set(\"acq_software\", \"PlanktoScope \" + msg.payload);\n", + "outputs": 1, + "timeout": "", + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 820, + "y": 500, + "wires": [ + [] + ] + }, + { + "id": "bdc6718a.dd5d48", + "type": "ui_text", + "z": "1371dec5.76e671", + "group": "ce9e278.781eed8", + "order": 2, + "width": 0, + "height": 0, + "name": "", + "label": "Instrument Type", + "format": "{{msg.payload}}", + "layout": "row-spread", + "className": "", + "style": false, + "font": "", + "fontSize": "", + "color": "#000000", + "x": 600, + "y": 620, + "wires": [] + }, + { + "id": "a400a97e.e333a8", + "type": "ui_text", + "z": "1371dec5.76e671", + "group": "ce9e278.781eed8", + "order": 1, + "width": 0, + "height": 0, + "name": "", + "label": "Instrument Name", + "format": "{{msg.payload}}", + "layout": "row-spread", + "className": "", + "style": false, + "font": "", + "fontSize": "", + "color": "#000000", + "x": 610, + "y": 660, + "wires": [] + }, + { + "id": "8343fa69.49339", + "type": "ui_text", + "z": "1371dec5.76e671", + "group": "ce9e278.781eed8", + "order": 3, + "width": 0, + "height": 0, + "name": "", + "label": "Software Version", + "format": "{{msg.payload}}", + "layout": "row-spread", + "className": "", + "style": false, + "font": "", + "fontSize": "", + "color": "#000000", + "x": 850, + "y": 540, + "wires": [] + }, + { + "id": "f783aefd.c3bfd8", + "type": "ui_text", + "z": "1371dec5.76e671", + "group": "ce9e278.781eed8", + "order": 4, + "width": 0, + "height": 0, + "name": "", + "label": "Camera Name", + "format": "{{msg.payload}}", + "layout": "row-spread", + "x": 600, + "y": 740, + "wires": [] + }, + { + "id": "30067f35.532f2", + "type": "link in", + "z": "1371dec5.76e671", + "name": "Camera Name", + "links": [ + "559a8085.1d6b9" + ], + "x": 205, + "y": 740, + "wires": [ + [ + "f783aefd.c3bfd8" + ] + ] + }, + { + "id": "11b51f8f.acd308", + "type": "python3-function", + "z": "1371dec5.76e671", + "d": true, + "name": "fan temperature", + "func": "import smbus\nbus = smbus.SMBus(1)\n\naddr = 0x0d\nfan_reg = 0x08\n\ntemp = float( msg[\"payload\"])\n\n# 0x01 full speed, 0x02: 20% speed, ..., 0x09: 90% speed\n\nif temp < 38:\n bus.write_byte_data(addr, fan_reg, 0x00)\nelif temp < 43:\n bus.write_byte_data(addr, fan_reg, 0x02)\nelif temp < 46:\n bus.write_byte_data(addr, fan_reg, 0x04)\nelif temp < 48:\n bus.write_byte_data(addr, fan_reg, 0x06)\nelif temp < 52:\n bus.write_byte_data(addr, fan_reg, 0x08)\nelse:\n bus.write_byte_data(addr, fan_reg, 0x01)\n\nreturn msg", + "outputs": 1, + "x": 1440, + "y": 120, + "wires": [ + [] + ] + }, + { + "id": "eaf74a43.fa27d", + "type": "switch", + "z": "1371dec5.76e671", + "name": "if disk > 90%", + "property": "payload", + "propertyType": "msg", + "rules": [ + { + "t": "gte", + "v": "90", + "vt": "num" + } + ], + "checkall": "true", + "repair": false, + "outputs": 1, + "x": 590, + "y": 120, + "wires": [ + [ + "6d09f428.930bcc" + ] + ] + }, + { + "id": "46d5e78b.15f998", + "type": "ui_toast", + "z": "1371dec5.76e671", + "position": "dialog", + "displayTime": "10", + "highlight": "", + "sendall": true, + "outputs": 1, + "ok": "OK", + "cancel": "", + "raw": false, + "className": "", + "topic": "", + "name": "", + "x": 1090, + "y": 120, + "wires": [ + [] + ] + }, + { + "id": "24df077a.cb252", + "type": "change", + "z": "1371dec5.76e671", + "name": "full disk msg", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "\"Your drive has reached 90% capacity, you should do a backup to an external drive and a purge.\"", + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 930, + "y": 120, + "wires": [ + [ + "46d5e78b.15f998" + ] + ] + }, + { + "id": "6d09f428.930bcc", + "type": "delay", + "z": "1371dec5.76e671", + "name": "", + "pauseType": "rate", + "timeout": "5", + "timeoutUnits": "seconds", + "rate": "1", + "nbRateUnits": "5", + "rateUnits": "minute", + "randomFirst": "1", + "randomLast": "5", + "randomUnits": "seconds", + "drop": true, + "allowrate": false, + "outputs": 1, + "x": 760, + "y": 120, + "wires": [ + [ + "24df077a.cb252" + ] + ] + }, + { + "id": "e640ebb5c397f424", + "type": "delay", + "z": "1371dec5.76e671", + "name": "", + "pauseType": "delay", + "timeout": "1", + "timeoutUnits": "seconds", + "rate": "1", + "nbRateUnits": "1", + "rateUnits": "second", + "randomFirst": "1", + "randomLast": "5", + "randomUnits": "seconds", + "drop": false, + "allowrate": false, + "outputs": 1, + "x": 1300, + "y": 40, + "wires": [ + [ + "b7ab1ada.1f4158" + ] + ] + }, + { + "id": "7fb13a4a53b612a0", + "type": "rbe", + "z": "1371dec5.76e671", + "name": "", + "func": "rbe", + "gap": "", + "start": "", + "inout": "out", + "septopics": true, + "property": "payload", + "topi": "topic", + "x": 1010, + "y": 40, + "wires": [ + [ + "2549f778.4eb828" + ] + ] + }, + { + "id": "ccb5172d10c1ccaf", + "type": "file in", + "z": "1371dec5.76e671", + "name": "Get machine name", + "filename": "/run/machine-name", + "filenameType": "str", + "format": "utf8", + "chunk": false, + "sendError": false, + "encoding": "none", + "allProps": false, + "x": 350, + "y": 680, + "wires": [ + [ + "a400a97e.e333a8", + "4828d2f4.7c712c" + ] + ] + }, + { + "id": "950b773ad4c0fdfe", + "type": "change", + "z": "1371dec5.76e671", + "name": "Get acq_instrument", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.acq_instrument", + "tot": "msg" + }, + { + "t": "set", + "p": "topic", + "pt": "msg", + "to": "acq_instrument", + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 350, + "y": 620, + "wires": [ + [ + "bdc6718a.dd5d48" + ] + ] + }, + { + "id": "24de7407445d2087", + "type": "inject", + "z": "1371dec5.76e671", + "name": "once", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": "", + "topic": "", + "payload": "start", + "payloadType": "str", + "x": 90, + "y": 520, + "wires": [ + [ + "e4f9ed2b337c2fa6" + ] + ] + }, + { + "id": "e4f9ed2b337c2fa6", + "type": "file in", + "z": "1371dec5.76e671", + "name": "Versioning File", + "filename": "/usr/share/planktoscope/installer-versioning.yml", + "filenameType": "str", + "format": "utf8", + "chunk": false, + "sendError": false, + "encoding": "none", + "allProps": false, + "x": 240, + "y": 520, + "wires": [ + [ + "db79aae8a7fe3512" + ] + ] + }, + { + "id": "db79aae8a7fe3512", + "type": "yaml", + "z": "1371dec5.76e671", + "property": "payload", + "name": "", + "x": 390, + "y": 520, + "wires": [ + [ + "04c313e8d9aac122", + "ef1970121e57c5e8", + "574361abfe75b3b3" + ] + ] + }, + { + "id": "04c313e8d9aac122", + "type": "change", + "z": "1371dec5.76e671", + "name": "Get repo", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.repo", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 580, + "y": 480, + "wires": [ + [ + "57b3b083a2455e09" + ] + ] + }, + { + "id": "ef1970121e57c5e8", + "type": "change", + "z": "1371dec5.76e671", + "name": "Get version", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.version", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 590, + "y": 520, + "wires": [ + [ + "3e64877a.9684b", + "8343fa69.49339" + ] + ] + }, + { + "id": "57b3b083a2455e09", + "type": "function", + "z": "1371dec5.76e671", + "name": "set global", + "func": "global.set(\"process_source\", msg.payload);\n", + "outputs": 1, + "timeout": "", + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 820, + "y": 460, + "wires": [ + [] + ] + }, + { + "id": "574361abfe75b3b3", + "type": "change", + "z": "1371dec5.76e671", + "name": "Get commit", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.commit", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 590, + "y": 560, + "wires": [ + [ + "016d1d2a2f19f1a6" + ] + ] + }, + { + "id": "016d1d2a2f19f1a6", + "type": "function", + "z": "1371dec5.76e671", + "name": "set global", + "func": "global.set(\"process_commit\", msg.payload);\n", + "outputs": 1, + "timeout": "", + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 820, + "y": 580, + "wires": [ + [] + ] + }, + { + "id": "4ed64bd91fa9fbdf", + "type": "ui_template", + "z": "1371dec5.76e671", + "group": "3da7da8f.179606", + "name": "Metrics panel", + "order": 1, + "width": "0", + "height": "0", + "format": "
\n

\n The instrument's system time is different from your web browser's time by {{drift}}.\n As a result, timestamps in your datasets will be incorrect.\n Additionally, system metrics will not be recorded or shown correctly.\n Additionally, you will see incorrectly-aligned graphs in the metrics below.\n

\n

Please change the instrument's system time or your web browser's time to accurate values.

\n

\n \n

\n
\n\n
\n

Loading system metrics, please wait...

\n
\n\n
\n \n
\n\n\n", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "className": "", + "x": 330, + "y": 280, + "wires": [ + [] + ] + }, + { + "id": "38bad1e220cd5d87", + "type": "ui_text", + "z": "1371dec5.76e671", + "group": "ce9e278.781eed8", + "order": 5, + "width": 0, + "height": 0, + "name": "", + "label": "System Time", + "format": "{{msg.payload}}", + "layout": "row-spread", + "className": "", + "style": false, + "font": "", + "fontSize": 16, + "color": "#000000", + "x": 590, + "y": 240, + "wires": [] + }, + { + "id": "ed5f2d963d85478b", + "type": "function", + "z": "1371dec5.76e671", + "name": "Get system time", + "func": "var date = new Date();\ndate.setSeconds(0, 0);\nmsg.payload = (\n date.toISOString().replace('T', ' ').replace(/:\\d+\\.\\d+Z/,' UTC')\n);\nreturn msg", + "outputs": 1, + "timeout": 0, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 340, + "y": 240, + "wires": [ + [ + "38bad1e220cd5d87" + ] + ] + }, + { + "id": "23a84a3856fb68bd", + "type": "ui_template", + "z": "1371dec5.76e671", + "group": "ce9e278.781eed8", + "name": "Browser time", + "order": 6, + "width": "6", + "height": "1", + "format": "
\n

Browser Time

\n

{{time}}

\n
\n\n", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "className": "", + "x": 330, + "y": 200, + "wires": [ + [] + ] + }, + { + "id": "19a45f972be2b0f1", + "type": "function", + "z": "1371dec5.76e671", + "name": "Get system time", + "func": "var date = new Date(msg.payload.timestamp);\nmsg.payload = (\n date.toISOString().replace('T', ' ').replace(/:\\d+\\.\\d+Z/,' UTC')\n);\nreturn msg", + "outputs": 1, + "timeout": 0, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 340, + "y": 340, + "wires": [ + [ + "ee2c5e7c29eb4760" + ] + ] + }, + { + "id": "8ba3e2774987fd58", + "type": "http in", + "z": "1371dec5.76e671", + "name": "POST /api/system-time", + "url": "/api/system-time", + "method": "post", + "upload": false, + "swaggerDoc": "", + "x": 120, + "y": 360, + "wires": [ + [ + "19a45f972be2b0f1", + "07bbdca8d6153210", + "595df18543c8328e" + ] + ] + }, + { + "id": "ee2c5e7c29eb4760", + "type": "ui_toast", + "z": "1371dec5.76e671", + "position": "top right", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 0, + "ok": "OK", + "cancel": "", + "raw": false, + "className": "", + "topic": "Setting system time", + "name": "", + "x": 610, + "y": 340, + "wires": [] + }, + { + "id": "07bbdca8d6153210", + "type": "function", + "z": "1371dec5.76e671", + "name": "Prepare timestamp", + "func": "msg.payload = ('@' + msg.payload.timestamp).slice(0, -3);\nreturn msg;", + "outputs": 1, + "timeout": 0, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 350, + "y": 380, + "wires": [ + [ + "7558e8f302d5b944" + ] + ] + }, + { + "id": "7558e8f302d5b944", + "type": "exec", + "z": "1371dec5.76e671", + "command": "sudo date -s", + "addpay": "payload", + "append": "", + "useSpawn": "", + "timer": "", + "winHide": false, + "name": "Set system time", + "x": 600, + "y": 380, + "wires": [ + [], + [], + [] + ] + }, + { + "id": "c8be8dad272e1fa5", + "type": "http in", + "z": "1371dec5.76e671", + "name": "GET /api/system-time", + "url": "/api/system-time", + "method": "get", + "upload": false, + "swaggerDoc": "", + "x": 120, + "y": 420, + "wires": [ + [ + "0f4ce59587fa14e1" + ] + ] + }, + { + "id": "0f4ce59587fa14e1", + "type": "function", + "z": "1371dec5.76e671", + "name": "Get system time", + "func": "var date = new Date();\nmsg.payload = {'timestamp': date.getTime()};\nreturn msg", + "outputs": 1, + "timeout": 0, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 340, + "y": 420, + "wires": [ + [ + "433d48a4b1bc0b27" + ] + ] + }, + { + "id": "433d48a4b1bc0b27", + "type": "http response", + "z": "1371dec5.76e671", + "name": "Send GET response", + "statusCode": "", + "headers": { + "Content-Type": "application/json; charset=UTF-8" }, - "base-font": { - "value": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif" - } - }, - "angularTheme": { - "primary": "indigo", - "accents": "blue", - "warn": "red", - "background": "grey", - "palette": "light" - } - }, - "site": { - "name": "PlanktoScope", - "hideToolbar": "false", - "allowSwipe": "false", - "lockMenu": "false", - "allowTempTheme": "true", - "dateFormat": "Y-MM-DD", - "sizes": { - "sx": 55, - "sy": 55, - "gx": 4, - "gy": 4, - "cx": 4, - "cy": 4, - "px": 4, - "py": 4 - } - } - }, - { - "id": "36739a35.7cce36", - "type": "ui_tab", - "name": "Gallery", - "icon": "fa-file-image-o", - "order": 6, - "disabled": false, - "hidden": false - }, - { - "id": "c0ebfc57.42527", - "type": "ui_group", - "name": "Group 1", - "tab": "36739a35.7cce36", - "order": 1, - "disp": false, - "width": "24", - "collapse": false - }, - { - "id": "737ec584.2eea2c", - "type": "ui_tab", - "name": "Sample", - "icon": "fa-eyedropper", - "order": 2, - "disabled": false, - "hidden": false - }, - { - "id": "6f97e7ae.270c48", - "type": "ui_group", - "name": "Group 1", - "tab": "3a6bb13f.c9703e", - "order": 1, - "disp": false, - "width": "4", - "collapse": false - }, - { - "id": "3e1ba03d.f01d8", - "type": "ui_group", - "name": "Sample Identification", - "tab": "737ec584.2eea2c", - "order": 1, - "disp": true, - "width": "10", - "collapse": false - }, - { - "id": "4e0cd5ea.17e59c", - "type": "ui_group", - "name": "Group 2", - "tab": "3a6bb13f.c9703e", - "order": 2, - "disp": false, - "width": "4", - "collapse": false - }, - { - "id": "ef590206.24f6", - "type": "ui_group", - "name": "Group 3", - "tab": "3a6bb13f.c9703e", - "order": 3, - "disp": false, - "width": "4", - "collapse": false - }, - { - "id": "ae8f6620.073358", - "type": "ui_group", - "name": "Group 4", - "tab": "3a6bb13f.c9703e", - "order": 4, - "disp": false, - "width": "4", - "collapse": false - }, - { - "id": "196518b2.4d53b7", - "type": "ui_group", - "name": "Group 5", - "tab": "3a6bb13f.c9703e", - "order": 5, - "disp": false, - "width": "4", - "collapse": false - }, - { - "id": "777a7c33.fcd804", - "type": "ui_group", - "name": "Group 6", - "tab": "3a6bb13f.c9703e", - "order": 6, - "disp": false, - "width": "4", - "collapse": false - }, - { - "id": "cef1e703.bcf3c8", - "type": "ui_group", - "name": "Sample Location", - "tab": "737ec584.2eea2c", - "order": 3, - "disp": false, - "width": "10", - "collapse": false - }, - { - "id": "5517c651.b2f668", - "type": "ui_group", - "name": "Validation", - "tab": "737ec584.2eea2c", - "order": 5, - "disp": false, - "width": 10, - "collapse": false - }, - { - "id": "fbd92986.1028c8", - "type": "ui_group", - "name": "Focus Adjustment", - "tab": "181bb236.1e94be", - "order": 2, - "disp": true, - "width": 4, - "collapse": false - }, - { - "id": "707d9797.c8e798", - "type": "ui_group", - "name": "Fluidic Manual Manipulation", - "tab": "181bb236.1e94be", - "order": 5, - "disp": true, - "width": 4, - "collapse": false - }, - { - "id": "7a0b4877.a5d268", - "type": "ui_group", - "name": "Navigation", - "tab": "181bb236.1e94be", - "order": 6, - "disp": false, - "width": 4, - "collapse": false - }, - { - "id": "404c301a.19c4e", - "type": "ui_group", - "name": "Fraction size", - "tab": "c9194f02.9d5e9", - "order": 2, - "disp": true, - "width": "10", - "collapse": false - }, - { - "id": "4322c187.e73e5", - "type": "ui_group", - "name": "Acquisition", - "tab": "c9194f02.9d5e9", - "order": 3, - "disp": true, - "width": 10, - "collapse": false - }, - { - "id": "b7919ae2.c01788", - "type": "ui_group", - "name": "Navigation", - "tab": "c9194f02.9d5e9", - "order": 6, - "disp": false, - "width": "10", - "collapse": false - }, - { - "id": "b5d61bc7.54fe48", - "type": "ui_group", - "name": "Statistics", - "tab": "c9194f02.9d5e9", - "order": 4, - "disp": true, - "width": "10", - "collapse": false - }, - { - "id": "8dc3722c.06efa8", - "type": "mqtt-broker", - "name": "", - "broker": "0.0.0.0", - "port": "1883", - "clientid": "Client_node", - "autoConnect": true, - "usetls": false, - "compatmode": false, - "protocolVersion": "4", - "keepalive": "60", - "cleansession": true, - "birthTopic": "", - "birthQos": "0", - "birthPayload": "", - "birthMsg": {}, - "closeTopic": "", - "closeQos": "0", - "closePayload": "", - "closeMsg": {}, - "willTopic": "", - "willQos": "0", - "willPayload": "", - "willMsg": {}, - "userProps": "", - "sessionExpiry": "" - }, - { - "id": "abeb6dad.635a2", - "type": "ui_group", - "name": "Control", - "tab": "8d16beb8.9b3fb", - "order": 1, - "disp": true, - "width": 10, - "collapse": false - }, - { - "id": "cf5d9f0e.d57e7", - "type": "ui_group", - "name": "Net Metadata", - "tab": "737ec584.2eea2c", - "order": 4, - "disp": false, - "width": "10", - "collapse": false - }, - { - "id": "ce9e278.781eed8", - "type": "ui_group", - "name": "Information", - "tab": "d9cd733b.ab73d", - "order": 5, - "disp": true, - "width": 6, - "collapse": false - }, - { - "id": "70de8209.68416c", - "type": "ui_group", - "name": "Status", - "tab": "c9194f02.9d5e9", - "order": 5, - "disp": true, - "width": 10, - "collapse": false - }, - { - "id": "46be9c86.dea684", - "type": "ui_group", - "name": "Status", - "tab": "8d16beb8.9b3fb", - "order": 2, - "disp": true, - "width": 10, - "collapse": false - }, - { - "id": "8c38a81e.9897a8", - "type": "ui_group", - "name": "Camera Settings", - "tab": "181bb236.1e94be", - "order": 3, - "disp": true, - "width": 6, - "collapse": false - }, - { - "id": "2489e51c.eed77a", - "type": "ui_tab", - "name": "Administration", - "icon": "dashboard", - "order": 9, - "disabled": false, - "hidden": false - }, - { - "id": "b0fb559a.6966a8", - "type": "ui_tab", - "name": "Hardware Settings", - "icon": "fa-cogs", - "disabled": false, - "hidden": false - }, - { - "id": "6be36295.0ab324", - "type": "ui_group", - "name": "Settings", - "tab": "b0fb559a.6966a8", - "order": 1, - "disp": false, - "width": "8", - "collapse": false, - "className": "" - }, - { - "id": "fc5e4e6f.5b1c8", - "type": "ui_group", - "name": "GPS Status", - "tab": "737ec584.2eea2c", - "order": 6, - "disp": true, - "width": 10, - "collapse": false - }, - { - "id": "f3ca28ef.4df0a8", - "type": "ui_group", - "name": "Shutdown", - "tab": "3a6bb13f.c9703e", - "order": 7, - "disp": true, - "width": 4, - "collapse": false - }, - { - "id": "3dfd8a69.69ed56", - "type": "ui_spacer", - "name": "spacer", - "group": "3e1ba03d.f01d8", - "order": 5, - "width": 10, - "height": 1 - }, - { - "id": "72a9216.2ff48e", - "type": "ui_spacer", - "name": "spacer", - "group": "4322c187.e73e5", - "order": 8, - "width": 10, - "height": 1 - }, - { - "id": "1b664927.c91d1f", - "type": "ui_spacer", - "name": "spacer", - "group": "b5d61bc7.54fe48", - "order": 2, - "width": 2, - "height": 1 - }, - { - "id": "1a663b6a.ab5805", - "type": "ui_spacer", - "name": "spacer", - "group": "b5d61bc7.54fe48", - "order": 4, - "width": 2, - "height": 1 - }, - { - "id": "8eeed8d8.ad9098", - "type": "ui_spacer", - "name": "spacer", - "group": "b5d61bc7.54fe48", - "order": 5, - "width": 2, - "height": 1 - }, - { - "id": "be1c5ce7.004e", - "type": "ui_spacer", - "name": "spacer", - "group": "b5d61bc7.54fe48", - "order": 6, - "width": 2, - "height": 1 - }, - { - "id": "c2fe38e9.555e3", - "type": "ui_spacer", - "name": "spacer", - "group": "b5d61bc7.54fe48", - "order": 7, - "width": 2, - "height": 1 - }, - { - "id": "89bd18b7.c779a8", - "type": "ui_spacer", - "name": "spacer", - "group": "b5d61bc7.54fe48", - "order": 8, - "width": 2, - "height": 1 - }, - { - "id": "3cbbfa5d.efa636", - "type": "ui_spacer", - "name": "spacer", - "group": "b7919ae2.c01788", - "order": 2, - "width": 5, - "height": 1 - }, - { - "id": "97148e8d8e298f1a", - "type": "ui_spacer", - "z": "cb95299c.2817c8", - "name": "spacer", - "group": "abeb6dad.635a2", - "order": 7, - "width": 10, - "height": 1 - }, - { - "id": "3b2eccc574e6a9ae", - "type": "ui_spacer", - "z": "cb95299c.2817c8", - "name": "spacer", - "group": "abeb6dad.635a2", - "order": 11, - "width": 1, - "height": 1 - }, - { - "id": "bbd6431d97c86f97", - "type": "ui_spacer", - "z": "cb95299c.2817c8", - "name": "spacer", - "group": "46be9c86.dea684", - "order": 4, - "width": 3, - "height": 1 - }, - { - "id": "5f98f5f140f0ecde", - "type": "ui_spacer", - "z": "cb95299c.2817c8", - "name": "spacer", - "group": "46be9c86.dea684", - "order": 6, - "width": 3, - "height": 1 - }, - { - "id": "7bc0a4c416e4545c", - "type": "ui_group", - "name": "Culture Date and Time", - "tab": "737ec584.2eea2c", - "order": 2, - "disp": true, - "width": "10", - "collapse": false, - "className": "" - }, - { - "id": "6c31ad948a9d62fd", - "type": "ui_spacer", - "name": "spacer", - "group": "4248342d.e55fac", - "order": 2, - "width": 1, - "height": 1 - }, - { - "id": "833bc5bb.217ba8", - "type": "ui_group", - "name": "Preview", - "tab": "181bb236.1e94be", - "order": 1, - "disp": true, - "width": 18, - "collapse": false - }, - { - "id": "a7d64879.38298", - "type": "ui_group", - "name": "Logs", - "tab": "2489e51c.eed77a", - "order": 1, - "disp": true, - "width": "12", - "collapse": true, - "className": "" - }, - { - "id": "6465bdd5.15eb8c", - "type": "file in", - "z": "1c24ad9c.bebec2", - "name": "", - "filename": "/home/pi/PlanktoScope/config.json", - "filenameType": "str", - "format": "utf8", - "chunk": false, - "sendError": false, - "encoding": "none", - "x": 560, - "y": 60, - "wires": [["15ceb135.6628bf"]], - "info": "# PlanktoScope Help\nThis Node will read the content of the file named **config.txt** containing all the input placeholders.\n" - }, - { - "id": "15ceb135.6628bf", - "type": "json", - "z": "1c24ad9c.bebec2", - "name": "config.json", - "property": "payload", - "action": "", - "pretty": false, - "x": 730, - "y": 60, - "wires": [["ad541674.4791c8"]] - }, - { - "id": "7205d267.36adcc", - "type": "file", - "z": "1c24ad9c.bebec2", - "name": "", - "filename": "/home/pi/PlanktoScope/config.json", - "appendNewline": true, - "createDir": true, - "overwriteFile": "true", - "encoding": "none", - "x": 990, - "y": 160, - "wires": [[]] - }, - { - "id": "2e6ddf51.c0dba", - "type": "json", - "z": "1c24ad9c.bebec2", - "name": "config.json", - "property": "payload", - "action": "str", - "pretty": true, - "x": 730, - "y": 160, - "wires": [["7205d267.36adcc"]] - }, - { - "id": "ad541674.4791c8", - "type": "function", - "z": "1c24ad9c.bebec2", - "name": "Global Set", - "func": "global.set(\"config_keys\", Object.keys(msg.payload));\n\nfor (const key in msg.payload) {\n global.set(key, msg.payload[key]);\n}\n\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 910, - "y": 60, - "wires": [[]] - }, - { - "id": "3e9a33c.141384c", - "type": "inject", - "z": "1c24ad9c.bebec2", - "name": "Load config", - "props": [ - { - "p": "topic", - "vt": "str" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "", - "payloadType": "str", - "x": 230, - "y": 60, - "wires": [["6465bdd5.15eb8c"]] - }, - { - "id": "3ad9835.08c937c", - "type": "function", - "z": "1c24ad9c.bebec2", - "name": "get config payload", - "func": "keys = global.get(\"config_keys\")\n\nvar payload = {}\n\nkeys.forEach(function(item, index, array) {\n payload[item] = global.get(item);\n})\n\nreturn {\"payload\": payload};", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 410, - "y": 160, - "wires": [["2e6ddf51.c0dba"]] - }, - { - "id": "f439663c.8abd3", - "type": "ui_ui_control", - "z": "1c24ad9c.bebec2", - "name": "Connect Event", - "events": "connect", - "x": 220, - "y": 100, - "wires": [["6465bdd5.15eb8c"]] - }, - { - "id": "82099021.9ceb08", - "type": "file", - "z": "4ed26b8b.253504", - "name": "", - "filename": "/home/pi/PlanktoScope/hardware.json", - "appendNewline": true, - "createDir": true, - "overwriteFile": "true", - "encoding": "none", - "x": 660, - "y": 40, - "wires": [[]] - }, - { - "id": "bb0a8725.a1849", - "type": "json", - "z": "4ed26b8b.253504", - "name": "Create JSON", - "property": "payload", - "action": "str", - "pretty": true, - "x": 490, - "y": 40, - "wires": [["82099021.9ceb08"]] - }, - { - "id": "53d163be.47cf24", - "type": "function", - "z": "4ed26b8b.253504", - "name": "Update and retrieve hardware_conf", - "func": "// change global\nhardware_conf = global.get(\"hardware_conf\");\n\nif (msg.topic == \"process_pixel_fixed\" && msg.payload == 0){\n delete hardware_conf[msg.topic]\n delete msg.topic\n}\n\nif (msg.topic !== null && msg.topic !== undefined){\n hardware_conf[msg.topic] = msg.payload;\n global.set(\"hardware_conf\", hardware_conf);\n}\n\nreturn {\"payload\": hardware_conf};", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 240, - "y": 40, - "wires": [["bb0a8725.a1849"]] - }, - { - "id": "48ceeda454438cb7", - "type": "file in", - "z": "e6665421f66ea4c8", - "name": "", - "filename": "/home/pi/PlanktoScope/hardware.json", - "filenameType": "str", - "format": "utf8", - "chunk": false, - "sendError": false, - "encoding": "none", - "x": 250, - "y": 40, - "wires": [["853c938a270fd85e"]], - "info": "# PlanktoScope Help\nThis Node will read the content of the file named **config.txt** containing all the input placeholders.\n" - }, - { - "id": "853c938a270fd85e", - "type": "json", - "z": "e6665421f66ea4c8", - "name": "Parse JSON", - "property": "payload", - "action": "", - "pretty": false, - "x": 510, - "y": 40, - "wires": [["2b1a67ac127f3fe7"]] - }, - { - "id": "2b1a67ac127f3fe7", - "type": "change", - "z": "e6665421f66ea4c8", - "name": "", - "rules": [ - { - "t": "set", - "p": "hardware_conf", - "pt": "global", - "to": "payload", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 730, - "y": 40, - "wires": [[]] - }, - { - "id": "2f30a6ee99587899", - "type": "comment", - "z": "eaae323a.31b3", - "name": "LICENSE", - "info": "Copyright 2022 Thibaut Pollina and Romain Bazile\nLicensed under GPL v3.0", - "x": 140, - "y": 600, - "wires": [] - }, - { - "id": "4e78af2d.90be7", - "type": "ui_ui_control", - "z": "eaae323a.31b3", - "name": "", - "events": "change", - "x": 440, - "y": 160, - "wires": [[]] - }, - { - "id": "7789839d.69b48c", - "type": "ui_template", - "z": "eaae323a.31b3", - "group": "4e0cd5ea.17e59c", - "name": "Optic Configuration", - "order": 1, - "width": 4, - "height": 4, - "format": "\n \n
Optic Configuration
\n
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "x": 130, - "y": 100, - "wires": [["4e78af2d.90be7"]] - }, - { - "id": "6ea6c306.f9c12c", - "type": "ui_template", - "z": "eaae323a.31b3", - "group": "ef590206.24f6", - "name": "Fluidic Acquisition", - "order": 1, - "width": 4, - "height": 4, - "format": "\n \n
Fluidic Acquisition
\n
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "x": 130, - "y": 140, - "wires": [["4e78af2d.90be7"]] - }, - { - "id": "bb9eb153.9e36c", - "type": "ui_template", - "z": "eaae323a.31b3", - "group": "ae8f6620.073358", - "name": "Segmentation", - "order": 1, - "width": 4, - "height": 4, - "format": "\n \n
Segmentation
\n
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "x": 140, - "y": 180, - "wires": [["4e78af2d.90be7"]] - }, - { - "id": "eaf8ee7f.96f44", - "type": "ui_template", - "z": "eaae323a.31b3", - "group": "196518b2.4d53b7", - "name": "Gallery", - "order": 1, - "width": 4, - "height": 4, - "format": "\n \n
Gallery
\n
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "x": 160, - "y": 220, - "wires": [["4e78af2d.90be7"]] - }, - { - "id": "c1b1469.9650eb8", - "type": "ui_template", - "z": "eaae323a.31b3", - "group": "777a7c33.fcd804", - "name": "System Monitoring", - "order": 1, - "width": 4, - "height": 4, - "format": "\n \n
System Monitoring
\n
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "x": 130, - "y": 260, - "wires": [["4e78af2d.90be7"]] - }, - { - "id": "abafd6e6.04a5f8", - "type": "ui_template", - "z": "eaae323a.31b3", - "group": "6f97e7ae.270c48", - "name": "Sample", - "order": 1, - "width": 4, - "height": 4, - "format": "\n \n
Sample
\n
\n In doubt? Start Here!\n
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "x": 160, - "y": 60, - "wires": [["4e78af2d.90be7"]] - }, - { - "id": "dab82064.26a8d", - "type": "ui_button", - "z": "eaae323a.31b3", - "name": "Unlock button", - "group": "f3ca28ef.4df0a8", - "order": 2, - "width": 0, - "height": 0, - "passthru": false, - "label": "Unlock button", - "tooltip": "", - "color": "", - "bgcolor": "", - "icon": "", - "payload": "shutdown", - "payloadType": "flow", - "topic": "", - "x": 120, - "y": 380, - "wires": [["6c3a3b4.78cad44"]] - }, - { - "id": "1c658761.b852a1", - "type": "ui_toast", - "z": "eaae323a.31b3", - "position": "dialog", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 1, - "ok": "YES PLEASE", - "cancel": "NO!", - "raw": false, - "topic": "Are you sure?", - "name": "Confirmation message", - "x": 800, - "y": 380, - "wires": [["8f1b8e23.daafe"]] - }, - { - "id": "a48ff63f.db5e18", - "type": "inject", - "z": "eaae323a.31b3", - "name": "disabled", - "props": [ - { - "p": "enabled", - "v": "false", - "vt": "bool" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "", - "x": 140, - "y": 420, - "wires": [["d58039a9.6e7928"]] - }, - { - "id": "b67a7147.65fcd8", - "type": "ui_button", - "z": "eaae323a.31b3", - "name": "Shutdown button", - "group": "f3ca28ef.4df0a8", - "order": 4, - "width": 0, - "height": 0, - "passthru": false, - "label": "Shutdown", - "tooltip": "", - "color": "", - "bgcolor": "#AD1625", - "icon": "fa-power-off fa-2x", - "payload": "Do you want to turn the machine off now?", - "payloadType": "str", - "topic": "", - "x": 550, - "y": 380, - "wires": [["1c658761.b852a1"]] - }, - { - "id": "d58039a9.6e7928", - "type": "change", - "z": "eaae323a.31b3", - "name": "", - "rules": [ - { - "t": "set", - "p": "shutdown", - "pt": "flow", - "to": "false", - "tot": "bool" - }, - { - "t": "set", - "p": "enabled", - "pt": "msg", - "to": "shutdown", - "tot": "flow" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 320, - "y": 420, - "wires": [["b67a7147.65fcd8"]] - }, - { - "id": "6c3a3b4.78cad44", - "type": "function", - "z": "eaae323a.31b3", - "name": "Toggle", - "func": "flow.set(\"shutdown\", !flow.get(\"shutdown\"))\nmsg.enabled = flow.get(\"shutdown\")\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 290, - "y": 380, - "wires": [["b67a7147.65fcd8"]] - }, - { - "id": "d1153ad6.40d738", - "type": "ui_template", - "z": "eaae323a.31b3", - "group": "f3ca28ef.4df0a8", - "name": "Shutdown information", - "order": 1, - "width": 0, - "height": 0, - "format": "
To prevent data corruption, please always shutdown the machine before unplugging the unit.\n

\nRemember to first unlock the shutdown button.\n
", - "storeOutMessages": true, - "fwdInMessages": false, - "resendOnRefresh": true, - "templateScope": "local", - "x": 120, - "y": 320, - "wires": [[]] - }, - { - "id": "e08cfcb8.2a67e8", - "type": "link out", - "z": "eaae323a.31b3", - "name": "Home shutdown button", - "links": ["b81b990a.d4dca"], - "x": 715, - "y": 500, - "wires": [] - }, - { - "id": "ce7087fc.dcc9e8", - "type": "ui_toast", - "z": "eaae323a.31b3", - "position": "dialog", - "displayTime": "10", - "highlight": "", - "sendall": true, - "outputs": 1, - "ok": "OK", - "cancel": "", - "raw": false, - "topic": "Turning off now!", - "name": "Shutdown message", - "x": 570, - "y": 540, - "wires": [[]] - }, - { - "id": "7d1626a0.deb85", - "type": "change", - "z": "eaae323a.31b3", - "name": "shutdown!", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "shutdown", - "tot": "str" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 300, - "y": 500, - "wires": [["e08cfcb8.2a67e8"]] - }, - { - "id": "8f1b8e23.daafe", - "type": "switch", - "z": "eaae323a.31b3", - "name": "", - "property": "payload", - "propertyType": "msg", - "rules": [ - { - "t": "eq", - "v": "NO!", - "vt": "str" - }, - { - "t": "else" - } - ], - "checkall": "true", - "repair": false, - "outputs": 2, - "x": 150, - "y": 500, - "wires": [["d58039a9.6e7928"], ["7d1626a0.deb85", "281a56c9.ec7902"]] - }, - { - "id": "281a56c9.ec7902", - "type": "change", - "z": "eaae323a.31b3", - "name": "Shutdown message", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "Please wait a minute before disconnecting the machine from its power supply!", - "tot": "str" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 330, - "y": 540, - "wires": [["ce7087fc.dcc9e8"]] - }, - { - "id": "4557d689.a4fa88", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "sample_ship", - "label": "Name of the ship", - "tooltip": "", - "group": "3e1ba03d.f01d8", - "order": 2, - "width": 0, - "height": 0, - "passthru": true, - "mode": "text", - "delay": "300", - "topic": "sample_ship", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 670, - "y": 80, - "wires": [["9f501f49.45645"]] - }, - { - "id": "fcfc31ae.af3af", - "type": "ui_dropdown", - "z": "b771c342.49603", - "name": "sample_sampling_gear", - "label": "Sampling gear*", - "tooltip": "", - "place": "Choose from list", - "group": "3e1ba03d.f01d8", - "order": 6, - "width": 0, - "height": 0, - "passthru": true, - "multiple": false, - "options": [ - { - "label": "High Speed Net", - "value": "net_hsn", - "type": "str" - }, - { - "label": "Tara Decknet", - "value": "net_decknet", - "type": "str" - }, - { - "label": "Plankton net", - "value": "net", - "type": "str" - }, - { - "label": "Niskin bottle 12L", - "value": "niskin_12L", - "type": "str" - }, - { - "label": "Niskin bottle 24L", - "value": "niskin_24L", - "type": "str" - }, - { - "label": "Pass Hull", - "value": "pass_hull", - "type": "str" - }, - { - "label": "Single location (with net or bucket)", - "value": "single_location", - "type": "str" - }, - { - "label": "Lab culture", - "value": "culture", - "type": "str" - }, - { - "label": "Test", - "value": "test", - "type": "str" - } - ], - "payload": "", - "topic": "sample_sampling_gear", - "topicType": "str", - "className": "", - "x": 630, - "y": 200, - "wires": [["9f501f49.45645", "46eb1bf8.3dc5f4", "3ac7b631f5d8ef90"]] - }, - { - "id": "82c5fc77.59c97", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "sample_operator", - "label": "Name of the operator*", - "tooltip": "", - "group": "3e1ba03d.f01d8", - "order": 3, - "width": 0, - "height": 0, - "passthru": true, - "mode": "text", - "delay": "300", - "topic": "sample_operator", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 650, - "y": 160, - "wires": [["9f501f49.45645"]] - }, - { - "id": "9c882b37.fde668", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "sample_project", - "label": "Name of the project*", - "tooltip": "", - "group": "3e1ba03d.f01d8", - "order": 1, - "width": 0, - "height": 0, - "passthru": true, - "mode": "text", - "delay": "300", - "topic": "sample_project", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 660, - "y": 40, - "wires": [["9f501f49.45645"]] - }, - { - "id": "94eb4221.9b92c", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "sample_id", - "label": "Station ID*", - "tooltip": "", - "group": "3e1ba03d.f01d8", - "order": 4, - "width": 0, - "height": 0, - "passthru": true, - "mode": "text", - "delay": "300", - "topic": "sample_id", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 670, - "y": 120, - "wires": [["9f501f49.45645"]] - }, - { - "id": "9f501f49.45645", - "type": "function", - "z": "b771c342.49603", - "name": "set global", - "func": "global.set(msg.topic,msg.payload);", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 1080, - "y": 200, - "wires": [[]] - }, - { - "id": "222c851d.5d0a3a", - "type": "ui_ui_control", - "z": "b771c342.49603", - "name": "", - "events": "change", - "x": 400, - "y": 880, - "wires": [[]] - }, - { - "id": "52f6b103.1efb6", - "type": "ui_toast", - "z": "b771c342.49603", - "position": "dialog", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 1, - "ok": "OK", - "cancel": "", - "raw": false, - "topic": "", - "name": "", - "x": 710, - "y": 980, - "wires": [[]] - }, - { - "id": "986d960a.c75908", - "type": "function", - "z": "b771c342.49603", - "name": "Check form", - "func": "var sample_project= global.get(\"sample_project\");\nvar sample_id= global.get(\"sample_id\");\nvar sample_operator= global.get(\"sample_operator\");\nvar sample_sampling_gear= global.get(\"sample_sampling_gear\");\nvar object_lat= global.get(\"object_lat\");\nvar object_lon= global.get(\"object_lon\");\nvar object_date= global.get(\"object_date\");\nvar object_time= global.get(\"object_time\");\nif (sample_project === undefined || sample_project === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Sample project\"\n return [null, msg];\n}\n\nelse if (sample_id === undefined || sample_id === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Sample ID\"\n return [null, msg];\n}\n\nelse if (sample_operator === undefined || sample_operator === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Sample operator\"\n return [null, msg];\n}\n\nelse if (sample_sampling_gear === undefined || sample_sampling_gear === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Sample sampling gear\"\n return [null, msg];\n}\n\nelse if (object_lat === undefined || object_lat === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Latitude of sample\"\n return [null, msg];\n}\n\nelse if (object_lon === undefined || object_lon === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Longitude of sample\"\n return [null, msg];\n}\n\nelse if (object_date === undefined || object_date === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Date of sample\"\n return [null, msg];\n}\n\nelse if (object_time === undefined || object_time === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Time of sample\"\n return [null, msg];\n}\nelse if (sample_sampling_gear.startsWith(\"net\")){\n var object_lat_end = global.get(\"object_lat_end\");\n var object_lon_end = global.get(\"object_lon_end\");\n var object_date_end = global.get(\"object_date_end\");\n var object_time_end = global.get(\"object_time_end\");\n var sample_gear_net_opening = global.get(\"sample_gear_net_opening\");\n\n if (object_lat_end === undefined || object_lat_end === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Latitude of retrieval\"\n return [null, msg];\n }\n \n else if (object_lon_end === undefined || object_lon_end === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Longitude of retrieval\"\n return [null, msg];\n }\n \n else if (object_date_end === undefined || object_date_end === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Date of retrieval\"\n return [null, msg];\n }\n \n else if (object_time_end === undefined || object_time_end === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Time of retrieval\"\n return [null, msg];\n }\n \n else if (sample_gear_net_opening === undefined || sample_gear_net_opening === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Net opening dimension\"\n return [null, msg];\n }\n \n if (sample_sampling_gear == \"net_decknet\"){\n var sample_total_volume = global.get(\"sample_total_volume\");\n if (sample_total_volume === undefined || sample_total_volume === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Decknet flowmeter readings\"\n return [null, msg];\n }\n }\n}\nmsg.topic = \"config_save\"\nmsg.payload={\"tab\":\"Optic Configuration\"};\n\nreturn [msg, null];", - "outputs": 2, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 470, - "y": 940, - "wires": [["726a7822.cd6298", "e2b277c1.07283"], ["52f6b103.1efb6"]], - "outputLabels": ["message", "error"] - }, - { - "id": "18f44504.cac66b", - "type": "gpsd", - "z": "b771c342.49603", - "name": "", - "hostname": "localhost", - "port": "2947", - "tpv": true, - "sky": false, - "info": false, - "device": false, - "gst": false, - "att": false, - "x": 250, - "y": 1240, - "wires": [ - [ - "258b4562.9f778a", - "54e37580.fdc31c", - "cc21ca16.b92928", - "4a4de52c.cf2884", - "73c4a14a.9b93c8" - ] - ] - }, - { - "id": "726a7822.cd6298", - "type": "ui_ui_control", - "z": "b771c342.49603", - "name": "", - "events": "change", - "x": 700, - "y": 900, - "wires": [[]] - }, - { - "id": "16de754c.cc969b", - "type": "ui_button", - "z": "b771c342.49603", - "name": "", - "group": "5517c651.b2f668", - "order": 1, - "width": 5, - "height": 1, - "passthru": false, - "label": "Previous", - "tooltip": "", - "color": "#097479", - "bgcolor": "white", - "icon": "keyboard_return", - "payload": "{\"tab\":\"Home\"}", - "payloadType": "json", - "topic": "", - "x": 240, - "y": 880, - "wires": [["222c851d.5d0a3a"]] - }, - { - "id": "84f3d040.5f7ea", - "type": "ui_button", - "z": "b771c342.49603", - "name": "", - "group": "5517c651.b2f668", - "order": 2, - "width": 5, - "height": 1, - "passthru": false, - "label": "Continue", - "tooltip": "", - "color": "#097479", - "bgcolor": "white", - "icon": "keyboard_tab", - "payload": "{\"tab\":\"Home\"}", - "payloadType": "json", - "topic": "", - "x": 240, - "y": 940, - "wires": [["986d960a.c75908"]] - }, - { - "id": "d027a6bf.7049e8", - "type": "function", - "z": "b771c342.49603", - "name": "get sample_projet", - "func": "msg.payload = msg.payload.sample_project;\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 310, - "y": 40, - "wires": [["9c882b37.fde668"]] - }, - { - "id": "5a811caf.0f3144", - "type": "function", - "z": "b771c342.49603", - "name": "get sample_ship", - "func": "msg.payload = msg.payload.sample_ship;\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 300, - "y": 80, - "wires": [["4557d689.a4fa88"]] - }, - { - "id": "45911c98.2bd83c", - "type": "function", - "z": "b771c342.49603", - "name": "get sample_id", - "func": "msg.payload = msg.payload.sample_id;\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 300, - "y": 120, - "wires": [["94eb4221.9b92c"]] - }, - { - "id": "1e09a4ab.72996b", - "type": "function", - "z": "b771c342.49603", - "name": "get sample_operator", - "func": "msg.payload = msg.payload.sample_operator;\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 320, - "y": 160, - "wires": [["82c5fc77.59c97"]] - }, - { - "id": "a3272681.f271c8", - "type": "function", - "z": "b771c342.49603", - "name": "get sample_sampling_gear", - "func": "msg.topic = \"sample_sampling_gear\"\nif (msg.payload.sample_sampling_gear === undefined){\n msg.payload = \"net\";\n}\nelse\n{\n msg.payload = msg.payload.sample_sampling_gear;\n}\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 340, - "y": 200, - "wires": [["fcfc31ae.af3af"]] - }, - { - "id": "a6907a38.f6611", - "type": "subflow:1c24ad9c.bebec2", - "z": "b771c342.49603", - "name": "", - "env": [], - "x": 70, - "y": 220, - "wires": [ - [ - "d027a6bf.7049e8", - "5a811caf.0f3144", - "45911c98.2bd83c", - "1e09a4ab.72996b", - "8dff1648.82e42", - "9f04c5ec.75f3d8", - "f408a273.4fb538", - "e73fd87d.d24e4", - "489c8e06.cc7d6", - "a3272681.f271c8" - ] - ] - }, - { - "id": "e2b277c1.07283", - "type": "subflow:1c24ad9c.bebec2", - "z": "b771c342.49603", - "name": "", - "env": [], - "x": 690, - "y": 940, - "wires": [[]] - }, - { - "id": "7116e906.9f50f", - "type": "ui_text", - "z": "b771c342.49603", - "group": "fc5e4e6f.5b1c8", - "order": 1, - "width": 10, - "height": 1, - "name": "GPS Status Display", - "label": "GPS Status:", - "format": "{{msg.payload}}", - "layout": "row-center", - "x": 730, - "y": 1080, - "wires": [] - }, - { - "id": "9c7f7fc9.c8d3a", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "object_depth_max", - "label": "Max sampling depth (m)", - "tooltip": "in m", - "group": "3e1ba03d.f01d8", - "order": 10, - "width": 5, - "height": 1, - "passthru": true, - "mode": "number", - "delay": "300", - "topic": "object_depth_max", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 650, - "y": 240, - "wires": [["9f501f49.45645"]] - }, - { - "id": "317eeeb7.8d3042", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "object_depth_min", - "label": "Min sampling depth (m)", - "tooltip": "in m", - "group": "3e1ba03d.f01d8", - "order": 9, - "width": 5, - "height": 1, - "passthru": true, - "mode": "number", - "delay": "300", - "topic": "object_depth_min", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 650, - "y": 280, - "wires": [["9f501f49.45645"]] - }, - { - "id": "cbb123ab.fd3428", - "type": "ui_ui_control", - "z": "b771c342.49603", - "name": "show/hide net groups", - "events": "change", - "x": 1320, - "y": 300, - "wires": [[]] - }, - { - "id": "642ff403.1ed91c", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "sample_concentrated_sample_volume", - "label": "Concentrated sample volume (mL)", - "tooltip": "Volume extracted from the net codend (in mL)", - "group": "3e1ba03d.f01d8", - "order": 12, - "width": 10, - "height": 1, - "passthru": true, - "mode": "number", - "delay": "300", - "topic": "sample_concentrated_sample_volume", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 590, - "y": 440, - "wires": [["9f501f49.45645"]] - }, - { - "id": "e967b844.46aa48", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "sample_gear_net_opening", - "label": "Net opening dimension (mm)", - "tooltip": "Size of the net mouth opening (in mm)", - "group": "cf5d9f0e.d57e7", - "order": 1, - "width": 10, - "height": 1, - "passthru": true, - "mode": "number", - "delay": "300", - "topic": "sample_gear_net_opening", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 620, - "y": 320, - "wires": [["9f501f49.45645"]] - }, - { - "id": "c0ce5626.b6c5", - "type": "ui_toast", - "z": "b771c342.49603", - "position": "dialog", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 1, - "ok": "OK", - "cancel": "", - "raw": false, - "topic": "", - "name": "", - "x": 1230, - "y": 620, - "wires": [[]] - }, - { - "id": "c33f1124.af6688", - "type": "ui_form", - "z": "b771c342.49603", - "name": "sample_location", - "label": "Sample Location", - "group": "cef1e703.bcf3c8", - "order": 1, - "width": 0, - "height": 0, - "options": [ - { - "label": "Latitude (36.574439°N or 36°57.4439'N)", - "value": "object_lat", - "type": "text", - "required": true, - "rows": null - }, - { - "label": "Longitude (110.42100°W or 110°4.2100'W)", - "value": "object_lon", - "type": "text", - "required": true, - "rows": null - }, - { - "label": "Date (YYYY-MM-DD, UTC)", - "value": "object_date", - "type": "text", - "required": true, - "rows": null - }, - { - "label": "Time (HH:MM(:SS), UTC 24h)", - "value": "object_time", - "type": "text", - "required": true, - "rows": null - } - ], - "formValue": { - "object_lat": "", - "object_lon": "", - "object_date": "", - "object_time": "" - }, - "payload": "", - "submit": "Validate", - "cancel": "Reset", - "topic": "sample_location", - "x": 660, - "y": 580, - "wires": [["14658615.47c862", "3318a1aaa70fc2ee"]] - }, - { - "id": "358908cd.416ab", - "type": "ui_form", - "z": "b771c342.49603", - "name": "net_throw_location", - "label": "Net Throw Location", - "group": "cf5d9f0e.d57e7", - "order": 3, - "width": 0, - "height": 0, - "options": [ - { - "label": "Latitude (36.574439°N or 36°57.4439'N)", - "value": "object_lat", - "type": "text", - "required": true, - "rows": null - }, - { - "label": "Longitude (110.42100°W or 110°4.2100'W)", - "value": "object_lon", - "type": "text", - "required": true, - "rows": null - }, - { - "label": "Date (YYYY-MM-DD UTC)", - "value": "object_date", - "type": "text", - "required": true, - "rows": null - }, - { - "label": "Time (HH:MM, UTC 24h)", - "value": "object_time", - "type": "text", - "required": true, - "rows": null - } - ], - "formValue": { - "object_lat": "", - "object_lon": "", - "object_date": "", - "object_time": "" - }, - "payload": "", - "submit": "Validate", - "cancel": "", - "topic": "net_throw_location", - "topicType": "str", - "splitLayout": false, - "className": "", - "x": 650, - "y": 620, - "wires": [["14658615.47c862", "cc67c97f55a340d3"]] - }, - { - "id": "56d40584.eff4e4", - "type": "ui_form", - "z": "b771c342.49603", - "name": "net_retrieval_location", - "label": "Net Retrieval Location", - "group": "cf5d9f0e.d57e7", - "order": 4, - "width": 0, - "height": 0, - "options": [ - { - "label": "Latitude (36.574439°N or 36°57.4439'N)", - "value": "object_lat_end", - "type": "text", - "required": true, - "rows": null - }, - { - "label": "Longitude (110.42100°W or 110°4.2100'W)", - "value": "object_lon_end", - "type": "text", - "required": true, - "rows": null - }, - { - "label": "Date (YYYY-MM-DD UTC)", - "value": "object_date_end", - "type": "text", - "required": true, - "rows": null - }, - { - "label": "Time (HH:MM, UTC 24h)", - "value": "object_time_end", - "type": "text", - "required": true, - "rows": null - } - ], - "formValue": { - "object_lat_end": "", - "object_lon_end": "", - "object_date_end": "", - "object_time_end": "" - }, - "payload": "", - "submit": "Validate", - "cancel": "", - "topic": "net_retrieval_location", - "topicType": "str", - "splitLayout": false, - "x": 640, - "y": 660, - "wires": [["14658615.47c862", "9c8f370d124a55e4"]] - }, - { - "id": "14658615.47c862", - "type": "function", - "z": "b771c342.49603", - "name": "Validate Location / Timestamp", - "func": "// Code added here will be run once\n// whenever the node is started.\nfunction ConvertDDMMToDD(input) {\n // Input Format 36°57.4439'N, 110°4.2100'W\n // From https://stackoverflow.com/questions/1140189/converting-latitude-and-longitude-to-decimal-values\n if (!input.match(/\\d+°\\d+\\.*\\d*\\'[NSEW]/)){\n \treturn \"parsing error\"\n }\n var parts = input.split(/[^\\d.\\w]+/)\n if (parts.length != 3){\n \treturn \"parsing error\"\n }\n var dd = Number(parts[0]) + Number(parts[1])/60\n return dd.toFixed(6) + parts[2]\n}\n\nfunction ValidateCoordinates(input, lat){\n // Input Format 36.574439°N, 110.42100°W\n // Or 36°57.4439'N, 110°4.2100'W\n if (input.match(\"'\")){\n input = ConvertDDMMToDD(input)\n }\n \n var error = {}\n\n if (input.startsWith(\"parsing error\")){\n error.topic = \"Error with the \"\n error.payload = \"You need to respect the format example, 36.574439°N or 36°57.4439'N\"\n return [null, error]\n }\n \n var direction = input.match(/[NSEW]/)\n var position = input.match(/[\\+\\-\\d\\.]+/)\n \n if (direction === null){\n error.topic = \"Error with the \"\n error.payload = \"You need to explicitely enter N/S/E/W\"\n return [null, error]\n }\n \n // Test that position is only made of digits!\n if(/^[\\+\\-]/.test(position)){\n error.topic = \"Error with the \"\n error.payload = \"Use of +/- sign is inconsistent with N/S/E/W letter! Please only use N/S/E/W!\"\n return [null, error]\n }\n \n var dd = Number(position)\n if (lat){\n // Check latitude\n if (direction == \"S\" || direction == \"N\") {\n if (dd>90.0){\n error.topic = \"Error with the \"\n error.payload = \"Latitude is more than 90°\"\n return [null, error]\n }\n }\n if (direction == \"W\" || direction == \"E\") {\n error.topic = \"Error with the \"\n error.payload = \"This is not a Latitude!\"\n return [null, error]\n }\n }\n else{\n // Check longitude\n if (direction == \"W\" || direction == \"E\") {\n if (dd>180.0){\n error.topic = \"Error with the \"\n error.payload = \"Longitude is more than 180°\"\n return [null, error]\n }\n }\n if (direction == \"N\" || direction == \"S\") {\n error.topic = \"Error with the \"\n error.payload = \"This is not a Longitude!\"\n return [null, error]\n }\n }\n \n if (direction == \"S\" || direction == \"W\") {\n dd = dd * -1\n } // Don't do anything for N or E\n return [dd.toFixed(4), null]\n \n}\n\nfunction ValidateDate(input){\n // Input Format 2020-12-25\n var error = {};\n \n if (! /20\\d{2}-[0-1]\\d-[0-3]\\d/.test(input)){\n error.topic = \"Error with the date\";\n error.payload = \"The date should respect the ISO format YYYY-MM-DD\";\n return [null, error];\n }\n else {\n var date = input.match(/\\d+/g);\n if (!((2000 < date[0]) && (date[0] < 2100))){\n error.topic = \"Error with the date\"\n error.payload = \"The year should be between 2000 and 2100\"\n return [null, error]\n }\n else if (!((0 < date[1]) && (date[1] <= 12))){\n error.topic = \"Error with the date\"\n error.payload = \"The month should be between 01 and 12\"\n return [null, error]\n }\n else if (!((0 < date[2]) && (date[2] <= 31))){\n error.topic = \"Error with the date\"\n error.payload = \"The day should be between 01 and 31\"\n return [null, error]\n }\n }\n return [input.replace(/-/g, ''), null]\n}\n\nfunction ValidateTime(input){\n // Input Format 12:00\n var error = {}\n \n if (! /[0-2]?\\d:[0-5]\\d/.test(input)){\n error.topic = \"Error with the time\"\n error.payload = \"The date should respect the ISO format HH:MM\"\n return [null, error]\n }\n else {\n var time = input.match(/\\d+/g)\n \n if (!((0 <= time[0]) && (time[0] < 24))){\n error.topic = \"Error with the time\"\n error.payload = \"The hours should be 0 and 23.\"\n return [null, error]\n }\n else if (!((0 <= time[1]) && (time[1] < 60))){\n error.topic = \"Error with the time\"\n error.payload = \"The minutes should be between 0 and 59\"\n return [null, error]\n }\n }\n return [input.replace(/:/g, ''), null]\n}\n\n\nvar ret\nvar payload_for_form = {payload:{}}\nmsg.valid = false\n\nif (msg.topic == \"culture_timestamp\"){\n ret = ValidateDate(msg.payload.object_date)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_date\", ret[0])\n \n ret = ValidateTime(msg.payload.object_time)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_time\", ret[0])\n return [{topic: \"Date and time format valid!\", payload: \"All good!\", valid: true}, payload_for_form]\n}\nelse if (msg.topic == \"net_retrieval_location\"){\n ret = ValidateCoordinates(msg.payload.object_lat_end, true);\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" Latitude\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_lat_end\", ret[0])\n ret = ValidateCoordinates(msg.payload.object_lon_end, false)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" Longitude\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_lon_end\", ret[0]);\n \n ret = ValidateDate(msg.payload.object_date_end)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample retrieval\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_date_end\", ret[0])\n \n ret = ValidateTime(msg.payload.object_time_end)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample retrieval\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_time_end\", ret[0])\n}\nelse{\n ret = ValidateCoordinates(msg.payload.object_lat, true);\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" Latitude\";\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_lat\", ret[0]);\n payload_for_form.payload[\"object_lat_end\"] = msg.payload.object_lat;\n \n ret = ValidateCoordinates(msg.payload.object_lon, false);\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" Longitude\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_lon\", ret[0])\n payload_for_form.payload[\"object_lon_end\"] = msg.payload.object_lon;\n\n ret = ValidateDate(msg.payload.object_date)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_date\", ret[0])\n payload_for_form.payload[\"object_date_end\"] = msg.payload.object_date;\n \n ret = ValidateTime(msg.payload.object_time)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_time\", ret[0])\n payload_for_form.payload[\"object_time_end\"] = msg.payload.object_time;\n}\nreturn [{topic: \"Coordinates valid!\", payload: \"All good!\", valid: true}, payload_for_form]\n", - "outputs": 2, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 930, - "y": 620, - "wires": [["c0ce5626.b6c5", "9a18a4b4.178448"], ["56d40584.eff4e4"]], - "inputLabels": ["Location form data"], - "outputLabels": ["Message", "Location validated"] - }, - { - "id": "46eb1bf8.3dc5f4", - "type": "function", - "z": "b771c342.49603", - "name": "Net check", - "func": "var decknet = {}\nvar activation_msg = {}\n\nif (msg.payload.startsWith(\"net_decknet\")){\n decknet.enabled = true;\n}\nelse {\n decknet.enabled = false;\n}\n\nif (msg.payload.startsWith(\"net\")){\n activation_msg.payload = {\"group\":{\"show\":[\"Sample_Net_Metadata\"],\"hide\":[\"Sample_Sample_Location\",\"Sample_Culture_Date_and_Time\"]}};\n}\nelse if (msg.payload != \"culture\" && msg.payload != \"test\"){\n activation_msg.payload = {\"group\":{\"show\":[\"Sample_Sample_Location\"], \"hide\":[\"Sample_Net_Metadata\",\"Sample_Culture_Date_and_Time\"]}};\n}\n\n\nreturn [decknet, activation_msg];", - "outputs": 2, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 1080, - "y": 240, - "wires": [ - ["516375fd.2ed61c", "470e382a.25691", "fbe32ac8.ff6a38"], - ["cbb123ab.fd3428"] - ], - "outputLabels": ["decknet activation", "group display control"] - }, - { - "id": "516375fd.2ed61c", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "sample_total_flowmeter_start", - "label": "Decknet flowmeter start", - "tooltip": "in L", - "group": "cf5d9f0e.d57e7", - "order": 6, - "width": 5, - "height": 1, - "passthru": false, - "mode": "text", - "delay": "300", - "topic": "sample_total_flowmeter_start", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 1340, - "y": 220, - "wires": [["e9bc112c.eb75f8"]] - }, - { - "id": "470e382a.25691", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "sample_total_flowmeter_end", - "label": "Decknet flowmeter end", - "tooltip": "in L", - "group": "cf5d9f0e.d57e7", - "order": 7, - "width": 5, - "height": 1, - "passthru": false, - "mode": "text", - "delay": "300", - "topic": "sample_total_flowmeter_end", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 1340, - "y": 260, - "wires": [["e9bc112c.eb75f8"]] - }, - { - "id": "fbe32ac8.ff6a38", - "type": "ui_template", - "z": "b771c342.49603", - "group": "cf5d9f0e.d57e7", - "name": "Decknet flowmeter read", - "order": 5, - "width": 10, - "height": 1, - "format": "
\n

Decknet flowmeter readings

\n

Those values are used to calculate sample_total_volume. Values are in L.

\n
\n", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": true, - "templateScope": "local", - "x": 1330, - "y": 180, - "wires": [[]] - }, - { - "id": "f408a273.4fb538", - "type": "function", - "z": "b771c342.49603", - "name": "get sample_gear_net_opening", - "func": "if (msg.payload.sample_gear_net_opening === null){\n msg.payload = 0;\n global.set(\"sample_gear_net_opening\",msg.payload);\n}\nelse\n{\n msg.payload = msg.payload.sample_gear_net_opening;\n}\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 350, - "y": 320, - "wires": [["e967b844.46aa48"]] - }, - { - "id": "8dff1648.82e42", - "type": "function", - "z": "b771c342.49603", - "name": "get object_depth_max", - "func": "if (msg.payload.object_depth_max === null){\n msg.payload = 0;\n global.set(\"object_depth_max\",msg.payload);\n}\nelse\n{\n msg.payload = msg.payload.object_depth_max;\n}\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 320, - "y": 240, - "wires": [["9c7f7fc9.c8d3a"]] - }, - { - "id": "9f04c5ec.75f3d8", - "type": "function", - "z": "b771c342.49603", - "name": "get object_depth_min", - "func": "if (msg.payload.object_depth_min === null){\n msg.payload = 0;\n global.set(\"object_depth_min\",msg.payload);\n}\nelse\n{\n msg.payload = msg.payload.object_depth_min;\n}\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 320, - "y": 280, - "wires": [["317eeeb7.8d3042"]] - }, - { - "id": "9a18a4b4.178448", - "type": "function", - "z": "b771c342.49603", - "name": "calculate sample_total_volume", - "func": "\n/*object_lat = 33.95 \nobject_lon = 118.4 \nobject_lat_end = 40.6333 \nobject_lon_end = 73.78333\nsample_gear_net_opening = 40*/\n\n// Copyright 1997 Ed Williams. All rights reserved\n// Adapted by Romain Bazile - Ocean Trotter - 01-2021\n\ndecpl=4 // Dec places of minutes output\n\nellipse = {\"name\":\"WSG84\", \"a\":6378.137/1.852, \"invf\":298.257223563}\n\nfunction ComputeDistance(lat1, lon1, lat2, lon2){\n var d,crs12,crs21\n var argacos\n var a,invf\n \n // lat and lon in radian\n lat1=(Math.PI/180)*lat1\n lat2=(Math.PI/180)*lat2\n lon1=(Math.PI/180)*lon1\n lon2=(Math.PI/180)*lon2\n \n //alert(\"lat1=\" + lat1 + \"lon1=\" + lon1 +\"\\nlat2=\" +lat2+ \"lon2=\"+lon2)\n \n /* get distance conversion factor */\n dc=1.852 //km\n //alert(\"dc=\" +dc)\n \n //showProps(ellipse,\"ellipse\")\n \n // elliptic code\n d=crsdist_ell(lat1,-lon1,lat2,-lon2,ellipse) // ellipse uses East negative\n d=d*dc // go to physical units\n \n //alert(\"d=\"+d+\" crs12=\"+crs12+\" crs21=\"+crs21)\n return d\n}\n\nfunction crsdist(lat1,lon1,lat2,lon2){ // radian args\n /* compute course and distance (spherical) */\n if ((lat1+lat2===0) && (Math.abs(lon1-lon2)==Math.PI) && \n (Math.abs(lat1) != (Math.PI/180)*90)){\t\n \talert(\"Course between antipodal points is undefined\")\n }\n \n d = Math.acos(Math.sin(lat1)*Math.sin(lat2)+Math.cos(lat1)*Math.cos(lat2)*Math.cos(lon1-lon2))\n return d\n}\n\nfunction crsdist_ell(glat1,glon1,glat2,glon2,ellipse){\n // glat1 initial geodetic latitude in radians N positive \n // glon1 initial geodetic longitude in radians E positive \n // glat2 final geodetic latitude in radians N positive \n // glon2 final geodetic longitude in radians E positive \n a=ellipse.a\n f=1/ellipse.invf\n //alert(\"a=\"+a+\" f=\"+f)\n var r, tu1, tu2, cu1, su1, cu2, s1, b1, f1\n var x, sx, cx, sy, cy,y, sa, c2a, cz, e, c, d\n var EPS= 0.00000000005\n var faz, baz, s\n var iter=1\n var MAXITER=100\n if ((glat1+glat2===0) && (Math.abs(glon1-glon2)==Math.PI)){\n alert(\"Course and distance between antipodal points is undefined\")\n glat1=glat1+0.00001 // allow algorithm to complete\n }\n if (glat1==glat2 && (glon1==glon2 || Math.abs(Math.abs(glon1-glon2)-2*Math.PI) < EPS)){\n alert(\"Points 1 and 2 are identical- course undefined\")\n out=new MakeArray(0)\n out.d=0\n out.crs12=0\n out.crs21=Math.PI\n return out\n }\n r = 1 - f\n tu1 = r * Math.tan (glat1)\n tu2 = r * Math.tan (glat2)\n cu1 = 1 / Math.sqrt (1 + tu1 * tu1)\n su1 = cu1 * tu1\n cu2 = 1 / Math.sqrt (1 + tu2 * tu2)\n s1 = cu1 * cu2\n b1 = s1 * tu2\n f1 = b1 * tu1\n x = glon2 - glon1\n d = x + 1 // force one pass\n while ((Math.abs(d - x) > EPS) && (iter < MAXITER))\n {\n iter=iter+1\n sx = Math.sin (x)\n // alert(\"sx=\"+sx)\n cx = Math.cos (x)\n tu1 = cu2 * sx\n tu2 = b1 - su1 * cu2 * cx\n sy = Math.sqrt(tu1 * tu1 + tu2 * tu2)\n cy = s1 * cx + f1\n y = atan2 (sy, cy)\n sa = s1 * sx / sy\n c2a = 1 - sa * sa\n cz = f1 + f1\n if (c2a > 0)\n cz = cy - cz / c2a\n e = cz * cz * 2 - 1\n c = ((-3 * c2a + 4) * f + 4) * c2a * f / 16\n d = x\n x = ((e * cy * c + cz) * sy * c + y) * sa\n x = (1 - c) * x * f + glon2 - glon1\n }\n x = Math.sqrt ((1 / (r * r) - 1) * c2a + 1)\n x +=1\n x = (x - 2) / x\n c = 1 - x\n c = (x * x / 4 + 1) / c\n d = (0.375 * x * x - 1) * x\n x = e * cy\n d = ((((sy*sy*4-3)*(1-e-e)*cz*d/6-x)*d/4+cz)*sy*d+y)*c*a*r\n if (Math.abs(iter-MAXITER)0) && (y>=0)){ out= Math.atan(y/x)}\n if ((x >0) && (y<0)) { out= Math.atan(y/x)+2*Math.PI}\n if ((x===0) && (y>0)) { out= Math.PI/2}\n if ((x===0) && (y<0)) { out= 3*Math.PI/2} \n if ((x===0) && (y===0)) {\n alert(\"atan2(0,0) undefined\")\n out= 0\n } \n return out\n}\n\nfunction showProps(obj,objName){\n var result=\"\"\n for (var i in obj){\n result +=objName + \".\" + i + \" = \" + obj[i] + \"\\n\"\n }\n alert(result)\n}\n\n\nif (msg.valid){\n msg.topic=\"sample_total_volume\"\n \n var object_lat_end = global.get(\"object_lat_end\")\n var object_lon_end = global.get(\"object_lon_end\")\n var sample_sampling_gear = global.get(\"sample_sampling_gear\")\n \n if (sample_sampling_gear.startsWith(\"net\") && sample_sampling_gear != \"net_decknet\") {\n if (!(isNaN(object_lat_end) && isNaN(object_lon_end))){\n var object_lat = global.get(\"object_lat\")\n var object_lon = global.get(\"object_lon\")\n var sample_gear_net_opening = global.get(\"sample_gear_net_opening\");\n\n distance_km = ComputeDistance(object_lat, object_lon, object_lat_end, object_lon_end)\n\n sample_total_volume = distance_km*(Math.PI*(sample_gear_net_opening/2)*(sample_gear_net_opening/2)) // liters\n sample_total_volume = Math.round(sample_total_volume + Number.EPSILON)\n msg.payload = sample_total_volume\n return msg\n }\n }\n}", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 930, - "y": 760, - "wires": [["4f6afc5a.81e454"]] - }, - { - "id": "4fb4e0ad.c417c", - "type": "ui_text", - "z": "b771c342.49603", - "group": "fc5e4e6f.5b1c8", - "order": 6, - "width": 5, - "height": 1, - "name": "Latitude", - "label": "Latitude", - "format": "{{msg.payload.lat.deg}}°{{msg.payload.lat.min}}'{{msg.payload.lat.sec}}{{msg.payload.lat.dir}}", - "layout": "col-center", - "x": 700, - "y": 1120, - "wires": [] - }, - { - "id": "8d2b5026.13e6e8", - "type": "ui_text", - "z": "b771c342.49603", - "group": "fc5e4e6f.5b1c8", - "order": 7, - "width": 5, - "height": 1, - "name": "Longitude", - "label": "Longitude", - "format": "{{msg.payload.lon.deg}}°{{msg.payload.lon.min}}'{{msg.payload.lon.sec}}{{msg.payload.lon.dir}}", - "layout": "col-center", - "x": 700, - "y": 1160, - "wires": [] - }, - { - "id": "258b4562.9f778a", - "type": "function", - "z": "b771c342.49603", - "name": "Convert DD to DMS", - "func": "function ConvertDDToDMS(D, lng){\n // from https://stackoverflow.com/a/5786281/2108279\n return {\n dir : D<0?lng?'W':'S':lng?'E':'N',\n deg : 0|(D<0?D=-D:D),\n min : 0|D%1*60,\n sec :(0|D*60%1*6000)/100\n };\n}\n\nmsg.payload = {\n \"lat\":ConvertDDToDMS(msg.payload.lat, false),\n \"lon\":ConvertDDToDMS(msg.payload.lon, true)\n};\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 490, - "y": 1140, - "wires": [["4fb4e0ad.c417c", "8d2b5026.13e6e8"]] - }, - { - "id": "7c4ce5f3.62dd5c", - "type": "ui_text", - "z": "b771c342.49603", - "group": "fc5e4e6f.5b1c8", - "order": 4, - "width": 2, - "height": 1, - "name": "Speed", - "label": "Speed", - "format": "{{msg.payload}} kts", - "layout": "col-center", - "x": 690, - "y": 1200, - "wires": [] - }, - { - "id": "54e37580.fdc31c", - "type": "ui_text", - "z": "b771c342.49603", - "group": "fc5e4e6f.5b1c8", - "order": 5, - "width": 2, - "height": 1, - "name": "Direction", - "label": "Direction", - "format": "{{msg.payload.track}} °", - "layout": "col-center", - "x": 700, - "y": 1240, - "wires": [] - }, - { - "id": "cc21ca16.b92928", - "type": "function", - "z": "b771c342.49603", - "name": "GPS Mode", - "func": "switch (msg.payload.mode){\n case 1:msg.payload = \"No Fix\"; break\n case 2:msg.payload = \"2D Fix\"; break\n case 3:msg.payload = \"3D Fix\"; break\n default: msg.payload = \"No info\"\n}\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 470, - "y": 1080, - "wires": [["7116e906.9f50f"]] - }, - { - "id": "4a4de52c.cf2884", - "type": "function", - "z": "b771c342.49603", - "name": "Speed conversion", - "func": "msg.payload = (0|msg.payload.speed) * 1.9438\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 490, - "y": 1200, - "wires": [["7c4ce5f3.62dd5c"]] - }, - { - "id": "35ad311f.344c76", - "type": "ui_text", - "z": "b771c342.49603", - "group": "fc5e4e6f.5b1c8", - "order": 2, - "width": 5, - "height": 1, - "name": "Time", - "label": "Time", - "format": "{{msg.payload.time}}", - "layout": "col-center", - "x": 690, - "y": 1280, - "wires": [] - }, - { - "id": "e73fd87d.d24e4", - "type": "function", - "z": "b771c342.49603", - "name": "get acq_minimum_mesh", - "func": "msg.payload = msg.payload.acq_minimum_mesh;\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 330, - "y": 360, - "wires": [["1aad56b31b5647ce"]] - }, - { - "id": "489c8e06.cc7d6", - "type": "function", - "z": "b771c342.49603", - "name": "get acq_maximum_mesh", - "func": "msg.payload = msg.payload.acq_maximum_mesh;\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 330, - "y": 400, - "wires": [["10eb31a2d7a6590c"]] - }, - { - "id": "73c4a14a.9b93c8", - "type": "function", - "z": "b771c342.49603", - "name": "Convert time", - "func": "msg.payload.time = msg.payload.time.replace('T', ' ');\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 470, - "y": 1280, - "wires": [["35ad311f.344c76"]] - }, - { - "id": "58de1340.3cc354", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "sample_dilution_factor", - "label": "Concentration Factor", - "tooltip": "0.5 if diluted by two; 2 if concentrated by a factor 2", - "group": "3e1ba03d.f01d8", - "order": 13, - "width": 10, - "height": 1, - "passthru": true, - "mode": "number", - "delay": "300", - "topic": "sample_dilution_factor", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 640, - "y": 480, - "wires": [["9f501f49.45645"]] - }, - { - "id": "4f6afc5a.81e454", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "sample_total_volume", - "label": "Filtered volume (in L)", - "tooltip": "Calculated or hand filled", - "group": "3e1ba03d.f01d8", - "order": 11, - "width": 0, - "height": 0, - "passthru": true, - "mode": "text", - "delay": "300", - "topic": "sample_total_volume", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 1220, - "y": 760, - "wires": [["e1f2f6eb.fe1dd"]] - }, - { - "id": "e1f2f6eb.fe1dd", - "type": "function", - "z": "b771c342.49603", - "name": "set global", - "func": "global.set(msg.topic,msg.payload);", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 1420, - "y": 760, - "wires": [[]] - }, - { - "id": "e9bc112c.eb75f8", - "type": "function", - "z": "b771c342.49603", - "name": "Calculate volume", - "func": "if (msg.topic == \"sample_total_flowmeter_start\"){\n context.set(\"sample_total_flowmeter_start\", msg.payload);\n}\nif (msg.topic == \"sample_total_flowmeter_end\"){\n context.set(\"sample_total_flowmeter_end\", msg.payload);\n}\n\nif (context.keys().length == 2){\n sample_total_volume = context.get(\"sample_total_flowmeter_end\") - context.get(\"sample_total_flowmeter_start\");\n msg.topic=\"sample_total_volume\"\n msg.payload=sample_total_volume\n return msg\n}\n", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 1610, - "y": 240, - "wires": [["4f6afc5a.81e454"]] - }, - { - "id": "cdd4181922eecf11", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "sample_speed_through_water", - "label": "Speed Through Water (kts)", - "tooltip": "in knots", - "group": "cf5d9f0e.d57e7", - "order": 2, - "width": 10, - "height": 1, - "passthru": true, - "mode": "number", - "delay": "300", - "topic": "sample_speed_through_water", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 610, - "y": 520, - "wires": [["9f501f49.45645"]] - }, - { - "id": "1aad56b31b5647ce", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "acq_minimum_mesh", - "label": "Minimal fraction size (μm)", - "tooltip": "Net mesh pore size or minimal filtration mesh pore size", - "group": "3e1ba03d.f01d8", - "order": 7, - "width": 5, - "height": 1, - "passthru": true, - "mode": "number", - "delay": "300", - "topic": "acq_minimum_mesh", - "topicType": "str", - "x": 640, - "y": 360, - "wires": [["9f501f49.45645"]] - }, - { - "id": "10eb31a2d7a6590c", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "acq_maximum_mesh", - "label": "Maximal fraction size (μm)", - "tooltip": "Maximal filtration mesh pore size", - "group": "3e1ba03d.f01d8", - "order": 8, - "width": 5, - "height": 1, - "passthru": true, - "mode": "number", - "delay": "300", - "topic": "acq_maximum_mesh", - "topicType": "str", - "x": 640, - "y": 400, - "wires": [["9f501f49.45645"]] - }, - { - "id": "3ac7b631f5d8ef90", - "type": "function", - "z": "b771c342.49603", - "name": "Culture check", - "func": "var activation_msg = {}\nvar date_msg = {}\nvar timestamp=new Date().toISOString();\n\nif (msg.payload === \"culture\"){\n activation_msg.payload = {\"group\":{\"show\":[\"Sample_Culture_Date_and_Time\"],\"hide\":[\"Sample_Sample_Location\", \"Sample_Net_Metadata\"]}};\n global.set(\"object_lat\", \"-90.0000\")\n global.set(\"object_lon\", \"0.0000\")\n date_msg.payload = {\"object_date\": timestamp.split('T')[0],\n \"object_time\": timestamp.split('T')[1].split('.')[0]}\n return [activation_msg, date_msg];\n}\nelse if (msg.payload === \"test\"){\n activation_msg.payload = {\"group\":{\"hide\":[\"Sample_Culture_Date_and_Time\", \"Sample_Sample_Location\", \"Sample_Net_Metadata\"]}};\n global.set(\"object_lat\", \"-90.0000\")\n global.set(\"object_lon\", \"0.0000\")\n global.set(\"object_date\", timestamp.split('T')[0])\n global.set(\"object_time\", timestamp.split('T')[1].split('.')[0])\n return [activation_msg, null];\n}\nelse{\n return [null, null]\n}\n\n", - "outputs": 2, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 1100, - "y": 320, - "wires": [["cbb123ab.fd3428"], ["05c6aff2afbd69cf"]], - "outputLabels": ["decknet activation", ""] - }, - { - "id": "05c6aff2afbd69cf", - "type": "ui_form", - "z": "b771c342.49603", - "name": "culture_timestamp", - "label": "Culture timestamp", - "group": "7bc0a4c416e4545c", - "order": 1, - "width": 0, - "height": 0, - "options": [ - { - "label": "Date (YYYY-MM-DD, UTC)", - "value": "object_date", - "type": "text", - "required": true, - "rows": null - }, - { - "label": "Time (HH:MM(:SS), UTC 24h)", - "value": "object_time", - "type": "text", - "required": true, - "rows": null - } - ], - "formValue": { - "object_date": "", - "object_time": "" - }, - "payload": "", - "submit": "Validate", - "cancel": "Reset", - "topic": "culture_timestamp", - "topicType": "str", - "splitLayout": false, - "className": "", - "x": 650, - "y": 700, - "wires": [["14658615.47c862", "38616e738f4f615b"]] - }, - { - "id": "3318a1aaa70fc2ee", - "type": "change", - "z": "b771c342.49603", - "name": "Repopulate input fields", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 400, - "y": 580, - "wires": [["c33f1124.af6688"]] - }, - { - "id": "cc67c97f55a340d3", - "type": "change", - "z": "b771c342.49603", - "name": "Repopulate input fields", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 400, - "y": 620, - "wires": [["358908cd.416ab"]] - }, - { - "id": "9c8f370d124a55e4", - "type": "change", - "z": "b771c342.49603", - "name": "Repopulate input fields", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 400, - "y": 660, - "wires": [["56d40584.eff4e4"]] - }, - { - "id": "38616e738f4f615b", - "type": "change", - "z": "b771c342.49603", - "name": "Repopulate input fields", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 400, - "y": 700, - "wires": [["05c6aff2afbd69cf"]] - }, - { - "id": "577be9c22c739ca0", - "type": "inject", - "z": "b771c342.49603", - "name": "", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "", - "payload": "1", - "payloadType": "num", - "x": 270, - "y": 480, - "wires": [["58de1340.3cc354"]] - }, - { - "id": "6a84252a.d52a0c", - "type": "ui_template", - "z": "bccd1f23.87219", - "group": "833bc5bb.217ba8", - "name": "Stream Pi Camera", - "order": 1, - "width": 18, - "height": 14, - "format": "
\n \"If\n
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "className": "", - "x": 610, - "y": 40, - "wires": [[]] - }, - { - "id": "dc48dc42.98d18", - "type": "function", - "z": "bccd1f23.87219", - "name": "set global", - "func": "global.set(msg.topic,msg.payload);", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 880, - "y": 440, - "wires": [[]] - }, - { - "id": "811cd88c.daf528", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "down", - "group": "fbd92986.1028c8", - "order": 6, - "width": 4, - "height": 1, - "passthru": true, - "label": "", - "tooltip": "", - "color": "", - "bgcolor": "", - "icon": "fa-angle-double-down fa-3x", - "payload": "DOWN", - "payloadType": "str", - "topic": "actuator/focus", - "x": 550, - "y": 800, - "wires": [["65ad39d.b6d4d48"]] - }, - { - "id": "edda4df4.76de2", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "up", - "group": "fbd92986.1028c8", - "order": 3, - "width": 4, - "height": 1, - "passthru": false, - "label": "", - "tooltip": "", - "color": "", - "bgcolor": "", - "icon": "fa-angle-double-up fa-3x", - "payload": "UP", - "payloadType": "str", - "topic": "actuator/focus", - "x": 550, - "y": 760, - "wires": [["65ad39d.b6d4d48"]] - }, - { - "id": "68962547.34a67c", - "type": "ui_text_input", - "z": "bccd1f23.87219", - "name": "pump_manual_volume", - "label": "Volume to pass (ml)", - "tooltip": "Tiny values are accepted down to 0.001mL", - "group": "707d9797.c8e798", - "order": 3, - "width": 2, - "height": 1, - "passthru": true, - "mode": "text", - "delay": "300", - "topic": "pump_manual_volume", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 600, - "y": 420, - "wires": [["dc48dc42.98d18"]] - }, - { - "id": "6c792043.b6ff9", - "type": "ui_ui_control", - "z": "bccd1f23.87219", - "name": "", - "events": "change", - "x": 560, - "y": 1140, - "wires": [[]] - }, - { - "id": "902429eb.ceacb8", - "type": "ui_toast", - "z": "bccd1f23.87219", - "position": "dialog", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 1, - "ok": "OK", - "cancel": "", - "raw": false, - "topic": "", - "name": "", - "x": 570, - "y": 1220, - "wires": [[]] - }, - { - "id": "fe840e05.b46f3", - "type": "function", - "z": "bccd1f23.87219", - "name": "Check form", - "func": "var acq_fnumber_objective= global.get(\"acq_fnumber_objective\");\n\nif (acq_fnumber_objective === undefined || acq_fnumber_objective === \"\") {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Focal Length of the objective\";\n return [null, msg];\n}\n\nmsg.topic = \"Change Tab\";\nmsg.payload={\"tab\":\"Fluidic Acquisition\"};\nreturn [msg, null];", - "outputs": 2, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 330, - "y": 1180, - "wires": [["6c792043.b6ff9", "326a1d95.ca21aa"], ["902429eb.ceacb8"]], - "outputLabels": ["message", "error"] - }, - { - "id": "5846b1d4.7971b", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "Backward", - "group": "707d9797.c8e798", - "order": 2, - "width": 1, - "height": 1, - "passthru": false, - "label": "", - "tooltip": "", - "color": "", - "bgcolor": "", - "icon": "fa-rotate-left fa-2x", - "payload": "BACKWARD", - "payloadType": "str", - "topic": "actuator/pump", - "x": 560, - "y": 280, - "wires": [["3cb96380.e575ec"]] - }, - { - "id": "2cab680b.baf888", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "Forward", - "group": "707d9797.c8e798", - "order": 4, - "width": 1, - "height": 1, - "passthru": true, - "label": "", - "tooltip": "", - "color": "", - "bgcolor": "", - "icon": "fa-rotate-right fa-2x", - "payload": "FORWARD", - "payloadType": "str", - "topic": "actuator/pump", - "x": 560, - "y": 320, - "wires": [["3cb96380.e575ec"]] - }, - { - "id": "8038414a.34461", - "type": "function", - "z": "bccd1f23.87219", - "name": "Calculate optics", - "func": "var acq_fnumber_objective = String(global.get(\"acq_fnumber_objective\"));\nvar acq_camera = global.get(\"acq_camera\")\n\n// Those values needs to be recalculated, they are not good!\nif (acq_camera == \"HQ Camera\"){\n switch(acq_fnumber_objective) {\n case \"25\":\n acq_magnification= 0.6;\n process_pixel= 1.56;\n sug_min= 60;\n sug_max= 670;\n sug_flowrate= 3;\n break;\n case \"16\":\n acq_magnification= 1.6;\n process_pixel= 1.01;\n sug_min= 40;\n sug_max= 430;\n sug_flowrate= 2.4;\n break;\n case \"12\":\n acq_magnification= 1.20;\n process_pixel= 0.79;\n sug_min= 30;\n sug_max= 340;\n sug_flowrate= 1.25;\n break;\n case \"8\":\n acq_magnification= 1.78;\n process_pixel= 0.53;\n sug_min= 20;\n sug_max= 230;\n sug_flowrate= 0.42;\n break;\n case \"6\":\n acq_magnification= 2.36;\n process_pixel= 0.41;\n sug_min= 15;\n sug_max= 170;\n sug_flowrate= 0.32;\n break;\n }\n}\nelse if (acq_camera == \"Camera v2.1\"){\n switch(acq_fnumber_objective) {\n case \"25\":\n acq_magnification= 0.6;\n process_pixel= 1.86;\n sug_min= 60;\n sug_max= 670;\n sug_flowrate= 3;\n break;\n case \"16\":\n acq_magnification= 1.6;\n process_pixel= 0.7;\n sug_min= 40;\n sug_max= 430;\n sug_flowrate= 2.4;\n break;\n case \"12\":\n acq_magnification= 1.20;\n process_pixel= 0.94;\n sug_min= 30;\n sug_max= 340;\n sug_flowrate= 1.25;\n break;\n case \"8\":\n acq_magnification= 1.78;\n process_pixel= 0.63;\n sug_min= 20;\n sug_max= 230;\n sug_flowrate= 0.42;\n break;\n case \"6\":\n acq_magnification= 2.36;\n process_pixel= 0.48;\n sug_min= 15;\n sug_max= 170;\n sug_flowrate= 0.32;\n break;\n }\n}else {\n acq_magnification= \"ERROR\";\n process_pixel= \"ERROR\";\n sug_min= \"ERROR\";\n sug_max= \"ERROR\";\n sug_flowrate= \"ERROR\";\n}\n\nvar process_pixel_fixed = global.get(\"process_pixel_fixed\")\n\nif (process_pixel_fixed !== undefined && process_pixel_fixed !== \"\") {\n process_pixel = process_pixel_fixed\n}\n\nglobal.set(\"process_pixel\",process_pixel);\n\nglobal.set(\"acq_magnification\",acq_magnification);\n\n\nreturn [{payload: acq_fnumber_objective}, {payload: acq_magnification}, {payload: process_pixel}, {payload: sug_min}, {payload: sug_max}];", - "outputs": 5, - "timeout": "", - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 1080, - "y": 120, - "wires": [[], [], [], [], []], - "inputLabels": ["acq_fnumber_objective"], - "outputLabels": [ - "acq_magnification", - "process_pixel", - "sug_min", - "sug_max", - "" - ] - }, - { - "id": "f61aaed5.1e64", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "", - "group": "7a0b4877.a5d268", - "order": 1, - "width": 2, - "height": 1, - "passthru": false, - "label": "Previous", - "tooltip": "", - "color": "#097479", - "bgcolor": "white", - "icon": "keyboard_return", - "payload": "{\"tab\":\"Sample\"}", - "payloadType": "json", - "topic": "", - "x": 140, - "y": 1140, - "wires": [["6c792043.b6ff9"]] - }, - { - "id": "9ba6ec0a.22c96", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "", - "group": "7a0b4877.a5d268", - "order": 2, - "width": 2, - "height": 1, - "passthru": false, - "label": "Continue", - "tooltip": "", - "color": "#097479", - "bgcolor": "white", - "icon": "keyboard_tab", - "payload": "{\"tab\":\"Home\"}", - "payloadType": "json", - "topic": "", - "x": 140, - "y": 1180, - "wires": [["fe840e05.b46f3"]] - }, - { - "id": "cbb8afed.0a026", - "type": "rpi-gpio out", - "z": "bccd1f23.87219", - "name": "LED Output", - "pin": "21", - "set": true, - "level": "0", - "freq": "", - "out": "out", - "bcm": true, - "x": 550, - "y": 120, - "wires": [] - }, - { - "id": "3cb96380.e575ec", - "type": "function", - "z": "bccd1f23.87219", - "name": "pump", - "func": "var manual_volume= global.get(\"pump_manual_volume\");\nvar flowrate= global.get(\"pump_flowrate\");\n\nif (manual_volume === undefined || manual_volume === \"\" || manual_volume === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Volume to pass\";\n return [null, msg];\n}\nelse if (flowrate === undefined || flowrate === \"\" || flowrate === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Flowrate\";\n return [null, msg];\n}\nelse {\n msg.topic = \"actuator/pump\";\n // msg.payload is FORWARD or BACKWARD here\n msg.payload={\"action\":\"move\", \n \"direction\":msg.payload,\n \"volume\":manual_volume,\n \"flowrate\":flowrate};\n}\nreturn [msg, null];", - "outputs": 2, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 750, - "y": 300, - "wires": [["bdc8ce57.de1f08"], ["8bcce348.efc1a"]], - "inputLabels": ["direction"], - "outputLabels": ["message", "error"] - }, - { - "id": "8bcce348.efc1a", - "type": "ui_toast", - "z": "bccd1f23.87219", - "position": "dialog", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 1, - "ok": "OK", - "cancel": "", - "raw": false, - "topic": "", - "name": "", - "x": 1090, - "y": 300, - "wires": [[]] - }, - { - "id": "bdc8ce57.de1f08", - "type": "mqtt out", - "z": "bccd1f23.87219", - "name": "", - "topic": "", - "qos": "", - "retain": "", - "broker": "8dc3722c.06efa8", - "x": 1210, - "y": 260, - "wires": [] - }, - { - "id": "d71d224f.0585d8", - "type": "ui_toast", - "z": "bccd1f23.87219", - "position": "dialog", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 1, - "ok": "OK", - "cancel": "", - "raw": false, - "topic": "", - "name": "", - "x": 1090, - "y": 800, - "wires": [[]] - }, - { - "id": "65ad39d.b6d4d48", - "type": "function", - "z": "bccd1f23.87219", - "name": "focus", - "func": "var distance = global.get(\"focus_distance\");\n\nif (distance === undefined || distance === \"\" || distance === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Distance\";\n return [null, msg]\n}else {\n distance = global.get(\"focus_distance\");\n // msg.payload is UP or DOWN here\n msg.payload={\"action\":\"move\", \n \"direction\":msg.payload,\n \"distance\":(distance/1000)};\n}\nreturn [msg, null];", - "outputs": 2, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 850, - "y": 780, - "wires": [["62030521.88317c"], ["d71d224f.0585d8"]], - "inputLabels": ["direction"], - "outputLabels": ["message", "error"] - }, - { - "id": "1962d999.4a97e6", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "stop focus", - "group": "fbd92986.1028c8", - "order": 9, - "width": 0, - "height": 0, - "passthru": true, - "label": " STOP FOCUS", - "tooltip": "", - "color": "", - "bgcolor": "#AD1625", - "icon": "fa-pause fa-2x", - "payload": "{\"action\":\"stop\"}", - "payloadType": "json", - "topic": "actuator/focus", - "x": 570, - "y": 560, - "wires": [["62030521.88317c"]] - }, - { - "id": "62030521.88317c", - "type": "mqtt out", - "z": "bccd1f23.87219", - "name": "", - "topic": "", - "qos": "", - "retain": "", - "broker": "8dc3722c.06efa8", - "x": 1210, - "y": 720, - "wires": [] - }, - { - "id": "3bd43039.bc5fb8", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "", - "group": "fbd92986.1028c8", - "order": 1, - "width": 4, - "height": 1, - "passthru": false, - "label": "UP 1mm", - "tooltip": "", - "color": "", - "bgcolor": "", - "icon": "fa-angle-up fa-3x", - "payload": "{\"action\":\"move\",\"direction\":\"UP\",\"distance\":1}", - "payloadType": "json", - "topic": "actuator/focus", - "topicType": "str", - "x": 560, - "y": 600, - "wires": [["62030521.88317c"]] - }, - { - "id": "c0663029.2d03b", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "", - "group": "fbd92986.1028c8", - "order": 8, - "width": 4, - "height": 1, - "passthru": false, - "label": "DOWN 1mm", - "tooltip": "", - "color": "", - "bgcolor": "", - "icon": "fa-angle-down fa-3x", - "payload": "{\"action\":\"move\",\"direction\":\"DOWN\",\"distance\":1}", - "payloadType": "json", - "topic": "actuator/focus", - "topicType": "str", - "x": 570, - "y": 720, - "wires": [["62030521.88317c"]] - }, - { - "id": "71f55a58.d7eaf4", - "type": "inject", - "z": "bccd1f23.87219", - "name": "Default: 500µm", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": "0.5", - "topic": "", - "payload": "500", - "payloadType": "num", - "x": 120, - "y": 460, - "wires": [["be33e564.029358"]] - }, - { - "id": "9a1d0e7c.2d5a1", - "type": "inject", - "z": "bccd1f23.87219", - "name": "Default: OFF", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "", - "payload": "off", - "payloadType": "str", - "x": 130, - "y": 120, - "wires": [["f0775525.cf806"]] - }, - { - "id": "f782a471.447748", - "type": "inject", - "z": "bccd1f23.87219", - "name": "Default: 2mL/min", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": "0.5", - "topic": "", - "payload": "2", - "payloadType": "num", - "x": 130, - "y": 380, - "wires": [["cb2d5174.cfe9f"]] - }, - { - "id": "73b8252a.5ca754", - "type": "inject", - "z": "bccd1f23.87219", - "name": "Default: 2mL", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": "0.5", - "topic": "", - "payload": "2", - "payloadType": "num", - "x": 110, - "y": 420, - "wires": [["68962547.34a67c"]] - }, - { - "id": "6451f991.aaac1", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "stop pump", - "group": "707d9797.c8e798", - "order": 5, - "width": 4, - "height": 1, - "passthru": true, - "label": " STOP PUMP", - "tooltip": "", - "color": "", - "bgcolor": "#AD1625", - "icon": "fa-pause fa-2x", - "payload": "{\"action\":\"stop\"}", - "payloadType": "json", - "topic": "actuator/pump", - "x": 570, - "y": 240, - "wires": [["bdc8ce57.de1f08"]] - }, - { - "id": "cfc783d7.d6ceb", - "type": "link in", - "z": "bccd1f23.87219", - "name": "Optics recalculation", - "links": ["559a8085.1d6b9", "5d5ad36d2c50dcc2"], - "x": 915, - "y": 120, - "wires": [["8038414a.34461"]] - }, - { - "id": "326a1d95.ca21aa", - "type": "subflow:1c24ad9c.bebec2", - "z": "bccd1f23.87219", - "name": "", - "x": 550, - "y": 1180, - "wires": [[]] - }, - { - "id": "2d371e59.b0e50a", - "type": "inject", - "z": "bccd1f23.87219", - "name": "Default: 1000µm/s", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": "0.5", - "topic": "", - "payload": "1000", - "payloadType": "num", - "x": 130, - "y": 500, - "wires": [["3a86de51.765b9a"]] - }, - { - "id": "167cda35.c9b6ae", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "", - "group": "fbd92986.1028c8", - "order": 2, - "width": 4, - "height": 1, - "passthru": false, - "label": "UP 100um", - "tooltip": "", - "color": "", - "bgcolor": "", - "icon": "fa-angle-up fa-3x", - "payload": "{\"action\":\"move\",\"direction\":\"UP\",\"distance\":0.1}", - "payloadType": "json", - "topic": "actuator/focus", - "topicType": "str", - "x": 570, - "y": 640, - "wires": [["62030521.88317c"]] - }, - { - "id": "72a7c597.9374fc", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "", - "group": "fbd92986.1028c8", - "order": 7, - "width": 4, - "height": 1, - "passthru": false, - "label": "DOWN 100um", - "tooltip": "", - "color": "", - "bgcolor": "", - "icon": "fa-angle-down fa-3x", - "payload": "{\"action\":\"move\",\"direction\":\"DOWN\",\"distance\":0.1}", - "payloadType": "json", - "topic": "actuator/focus", - "topicType": "str", - "x": 580, - "y": 680, - "wires": [["62030521.88317c"]] - }, - { - "id": "f0775525.cf806", - "type": "ui_multistate_switch", - "z": "bccd1f23.87219", - "name": "light_control", - "group": "4248342d.e55fac", - "order": 1, - "width": 5, - "height": 1, - "label": "Light ", - "stateField": "payload", - "enableField": "enable", - "rounded": true, - "useThemeColors": true, - "hideSelectedLabel": false, - "options": [ - { - "label": "Off", - "value": "0", - "valueType": "num", - "color": "#009933" - }, - { - "label": "On", - "value": "1", - "valueType": "num", - "color": "#999999" - } - ], - "x": 350, - "y": 120, - "wires": [["cbb8afed.0a026"]] - }, - { - "id": "8ea9dc9a.c7d87", - "type": "function", - "z": "bccd1f23.87219", - "name": "Encapsulate settings", - "func": "msg.payload = {\n \"action\":\"settings\", \n \"settings\":{[msg.topic]:msg.payload}\n}\n\nmsg.topic = \"imager/image\"\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 1120, - "y": 940, - "wires": [["845e06e1.0d812"]] - }, - { - "id": "5765a825.a595c8", - "type": "ui_slider", - "z": "bccd1f23.87219", - "name": "Shutter speed slider", - "label": "Shutter Speed", - "tooltip": "In microseconds, up to 1000µs, 125µs by default", - "group": "8c38a81e.9897a8", - "order": 4, - "width": 0, - "height": 0, - "passthru": true, - "outs": "end", - "topic": "shutter_speed", - "topicType": "str", - "min": "125", - "max": "1000", - "step": "1", - "className": "", - "x": 600, - "y": 880, - "wires": [["8ea9dc9a.c7d87"]] - }, - { - "id": "845e06e1.0d812", - "type": "mqtt out", - "z": "bccd1f23.87219", - "name": "", - "topic": "", - "qos": "", - "retain": "", - "broker": "8dc3722c.06efa8", - "x": 1390, - "y": 980, - "wires": [] - }, - { - "id": "2350e507.d4e302", - "type": "inject", - "z": "bccd1f23.87219", - "name": "Default: 125µs", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": "1", - "topic": "", - "payload": "125", - "payloadType": "num", - "x": 120, - "y": 880, - "wires": [["5765a825.a595c8"]] - }, - { - "id": "5e147425.7666ec", - "type": "function", - "z": "bccd1f23.87219", - "name": "Encapsulate wb gain settings", - "func": "msg.payload = {\n \"action\":\"settings\", \n \"settings\":{\"white_balance_gain\":{\n [msg.topic]:Math.round(msg.payload*100)\n }\n }\n}\nmsg.topic = \"imager/image\"\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 1100, - "y": 1060, - "wires": [["845e06e1.0d812"]] - }, - { - "id": "82722a3c.846b3", - "type": "inject", - "z": "bccd1f23.87219", - "name": "Default: OFF", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": "1", - "topic": "", - "payload": "false", - "payloadType": "bool", - "x": 110, - "y": 920, - "wires": [["60e44330.50bdec"]] - }, - { - "id": "60e44330.50bdec", - "type": "ui_switch", - "z": "bccd1f23.87219", - "name": "AWB", - "label": "Auto White Balance", - "tooltip": "", - "group": "8c38a81e.9897a8", - "order": 5, - "width": 2, - "height": 2, - "passthru": true, - "decouple": "false", - "topic": "white_balance", - "topicType": "str", - "style": "", - "onvalue": "auto", - "onvalueType": "str", - "onicon": "", - "oncolor": "", - "offvalue": "off", - "offvalueType": "str", - "officon": "", - "offcolor": "", - "animate": true, - "className": "", - "x": 550, - "y": 920, - "wires": [["8ea9dc9a.c7d87"]] - }, - { - "id": "6be64480.7e7e24", - "type": "change", - "z": "bccd1f23.87219", - "name": "Get red_gain", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.red_gain", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 370, - "y": 1040, - "wires": [["d5415af6.e06cc"]] - }, - { - "id": "6d49d161.13628", - "type": "change", - "z": "bccd1f23.87219", - "name": "Get blue_gain", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.blue_gain", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 380, - "y": 1080, - "wires": [["dba68c1f.e3144"]] - }, - { - "id": "56835fa1.2fe538", - "type": "subflow:4ed26b8b.253504", - "z": "bccd1f23.87219", - "name": "", - "env": [], - "x": 1160, - "y": 1020, - "wires": [] - }, - { - "id": "8ef294ba.12213", - "type": "change", - "z": "bccd1f23.87219", - "name": "Get analog_gain", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "1", - "tot": "num" - }, - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.analog_gain", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 380, - "y": 960, - "wires": [["a6c7eec4.f7a918"]] - }, - { - "id": "8e336e58.14722", - "type": "change", - "z": "bccd1f23.87219", - "name": "Get digital_gain", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "1", - "tot": "num" - }, - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.digital_gain", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 380, - "y": 1000, - "wires": [["66b37eef.f3f9e"]] - }, - { - "id": "a6c7eec4.f7a918", - "type": "ui_text_input", - "z": "bccd1f23.87219", - "d": true, - "name": "Analog gain field", - "label": "Analog Gain", - "tooltip": "From 1.0 to 12.0", - "group": "8c38a81e.9897a8", - "order": 2, - "width": 0, - "height": 0, - "passthru": true, - "mode": "number", - "delay": 300, - "topic": "analog", - "topicType": "str", - "x": 580, - "y": 960, - "wires": [["44e02933.a66688", "d361a2c4.0990f8"]] - }, - { - "id": "66b37eef.f3f9e", - "type": "ui_text_input", - "z": "bccd1f23.87219", - "d": true, - "name": "Digital gain field", - "label": "Digital Gain", - "tooltip": "From 1.0 to 64.0. Overexpose starting at 4.0", - "group": "8c38a81e.9897a8", - "order": 3, - "width": 0, - "height": 0, - "passthru": true, - "mode": "number", - "delay": 300, - "topic": "digital", - "topicType": "str", - "x": 580, - "y": 1000, - "wires": [["44e02933.a66688", "d361a2c4.0990f8"]] - }, - { - "id": "44e02933.a66688", - "type": "function", - "z": "bccd1f23.87219", - "name": "Encapsulate image gain settings", - "func": "msg.payload = {\n \"action\":\"settings\", \n \"settings\":{\"image_gain\":{\n [msg.topic]:Math.round(msg.payload*100)\n }\n }\n}\nmsg.topic = \"imager/image\"\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 1090, - "y": 980, - "wires": [["845e06e1.0d812"]] - }, - { - "id": "d361a2c4.0990f8", - "type": "change", - "z": "bccd1f23.87219", - "name": "topic *_gain", - "rules": [ - { - "t": "set", - "p": "topic", - "pt": "msg", - "to": "topic&'_gain'", - "tot": "jsonata" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 970, - "y": 1020, - "wires": [["56835fa1.2fe538"]] - }, - { - "id": "d8d006bf.2947f", - "type": "inject", - "z": "bccd1f23.87219", - "name": "Default: ISO 150", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": "1", - "topic": "", - "payload": "150", - "payloadType": "num", - "x": 130, - "y": 840, - "wires": [["37f412d1454deb64"]] - }, - { - "id": "eb9966de.cf13c8", - "type": "change", - "z": "bccd1f23.87219", - "name": "", - "rules": [ - { - "t": "set", - "p": "topic", - "pt": "msg", - "to": "iso", - "tot": "str" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 740, - "y": 840, - "wires": [["8ea9dc9a.c7d87"]] - }, - { - "id": "be33e564.029358", - "type": "ui_text_input", - "z": "bccd1f23.87219", - "name": "focus_distance", - "label": "Focus Distance (in µm)", - "tooltip": "in µm, 25µm resolution", - "group": "fbd92986.1028c8", - "order": 4, - "width": 0, - "height": 0, - "passthru": true, - "mode": "number", - "delay": 300, - "topic": "focus_distance", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 580, - "y": 460, - "wires": [["dc48dc42.98d18"]] - }, - { - "id": "3a86de51.765b9a", - "type": "ui_text_input", - "z": "bccd1f23.87219", - "name": "focus_speed", - "label": "Focus Speed (in µm/sec)", - "tooltip": "in µm/sec", - "group": "fbd92986.1028c8", - "order": 5, - "width": 0, - "height": 0, - "passthru": true, - "mode": "number", - "delay": 300, - "topic": "focus_speed", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 570, - "y": 500, - "wires": [["dc48dc42.98d18"]] - }, - { - "id": "cb2d5174.cfe9f", - "type": "ui_text_input", - "z": "bccd1f23.87219", - "name": "pump_flowrate", - "label": "Flowrate (ml/min)*", - "tooltip": "", - "group": "707d9797.c8e798", - "order": 1, - "width": 0, - "height": 0, - "passthru": true, - "mode": "text", - "delay": 300, - "topic": "pump_flowrate", - "topicType": "str", - "x": 580, - "y": 380, - "wires": [["dc48dc42.98d18"]] - }, - { - "id": "d5415af6.e06cc", - "type": "ui_text_input", - "z": "bccd1f23.87219", - "name": "WB Red input", - "label": "WB: Red", - "tooltip": "From 0.0 to 32.0", - "group": "8c38a81e.9897a8", - "order": 6, - "width": 4, - "height": 1, - "passthru": true, - "mode": "number", - "delay": "0", - "topic": "red", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 580, - "y": 1040, - "wires": [["f7a7398fd6ce4a4f"]] - }, - { - "id": "dba68c1f.e3144", - "type": "ui_text_input", - "z": "bccd1f23.87219", - "name": "WB Blue input", - "label": "WB: Blue", - "tooltip": "From 0.0 to 64.0", - "group": "8c38a81e.9897a8", - "order": 7, - "width": 4, - "height": 1, - "passthru": true, - "mode": "number", - "delay": "0", - "topic": "blue", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 580, - "y": 1080, - "wires": [["df8a7667c9d133b1"]] - }, - { - "id": "d91550e8b15ed3b8", - "type": "subflow:e6665421f66ea4c8", - "z": "bccd1f23.87219", - "name": "", - "x": 160, - "y": 1020, - "wires": [ - ["8ef294ba.12213", "8e336e58.14722", "6be64480.7e7e24", "6d49d161.13628"] - ] - }, - { - "id": "04920f50bbbf6a2a", - "type": "link in", - "z": "bccd1f23.87219", - "name": "Load hardware config", - "links": ["e4ead350b3d07578", "4a1f303f0b6f7f42"], - "x": 25, - "y": 1000, - "wires": [["d91550e8b15ed3b8"]] - }, - { - "id": "7386eaf7ca9d8bfa", - "type": "inject", - "z": "bccd1f23.87219", - "name": "Once", - "props": [], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "", - "x": 50, - "y": 1080, - "wires": [["d91550e8b15ed3b8"]] - }, - { - "id": "f7a7398fd6ce4a4f", - "type": "switch", - "z": "bccd1f23.87219", - "name": "Validate", - "property": "payload", - "propertyType": "msg", - "rules": [ - { - "t": "btwn", - "v": "0.0", - "vt": "num", - "v2": "32.0", - "v2t": "num" - }, - { - "t": "else" - } - ], - "checkall": "false", - "repair": false, - "outputs": 2, - "x": 740, - "y": 1040, - "wires": [ - ["d361a2c4.0990f8", "5e147425.7666ec"], - ["64b05eea4c5469be", "4a1f303f0b6f7f42"] - ] - }, - { - "id": "df8a7667c9d133b1", - "type": "switch", - "z": "bccd1f23.87219", - "name": "Validate", - "property": "payload", - "propertyType": "msg", - "rules": [ - { - "t": "btwn", - "v": "0.0", - "vt": "num", - "v2": "32.0", - "v2t": "num" - }, - { - "t": "else" - } - ], - "checkall": "false", - "repair": false, - "outputs": 2, - "x": 740, - "y": 1080, - "wires": [ - ["d361a2c4.0990f8", "5e147425.7666ec"], - ["64b05eea4c5469be", "4a1f303f0b6f7f42"] - ] - }, - { - "id": "64b05eea4c5469be", - "type": "ui_toast", - "z": "bccd1f23.87219", - "position": "top right", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 0, - "ok": "OK", - "cancel": "", - "raw": false, - "className": "", - "topic": "Invalid white balance value", - "name": "", - "x": 990, - "y": 1100, - "wires": [] - }, - { - "id": "4a1f303f0b6f7f42", - "type": "link out", - "z": "bccd1f23.87219", - "name": "Reload hardware config", - "mode": "link", - "links": ["04920f50bbbf6a2a"], - "x": 915, - "y": 1140, - "wires": [] - }, - { - "id": "37f412d1454deb64", - "type": "ui_slider", - "z": "bccd1f23.87219", - "name": "ISO selector", - "label": "ISO", - "tooltip": "", - "group": "8c38a81e.9897a8", - "order": 1, - "width": 0, - "height": 0, - "passthru": true, - "outs": "end", - "topic": "topic", - "topicType": "msg", - "min": "50", - "max": "800", - "step": "50", - "className": "", - "x": 570, - "y": 840, - "wires": [["eb9966de.cf13c8"]] - }, - { - "id": "f59a2f0d.5e9af", - "type": "ui_numeric", - "z": "baa1e3d9.cb29d", - "name": "acq_minimum_mesh", - "label": "Min fraction size (μm)", - "tooltip": "", - "group": "404c301a.19c4e", - "order": 1, - "width": 5, - "height": 1, - "wrap": false, - "passthru": true, - "topic": "acq_minimum_mesh", - "format": "{{value}}", - "min": 0, - "max": "300", - "step": "10", - "x": 640, - "y": 160, - "wires": [["fb887036.12429"]] - }, - { - "id": "6008a8bb.259f08", - "type": "ui_numeric", - "z": "baa1e3d9.cb29d", - "name": "acq_maximum_mesh", - "label": "Max fraction size (μm)", - "tooltip": "", - "group": "404c301a.19c4e", - "order": 2, - "width": 5, - "height": 1, - "wrap": false, - "passthru": true, - "topic": "acq_maximum_mesh", - "format": "{{value}}", - "min": "200", - "max": "2000", - "step": "100", - "x": 640, - "y": 200, - "wires": [["fb887036.12429"]] - }, - { - "id": "6b34c456.83178c", - "type": "ui_text_input", - "z": "baa1e3d9.cb29d", - "name": "acq_id", - "label": "Acquisition unique ID*", - "tooltip": "", - "group": "4322c187.e73e5", - "order": 1, - "width": 5, - "height": 1, - "passthru": true, - "mode": "text", - "delay": 300, - "topic": "acq_id", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 690, - "y": 240, - "wires": [["fb887036.12429"]] - }, - { - "id": "cc0ca68b.4263a8", - "type": "ui_dropdown", - "z": "baa1e3d9.cb29d", - "name": "acq_celltype", - "label": "Flowcell thickness*", - "tooltip": "", - "place": "Select option", - "group": "4322c187.e73e5", - "order": 6, - "width": 5, - "height": 1, - "passthru": true, - "multiple": false, - "options": [ - { - "label": "200 μm µ-Slide I Luer", - "value": 200, - "type": "num" - }, - { - "label": "300 µm capillary", - "value": 300, - "type": "num" - }, - { - "label": "400 μm µ-Slide I Luer", - "value": 400, - "type": "num" - }, - { - "label": "600 μm µ-Slide I Luer", - "value": 600, - "type": "num" - }, - { - "label": "800 μm µ-Slide I Luer", - "value": 800, - "type": "num" - } - ], - "payload": "", - "topic": "acq_celltype", - "topicType": "str", - "className": "", - "x": 670, - "y": 80, - "wires": [["fb887036.12429", "99b11fe4.2795d"]] - }, - { - "id": "fb887036.12429", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "set global", - "func": "global.set(msg.topic, msg.payload);\nreturn msg", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 920, - "y": 220, - "wires": [["52ea7d01.711034"]] - }, - { - "id": "bb2bb7ce.1d1458", - "type": "ui_template", - "z": "baa1e3d9.cb29d", - "group": "858a0e3c.987fe", - "name": "Stream Pi Camera", - "order": 1, - "width": 10, - "height": 8, - "format": "
\n \"If\n
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "className": "", - "x": 650, - "y": 20, - "wires": [[]] - }, - { - "id": "d0c5b57d.590818", - "type": "ui_ui_control", - "z": "baa1e3d9.cb29d", - "name": "", - "events": "change", - "x": 1280, - "y": 660, - "wires": [[]] - }, - { - "id": "c72f8fae.23bd4", - "type": "ui_button", - "z": "baa1e3d9.cb29d", - "name": "", - "group": "b7919ae2.c01788", - "order": 1, - "width": 5, - "height": 1, - "passthru": false, - "label": "Previous", - "tooltip": "", - "color": "#097479", - "bgcolor": "white", - "icon": "keyboard_return", - "payload": "{\"tab\":\"Optic Configuration\"}", - "payloadType": "json", - "topic": "", - "x": 1140, - "y": 660, - "wires": [["d0c5b57d.590818"]] - }, - { - "id": "29be525e.0c87fe", - "type": "ui_template", - "z": "baa1e3d9.cb29d", - "group": "b5d61bc7.54fe48", - "name": "Show Metadata", - "order": 9, - "width": 0, - "height": 0, - "format": "
\n \n \n \n \n \n \n \n \n \n
\n

Sample

\n

id:

\n

project:\n

\n

ship:

\n

operator:\n

\n

sampling gear:\n

\n

concentrated volume:\n

\n

gear net opening:\n

\n

total volume filtered:\n

\n
\n

Acquisition

\n

id:

\n

instrument:\n

\n

instrument id:\n

\n

camera:

\n

celltype: \n

\n

minimum mesh:\n

\n

maximum mesh:\n

\n

min esd: \n

\n

max esd: \n

\n

volume:

\n

magnification:\n

\n

fnumber objective:\n

\n

software: \n

\n
\n

Object

\n

latitude: \n

\n

longitude: \n

\n

latitude end:\n

\n

longitude end:\n

\n

date:

\n

time:

\n

date end:\n

\n

time end:\n

\n

depth min:\n

\n

depth max:\n

\n
\n

Process

\n

pixel: \n

\n

id:

\n
\n
", - "storeOutMessages": false, - "fwdInMessages": false, - "resendOnRefresh": false, - "templateScope": "local", - "className": "", - "x": 1180, - "y": 380, - "wires": [[]] - }, - { - "id": "c9f510c0.7d1328", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "Image control", - "func": "// Reset the number of images taken\nflow.set('img_counter', 0);\n\nvar acq_celltype = global.get(\"acq_celltype\");\nvar acq_minimum_mesh = global.get(\"acq_minimum_mesh\");\nvar acq_maximum_mesh = global.get(\"acq_maximum_mesh\");\nvar imaging_pump_volume = global.get(\"imaging_pump_volume\");\nvar acq_id = global.get(\"acq_id\");\nvar nb_frame = global.get(\"nb_frame\");\nvar pump_direction = global.get(\"pump_direction\");\nvar sleep_before = global.get(\"sleep_before\");\nvar object_date = global.get(\"object_date\");\n\nif (acq_celltype === undefined || acq_celltype === \"\") {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Type of the flowcell\";\n return [null, msg];\n} else if (acq_minimum_mesh === undefined || acq_minimum_mesh === \"\") {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Lower fraction size\";\n return [null, msg];\n} else if (acq_maximum_mesh === undefined || acq_maximum_mesh === \"\") {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Upper fraction size\";\n return [null, msg];\n} else if (imaging_pump_volume === undefined || imaging_pump_volume === \"\" || imaging_pump_volume === null) {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Volume inbetween images\";\n return [null, msg];\n} else if (acq_id === undefined || acq_id === \"\") {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Acquisition ID\";\n return [null, msg];\n} else if (nb_frame === undefined || nb_frame === \"\" || nb_frame === null) {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Number of image to save\";\n return [null, msg];\n} else if (pump_direction === undefined || pump_direction === \"\" || pump_direction === null) {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Pump direction\";\n return [null, msg];\n} else if (sleep_before === undefined || sleep_before === \"\" || sleep_before === null) {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Delay before image\";\n return [null, msg];\n}else if (object_date === undefined || object_date === \"\" || object_date === null) {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Object date\";\n return [null, msg];\n}\n\nmsg.payload = {\n \"action\": \"image\",\n \"sleep\": sleep_before,\n \"pump_direction\": pump_direction,\n \"volume\": imaging_pump_volume,\n \"nb_frame\": nb_frame,\n}\nmsg.send = true\n\nreturn [msg, null];", - "outputs": 2, - "timeout": "", - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 680, - "y": 480, - "wires": [ - ["52ea7d01.711034", "40c12463.a1f84c", "a4abb1ae.2ae418"], - ["20e0a8c8.edbeb"] - ] - }, - { - "id": "20e0a8c8.edbeb", - "type": "ui_toast", - "z": "baa1e3d9.cb29d", - "position": "dialog", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 1, - "ok": "OK", - "cancel": "", - "raw": false, - "className": "", - "topic": "", - "name": "", - "x": 950, - "y": 560, - "wires": [[]] - }, - { - "id": "c3e50240.82aa58", - "type": "mqtt out", - "z": "baa1e3d9.cb29d", - "name": "", - "topic": "", - "qos": "", - "retain": "", - "respTopic": "", - "contentType": "", - "userProps": "", - "correl": "", - "expiry": "", - "broker": "8dc3722c.06efa8", - "x": 1150, - "y": 440, - "wires": [] - }, - { - "id": "3a4450b1.4459a8", - "type": "ui_button", - "z": "baa1e3d9.cb29d", - "name": "Stop Acquisition", - "group": "4322c187.e73e5", - "order": 11, - "width": 5, - "height": 1, - "passthru": true, - "label": "STOP ACQUISITION", - "tooltip": "", - "color": "", - "bgcolor": "#AD1625", - "className": "", - "icon": "cancel", - "payload": "{\"action\":\"stop\"}", - "payloadType": "json", - "topic": "imager/image", - "topicType": "str", - "x": 460, - "y": 520, - "wires": [["d74210ef.edc15"]] - }, - { - "id": "d74210ef.edc15", - "type": "mqtt out", - "z": "baa1e3d9.cb29d", - "name": "", - "topic": "", - "qos": "", - "retain": "", - "broker": "8dc3722c.06efa8", - "x": 650, - "y": 520, - "wires": [] - }, - { - "id": "bb62da8a.ebc328", - "type": "ui_switch", - "z": "baa1e3d9.cb29d", - "name": "Pump direction", - "label": "Pump direction", - "tooltip": "BACKWARD / FORWARD", - "group": "4322c187.e73e5", - "order": 9, - "width": 5, - "height": 1, - "passthru": true, - "decouple": "false", - "topic": "pump_direction", - "style": "", - "onvalue": "FORWARD", - "onvalueType": "str", - "onicon": "", - "oncolor": "", - "offvalue": "BACKWARD", - "offvalueType": "str", - "officon": "", - "offcolor": "", - "x": 460, - "y": 560, - "wires": [["6b2239f3.41fa3"]] - }, - { - "id": "52ea7d01.711034", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "Encapsulate config", - "func": "msg.payload = {\n\t\"action\": \"update_config\",\n\t\"config\": {\n \t\"description\": {\n \t\t\"sample_project\": \"Project's name\",\n \t\t\"sample_id\": \"Sample ID\",\n \t\t\"sample_uuid\": \"Sample UUID (Autogenerated)\",\n \t\t\"sample_ship\": \"Ship's name\",\n \t\t\"sample_operator\": \"Operator's name\",\n \t\t\"sample_sampling_gear\": \"Sampling gear used\",\n \t\t\"sample_concentrated_sample_volume\": \"Volume of concentrated sample, in mL\",\n \t\t\"sample_total_volume\": \"Total volume filtered by the net used, in L\",\n \t\t\"sample_dilution_factor\": \"Dilution factor of the sample, 0.5 if diluted by 2, 2 if concentrated by 2\",\n \t\t\"sample_speed_through_water\": \"Speed of the boat through water when sampling, in kts\",\n \t\t\"acq_id\": \"Acquisition ID\",\n \t\t\"acq_uuid\": \"Acquisition UUID (Autogenerated)\",\n \t\t\"acq_instrument\": \"Instrument type\",\n \t\t\"acq_instrument_id\": \"Instrument ID\",\n \t\t\"acq_celltype\": \"Flow cell dimension thickness, in µm\",\n \t\t\"acq_minimum_mesh\": \"Minimum filtration mesh size, in µm\",\n \t\t\"acq_maximum_mesh\": \"Maximum filtration mesh size, in µm\",\n \t\t\"acq_min_esd\": \"\",\n \t\t\"acq_max_esd\": \"\",\n \t\t\"acq_volume\": \"Pumped volume, in mL\",\n\t\t \"acq_imaged_volume\": \"Total imaged volume, in mL\",\n \t\t\"acq_magnification\": \"Optical magnification\",\n \t\t\"acq_fnumber_objective\": \"Focal length of the objective, in mm\",\n \t\t\"acq_camera_name\": \"Name of the camera used\",\n \t\t\"acq_nb_frame\": \"Number of picture taken\",\n \"acq_local_datetime\": \"Instrument local datetime\",\n \"acq_camera_resolution\": \"Resolution of the images\",\n \"acq_camera_iso\": \"ISO Number of the images\",\n \"acq_camera_shutter_speed\": \"Shutter speed of the images, in µs\",\n \"acq_software\": \"Software version number\",\n \t\t\"object_date\": \"Sample collection date (or beginning if using a net)\",\n \t\t\"object_time\": \"Sample collection time (or beginning if using a net)\",\n \t\t\"object_lat\": \"Sample collection latitude (or beginning if using a net)\",\n \t\t\"object_lon\": \"Sample collection longitude (or beginning if using a net)\",\n \t\t\"object_depth_min\": \"Sample collection minimal depth, in m\",\n \t\t\"object_depth_max\": \"Sample collection maximum depth, in m\",\n \t\t\"process_pixel\": \"Pixel imaging resolution, in µm/pixel\",\n \t\t\"process_datetime\": \"Segmentation timestamp\",\n \t\t\"process_id\": \"Segmentation ID\",\n \t\t\"process_uuid\": \"Segmentation UUID (Autogenerated)\",\n \t\t\"process_source\": \"Code source link of the executed code\",\n \t\t\"process_commit\": \"Version reference of the executed code\",\n \t\t\"sample_gear_net_opening\": \"Sample mouth opening dimension, in mm\",\n \t\t\"object_date_end\": \"Sample end collection date when using a net\",\n \t\t\"object_time_end\": \"Sample end collection time when using a net\",\n \t\t\"object_lat_end\": \"Sample end collection latitude when using a net\",\n \t\t\"object_lon_end\": \"Sample end collection longitude when using a net\",\n \t},\n\t\t\"sample_project\": global.get(\"sample_project\"),\n\t\t\"sample_id\": global.get(\"sample_project\") + \"_\" + global.get(\"sample_id\"),\n\t\t\"sample_ship\": global.get(\"sample_ship\"),\n\t\t\"sample_operator\": global.get(\"sample_operator\"),\n\t\t\"sample_sampling_gear\": global.get(\"sample_sampling_gear\"),\n\t\t\"sample_concentrated_sample_volume\": global.get(\"sample_concentrated_sample_volume\"),\n\t\t\"sample_total_volume\": global.get(\"sample_total_volume\"),\n\t\t\"sample_dilution_factor\": global.get(\"sample_dilution_factor\"),\n\t\t\"sample_speed_through_water\": global.get(\"sample_speed_through_water\"),\n\n\t\t\"acq_id\": global.get(\"sample_project\") + \"_\" + global.get(\"sample_id\")+ \"_\" + global.get(\"acq_id\"),\n\t\t\"acq_instrument\": global.get(\"acq_instrument\"),\n\t\t\"acq_instrument_id\": global.get(\"acq_instrument_id\"),\n\t\t\"acq_celltype\": global.get(\"acq_celltype\"),\n\t\t\"acq_minimum_mesh\": global.get(\"acq_minimum_mesh\"),\n\t\t\"acq_maximum_mesh\": global.get(\"acq_maximum_mesh\"),\n\t\t\"acq_min_esd\": global.get(\"acq_min_esd\"),\n\t\t\"acq_max_esd\": global.get(\"acq_max_esd\"),\n\t\t\"acq_volume\": global.get(\"acq_volume\"),\n\t\t\"acq_imaged_volume\": global.get(\"acq_imaged_volume\"),\n\t\t\"acq_magnification\": global.get(\"acq_magnification\"),\n\t\t\"acq_fnumber_objective\": global.get(\"acq_fnumber_objective\"),\n\t\t\"acq_camera\": global.get(\"acq_camera\"),\n\t\t\"acq_nb_frame\": global.get(\"nb_frame\"),\n\t\t\"acq_software\": global.get(\"acq_software\"),\n\n\t\t\"object_date\": global.get(\"object_date\"),\n\t\t\"object_time\": global.get(\"object_time\"),\n\t\t\"object_lat\": global.get(\"object_lat\"),\n\t\t\"object_lon\": global.get(\"object_lon\"),\n\t\t\"object_depth_min\": global.get(\"object_depth_min\"),\n\t\t\"object_depth_max\": global.get(\"object_depth_max\"),\n\n\t\t\"process_pixel\": global.get(\"process_pixel\"),\n\t\t\"process_source\": global.get(\"process_source\"),\n\t\t\"process_commit\": global.get(\"process_commit\")\n\t}\n};\n\nif (msg.payload.config.sample_sampling_gear.startsWith(\"net\")) {\n\tmsg.payload.config[\"sample_gear_net_opening\"] = global.get(\"sample_gear_net_opening\")\n\tmsg.payload.config[\"object_date_end\"] = global.get(\"object_date_end\")\n\tmsg.payload.config[\"object_time_end\"] = global.get(\"object_time_end\")\n\tmsg.payload.config[\"object_lat_end\"] = global.get(\"object_lat_end\")\n\tmsg.payload.config[\"object_lon_end\"] = global.get(\"object_lon_end\")\n}\n\nif ( msg.send == true){\n\treturn [msg, msg]\n}\nelse{\n\treturn [msg, null]\n}", - "outputs": 2, - "timeout": "", - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 910, - "y": 440, - "wires": [["29be525e.0c87fe"], ["c3e50240.82aa58"]] - }, - { - "id": "40c12463.a1f84c", - "type": "delay", - "z": "baa1e3d9.cb29d", - "name": "", - "pauseType": "delay", - "timeout": "1", - "timeoutUnits": "seconds", - "rate": "1", - "nbRateUnits": "1", - "rateUnits": "second", - "randomFirst": "1", - "randomLast": "5", - "randomUnits": "seconds", - "drop": false, - "outputs": 1, - "x": 940, - "y": 480, - "wires": [["c3e50240.82aa58"]] - }, - { - "id": "4d1b02cb.83b51c", - "type": "ui_button", - "z": "baa1e3d9.cb29d", - "name": "", - "group": "4322c187.e73e5", - "order": 10, - "width": 5, - "height": 1, - "passthru": false, - "label": "Update config", - "tooltip": "", - "color": "", - "bgcolor": "", - "className": "", - "icon": "save", - "payload": "", - "payloadType": "str", - "topic": "imager/image", - "topicType": "str", - "x": 680, - "y": 440, - "wires": [["52ea7d01.711034"]] - }, - { - "id": "5921d0d0.a3d568", - "type": "subflow:1c24ad9c.bebec2", - "z": "baa1e3d9.cb29d", - "name": "", - "env": [], - "x": 110, - "y": 220, - "wires": [ - [ - "f3658d30.b8448", - "de2c90cf.b73b08", - "4be09c97f86897d9", - "f573206abefa9518", - "f948151ab4031df4", - "5e3dec55.881074", - "d3ca8847.4d1ae" - ] - ] - }, - { - "id": "f3658d30.b8448", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "get acq_id", - "func": "msg.payload = msg.payload.acq_id;\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 330, - "y": 240, - "wires": [["6b34c456.83178c"]] - }, - { - "id": "de2c90cf.b73b08", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "get acq_celltype", - "func": "msg.topic = 'acq_celltype';\nmsg.payload = msg.payload.acq_celltype;\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 340, - "y": 80, - "wires": [["cc0ca68b.4263a8"]] - }, - { - "id": "5e3dec55.881074", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "get acq_minimum_mesh", - "func": "msg.payload = msg.payload.acq_minimum_mesh;\nreturn msg;", - "outputs": 1, - "noerr": 0, - "x": 370, - "y": 160, - "wires": [["f59a2f0d.5e9af"]] - }, - { - "id": "d3ca8847.4d1ae", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "get acq_maximum_mesh", - "func": "msg.payload = msg.payload.acq_maximum_mesh;\nreturn msg;", - "outputs": 1, - "noerr": 0, - "x": 370, - "y": 200, - "wires": [["6008a8bb.259f08"]] - }, - { - "id": "b402f719.55bc98", - "type": "inject", - "z": "baa1e3d9.cb29d", - "name": "Default: FORWARD", - "props": [ - { - "p": "payload" - }, - { - "p": "topic", - "vt": "str" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "pump_direction", - "payload": "FORWARD", - "payloadType": "str", - "x": 220, - "y": 560, - "wires": [["bb62da8a.ebc328"]] - }, - { - "id": "6b2239f3.41fa3", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "set global", - "func": "global.set(msg.topic, msg.payload);", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 660, - "y": 560, - "wires": [[]] - }, - { - "id": "51b4d0df.d70a88", - "type": "ui_text_input", - "z": "baa1e3d9.cb29d", - "name": "nb_frame", - "label": "Number of images to acquire", - "tooltip": "", - "group": "4322c187.e73e5", - "order": 2, - "width": 5, - "height": 1, - "passthru": true, - "mode": "number", - "delay": 300, - "topic": "nb_frame", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 680, - "y": 280, - "wires": [["fb887036.12429", "67091ac0.8f9f6c", "99b11fe4.2795d"]] - }, - { - "id": "999065ca.27edb8", - "type": "switch", - "z": "baa1e3d9.cb29d", - "name": "topic filter", - "property": "topic", - "propertyType": "msg", - "rules": [ - { - "t": "eq", - "v": "status/pump", - "vt": "str" - }, - { - "t": "eq", - "v": "status/focus", - "vt": "str" - }, - { - "t": "eq", - "v": "status/imager", - "vt": "str" - } - ], - "checkall": "true", - "repair": false, - "outputs": 3, - "x": 320, - "y": 800, - "wires": [ - ["a46a1e7f.88a92", "6742014e.1bb238"], - ["c516d9ea.f7f6e", "6742014e.1bb238"], - ["307c851e.fb0f7a", "2b9d6988.d84836"] - ] - }, - { - "id": "2b009bd7.c07004", - "type": "ui_text", - "z": "baa1e3d9.cb29d", - "group": "70de8209.68416c", - "order": 3, - "width": 10, - "height": 2, - "name": "imager", - "label": "Imager status:", - "format": "{{msg.payload.status}}", - "layout": "col-center", - "x": 770, - "y": 740, - "wires": [] - }, - { - "id": "c516d9ea.f7f6e", - "type": "ui_text", - "z": "baa1e3d9.cb29d", - "group": "70de8209.68416c", - "order": 1, - "width": 5, - "height": 1, - "name": "focus", - "label": "Focus status:", - "format": "{{msg.payload.status}}", - "layout": "col-center", - "x": 770, - "y": 700, - "wires": [] - }, - { - "id": "a46a1e7f.88a92", - "type": "ui_text", - "z": "baa1e3d9.cb29d", - "group": "70de8209.68416c", - "order": 2, - "width": 5, - "height": 1, - "name": "pump", - "label": "Pump status:", - "format": "{{msg.payload.status}}", - "layout": "col-center", - "x": 770, - "y": 660, - "wires": [] - }, - { - "id": "bb628f8d.98f108", - "type": "link in", - "z": "baa1e3d9.cb29d", - "name": "Status for fluidic module", - "links": ["58f2e0f.4e8b12"], - "x": 175, - "y": 800, - "wires": [["999065ca.27edb8"]] - }, - { - "id": "307c851e.fb0f7a", - "type": "switch", - "z": "baa1e3d9.cb29d", - "name": "Imaging state", - "property": "payload", - "propertyType": "msg", - "rules": [ - { - "t": "jsonata_exp", - "v": "$contains(msg.payload.status, \"jpg\")\t", - "vt": "jsonata" - }, - { - "t": "else" - } - ], - "checkall": "false", - "repair": false, - "outputs": 2, - "x": 540, - "y": 880, - "wires": [["db8e3dde.44efb8"], ["6742014e.1bb238"]] - }, - { - "id": "db8e3dde.44efb8", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "img_counter", - "func": "img_counter=flow.get('img_counter')\nif (img_counter === undefined || img_counter === \"\"){\n img_counter = 0\n}\nimg_counter=img_counter+1\nflow.set('img_counter',img_counter)\nmsg.payload = img_counter\nmsg.payload = (100 * img_counter/global.get('nb_frame')).toFixed(2)\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 770, - "y": 860, - "wires": [["1a2e721a.f5e876"]] - }, - { - "id": "59164d65.e7993c", - "type": "ui_toast", - "z": "baa1e3d9.cb29d", - "position": "top right", - "displayTime": "5", - "highlight": "", - "sendall": true, - "outputs": 0, - "ok": "OK", - "cancel": "", - "raw": false, - "topic": "", - "name": "", - "x": 1260, - "y": 900, - "wires": [] - }, - { - "id": "8c7348aa.1962e8", - "type": "template", - "z": "baa1e3d9.cb29d", - "name": "Create sentence", - "field": "payload", - "fieldType": "msg", - "format": "handlebars", - "syntax": "mustache", - "template": "The {{topic}} is {{payload.status}}", - "output": "str", - "x": 1050, - "y": 900, - "wires": [["59164d65.e7993c"]] - }, - { - "id": "6742014e.1bb238", - "type": "change", - "z": "baa1e3d9.cb29d", - "name": "Remove high-level topic", - "rules": [ - { - "t": "change", - "p": "topic", - "pt": "msg", - "from": "status/", - "fromt": "str", + "x": 620, + "y": 420, + "wires": [] + }, + { + "id": "595df18543c8328e", + "type": "http response", + "z": "1371dec5.76e671", + "name": "Send POST response", + "statusCode": "", + "headers": {}, + "x": 620, + "y": 300, + "wires": [] + }, + { + "id": "1fdf77b5.24e4e", + "type": "mqtt in", + "z": "9a22e67a.378818", + "name": "", + "topic": "status/#", + "qos": "0", + "datatype": "json", + "broker": "8dc3722c.06efa8", + "inputs": 0, + "x": 290, + "y": 340, + "wires": [ + [ + "fa73983d.318188" + ] + ] + }, + { + "id": "4a1e9e3e.27506", + "type": "switch", + "z": "9a22e67a.378818", + "name": "Filter segmenter out", + "property": "topic", + "propertyType": "msg", + "rules": [ + { + "t": "else" + }, + { + "t": "cont", + "v": "status/segmenter", + "vt": "str" + } + ], + "checkall": "true", + "repair": false, + "outputs": 2, + "x": 620, + "y": 340, + "wires": [ + [ + "58f2e0f.4e8b12" + ], + [ + "dcf5bd45.16a8d" + ] + ] + }, + { + "id": "fa73983d.318188", + "type": "json", + "z": "9a22e67a.378818", + "name": "", + "property": "payload", + "action": "obj", + "pretty": true, + "x": 430, + "y": 340, + "wires": [ + [ + "4a1e9e3e.27506" + ] + ] + }, + { + "id": "58f2e0f.4e8b12", + "type": "link out", + "z": "9a22e67a.378818", + "name": "Fluidic module status", + "links": [ + "bb628f8d.98f108" + ], + "x": 795, + "y": 320, + "wires": [] + }, + { + "id": "dcf5bd45.16a8d", + "type": "link out", + "z": "9a22e67a.378818", + "name": "Segmenter module status", + "links": [ + "25867454.a8e334" + ], + "x": 795, + "y": 360, + "wires": [] + }, + { + "id": "e41870d7.300eb8", + "type": "link out", + "z": "1eaf21c8.f7a21e", + "name": "Stepper config change", + "links": [ + "45a7b5aa.2ed20c" + ], + "x": 1475, + "y": 380, + "wires": [] + }, + { + "id": "2068e7f.f4efb18", + "type": "delay", + "z": "1eaf21c8.f7a21e", + "name": "", + "pauseType": "delay", + "timeout": "1", + "timeoutUnits": "seconds", + "rate": "1", + "nbRateUnits": "1", + "rateUnits": "second", + "randomFirst": "1", + "randomLast": "5", + "randomUnits": "seconds", + "drop": false, + "outputs": 1, + "x": 1160, + "y": 380, + "wires": [ + [ + "e41870d7.300eb8" + ] + ] + }, + { + "id": "8e3b3d3c.955148", + "type": "subflow:4ed26b8b.253504", + "z": "1eaf21c8.f7a21e", + "name": "", + "env": [], + "x": 1200, + "y": 420, + "wires": [] + }, + { + "id": "c534fd26.13741", + "type": "change", + "z": "1eaf21c8.f7a21e", + "name": "Get stepper_reverse", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.stepper_reverse", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", "to": "", - "tot": "str" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 810, - "y": 900, - "wires": [["8c7348aa.1962e8"]] - }, - { - "id": "1a2e721a.f5e876", - "type": "ui_gauge", - "z": "baa1e3d9.cb29d", - "name": "progress donut", - "group": "b5d61bc7.54fe48", - "order": 3, - "width": 6, - "height": 3, - "gtype": "donut", - "title": "", - "label": "%", - "format": "{{value}}", - "min": 0, - "max": "100", - "colors": ["#ffa83f", "#e6ff02", "#00dfe9"], - "seg1": "50", - "seg2": "75", - "x": 1260, - "y": 860, - "wires": [] - }, - { - "id": "9bd72495.a8a098", - "type": "ui_text", - "z": "baa1e3d9.cb29d", - "group": "4322c187.e73e5", - "order": 5, - "width": 5, - "height": 1, - "name": "Total imaged volume", - "label": "Total imaged volume", - "format": "{{msg.payload}}", - "layout": "col-center", - "x": 1200, - "y": 140, - "wires": [] - }, - { - "id": "99b11fe4.2795d", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "imaged volume calc", - "func": "camera = global.get(\"acq_camera\");\ncell = global.get(\"acq_celltype\");\nnb_frame = global.get(\"nb_frame\");\nprocess_pixel = global.get(\"process_pixel\");\n\nvar volume = 0\nif (camera == \"HQ Camera\"){\n volume = nb_frame * (process_pixel*4056*process_pixel*3040*cell/1000000000) / 1000;\n}\nelse if (camera == \"Camera v2.1\"){\n volume = nb_frame * (process_pixel*3280*process_pixel*2464*cell/1000000000) / 1000;\n}\nelse{\n msg.payload = \"The camera is not known to this system\";\n return msg;\n}\n\nglobal.set(\"acq_imaged_volume\", volume.toFixed(4))\n\nmsg.payload = volume.toFixed(2) + \" mL\"\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 960, - "y": 140, - "wires": [["9bd72495.a8a098"]], - "info": "### Focusing\n##### focus.py `nb_step` `orientation`\n\n- `nb_step` : **integer** (from 1 to 100000) - number of step to perform by the stage (about 31um/step)\n- `orientation` : **string** - orientation of the focus either `up` or `down`\n\nExample:\n\n python3.7 $HOME/PlanktoScope/scripts/focus.py 650 up\n" - }, - { - "id": "8e16aa2f.e40398", - "type": "ui_text", - "z": "baa1e3d9.cb29d", - "group": "4322c187.e73e5", - "order": 7, - "width": 5, - "height": 1, - "name": "Total pumped volume", - "label": "Total pumped volume", - "format": "{{msg.payload}} mL", - "layout": "col-center", - "x": 1200, - "y": 300, - "wires": [] - }, - { - "id": "67091ac0.8f9f6c", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "acq_volume calc", - "func": "var imaging_pump_volume = global.get(\"imaging_pump_volume\");\nvar nb_frame = global.get(\"nb_frame\");\nvar acq_volume = 0\n\nacq_volume = (Number(nb_frame)*Number(imaging_pump_volume)).toFixed(2)\nglobal.set(\"acq_volume\", acq_volume)\n\nmsg.payload = acq_volume\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 950, - "y": 300, - "wires": [["8e16aa2f.e40398"]], - "info": "### Focusing\n##### focus.py `nb_step` `orientation`\n\n- `nb_step` : **integer** (from 1 to 100000) - number of step to perform by the stage (about 31um/step)\n- `orientation` : **string** - orientation of the focus either `up` or `down`\n\nExample:\n\n python3.7 $HOME/PlanktoScope/scripts/focus.py 650 up\n" - }, - { - "id": "2b9d6988.d84836", - "type": "switch", - "z": "baa1e3d9.cb29d", - "name": "", - "property": "payload", - "propertyType": "msg", - "rules": [ - { - "t": "hask", - "v": "status", - "vt": "str" - }, - { - "t": "hask", - "v": "camera_name", - "vt": "str" - } - ], - "checkall": "true", - "repair": false, - "outputs": 2, - "x": 650, - "y": 760, - "wires": [["2b009bd7.c07004"], ["3bbb756a.84190a"]] - }, - { - "id": "3bbb756a.84190a", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "set camera name", - "func": "global.set(\"acq_camera\", msg.payload.camera_name);\n\nmsg.payload = msg.payload.camera_name;\n\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 810, - "y": 780, - "wires": [["559a8085.1d6b9"]] - }, - { - "id": "559a8085.1d6b9", - "type": "link out", - "z": "baa1e3d9.cb29d", - "name": "Camera Name", - "links": ["30067f35.532f2", "572a6daa.6004c4"], - "x": 965, - "y": 780, - "wires": [] - }, - { - "id": "49ea1123.ee1768", - "type": "ui_numeric", - "z": "baa1e3d9.cb29d", - "name": "sleep_before", - "label": "Delay to stabilize image (s)", - "tooltip": "Happens before every capture", - "group": "4322c187.e73e5", - "order": 4, - "width": 5, - "height": 1, - "wrap": false, - "passthru": true, - "topic": "sleep_before", - "topicType": "str", - "format": "{{value}}", - "min": "0.1", - "max": "5", - "step": "0.1", - "className": "", - "x": 670, - "y": 120, - "wires": [["fb887036.12429"]] - }, - { - "id": "572a6daa.6004c4", - "type": "link in", - "z": "baa1e3d9.cb29d", - "name": "", - "links": ["559a8085.1d6b9"], - "x": 795, - "y": 140, - "wires": [["99b11fe4.2795d"]] - }, - { - "id": "8032ea50.1b57f", - "type": "ui_template", - "z": "baa1e3d9.cb29d", - "group": "b5d61bc7.54fe48", - "name": "progress header", - "order": 1, - "width": 0, - "height": 0, - "format": "

Capture progress

", - "storeOutMessages": false, - "fwdInMessages": false, - "resendOnRefresh": false, - "templateScope": "local", - "x": 1260, - "y": 820, - "wires": [[]] - }, - { - "id": "a4abb1ae.2ae418", - "type": "subflow:1c24ad9c.bebec2", - "z": "baa1e3d9.cb29d", - "name": "", - "env": [], - "x": 930, - "y": 520, - "wires": [[]] - }, - { - "id": "4be09c97f86897d9", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "get nb_frame", - "func": "msg.payload = msg.payload.nb_frame;\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 330, - "y": 280, - "wires": [["51b4d0df.d70a88"]] - }, - { - "id": "f573206abefa9518", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "get imaging_pump_volume", - "func": "msg.payload = msg.payload.imaging_pump_volume;\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 380, - "y": 320, - "wires": [["e1acc6c599033114"]] - }, - { - "id": "f948151ab4031df4", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "get sleep_before", - "func": "msg.payload = msg.payload.sleep_before;\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 340, - "y": 120, - "wires": [["49ea1123.ee1768"]] - }, - { - "id": "ad153212312f0347", - "type": "ui_ui_control", - "z": "baa1e3d9.cb29d", - "name": "onTab", - "events": "all", - "x": 330, - "y": 380, - "wires": [["9b69ea945b587192"]] - }, - { - "id": "9b69ea945b587192", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "check tab", - "func": "if (msg.name == \"Fluidic Acquisition\"){\n return { \"topic\": \"imager/ image\" }\n}", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 480, - "y": 380, - "wires": [["52ea7d01.711034"]], - "outputLabels": ["interface"] - }, - { - "id": "e1acc6c599033114", - "type": "ui_text_input", - "z": "baa1e3d9.cb29d", - "name": "imaging_pump_volume", - "label": "Pumped volume (mL)", - "tooltip": "between frames", - "group": "4322c187.e73e5", - "order": 3, - "width": 0, - "height": 0, - "passthru": true, - "mode": "text", - "delay": 300, - "topic": "imaging_pump_volume", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 630, - "y": 320, - "wires": [["fb887036.12429", "67091ac0.8f9f6c"]] - }, - { - "id": "f4caa15e2bbfd6e7", - "type": "ui_template", - "z": "baa1e3d9.cb29d", - "group": "4322c187.e73e5", - "name": "Start Acquisition", - "order": 13, - "width": "5", - "height": "1", - "format": "\n\n", - "storeOutMessages": false, - "fwdInMessages": false, - "resendOnRefresh": false, - "templateScope": "local", - "className": "", - "x": 460, - "y": 480, - "wires": [["c9f510c0.7d1328"]] - }, - { - "id": "9d6abe67.6bb3d", - "type": "ui_button", - "z": "cb95299c.2817c8", - "name": "", - "group": "64903b47.4034e4", - "order": 1, - "width": 0, - "height": 0, - "passthru": false, - "label": "Home", - "tooltip": "", - "color": "", - "bgcolor": "", - "icon": "home", - "payload": "{\"tab\":\"Home\"}", - "payloadType": "json", - "topic": "", - "x": 430, - "y": 600, - "wires": [["f0fb77cf.8f1c28"]] - }, - { - "id": "f0fb77cf.8f1c28", - "type": "ui_ui_control", - "z": "cb95299c.2817c8", - "name": "", - "events": "change", - "x": 740, - "y": 600, - "wires": [[]] - }, - { - "id": "8ec68b82.17e3d8", - "type": "ui_button", - "z": "cb95299c.2817c8", - "name": "Start segmentation", - "group": "abeb6dad.635a2", - "order": 10, - "width": 5, - "height": 1, - "passthru": false, - "label": "Start segmentation", - "tooltip": "", - "color": "", - "bgcolor": "", - "icon": "", - "payload": "{\"action\":\"segment\"}", - "payloadType": "json", - "topic": "segmenter/segment", - "x": 370, - "y": 460, - "wires": [["33c28dc1.238002", "c72a1064.1ec388"]] - }, - { - "id": "27be7971.b3fbce", - "type": "ui_button", - "z": "cb95299c.2817c8", - "d": true, - "name": "Stop segmentation", - "group": "abeb6dad.635a2", - "order": 12, - "width": 4, - "height": 1, - "passthru": true, - "label": "Stop segmentation", - "tooltip": "", - "color": "", - "bgcolor": "#AD1625", - "icon": "", - "payload": "{\"action\":\"stop\"}", - "payloadType": "json", - "topic": "segmenter/segment", - "x": 370, - "y": 520, - "wires": [["16f3cef4.0acac9"]] - }, - { - "id": "16f3cef4.0acac9", - "type": "mqtt out", - "z": "cb95299c.2817c8", - "name": "", - "topic": "", - "qos": "", - "retain": "", - "broker": "8dc3722c.06efa8", - "x": 850, - "y": 520, - "wires": [] - }, - { - "id": "8f3788f6.ddcf98", - "type": "function", - "z": "cb95299c.2817c8", - "name": "obj_counter", - "func": "obj_counter = flow.get('obj_counter')\nobj_counter = obj_counter + 1\nflow.set('obj_counter', obj_counter)\nmsg.payload = obj_counter\nmsg.topic = \"object count\"\nreturn msg", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 810, - "y": 800, - "wires": [["fa3b7929.ac7da8", "9d53dbe2.dbffe8"]] - }, - { - "id": "aa38dbbc.cf0a9", - "type": "switch", - "z": "cb95299c.2817c8", - "name": "Segmenter", - "property": "topic", - "propertyType": "msg", - "rules": [ - { - "t": "eq", - "v": "status/segmenter", - "vt": "str" - }, - { - "t": "eq", - "v": "status/segmenter/name", - "vt": "str" - }, - { - "t": "eq", - "v": "status/segmenter/object_id", - "vt": "str" - }, - { - "t": "eq", - "v": "status/segmenter/metric", - "vt": "str" - } - ], - "checkall": "true", - "repair": false, - "outputs": 4, - "x": 490, - "y": 740, - "wires": [ - ["b9a23b91.93638", "6919465f.332e5"], - ["49af3d24.1799e4"], - ["8f3788f6.ddcf98"], - [] - ] - }, - { - "id": "9d53dbe2.dbffe8", - "type": "ui_chart", - "z": "cb95299c.2817c8", - "name": "counter graph", - "group": "46be9c86.dea684", - "order": 7, - "width": 10, - "height": 2, - "label": "", - "chartType": "horizontalBar", - "legend": "false", - "xformat": "HH:mm:ss", - "interpolate": "linear", - "nodata": "Objects count will be shown here once the segmentation is started", - "dot": false, - "ymin": "", - "ymax": "", - "removeOlder": 1, - "removeOlderPoints": "", - "removeOlderUnit": "3600", - "cutout": 0, - "useOneColor": true, - "useUTC": false, - "colors": [ - "#1f77b4", - "#aec7e8", - "#ff7f0e", - "#2ca02c", - "#98df8a", - "#d62728", - "#ff9896", - "#9467bd", - "#c5b0d5" - ], - "outputs": 1, - "x": 1340, - "y": 840, - "wires": [[]] - }, - { - "id": "a4f0f0d1.3aca88", - "type": "ui_toast", - "z": "cb95299c.2817c8", - "position": "top right", - "displayTime": "5", - "highlight": "", - "sendall": true, - "outputs": 0, - "ok": "OK", - "cancel": "", - "raw": false, - "topic": "", - "name": "", - "x": 1340, - "y": 680, - "wires": [] - }, - { - "id": "49af3d24.1799e4", - "type": "debug", - "z": "cb95299c.2817c8", - "name": "segmentation name", - "active": true, - "tosidebar": true, - "console": false, - "tostatus": false, - "complete": "true", - "targetType": "full", - "statusVal": "", - "statusType": "auto", - "x": 830, - "y": 760, - "wires": [] - }, - { - "id": "7088a5be.0c79a4", - "type": "template", - "z": "cb95299c.2817c8", - "name": "Create sentence", - "field": "payload", - "fieldType": "msg", - "format": "handlebars", - "syntax": "mustache", - "template": "The {{topic}} is {{payload.status}}", - "output": "str", - "x": 1100, - "y": 680, - "wires": [["a4f0f0d1.3aca88"]] - }, - { - "id": "b9a23b91.93638", - "type": "change", - "z": "cb95299c.2817c8", - "name": "Remove high-level topic", - "rules": [ - { - "t": "change", - "p": "topic", - "pt": "msg", - "from": "status/", - "fromt": "str", + "reg": false, + "x": 640, + "y": 440, + "wires": [ + [ + "cd1987c7.027f58" + ] + ] + }, + { + "id": "cd1987c7.027f58", + "type": "ui_switch", + "z": "1eaf21c8.f7a21e", + "name": "stepper_reverse", + "label": "Invert stepper output", + "tooltip": "Stepper 1 is controlled by output 1 or the other way around", + "group": "6be36295.0ab324", + "order": 5, + "width": 0, + "height": 0, + "passthru": false, + "decouple": "false", + "topic": "stepper_reverse", + "style": "", + "onvalue": "true", + "onvalueType": "bool", + "onicon": "", + "oncolor": "", + "offvalue": "false", + "offvalueType": "bool", + "officon": "", + "offcolor": "", + "x": 940, + "y": 440, + "wires": [ + [ + "8e3b3d3c.955148", + "2068e7f.f4efb18" + ] + ] + }, + { + "id": "54ba7f16.709ad8", + "type": "change", + "z": "1eaf21c8.f7a21e", + "name": "Get pump_steps_per_ml", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.pump_steps_per_ml", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", "to": "", - "tot": "str" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 850, - "y": 680, - "wires": [["7088a5be.0c79a4"]] - }, - { - "id": "6919465f.332e5", - "type": "ui_text", - "z": "cb95299c.2817c8", - "group": "46be9c86.dea684", - "order": 1, - "width": 10, - "height": 1, - "name": "segmenter", - "label": "Segmenter status:", - "format": "{{msg.payload.status}}", - "layout": "row-spread", - "x": 810, - "y": 720, - "wires": [] - }, - { - "id": "fa3b7929.ac7da8", - "type": "ui_text", - "z": "cb95299c.2817c8", - "group": "46be9c86.dea684", - "order": 5, - "width": 4, - "height": 1, - "name": "counter", - "label": "", - "format": "{{msg.payload}}", - "layout": "col-center", - "x": 1320, - "y": 800, - "wires": [] - }, - { - "id": "640ece83.88cab", - "type": "inject", - "z": "cb95299c.2817c8", - "name": "Init graphs", - "props": [ - { - "p": "payload" - }, - { - "p": "topic", - "vt": "str" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "object count", - "payload": "0", - "payloadType": "num", - "x": 810, - "y": 880, - "wires": [["4f3f7c4a.cb21c4"]] - }, - { - "id": "25867454.a8e334", - "type": "link in", - "z": "cb95299c.2817c8", - "name": "Segmenter module status", - "links": ["dcf5bd45.16a8d"], - "x": 295, - "y": 740, - "wires": [["aa38dbbc.cf0a9"]] - }, - { - "id": "c8749cbb.55254", - "type": "function", - "z": "cb95299c.2817c8", - "name": "set global", - "func": "global.set(msg.topic, msg.payload);", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 960, - "y": 380, - "wires": [[]] - }, - { - "id": "d43c3ed9.e6cb1", - "type": "ui_template", - "z": "cb95299c.2817c8", - "group": "46be9c86.dea684", - "name": "Object counts", - "order": 3, - "width": 0, - "height": 0, - "format": "

Object counts

", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": true, - "templateScope": "local", - "className": "", - "x": 1340, - "y": 760, - "wires": [[]] - }, - { - "id": "33c28dc1.238002", - "type": "function", - "z": "cb95299c.2817c8", - "name": "prepare segmentation", - "func": "global.set('obj_counter', 0);\n\nvar segmentation_list = flow.get('segmentation_list')\nif (segmentation_list !== undefined && segmentation_list !== \"\") {\n msg.payload['path'] = segmentation_list\n}\n\n\nvar force = flow.get('force')\nif (force !== undefined && force !== \"\") {\n msg.payload['settings'] = {\"force\":Boolean(force)}\n}\n\n\nvar recursive = flow.get('recursive')\nif (recursive !== undefined && recursive !== \"\") {\n if (\"settings\" in msg.payload){\n msg.payload.settings[\"recursive\"] = Boolean(recursive)\n }\n else{\n msg.payload['settings'] = {\"recursive\": Boolean(recursive)}\n }\n}\n\nvar ecotaxa = flow.get('ecotaxa')\nif (ecotaxa !== undefined && ecotaxa !== \"\") {\n if (\"settings\" in msg.payload){\n msg.payload.settings[\"ecotaxa\"] = Boolean(ecotaxa)\n }\n else{\n msg.payload['settings'] = {\"ecotaxa\": Boolean(ecotaxa)}\n }\n}\n\nvar keep = flow.get('keep')\nif (keep !== undefined && keep !== \"\") {\n if (\"settings\" in msg.payload){\n msg.payload.settings[\"keep\"] = Boolean(keep)\n }\n else{\n msg.payload['settings'] = {\"keep\": Boolean(keep)}\n }\n}\n\nvar process_id = global.get('process_id')\nif (process_id !== undefined && process_id !== \"\") {\n if (\"settings\" in msg.payload){\n msg.payload.settings[\"process_id\"] = process_id\n }\n else{\n msg.payload['settings'] = {\"process_id\": process_id}\n }\n}\n\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 620, - "y": 460, - "wires": [["16f3cef4.0acac9"]] - }, - { - "id": "fa12f9f8.00cfa8", - "type": "subflow:1c24ad9c.bebec2", - "z": "cb95299c.2817c8", - "name": "", - "env": [], - "x": 430, - "y": 380, - "wires": [["3b72d11c.86e9e6"]] - }, - { - "id": "3b72d11c.86e9e6", - "type": "function", - "z": "cb95299c.2817c8", - "name": "get process_id", - "func": "msg.payload = msg.payload.process_id;\nmsg.topic = \"process_id\";\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 600, - "y": 380, - "wires": [["56971109c8be3b54"]] - }, - { - "id": "3ea12061.ce62c", - "type": "ui_list", - "z": "cb95299c.2817c8", - "group": "abeb6dad.635a2", - "name": "", - "order": 9, - "width": 10, - "height": 11, - "lineType": "one", - "actionType": "check", - "allowHTML": false, - "outputs": 1, - "topic": "", - "x": 790, - "y": 140, - "wires": [["cb3b87b5.63c4"]] - }, - { - "id": "8bd8fb2c.53fa4", - "type": "dir2files", - "z": "cb95299c.2817c8", - "name": "", - "dirname": "/home/pi/data/img/", - "pathRegex": "", - "isRecursive": true, - "findDir": true, - "isArray": true, - "x": 460, - "y": 140, - "wires": [["ba2947.c854deb8"]] - }, - { - "id": "127d4ee.f8ad1b1", - "type": "ui_button", - "z": "cb95299c.2817c8", - "name": "Refresh", - "group": "abeb6dad.635a2", - "order": 8, - "width": 0, - "height": 0, - "passthru": false, - "label": "Update acquisition's folder list", - "tooltip": "Refresh the list of previous acquisitions", - "color": "", - "bgcolor": "", - "icon": "mi-find_replace", - "payload": "", - "payloadType": "date", - "topic": "update", - "x": 260, - "y": 140, - "wires": [["8bd8fb2c.53fa4", "56f845f5.e7c054"]] - }, - { - "id": "946ce9ee.092cf", - "type": "inject", - "z": "cb95299c.2817c8", - "name": "Init", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "", - "payload": "", - "payloadType": "date", - "x": 270, - "y": 100, - "wires": [["8bd8fb2c.53fa4", "56f845f5.e7c054"]] - }, - { - "id": "cb3b87b5.63c4", - "type": "function", - "z": "cb95299c.2817c8", - "name": "update segmentation_list", - "func": "var segmentation_list = flow.get('segmentation_list');\n\nif (segmentation_list === undefined || segmentation_list === \"\") {\n segmentation_list = []\n console.log(\"error\")\n}\n\npath = \"/home/pi/data/img/\" + msg.payload.title\n\nif (msg.payload.isChecked){\n if (segmentation_list.includes(path) === false){\n segmentation_list.push(path)\n }\n // Element already in list, don't push it more than once\n //segmentation_list.push(msg.payload[\"title\"])\n}\nelse {\n var pos = segmentation_list.indexOf(path)\n segmentation_list.splice(pos, 1)\n}\n\nflow.set('segmentation_list', segmentation_list)", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 990, - "y": 140, - "wires": [[]] - }, - { - "id": "56f845f5.e7c054", - "type": "change", - "z": "cb95299c.2817c8", - "name": "Reset segmentation_list", - "rules": [ - { - "t": "set", - "p": "segmentation_list", - "pt": "flow", - "to": "[]", - "tot": "json" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 510, - "y": 100, - "wires": [[]] - }, - { - "id": "7fc72364.8f038c", - "type": "ui_template", - "z": "cb95299c.2817c8", - "group": "abeb6dad.635a2", - "name": "Update message", - "order": 1, - "width": 10, - "height": 3, - "format": "
You can choose here in which folder(s) you want the segmentation script to run. A few details though:\n
The segmentation is run recursively in all folders. So if you select a top level folder, the segmentation will be run in all subfolders.\n
Also, you will be able to chose wether for force the segmentation for folders in which it has run already.
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": true, - "templateScope": "local", - "x": 270, - "y": 40, - "wires": [[]] - }, - { - "id": "ba2947.c854deb8", - "type": "function", - "z": "cb95299c.2817c8", - "name": "remove common", - "func": "function remove_path(item, index, array) {\n array[index] = item.replace(\"/home/pi/data/img/\", \"\")\n} \n\nmsg.payload.forEach(remove_path)\n\nreturn msg", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 630, - "y": 140, - "wires": [["3ea12061.ce62c"]] - }, - { - "id": "21af0db1.c2c182", - "type": "ui_multistate_switch", - "z": "cb95299c.2817c8", - "name": "recursive toggle", - "group": "abeb6dad.635a2", - "order": 4, - "width": 5, - "height": 1, - "label": "Recursive folder", - "stateField": "payload", - "enableField": "enable", - "rounded": true, - "useThemeColors": true, - "hideSelectedLabel": false, - "options": [ - { - "label": "No", - "value": "0", - "valueType": "num", - "color": "#009933" - }, - { - "label": "Yes", - "value": "1", - "valueType": "num", - "color": "#999999" - } - ], - "x": 480, - "y": 220, - "wires": [["880b192a.88e2d"]] - }, - { - "id": "dffb9881.feef8", - "type": "ui_multistate_switch", - "z": "cb95299c.2817c8", - "name": "force toggle", - "group": "abeb6dad.635a2", - "order": 3, - "width": 5, - "height": 1, - "label": "Force rework", - "stateField": "payload", - "enableField": "enable", - "rounded": true, - "useThemeColors": true, - "hideSelectedLabel": false, - "options": [ - { - "label": "No", - "value": "0", - "valueType": "num", - "color": "#009933" - }, - { - "label": "Yes", - "value": "1", - "valueType": "num", - "color": "#999999" - } - ], - "x": 470, - "y": 300, - "wires": [["a4f68fa6.5d77f8"]] - }, - { - "id": "880b192a.88e2d", - "type": "change", - "z": "cb95299c.2817c8", - "name": "", - "rules": [ - { - "t": "set", - "p": "recursive", - "pt": "flow", - "to": "payload", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 690, - "y": 240, - "wires": [[]] - }, - { - "id": "a4f68fa6.5d77f8", - "type": "change", - "z": "cb95299c.2817c8", - "name": "", - "rules": [ - { - "t": "set", - "p": "force", - "pt": "flow", - "to": "payload", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 670, - "y": 280, - "wires": [[]] - }, - { - "id": "1ef1b43b.b0f064", - "type": "inject", - "z": "cb95299c.2817c8", - "name": "0", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "", - "payload": "0", - "payloadType": "num", - "x": 270, - "y": 280, - "wires": [["dffb9881.feef8", "a4f68fa6.5d77f8"]] - }, - { - "id": "f078c068.eacf58", - "type": "ui_template", - "z": "cb95299c.2817c8", - "group": "46be9c86.dea684", - "name": "Stream Segmented object", - "order": 2, - "width": 10, - "height": 8, - "format": "
\n Latest object segmented:
\n \"If\n
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "className": "", - "x": 1370, - "y": 600, - "wires": [[]] - }, - { - "id": "43f97b93.b76294", - "type": "inject", - "z": "cb95299c.2817c8", - "name": "1", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "", - "payload": "1", - "payloadType": "num", - "x": 270, - "y": 240, - "wires": [["21af0db1.c2c182", "880b192a.88e2d"]] - }, - { - "id": "4f3f7c4a.cb21c4", - "type": "change", - "z": "cb95299c.2817c8", - "name": "", - "rules": [ - { - "t": "set", - "p": "obj_counter", - "pt": "flow", - "to": "0", - "tot": "num" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 1010, - "y": 840, - "wires": [["fa3b7929.ac7da8", "9d53dbe2.dbffe8"]] - }, - { - "id": "6bce0f60.f48998", - "type": "link in", - "z": "cb95299c.2817c8", - "name": "", - "links": ["596fc9d4.46c75"], - "x": 855, - "y": 840, - "wires": [["4f3f7c4a.cb21c4"]] - }, - { - "id": "596fc9d4.46c75", - "type": "link out", - "z": "cb95299c.2817c8", - "name": "", - "links": ["6bce0f60.f48998"], - "x": 715, - "y": 500, - "wires": [] - }, - { - "id": "c72a1064.1ec388", - "type": "change", - "z": "cb95299c.2817c8", - "name": "Reset counters", - "rules": [ - { - "t": "set", - "p": "topic", - "pt": "msg", - "to": "object count", - "tot": "str" - }, - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "0", - "tot": "num" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 600, - "y": 500, - "wires": [["596fc9d4.46c75"]] - }, - { - "id": "9367534a.fb8568", - "type": "ui_multistate_switch", - "z": "cb95299c.2817c8", - "name": "Ecotaxa archive", - "group": "abeb6dad.635a2", - "order": 6, - "width": 5, - "height": 1, - "label": "Ecotaxa archive", - "stateField": "payload", - "enableField": "enable", - "rounded": true, - "useThemeColors": true, - "hideSelectedLabel": false, - "options": [ - { - "label": "No", - "value": "0", - "valueType": "num", - "color": "#009933" - }, - { - "label": "Yes", - "value": "1", - "valueType": "num", - "color": "#999999" - } - ], - "x": 1080, - "y": 220, - "wires": [["25ac4f9a.5b05c8"]] - }, - { - "id": "25ac4f9a.5b05c8", - "type": "change", - "z": "cb95299c.2817c8", - "name": "", - "rules": [ - { - "t": "set", - "p": "ecotaxa", - "pt": "flow", - "to": "payload", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 1280, - "y": 240, - "wires": [[]] - }, - { - "id": "bef78886.8f0b98", - "type": "inject", - "z": "cb95299c.2817c8", - "name": "1", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "", - "payload": "1", - "payloadType": "num", - "x": 910, - "y": 240, - "wires": [["9367534a.fb8568", "25ac4f9a.5b05c8"]] - }, - { - "id": "32465a4e.8fcac6", - "type": "ui_multistate_switch", - "z": "cb95299c.2817c8", - "name": "Keep objects", - "group": "abeb6dad.635a2", - "order": 5, - "width": 5, - "height": 1, - "label": "Keep objects", - "stateField": "payload", - "enableField": "enable", - "rounded": true, - "useThemeColors": true, - "hideSelectedLabel": false, - "options": [ - { - "label": "No", - "value": "0", - "valueType": "num", - "color": "#009933" - }, - { - "label": "Yes", - "value": "1", - "valueType": "num", - "color": "#999999" - } - ], - "x": 1070, - "y": 300, - "wires": [["8dd6f57f.b77f98"]] - }, - { - "id": "8dd6f57f.b77f98", - "type": "change", - "z": "cb95299c.2817c8", - "name": "", - "rules": [ - { - "t": "set", - "p": "keep", - "pt": "flow", - "to": "payload", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 1270, - "y": 280, - "wires": [[]] - }, - { - "id": "8090df89.c029e", - "type": "inject", - "z": "cb95299c.2817c8", - "name": "1", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "", - "payload": "1", - "payloadType": "num", - "x": 910, - "y": 280, - "wires": [["32465a4e.8fcac6", "8dd6f57f.b77f98"]] - }, - { - "id": "56971109c8be3b54", - "type": "ui_text_input", - "z": "cb95299c.2817c8", - "name": "process_id", - "label": "Process unique ID*", - "tooltip": "", - "group": "abeb6dad.635a2", - "order": 2, - "width": 10, - "height": 1, - "passthru": true, - "mode": "text", - "delay": 300, - "topic": "process_id", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 790, - "y": 380, - "wires": [["c8749cbb.55254"]] - }, - { - "id": "2911fbc6.d28c24", - "type": "ui_template", - "z": "c1660bc.e7ff7f8", - "group": "c0ebfc57.42527", - "name": "Image browser", - "order": 1, - "width": "0", - "height": "0", - "format": "
\n\n
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "className": "", - "x": 400, - "y": 100, - "wires": [[]] - }, - { - "id": "4f02c726.de69b8", - "type": "ui_button", - "z": "9daf9e2b.019fc", - "name": "", - "group": "a7d64879.38298", - "order": 4, - "width": 6, - "height": 1, - "passthru": false, - "label": "Reboot", - "tooltip": "", - "color": "", - "bgcolor": "#AD1625", - "className": "", - "icon": "fa-repeat fa-2x", - "payload": "reboot", - "payloadType": "str", - "topic": "reboot", - "topicType": "str", - "x": 160, - "y": 240, - "wires": [["4af9112d.87767"]] - }, - { - "id": "611a8b1c.a829b4", - "type": "exec", - "z": "9daf9e2b.019fc", - "command": "sudo", - "addpay": "payload", - "append": "now", - "useSpawn": "false", - "timer": "2", - "winHide": false, - "oldrc": false, - "name": "sudo cmd now", - "x": 480, - "y": 280, - "wires": [[], [], []] - }, - { - "id": "bc76c4d6.a7ad28", - "type": "ui_button", - "z": "9daf9e2b.019fc", - "name": "", - "group": "a7d64879.38298", - "order": 5, - "width": 6, - "height": 1, - "passthru": false, - "label": "Shutdown", - "tooltip": "", - "color": "", - "bgcolor": "#AD1625", - "className": "", - "icon": "fa-power-off fa-2x", - "payload": "shutdown", - "payloadType": "str", - "topic": "shutdown", - "topicType": "str", - "x": 160, - "y": 320, - "wires": [["4af9112d.87767"]] - }, - { - "id": "4af9112d.87767", - "type": "python3-function", - "z": "9daf9e2b.019fc", - "name": "action", - "func": "#!/usr/bin/python3\nimport smbus2 as smbus\n\nbus = smbus.SMBus(1)\n#turn off LED\nbus.write_byte_data(0x0d, 0x07, 0x00)\n#turn off Fan\nbus.write_byte_data(0x0d, 0x08, 0x00)\n\n#msg[\"payload\"] = str(msg[\"topic\"])+' now'\nreturn msg", - "outputs": 1, - "x": 330, - "y": 280, - "wires": [["611a8b1c.a829b4"]] - }, - { - "id": "466eb611.4da048", - "type": "ui_button", - "z": "9daf9e2b.019fc", - "name": "", - "group": "a7d64879.38298", - "order": 2, - "width": 6, - "height": 1, - "passthru": true, - "label": "Restart Hardware Controller", - "tooltip": "", - "color": "", - "bgcolor": "#AD1625", - "className": "", - "icon": "fa-refresh fa-2x", - "payload": "Restarting hardware controller...", - "payloadType": "str", - "topic": "", - "topicType": "str", - "x": 460, - "y": 420, - "wires": [["bd5cceef.b17ad", "414353cde6a62346"]] - }, - { - "id": "bd5cceef.b17ad", - "type": "exec", - "z": "9daf9e2b.019fc", - "command": "sudo systemctl restart planktoscope-org.device-backend.controller.service", - "addpay": false, - "append": "", - "useSpawn": "false", - "timer": "", - "winHide": false, - "oldrc": false, - "name": "Restart hardware controller", - "x": 800, - "y": 420, - "wires": [[], [], []] - }, - { - "id": "43cf8ff7.75231", - "type": "rpi-gpio out", - "z": "9daf9e2b.019fc", - "name": "Pump Enable", - "pin": "4", - "set": true, - "level": "1", - "freq": "", - "out": "out", - "bcm": true, - "x": 420, - "y": 80, - "wires": [] - }, - { - "id": "4bca8a25.15be3c", - "type": "rpi-gpio out", - "z": "9daf9e2b.019fc", - "name": "Focus Enable", - "pin": "12", - "set": true, - "level": "1", - "freq": "", - "out": "out", - "bcm": true, - "x": 420, - "y": 120, - "wires": [] - }, - { - "id": "50f9b5b.a84bccc", - "type": "inject", - "z": "9daf9e2b.019fc", - "name": "Default: ON", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": "0.01", - "topic": "", - "payload": "true", - "payloadType": "bool", - "x": 150, - "y": 100, - "wires": [ - [ - "43cf8ff7.75231", - "4bca8a25.15be3c", - "6db0fcf5.f0effc", - "5fc4ede4.72516c" - ] - ] - }, - { - "id": "45a7b5aa.2ed20c", - "type": "link in", - "z": "9daf9e2b.019fc", - "name": "Restart Hardware Controller", - "links": ["e41870d7.300eb8", "e4ead350b3d07578"], - "x": 195, - "y": 420, - "wires": [["466eb611.4da048"]] - }, - { - "id": "b81b990a.d4dca", - "type": "link in", - "z": "9daf9e2b.019fc", - "name": "Shutdown", - "links": ["e08cfcb8.2a67e8"], - "x": 195, - "y": 280, - "wires": [["4af9112d.87767"]] - }, - { - "id": "5fc4ede4.72516c", - "type": "rpi-gpio out", - "z": "9daf9e2b.019fc", - "name": "HAT Pump Enable", - "pin": "23", - "set": true, - "level": "1", - "freq": "", - "out": "out", - "bcm": true, - "x": 430, - "y": 40, - "wires": [] - }, - { - "id": "6db0fcf5.f0effc", - "type": "rpi-gpio out", - "z": "9daf9e2b.019fc", - "name": "HAT Focus Enable", - "pin": "5", - "set": true, - "level": "1", - "freq": "", - "out": "out", - "bcm": true, - "x": 430, - "y": 160, - "wires": [] - }, - { - "id": "38c05fcb891c82bf", - "type": "exec", - "z": "9daf9e2b.019fc", - "command": "docker restart apps_ps_backend_proc-segmenter-server-1", - "addpay": false, - "append": "", - "useSpawn": "false", - "timer": "", - "winHide": false, - "oldrc": false, - "name": "Restart segmenter", - "x": 770, - "y": 500, - "wires": [[], [], []] - }, - { - "id": "631b8626185addfc", - "type": "ui_button", - "z": "9daf9e2b.019fc", - "name": "", - "group": "a7d64879.38298", - "order": 3, - "width": 6, - "height": 1, - "passthru": true, - "label": "Restart Segmenter", - "tooltip": "", - "color": "", - "bgcolor": "#AD1625", - "className": "", - "icon": "fa-refresh fa-2x", - "payload": "Restarting segmenter...", - "payloadType": "str", - "topic": "", - "topicType": "str", - "x": 430, - "y": 500, - "wires": [["38c05fcb891c82bf", "e036d07cf78fde85"]] - }, - { - "id": "cec5bd6f962f6903", - "type": "ui_template", - "z": "9daf9e2b.019fc", - "group": "a7d64879.38298", - "name": "Logs", - "order": 1, - "width": 0, - "height": 0, - "format": "

\n The PlanktoScope software application consists of three components: a Node-RED dashboard which provides the user interface you're using; a Hardware Controller\n which executes commands sent from the Node-RED dashboard for hardware control and image acquisition; and a Segmenter which processes an acquired dataset of\n images and isolates objects from those images. Each component has its own independent log of messages, managed separately from the logs for the other components.\n

\n

\n All three components have live-updating logs which you can monitor. Additionally, the Hardware Controller and the Segmenter also save all of their log messages\n to files which you can browse and download. Those software components create a new log file each time they start, and the name of the log file includes the time\n in the PlanktoScope's clock when the software component started. However, if your PlanktoScope's clock is usually wrong, it makes the log files difficult to navigate.\n This will be fixed in a future version of the software.\n

\n

\n If you need to share your logs with other people (e.g. on Slack or GitHub), you should open the \"Downloadable Logs\" links, and then you can select one file or multiple\n log files for downloading as a zip archive.\n

\n", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": true, - "templateScope": "local", - "className": "", - "x": 650, - "y": 180, - "wires": [[]] - }, - { - "id": "414353cde6a62346", - "type": "ui_toast", - "z": "9daf9e2b.019fc", - "position": "top right", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 0, - "ok": "OK", - "cancel": "", - "raw": false, - "className": "", - "topic": "", - "name": "", - "x": 770, - "y": 380, - "wires": [] - }, - { - "id": "e036d07cf78fde85", - "type": "ui_toast", - "z": "9daf9e2b.019fc", - "position": "top right", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 0, - "ok": "OK", - "cancel": "", - "raw": false, - "className": "", - "topic": "", - "name": "", - "x": 770, - "y": 460, - "wires": [] - }, - { - "id": "ddcbbfa5.cd158", - "type": "exec", - "z": "1371dec5.76e671", - "command": "vcgencmd measure_temp | tr -d \"temp=\" | tr -d \"'C\" | tr -d \"\\n\"", - "addpay": false, - "append": "", - "useSpawn": "", - "timer": "", - "name": "RPi Temp.", - "x": 330, - "y": 40, - "wires": [["bc503fa5.f46dd"], [], []] - }, - { - "id": "3910d662.fa1f7a", - "type": "exec", - "z": "1371dec5.76e671", - "command": "df -h | grep /dev/root | awk -F ' ' '{print $5}' | tr -d % | tr \"\\n$\" \"\\ \" | sed 's/,/./' | tr -d \" \"", - "addpay": false, - "append": "", - "useSpawn": "", - "timer": "", - "name": "Disk Usage", - "x": 330, - "y": 120, - "wires": [["eaf74a43.fa27d"], [], []] - }, - { - "id": "1cd5b4c0.46af9b", - "type": "inject", - "z": "1371dec5.76e671", - "name": "update: 5s", - "props": [ - { - "p": "payload" - }, - { - "p": "topic", - "vt": "str" - } - ], - "repeat": "5", - "crontab": "", - "once": false, - "onceDelay": "", - "topic": "", - "payload": "", - "payloadType": "date", - "x": 110, - "y": 160, - "wires": [ - [ - "3910d662.fa1f7a", - "ddcbbfa5.cd158", - "23a84a3856fb68bd", - "4ed64bd91fa9fbdf", - "ed5f2d963d85478b" - ] - ] - }, - { - "id": "2549f778.4eb828", - "type": "python3-function", - "z": "1371dec5.76e671", - "name": "fan control", - "func": "import smbus2 as smbus\n\nstate = msg[\"payload\"]\nbus = smbus.SMBus(1)\n\nDEVICE_ADDRESS = 0x0d\n# command happens twice, for reasons\nif state == \"off\":\n with smbus.SMBus(1) as bus:\n bus.write_byte_data(DEVICE_ADDRESS, 0x08, 0x00)\n bus.write_byte_data(DEVICE_ADDRESS, 0x08, 0x00)\n return msg\nif state == \"on\":\n with smbus.SMBus(1) as bus:\n bus.write_byte_data(DEVICE_ADDRESS, 0x08, 0x01)\n bus.write_byte_data(DEVICE_ADDRESS, 0x08, 0x01)\n return msg\n", - "outputs": 1, - "x": 1150, - "y": 40, - "wires": [["e640ebb5c397f424"]] - }, - { - "id": "b7ab1ada.1f4158", - "type": "exec", - "z": "1371dec5.76e671", - "command": "i2cdetect -y 1", - "addpay": false, - "append": "", - "useSpawn": "false", - "timer": "1", - "winHide": false, - "oldrc": false, - "name": "i2c update", - "x": 1440, - "y": 40, - "wires": [[], [], []] - }, - { - "id": "bc503fa5.f46dd", - "type": "switch", - "z": "1371dec5.76e671", - "name": "", - "property": "payload", - "propertyType": "msg", - "rules": [ - { - "t": "gt", - "v": "40", - "vt": "num" - }, - { - "t": "lte", - "v": "35", - "vt": "num" - } - ], - "checkall": "true", - "repair": false, - "outputs": 2, - "x": 570, - "y": 40, - "wires": [["a25d6486.e1ce28"], ["5d4f3e71.1bad4"]] - }, - { - "id": "5d4f3e71.1bad4", - "type": "change", - "z": "1371dec5.76e671", - "name": "Set OFF", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "off", - "tot": "str" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 720, - "y": 60, - "wires": [["7fb13a4a53b612a0"]] - }, - { - "id": "a25d6486.e1ce28", - "type": "change", - "z": "1371dec5.76e671", - "name": "Set ON", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "on", - "tot": "str" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 720, - "y": 20, - "wires": [["7fb13a4a53b612a0"]] - }, - { - "id": "569154a.b53182c", - "type": "inject", - "z": "1371dec5.76e671", - "name": "once", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": "", - "topic": "", - "payload": "start", - "payloadType": "str", - "x": 170, - "y": 680, - "wires": [["ccb5172d10c1ccaf"]] - }, - { - "id": "4828d2f4.7c712c", - "type": "function", - "z": "1371dec5.76e671", - "name": "set global", - "func": "global.set(\"acq_instrument_id\",msg.payload);\n", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 580, - "y": 700, - "wires": [[]] - }, - { - "id": "e2f39a35.f57298", - "type": "subflow:1c24ad9c.bebec2", - "z": "1371dec5.76e671", - "name": "", - "env": [], - "x": 170, - "y": 620, - "wires": [["950b773ad4c0fdfe"]] - }, - { - "id": "3e64877a.9684b", - "type": "function", - "z": "1371dec5.76e671", - "name": "set global", - "func": "global.set(\"acq_software\", \"PlanktoScope \" + msg.payload);\n", - "outputs": 1, - "timeout": "", - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 820, - "y": 500, - "wires": [[]] - }, - { - "id": "bdc6718a.dd5d48", - "type": "ui_text", - "z": "1371dec5.76e671", - "group": "ce9e278.781eed8", - "order": 2, - "width": 0, - "height": 0, - "name": "", - "label": "Instrument Type", - "format": "{{msg.payload}}", - "layout": "row-spread", - "className": "", - "style": false, - "font": "", - "fontSize": "", - "color": "#000000", - "x": 600, - "y": 620, - "wires": [] - }, - { - "id": "a400a97e.e333a8", - "type": "ui_text", - "z": "1371dec5.76e671", - "group": "ce9e278.781eed8", - "order": 1, - "width": 0, - "height": 0, - "name": "", - "label": "Instrument Name", - "format": "{{msg.payload}}", - "layout": "row-spread", - "className": "", - "style": false, - "font": "", - "fontSize": "", - "color": "#000000", - "x": 610, - "y": 660, - "wires": [] - }, - { - "id": "8343fa69.49339", - "type": "ui_text", - "z": "1371dec5.76e671", - "group": "ce9e278.781eed8", - "order": 3, - "width": 0, - "height": 0, - "name": "", - "label": "Software Version", - "format": "{{msg.payload}}", - "layout": "row-spread", - "className": "", - "style": false, - "font": "", - "fontSize": "", - "color": "#000000", - "x": 850, - "y": 540, - "wires": [] - }, - { - "id": "f783aefd.c3bfd8", - "type": "ui_text", - "z": "1371dec5.76e671", - "group": "ce9e278.781eed8", - "order": 4, - "width": 0, - "height": 0, - "name": "", - "label": "Camera Name", - "format": "{{msg.payload}}", - "layout": "row-spread", - "x": 600, - "y": 740, - "wires": [] - }, - { - "id": "30067f35.532f2", - "type": "link in", - "z": "1371dec5.76e671", - "name": "Camera Name", - "links": ["559a8085.1d6b9"], - "x": 205, - "y": 740, - "wires": [["f783aefd.c3bfd8"]] - }, - { - "id": "11b51f8f.acd308", - "type": "python3-function", - "z": "1371dec5.76e671", - "d": true, - "name": "fan temperature", - "func": "import smbus\nbus = smbus.SMBus(1)\n\naddr = 0x0d\nfan_reg = 0x08\n\ntemp = float( msg[\"payload\"])\n\n# 0x01 full speed, 0x02: 20% speed, ..., 0x09: 90% speed\n\nif temp < 38:\n bus.write_byte_data(addr, fan_reg, 0x00)\nelif temp < 43:\n bus.write_byte_data(addr, fan_reg, 0x02)\nelif temp < 46:\n bus.write_byte_data(addr, fan_reg, 0x04)\nelif temp < 48:\n bus.write_byte_data(addr, fan_reg, 0x06)\nelif temp < 52:\n bus.write_byte_data(addr, fan_reg, 0x08)\nelse:\n bus.write_byte_data(addr, fan_reg, 0x01)\n\nreturn msg", - "outputs": 1, - "x": 1440, - "y": 120, - "wires": [[]] - }, - { - "id": "eaf74a43.fa27d", - "type": "switch", - "z": "1371dec5.76e671", - "name": "if disk > 90%", - "property": "payload", - "propertyType": "msg", - "rules": [ - { - "t": "gte", - "v": "90", - "vt": "num" - } - ], - "checkall": "true", - "repair": false, - "outputs": 1, - "x": 590, - "y": 120, - "wires": [["6d09f428.930bcc"]] - }, - { - "id": "46d5e78b.15f998", - "type": "ui_toast", - "z": "1371dec5.76e671", - "position": "dialog", - "displayTime": "10", - "highlight": "", - "sendall": true, - "outputs": 1, - "ok": "OK", - "cancel": "", - "raw": false, - "className": "", - "topic": "", - "name": "", - "x": 1090, - "y": 120, - "wires": [[]] - }, - { - "id": "24df077a.cb252", - "type": "change", - "z": "1371dec5.76e671", - "name": "full disk msg", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "\"Your drive has reached 90% capacity, you should do a backup to an external drive and a purge.\"", - "tot": "str" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 930, - "y": 120, - "wires": [["46d5e78b.15f998"]] - }, - { - "id": "6d09f428.930bcc", - "type": "delay", - "z": "1371dec5.76e671", - "name": "", - "pauseType": "rate", - "timeout": "5", - "timeoutUnits": "seconds", - "rate": "1", - "nbRateUnits": "5", - "rateUnits": "minute", - "randomFirst": "1", - "randomLast": "5", - "randomUnits": "seconds", - "drop": true, - "allowrate": false, - "outputs": 1, - "x": 760, - "y": 120, - "wires": [["24df077a.cb252"]] - }, - { - "id": "e640ebb5c397f424", - "type": "delay", - "z": "1371dec5.76e671", - "name": "", - "pauseType": "delay", - "timeout": "1", - "timeoutUnits": "seconds", - "rate": "1", - "nbRateUnits": "1", - "rateUnits": "second", - "randomFirst": "1", - "randomLast": "5", - "randomUnits": "seconds", - "drop": false, - "allowrate": false, - "outputs": 1, - "x": 1300, - "y": 40, - "wires": [["b7ab1ada.1f4158"]] - }, - { - "id": "7fb13a4a53b612a0", - "type": "rbe", - "z": "1371dec5.76e671", - "name": "", - "func": "rbe", - "gap": "", - "start": "", - "inout": "out", - "septopics": true, - "property": "payload", - "topi": "topic", - "x": 1010, - "y": 40, - "wires": [["2549f778.4eb828"]] - }, - { - "id": "ccb5172d10c1ccaf", - "type": "file in", - "z": "1371dec5.76e671", - "name": "Get machine name", - "filename": "/run/machine-name", - "filenameType": "str", - "format": "utf8", - "chunk": false, - "sendError": false, - "encoding": "none", - "allProps": false, - "x": 350, - "y": 680, - "wires": [["a400a97e.e333a8", "4828d2f4.7c712c"]] - }, - { - "id": "950b773ad4c0fdfe", - "type": "change", - "z": "1371dec5.76e671", - "name": "Get acq_instrument", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.acq_instrument", - "tot": "msg" - }, - { - "t": "set", - "p": "topic", - "pt": "msg", - "to": "acq_instrument", - "tot": "str" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 350, - "y": 620, - "wires": [["bdc6718a.dd5d48"]] - }, - { - "id": "24de7407445d2087", - "type": "inject", - "z": "1371dec5.76e671", - "name": "once", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": "", - "topic": "", - "payload": "start", - "payloadType": "str", - "x": 90, - "y": 520, - "wires": [["e4f9ed2b337c2fa6"]] - }, - { - "id": "e4f9ed2b337c2fa6", - "type": "file in", - "z": "1371dec5.76e671", - "name": "Versioning File", - "filename": "/usr/share/planktoscope/installer-versioning.yml", - "filenameType": "str", - "format": "utf8", - "chunk": false, - "sendError": false, - "encoding": "none", - "allProps": false, - "x": 240, - "y": 520, - "wires": [["db79aae8a7fe3512"]] - }, - { - "id": "db79aae8a7fe3512", - "type": "yaml", - "z": "1371dec5.76e671", - "property": "payload", - "name": "", - "x": 390, - "y": 520, - "wires": [["04c313e8d9aac122", "ef1970121e57c5e8", "574361abfe75b3b3"]] - }, - { - "id": "04c313e8d9aac122", - "type": "change", - "z": "1371dec5.76e671", - "name": "Get repo", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.repo", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 580, - "y": 480, - "wires": [["57b3b083a2455e09"]] - }, - { - "id": "ef1970121e57c5e8", - "type": "change", - "z": "1371dec5.76e671", - "name": "Get version", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.version", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 590, - "y": 520, - "wires": [["3e64877a.9684b", "8343fa69.49339"]] - }, - { - "id": "57b3b083a2455e09", - "type": "function", - "z": "1371dec5.76e671", - "name": "set global", - "func": "global.set(\"process_source\", msg.payload);\n", - "outputs": 1, - "timeout": "", - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 820, - "y": 460, - "wires": [[]] - }, - { - "id": "574361abfe75b3b3", - "type": "change", - "z": "1371dec5.76e671", - "name": "Get commit", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.commit", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 590, - "y": 560, - "wires": [["016d1d2a2f19f1a6"]] - }, - { - "id": "016d1d2a2f19f1a6", - "type": "function", - "z": "1371dec5.76e671", - "name": "set global", - "func": "global.set(\"process_commit\", msg.payload);\n", - "outputs": 1, - "timeout": "", - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 820, - "y": 580, - "wires": [[]] - }, - { - "id": "4ed64bd91fa9fbdf", - "type": "ui_template", - "z": "1371dec5.76e671", - "group": "3da7da8f.179606", - "name": "Metrics panel", - "order": 1, - "width": "0", - "height": "0", - "format": "
\n

\n The instrument's system time is different from your web browser's time by {{drift}}.\n As a result, timestamps in your datasets will be incorrect.\n Additionally, system metrics will not be recorded or shown correctly.\n Additionally, you will see incorrectly-aligned graphs in the metrics below.\n

\n

Please change the instrument's system time or your web browser's time to accurate values.

\n

\n \n

\n
\n\n
\n

Loading system metrics, please wait...

\n
\n\n
\n \n
\n\n\n", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "className": "", - "x": 330, - "y": 280, - "wires": [[]] - }, - { - "id": "38bad1e220cd5d87", - "type": "ui_text", - "z": "1371dec5.76e671", - "group": "ce9e278.781eed8", - "order": 5, - "width": 0, - "height": 0, - "name": "", - "label": "System Time", - "format": "{{msg.payload}}", - "layout": "row-spread", - "className": "", - "style": false, - "font": "", - "fontSize": 16, - "color": "#000000", - "x": 590, - "y": 240, - "wires": [] - }, - { - "id": "ed5f2d963d85478b", - "type": "function", - "z": "1371dec5.76e671", - "name": "Get system time", - "func": "var date = new Date();\ndate.setSeconds(0, 0);\nmsg.payload = (\n date.toISOString().replace('T', ' ').replace(/:\\d+\\.\\d+Z/,' UTC')\n);\nreturn msg", - "outputs": 1, - "timeout": 0, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 340, - "y": 240, - "wires": [["38bad1e220cd5d87"]] - }, - { - "id": "23a84a3856fb68bd", - "type": "ui_template", - "z": "1371dec5.76e671", - "group": "ce9e278.781eed8", - "name": "Browser time", - "order": 6, - "width": "6", - "height": "1", - "format": "
\n

Browser Time

\n

{{time}}

\n
\n\n", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "className": "", - "x": 330, - "y": 200, - "wires": [[]] - }, - { - "id": "19a45f972be2b0f1", - "type": "function", - "z": "1371dec5.76e671", - "name": "Get system time", - "func": "var date = new Date(msg.payload.timestamp);\nmsg.payload = (\n date.toISOString().replace('T', ' ').replace(/:\\d+\\.\\d+Z/,' UTC')\n);\nreturn msg", - "outputs": 1, - "timeout": 0, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 340, - "y": 340, - "wires": [["ee2c5e7c29eb4760"]] - }, - { - "id": "8ba3e2774987fd58", - "type": "http in", - "z": "1371dec5.76e671", - "name": "POST /api/system-time", - "url": "/api/system-time", - "method": "post", - "upload": false, - "swaggerDoc": "", - "x": 120, - "y": 360, - "wires": [["19a45f972be2b0f1", "07bbdca8d6153210", "595df18543c8328e"]] - }, - { - "id": "ee2c5e7c29eb4760", - "type": "ui_toast", - "z": "1371dec5.76e671", - "position": "top right", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 0, - "ok": "OK", - "cancel": "", - "raw": false, - "className": "", - "topic": "Setting system time", - "name": "", - "x": 610, - "y": 340, - "wires": [] - }, - { - "id": "07bbdca8d6153210", - "type": "function", - "z": "1371dec5.76e671", - "name": "Prepare timestamp", - "func": "msg.payload = ('@' + msg.payload.timestamp).slice(0, -3);\nreturn msg;", - "outputs": 1, - "timeout": 0, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 350, - "y": 380, - "wires": [["7558e8f302d5b944"]] - }, - { - "id": "7558e8f302d5b944", - "type": "exec", - "z": "1371dec5.76e671", - "command": "sudo date -s", - "addpay": "payload", - "append": "", - "useSpawn": "", - "timer": "", - "winHide": false, - "name": "Set system time", - "x": 600, - "y": 380, - "wires": [[], [], []] - }, - { - "id": "c8be8dad272e1fa5", - "type": "http in", - "z": "1371dec5.76e671", - "name": "GET /api/system-time", - "url": "/api/system-time", - "method": "get", - "upload": false, - "swaggerDoc": "", - "x": 120, - "y": 420, - "wires": [["0f4ce59587fa14e1"]] - }, - { - "id": "0f4ce59587fa14e1", - "type": "function", - "z": "1371dec5.76e671", - "name": "Get system time", - "func": "var date = new Date();\nmsg.payload = {'timestamp': date.getTime()};\nreturn msg", - "outputs": 1, - "timeout": 0, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 340, - "y": 420, - "wires": [["433d48a4b1bc0b27"]] - }, - { - "id": "433d48a4b1bc0b27", - "type": "http response", - "z": "1371dec5.76e671", - "name": "Send GET response", - "statusCode": "", - "headers": { - "Content-Type": "application/json; charset=UTF-8" - }, - "x": 620, - "y": 420, - "wires": [] - }, - { - "id": "595df18543c8328e", - "type": "http response", - "z": "1371dec5.76e671", - "name": "Send POST response", - "statusCode": "", - "headers": {}, - "x": 620, - "y": 300, - "wires": [] - }, - { - "id": "1fdf77b5.24e4e", - "type": "mqtt in", - "z": "9a22e67a.378818", - "name": "", - "topic": "status/#", - "qos": "0", - "datatype": "json", - "broker": "8dc3722c.06efa8", - "inputs": 0, - "x": 290, - "y": 340, - "wires": [["fa73983d.318188"]] - }, - { - "id": "4a1e9e3e.27506", - "type": "switch", - "z": "9a22e67a.378818", - "name": "Filter segmenter out", - "property": "topic", - "propertyType": "msg", - "rules": [ - { - "t": "else" - }, - { - "t": "cont", - "v": "status/segmenter", - "vt": "str" - } - ], - "checkall": "true", - "repair": false, - "outputs": 2, - "x": 620, - "y": 340, - "wires": [["58f2e0f.4e8b12"], ["dcf5bd45.16a8d"]] - }, - { - "id": "fa73983d.318188", - "type": "json", - "z": "9a22e67a.378818", - "name": "", - "property": "payload", - "action": "obj", - "pretty": true, - "x": 430, - "y": 340, - "wires": [["4a1e9e3e.27506"]] - }, - { - "id": "58f2e0f.4e8b12", - "type": "link out", - "z": "9a22e67a.378818", - "name": "Fluidic module status", - "links": ["bb628f8d.98f108"], - "x": 795, - "y": 320, - "wires": [] - }, - { - "id": "dcf5bd45.16a8d", - "type": "link out", - "z": "9a22e67a.378818", - "name": "Segmenter module status", - "links": ["25867454.a8e334"], - "x": 795, - "y": 360, - "wires": [] - }, - { - "id": "e41870d7.300eb8", - "type": "link out", - "z": "1eaf21c8.f7a21e", - "name": "Stepper config change", - "links": ["45a7b5aa.2ed20c"], - "x": 1475, - "y": 380, - "wires": [] - }, - { - "id": "2068e7f.f4efb18", - "type": "delay", - "z": "1eaf21c8.f7a21e", - "name": "", - "pauseType": "delay", - "timeout": "1", - "timeoutUnits": "seconds", - "rate": "1", - "nbRateUnits": "1", - "rateUnits": "second", - "randomFirst": "1", - "randomLast": "5", - "randomUnits": "seconds", - "drop": false, - "outputs": 1, - "x": 1160, - "y": 380, - "wires": [["e41870d7.300eb8"]] - }, - { - "id": "8e3b3d3c.955148", - "type": "subflow:4ed26b8b.253504", - "z": "1eaf21c8.f7a21e", - "name": "", - "env": [], - "x": 1200, - "y": 420, - "wires": [] - }, - { - "id": "c534fd26.13741", - "type": "change", - "z": "1eaf21c8.f7a21e", - "name": "Get stepper_reverse", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.stepper_reverse", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 640, - "y": 440, - "wires": [["cd1987c7.027f58"]] - }, - { - "id": "cd1987c7.027f58", - "type": "ui_switch", - "z": "1eaf21c8.f7a21e", - "name": "stepper_reverse", - "label": "Invert stepper output", - "tooltip": "Stepper 1 is controlled by output 1 or the other way around", - "group": "6be36295.0ab324", - "order": 5, - "width": 0, - "height": 0, - "passthru": false, - "decouple": "false", - "topic": "stepper_reverse", - "style": "", - "onvalue": "true", - "onvalueType": "bool", - "onicon": "", - "oncolor": "", - "offvalue": "false", - "offvalueType": "bool", - "officon": "", - "offcolor": "", - "x": 940, - "y": 440, - "wires": [["8e3b3d3c.955148", "2068e7f.f4efb18"]] - }, - { - "id": "54ba7f16.709ad8", - "type": "change", - "z": "1eaf21c8.f7a21e", - "name": "Get pump_steps_per_ml", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.pump_steps_per_ml", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 650, - "y": 400, - "wires": [["ee58b91c.396108"]] - }, - { - "id": "ee58b91c.396108", - "type": "ui_text_input", - "z": "1eaf21c8.f7a21e", - "name": "pump_steps_per_ml", - "label": "Pump: steps per mL", - "tooltip": "", - "group": "6be36295.0ab324", - "order": 6, - "width": 0, - "height": 0, - "passthru": false, - "mode": "number", - "delay": "2000", - "topic": "pump_steps_per_ml", - "topicType": "str", - "x": 920, - "y": 400, - "wires": [["2068e7f.f4efb18", "8e3b3d3c.955148"]] - }, - { - "id": "7534dfd9.8cf3e8", - "type": "ui_template", - "z": "1eaf21c8.f7a21e", - "group": "6be36295.0ab324", - "name": "Information", - "order": 1, - "width": "8", - "height": 3, - "format": "
\n

\n Changing one of these values will cause the Python hardware controller to restart, to reload the new hardware configuration.\n

\n

\n Warning: selecting a hardware version from the dropdown menu below will also overwrite all of your hardware settings, including your camera white balance settings.\n

\n

\n If you are not sure, you probably should not be touching anything here!\n

\n
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": true, - "templateScope": "local", - "className": "", - "x": 590, - "y": 60, - "wires": [[]] - }, - { - "id": "a7e5c7f4.644678", - "type": "ui_dropdown", - "z": "1eaf21c8.f7a21e", - "name": "", - "label": "Hardware version", - "tooltip": "", - "place": "Select option", - "group": "6be36295.0ab324", - "order": 2, - "width": 0, - "height": 0, - "passthru": false, - "multiple": false, - "options": [ - { - "label": "", - "value": "PlanktoScope v2.1", - "type": "str" - }, - { - "label": "", - "value": "PlanktoScope v2.3", - "type": "str" - }, - { - "label": "", - "value": "PlanktoScope v2.5", - "type": "str" - }, - { - "label": "", - "value": "PlanktoScope v2.6", - "type": "str" - } - ], - "payload": "", - "topic": "acq_instrument", - "topicType": "str", - "className": "", - "x": 580, - "y": 160, - "wires": [["3e2c5c1c.4c57b4", "932a1ef8c2e81979", "025ad3cdaa557843"]] - }, - { - "id": "1cfadc66.3cde8c", - "type": "subflow:1c24ad9c.bebec2", - "z": "1eaf21c8.f7a21e", - "name": "", - "env": [], - "x": 970, - "y": 160, - "wires": [[]] - }, - { - "id": "3e2c5c1c.4c57b4", - "type": "function", - "z": "1eaf21c8.f7a21e", - "name": "Save global", - "func": "global.set(msg.topic,msg.payload);\nreturn msg;", - "outputs": 1, - "timeout": "", - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 810, - "y": 160, - "wires": [["1cfadc66.3cde8c"]] - }, - { - "id": "427c312.fc5e65", - "type": "subflow:1c24ad9c.bebec2", - "z": "1eaf21c8.f7a21e", - "name": "", - "env": [], - "x": 130, - "y": 160, - "wires": [["2716aa5b3d027f95"]] - }, - { - "id": "c67c305004f87e39", - "type": "change", - "z": "1eaf21c8.f7a21e", - "name": "Get process_pixel_fixed", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.process_pixel_fixed", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 650, - "y": 480, - "wires": [["244ca5dd62df2bcd"]] - }, - { - "id": "244ca5dd62df2bcd", - "type": "ui_text_input", - "z": "1eaf21c8.f7a21e", - "name": "process_pixel_fixed", - "label": "Pixel size calibration: um per pixel", - "tooltip": "Object size in µm / pixel. 0 will remove this calibration.", - "group": "6be36295.0ab324", - "order": 8, - "width": 0, - "height": 0, - "passthru": true, - "mode": "number", - "delay": "1000", - "topic": "process_pixel_fixed", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 930, - "y": 480, - "wires": [["8e3b3d3c.955148", "f9b47f4b1da15778"]] - }, - { - "id": "f9b47f4b1da15778", - "type": "function", - "z": "1eaf21c8.f7a21e", - "name": "Set or remove if null", - "func": "if (msg.payload == 0){\n global.set(msg.topic,undefined)\n}\nelse {\n global.set(msg.topic,msg.payload);\n}\n\nreturn msg", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 1200, - "y": 480, - "wires": [["5d5ad36d2c50dcc2"]] - }, - { - "id": "5d5ad36d2c50dcc2", - "type": "link out", - "z": "1eaf21c8.f7a21e", - "name": "Process_pixel calibration", - "links": [], - "x": 1475, - "y": 500, - "wires": [] - }, - { - "id": "6146ba22df928516", - "type": "ui_dropdown", - "z": "1eaf21c8.f7a21e", - "name": "acq_fnumber_objective", - "label": "M12 Lens", - "tooltip": "", - "place": "Select option", - "group": "6be36295.0ab324", - "order": 7, - "width": 0, - "height": 0, - "passthru": true, - "multiple": false, - "options": [ - { - "label": "f 25mm 1/2\" 5MP IR", - "value": 25, - "type": "num" - }, - { - "label": "f 16mm 1/2.5\" 5MP IR", - "value": 16, - "type": "num" - }, - { - "label": "f 12mm 1/2.5\" 5MP IR", - "value": 12, - "type": "num" - }, - { - "label": "f 8mm 1/2.5\" 5MP IR", - "value": 8, - "type": "num" - }, - { - "label": "f 6mm 1/2.5\" 5MP IR", - "value": 6, - "type": "num" - } - ], - "payload": "", - "topic": "acq_fnumber_objective", - "topicType": "str", - "x": 910, - "y": 520, - "wires": [["a6983d3232b570a7", "8e3b3d3c.955148"]] - }, - { - "id": "a6983d3232b570a7", - "type": "change", - "z": "1eaf21c8.f7a21e", - "name": "", - "rules": [ - { - "t": "set", - "p": "acq_fnumber_objective", - "pt": "global", - "to": "payload", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 1240, - "y": 520, - "wires": [["5d5ad36d2c50dcc2"]] - }, - { - "id": "11955bbeefc29ab4", - "type": "change", - "z": "1eaf21c8.f7a21e", - "name": "Get acq_fnumber_objective", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.acq_fnumber_objective", - "tot": "msg" - }, - { - "t": "set", - "p": "topic", - "pt": "msg", - "to": "acq_fnumber_objective", - "tot": "str" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 660, - "y": 520, - "wires": [["6146ba22df928516"]] - }, - { - "id": "da3d4a90384d62a8", - "type": "subflow:e6665421f66ea4c8", - "z": "1eaf21c8.f7a21e", - "name": "", - "x": 360, - "y": 440, - "wires": [ - [ - "c534fd26.13741", - "54ba7f16.709ad8", - "c67c305004f87e39", - "11955bbeefc29ab4" - ] - ] - }, - { - "id": "f83560053c609914", - "type": "inject", - "z": "1eaf21c8.f7a21e", - "name": "Once", - "props": [], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "", - "x": 130, - "y": 440, - "wires": [["da3d4a90384d62a8"]] - }, - { - "id": "e4ead350b3d07578", - "type": "link out", - "z": "1eaf21c8.f7a21e", - "name": "Reload hardware config", - "mode": "link", - "links": ["04920f50bbbf6a2a", "45a7b5aa.2ed20c"], - "x": 875, - "y": 240, - "wires": [] - }, - { - "id": "025ad3cdaa557843", - "type": "ui_toast", - "z": "1eaf21c8.f7a21e", - "position": "top right", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 0, - "ok": "OK", - "cancel": "", - "raw": false, - "className": "", - "topic": "Resetting hardware configuration to version-specific default", - "name": "", - "x": 830, - "y": 120, - "wires": [] - }, - { - "id": "932a1ef8c2e81979", - "type": "change", - "z": "1eaf21c8.f7a21e", - "name": "Choose default hardware config", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "$join([\"/home/pi/PlanktoScope/device-backend/default-configs/\", $substringAfter(msg.payload, \"PlanktoScope \"), \".hardware.json\"])", - "tot": "jsonata" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 210, - "y": 240, - "wires": [["833dac7cbd693c53"]] - }, - { - "id": "833dac7cbd693c53", - "type": "exec", - "z": "1eaf21c8.f7a21e", - "command": "cp", - "addpay": "payload", - "append": "/home/pi/PlanktoScope/hardware.json", - "useSpawn": "false", - "timer": "", - "winHide": false, - "oldrc": false, - "name": "Copy default hardware config", - "x": 500, - "y": 240, - "wires": [["0b67ccf37c034e90"], [], []] - }, - { - "id": "0b67ccf37c034e90", - "type": "delay", - "z": "1eaf21c8.f7a21e", - "name": "", - "pauseType": "delay", - "timeout": "500", - "timeoutUnits": "milliseconds", - "rate": "1", - "nbRateUnits": "1", - "rateUnits": "second", - "randomFirst": "1", - "randomLast": "5", - "randomUnits": "seconds", - "drop": false, - "allowrate": false, - "outputs": 1, - "x": 730, - "y": 240, - "wires": [["da3d4a90384d62a8", "e4ead350b3d07578"]] - }, - { - "id": "2716aa5b3d027f95", - "type": "change", - "z": "1eaf21c8.f7a21e", - "name": "Get acq_instrument", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.acq_instrument", - "tot": "msg" - }, - { - "t": "set", - "p": "topic", - "pt": "msg", - "to": "acq_instrument", - "tot": "str" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 330, - "y": 160, - "wires": [["a7e5c7f4.644678"]] - } + "reg": false, + "x": 650, + "y": 400, + "wires": [ + [ + "ee58b91c.396108" + ] + ] + }, + { + "id": "ee58b91c.396108", + "type": "ui_text_input", + "z": "1eaf21c8.f7a21e", + "name": "pump_steps_per_ml", + "label": "Pump: steps per mL", + "tooltip": "", + "group": "6be36295.0ab324", + "order": 6, + "width": 0, + "height": 0, + "passthru": false, + "mode": "number", + "delay": "2000", + "topic": "pump_steps_per_ml", + "topicType": "str", + "x": 920, + "y": 400, + "wires": [ + [ + "2068e7f.f4efb18", + "8e3b3d3c.955148" + ] + ] + }, + { + "id": "7534dfd9.8cf3e8", + "type": "ui_template", + "z": "1eaf21c8.f7a21e", + "group": "6be36295.0ab324", + "name": "Information", + "order": 1, + "width": "8", + "height": 3, + "format": "
\n

\n Changing one of these values will cause the Python hardware controller to restart, to reload the new hardware configuration.\n

\n

\n Warning: selecting a hardware version from the dropdown menu below will also overwrite all of your hardware settings, including your camera white balance settings.\n

\n

\n If you are not sure, you probably should not be touching anything here!\n

\n
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": true, + "templateScope": "local", + "className": "", + "x": 590, + "y": 60, + "wires": [ + [] + ] + }, + { + "id": "a7e5c7f4.644678", + "type": "ui_dropdown", + "z": "1eaf21c8.f7a21e", + "name": "", + "label": "Hardware version", + "tooltip": "", + "place": "Select option", + "group": "6be36295.0ab324", + "order": 2, + "width": 0, + "height": 0, + "passthru": false, + "multiple": false, + "options": [ + { + "label": "", + "value": "PlanktoScope v2.1", + "type": "str" + }, + { + "label": "", + "value": "PlanktoScope v2.3", + "type": "str" + }, + { + "label": "", + "value": "PlanktoScope v2.5", + "type": "str" + }, + { + "label": "", + "value": "PlanktoScope v2.6", + "type": "str" + } + ], + "payload": "", + "topic": "acq_instrument", + "topicType": "str", + "className": "", + "x": 580, + "y": 160, + "wires": [ + [ + "3e2c5c1c.4c57b4", + "932a1ef8c2e81979", + "025ad3cdaa557843" + ] + ] + }, + { + "id": "1cfadc66.3cde8c", + "type": "subflow:1c24ad9c.bebec2", + "z": "1eaf21c8.f7a21e", + "name": "", + "env": [], + "x": 970, + "y": 160, + "wires": [ + [] + ] + }, + { + "id": "3e2c5c1c.4c57b4", + "type": "function", + "z": "1eaf21c8.f7a21e", + "name": "Save global", + "func": "global.set(msg.topic,msg.payload);\nreturn msg;", + "outputs": 1, + "timeout": "", + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 810, + "y": 160, + "wires": [ + [ + "1cfadc66.3cde8c" + ] + ] + }, + { + "id": "427c312.fc5e65", + "type": "subflow:1c24ad9c.bebec2", + "z": "1eaf21c8.f7a21e", + "name": "", + "env": [], + "x": 130, + "y": 160, + "wires": [ + [ + "2716aa5b3d027f95" + ] + ] + }, + { + "id": "c67c305004f87e39", + "type": "change", + "z": "1eaf21c8.f7a21e", + "name": "Get process_pixel_fixed", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.process_pixel_fixed", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 650, + "y": 480, + "wires": [ + [ + "244ca5dd62df2bcd" + ] + ] + }, + { + "id": "244ca5dd62df2bcd", + "type": "ui_text_input", + "z": "1eaf21c8.f7a21e", + "name": "process_pixel_fixed", + "label": "Pixel size calibration: um per pixel", + "tooltip": "Object size in µm / pixel. 0 will remove this calibration.", + "group": "6be36295.0ab324", + "order": 8, + "width": 0, + "height": 0, + "passthru": true, + "mode": "number", + "delay": "1000", + "topic": "process_pixel_fixed", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 930, + "y": 480, + "wires": [ + [ + "8e3b3d3c.955148", + "f9b47f4b1da15778" + ] + ] + }, + { + "id": "f9b47f4b1da15778", + "type": "function", + "z": "1eaf21c8.f7a21e", + "name": "Set or remove if null", + "func": "if (msg.payload == 0){\n global.set(msg.topic,undefined)\n}\nelse {\n global.set(msg.topic,msg.payload);\n}\n\nreturn msg", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 1200, + "y": 480, + "wires": [ + [ + "5d5ad36d2c50dcc2" + ] + ] + }, + { + "id": "5d5ad36d2c50dcc2", + "type": "link out", + "z": "1eaf21c8.f7a21e", + "name": "Process_pixel calibration", + "links": [], + "x": 1475, + "y": 500, + "wires": [] + }, + { + "id": "6146ba22df928516", + "type": "ui_dropdown", + "z": "1eaf21c8.f7a21e", + "name": "acq_fnumber_objective", + "label": "M12 Lens", + "tooltip": "", + "place": "Select option", + "group": "6be36295.0ab324", + "order": 7, + "width": 0, + "height": 0, + "passthru": true, + "multiple": false, + "options": [ + { + "label": "f 25mm 1/2\" 5MP IR", + "value": 25, + "type": "num" + }, + { + "label": "f 16mm 1/2.5\" 5MP IR", + "value": 16, + "type": "num" + }, + { + "label": "f 12mm 1/2.5\" 5MP IR", + "value": 12, + "type": "num" + }, + { + "label": "f 8mm 1/2.5\" 5MP IR", + "value": 8, + "type": "num" + }, + { + "label": "f 6mm 1/2.5\" 5MP IR", + "value": 6, + "type": "num" + } + ], + "payload": "", + "topic": "acq_fnumber_objective", + "topicType": "str", + "x": 910, + "y": 520, + "wires": [ + [ + "a6983d3232b570a7", + "8e3b3d3c.955148" + ] + ] + }, + { + "id": "a6983d3232b570a7", + "type": "change", + "z": "1eaf21c8.f7a21e", + "name": "", + "rules": [ + { + "t": "set", + "p": "acq_fnumber_objective", + "pt": "global", + "to": "payload", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 1240, + "y": 520, + "wires": [ + [ + "5d5ad36d2c50dcc2" + ] + ] + }, + { + "id": "11955bbeefc29ab4", + "type": "change", + "z": "1eaf21c8.f7a21e", + "name": "Get acq_fnumber_objective", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.acq_fnumber_objective", + "tot": "msg" + }, + { + "t": "set", + "p": "topic", + "pt": "msg", + "to": "acq_fnumber_objective", + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 660, + "y": 520, + "wires": [ + [ + "6146ba22df928516" + ] + ] + }, + { + "id": "da3d4a90384d62a8", + "type": "subflow:e6665421f66ea4c8", + "z": "1eaf21c8.f7a21e", + "name": "", + "x": 360, + "y": 440, + "wires": [ + [ + "c534fd26.13741", + "54ba7f16.709ad8", + "c67c305004f87e39", + "11955bbeefc29ab4" + ] + ] + }, + { + "id": "f83560053c609914", + "type": "inject", + "z": "1eaf21c8.f7a21e", + "name": "Once", + "props": [], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "x": 130, + "y": 440, + "wires": [ + [ + "da3d4a90384d62a8" + ] + ] + }, + { + "id": "e4ead350b3d07578", + "type": "link out", + "z": "1eaf21c8.f7a21e", + "name": "Reload hardware config", + "mode": "link", + "links": [ + "04920f50bbbf6a2a", + "45a7b5aa.2ed20c" + ], + "x": 875, + "y": 240, + "wires": [] + }, + { + "id": "025ad3cdaa557843", + "type": "ui_toast", + "z": "1eaf21c8.f7a21e", + "position": "top right", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 0, + "ok": "OK", + "cancel": "", + "raw": false, + "className": "", + "topic": "Resetting hardware configuration to version-specific default", + "name": "", + "x": 830, + "y": 120, + "wires": [] + }, + { + "id": "932a1ef8c2e81979", + "type": "change", + "z": "1eaf21c8.f7a21e", + "name": "Choose default hardware config", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "$join([\"/home/pi/PlanktoScope/device-backend/default-configs/\", $substringAfter(msg.payload, \"PlanktoScope \"), \".hardware.json\"])", + "tot": "jsonata" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 210, + "y": 240, + "wires": [ + [ + "833dac7cbd693c53" + ] + ] + }, + { + "id": "833dac7cbd693c53", + "type": "exec", + "z": "1eaf21c8.f7a21e", + "command": "cp", + "addpay": "payload", + "append": "/home/pi/PlanktoScope/hardware.json", + "useSpawn": "false", + "timer": "", + "winHide": false, + "oldrc": false, + "name": "Copy default hardware config", + "x": 500, + "y": 240, + "wires": [ + [ + "0b67ccf37c034e90" + ], + [], + [] + ] + }, + { + "id": "0b67ccf37c034e90", + "type": "delay", + "z": "1eaf21c8.f7a21e", + "name": "", + "pauseType": "delay", + "timeout": "500", + "timeoutUnits": "milliseconds", + "rate": "1", + "nbRateUnits": "1", + "rateUnits": "second", + "randomFirst": "1", + "randomLast": "5", + "randomUnits": "seconds", + "drop": false, + "allowrate": false, + "outputs": 1, + "x": 730, + "y": 240, + "wires": [ + [ + "da3d4a90384d62a8", + "e4ead350b3d07578" + ] + ] + }, + { + "id": "2716aa5b3d027f95", + "type": "change", + "z": "1eaf21c8.f7a21e", + "name": "Get acq_instrument", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.acq_instrument", + "tot": "msg" + }, + { + "t": "set", + "p": "topic", + "pt": "msg", + "to": "acq_instrument", + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 330, + "y": 160, + "wires": [ + [ + "a7e5c7f4.644678" + ] + ] + } ] diff --git a/software/node-red-dashboard/planktoscopehat/flows.json b/software/node-red-dashboard/planktoscopehat/flows.json index d4964f0ab..5b6fe2817 100644 --- a/software/node-red-dashboard/planktoscopehat/flows.json +++ b/software/node-red-dashboard/planktoscopehat/flows.json @@ -1,7492 +1,8749 @@ [ - { - "id": "eaae323a.31b3", - "type": "tab", - "label": "Home", - "disabled": false, - "info": "" - }, - { - "id": "b771c342.49603", - "type": "tab", - "label": "Sample", - "disabled": false, - "info": "" - }, - { - "id": "bccd1f23.87219", - "type": "tab", - "label": "Optic Configuration", - "disabled": false, - "info": "" - }, - { - "id": "baa1e3d9.cb29d", - "type": "tab", - "label": "Fluidic Acquisition", - "disabled": false, - "info": "" - }, - { - "id": "cb95299c.2817c8", - "type": "tab", - "label": "Segmentation", - "disabled": false, - "info": "" - }, - { - "id": "c1660bc.e7ff7f8", - "type": "tab", - "label": "Gallery", - "disabled": false, - "info": "" - }, - { - "id": "9daf9e2b.019fc", - "type": "tab", - "label": "Administration", - "disabled": false, - "info": "" - }, - { - "id": "1371dec5.76e671", - "type": "tab", - "label": "System Monitoring", - "disabled": false, - "info": "" - }, - { - "id": "9a22e67a.378818", - "type": "tab", - "label": "MQTT Receive", - "disabled": false, - "info": "" - }, - { - "id": "1eaf21c8.f7a21e", - "type": "tab", - "label": "Hardware Settings", - "disabled": false, - "info": "" - }, - { - "id": "1c24ad9c.bebec2", - "type": "subflow", - "name": "Config", - "info": "An input to this subflow will get the configuration to be saved to disk.\n\nOn startup, this node outputs the loaded configuration", - "category": "", - "in": [ - { - "x": 220, + { + "id": "eaae323a.31b3", + "type": "tab", + "label": "Home", + "disabled": false, + "info": "" + }, + { + "id": "b771c342.49603", + "type": "tab", + "label": "Sample", + "disabled": false, + "info": "" + }, + { + "id": "bccd1f23.87219", + "type": "tab", + "label": "Optic Configuration", + "disabled": false, + "info": "" + }, + { + "id": "baa1e3d9.cb29d", + "type": "tab", + "label": "Fluidic Acquisition", + "disabled": false, + "info": "" + }, + { + "id": "cb95299c.2817c8", + "type": "tab", + "label": "Segmentation", + "disabled": false, + "info": "" + }, + { + "id": "c1660bc.e7ff7f8", + "type": "tab", + "label": "Gallery", + "disabled": false, + "info": "" + }, + { + "id": "9daf9e2b.019fc", + "type": "tab", + "label": "Administration", + "disabled": false, + "info": "" + }, + { + "id": "1371dec5.76e671", + "type": "tab", + "label": "System Monitoring", + "disabled": false, + "info": "" + }, + { + "id": "9a22e67a.378818", + "type": "tab", + "label": "MQTT Receive", + "disabled": false, + "info": "" + }, + { + "id": "1eaf21c8.f7a21e", + "type": "tab", + "label": "Hardware Settings", + "disabled": false, + "info": "" + }, + { + "id": "1c24ad9c.bebec2", + "type": "subflow", + "name": "Config", + "info": "An input to this subflow will get the configuration to be saved to disk.\n\nOn startup, this node outputs the loaded configuration", + "category": "", + "in": [ + { + "x": 220, + "y": 160, + "wires": [ + { + "id": "3ad9835.08c937c" + } + ] + } + ], + "out": [ + { + "x": 1040, + "y": 60, + "wires": [ + { + "id": "ad541674.4791c8", + "port": 0 + } + ] + } + ], + "env": [], + "color": "#DDAA99" + }, + { + "id": "4ed26b8b.253504", + "type": "subflow", + "name": "Save hardware config", + "info": "", + "category": "", + "in": [ + { + "x": 40, + "y": 40, + "wires": [ + { + "id": "53d163be.47cf24" + } + ] + } + ], + "out": [], + "env": [], + "meta": {}, + "color": "#DDAA99" + }, + { + "id": "b7861ce703215a01", + "type": "subflow", + "name": "Load hardware config", + "info": "", + "category": "", + "in": [ + { + "x": 40, + "y": 40, + "wires": [ + { + "id": "0f16258953fae292" + } + ] + } + ], + "out": [ + { + "x": 900, + "y": 40, + "wires": [ + { + "id": "d0fbcd200cd09981", + "port": 0 + } + ] + } + ], + "env": [], + "meta": {}, + "color": "#DDAA99" + }, + { + "id": "3a6bb13f.c9703e", + "type": "ui_tab", + "name": "Home", + "icon": "home", + "order": 1, + "disabled": false, + "hidden": false + }, + { + "id": "181bb236.1e94be", + "type": "ui_tab", + "name": "Optic Configuration", + "icon": "fa-eye", + "order": 3, + "disabled": false, + "hidden": false + }, + { + "id": "c9194f02.9d5e9", + "type": "ui_tab", + "name": "Fluidic Acquisition", + "icon": "fa-flask", + "order": 4, + "disabled": false, + "hidden": false + }, + { + "id": "8d16beb8.9b3fb", + "type": "ui_tab", + "name": "Segmentation", + "icon": "fa-crop", + "order": 5, + "disabled": false, + "hidden": false + }, + { + "id": "d9cd733b.ab73d", + "type": "ui_tab", + "name": "System Monitoring", + "icon": "fa-thermometer-full", + "order": 7, + "disabled": false, + "hidden": false + }, + { + "id": "4248342d.e55fac", + "type": "ui_group", + "name": "Optic Characterization", + "tab": "181bb236.1e94be", + "order": 4, + "disp": true, + "width": "6", + "collapse": false + }, + { + "id": "858a0e3c.987fe", + "type": "ui_group", + "name": "Preview", + "tab": "c9194f02.9d5e9", + "order": 1, + "disp": true, + "width": 10, + "collapse": false + }, + { + "id": "64903b47.4034e4", + "type": "ui_group", + "name": "Navigation", + "tab": "8d16beb8.9b3fb", + "order": 3, + "disp": false, + "width": "6", + "collapse": false + }, + { + "id": "3da7da8f.179606", + "type": "ui_group", + "name": "Metrics", + "tab": "d9cd733b.ab73d", + "order": 1, + "disp": true, + "width": "24", + "collapse": true, + "className": "" + }, + { + "id": "cc8bc4eb.651868", + "type": "ui_base", + "theme": { + "name": "theme-dark", + "lightTheme": { + "default": "#0094CE", + "baseColor": "#5900ce", + "baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif", + "edited": false, + "reset": false + }, + "darkTheme": { + "default": "#097479", + "baseColor": "#097479", + "baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif", + "edited": true, + "reset": false + }, + "customTheme": { + "name": "Untitled Theme 1", + "default": "#4B7930", + "baseColor": "#4B7930", + "baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif" + }, + "themeState": { + "base-color": { + "default": "#097479", + "value": "#097479", + "edited": true + }, + "page-titlebar-backgroundColor": { + "value": "#097479", + "edited": false + }, + "page-backgroundColor": { + "value": "#111111", + "edited": false + }, + "page-sidebar-backgroundColor": { + "value": "#333333", + "edited": false + }, + "group-textColor": { + "value": "#0eb8c0", + "edited": false + }, + "group-borderColor": { + "value": "#555555", + "edited": false + }, + "group-backgroundColor": { + "value": "#333333", + "edited": false + }, + "widget-textColor": { + "value": "#eeeeee", + "edited": false + }, + "widget-backgroundColor": { + "value": "#097479", + "edited": false + }, + "widget-borderColor": { + "value": "#333333", + "edited": false + }, + "base-font": { + "value": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif" + } + }, + "angularTheme": { + "primary": "indigo", + "accents": "blue", + "warn": "red", + "background": "grey", + "palette": "light" + } + }, + "site": { + "name": "PlanktoScope", + "hideToolbar": "false", + "allowSwipe": "false", + "lockMenu": "false", + "allowTempTheme": "true", + "dateFormat": "Y-MM-DD", + "sizes": { + "sx": 55, + "sy": 55, + "gx": 4, + "gy": 4, + "cx": 4, + "cy": 4, + "px": 4, + "py": 4 + } + } + }, + { + "id": "36739a35.7cce36", + "type": "ui_tab", + "name": "Gallery", + "icon": "fa-file-image-o", + "order": 6, + "disabled": false, + "hidden": false + }, + { + "id": "c0ebfc57.42527", + "type": "ui_group", + "name": "Group 1", + "tab": "36739a35.7cce36", + "order": 1, + "disp": false, + "width": "24", + "collapse": false, + "className": "" + }, + { + "id": "737ec584.2eea2c", + "type": "ui_tab", + "name": "Sample", + "icon": "fa-eyedropper", + "order": 2, + "disabled": false, + "hidden": false + }, + { + "id": "6f97e7ae.270c48", + "type": "ui_group", + "name": "Group 1", + "tab": "3a6bb13f.c9703e", + "order": 2, + "disp": false, + "width": "4", + "collapse": false, + "className": "" + }, + { + "id": "3e1ba03d.f01d8", + "type": "ui_group", + "name": "Sample Identification", + "tab": "737ec584.2eea2c", + "order": 1, + "disp": true, + "width": "10", + "collapse": false + }, + { + "id": "4e0cd5ea.17e59c", + "type": "ui_group", + "name": "Group 2", + "tab": "3a6bb13f.c9703e", + "order": 3, + "disp": false, + "width": "4", + "collapse": false + }, + { + "id": "ef590206.24f6", + "type": "ui_group", + "name": "Group 3", + "tab": "3a6bb13f.c9703e", + "order": 4, + "disp": false, + "width": "4", + "collapse": false + }, + { + "id": "ae8f6620.073358", + "type": "ui_group", + "name": "Group 4", + "tab": "3a6bb13f.c9703e", + "order": 5, + "disp": false, + "width": "4", + "collapse": false + }, + { + "id": "196518b2.4d53b7", + "type": "ui_group", + "name": "Group 5", + "tab": "3a6bb13f.c9703e", + "order": 6, + "disp": false, + "width": "4", + "collapse": false + }, + { + "id": "777a7c33.fcd804", + "type": "ui_group", + "name": "Group 6", + "tab": "3a6bb13f.c9703e", + "order": 7, + "disp": false, + "width": "4", + "collapse": false + }, + { + "id": "cef1e703.bcf3c8", + "type": "ui_group", + "name": "Sample Location", + "tab": "737ec584.2eea2c", + "order": 3, + "disp": false, + "width": "10", + "collapse": false + }, + { + "id": "5517c651.b2f668", + "type": "ui_group", + "name": "Validation", + "tab": "737ec584.2eea2c", + "order": 5, + "disp": false, + "width": 10, + "collapse": false + }, + { + "id": "fbd92986.1028c8", + "type": "ui_group", + "name": "Focus Adjustment", + "tab": "181bb236.1e94be", + "order": 2, + "disp": true, + "width": 4, + "collapse": false + }, + { + "id": "707d9797.c8e798", + "type": "ui_group", + "name": "Fluidic Manual Manipulation", + "tab": "181bb236.1e94be", + "order": 5, + "disp": true, + "width": 4, + "collapse": false + }, + { + "id": "7a0b4877.a5d268", + "type": "ui_group", + "name": "Navigation", + "tab": "181bb236.1e94be", + "order": 6, + "disp": false, + "width": 4, + "collapse": false + }, + { + "id": "4322c187.e73e5", + "type": "ui_group", + "name": "Acquisition", + "tab": "c9194f02.9d5e9", + "order": 3, + "disp": true, + "width": 10, + "collapse": false + }, + { + "id": "b7919ae2.c01788", + "type": "ui_group", + "name": "Navigation", + "tab": "c9194f02.9d5e9", + "order": 6, + "disp": false, + "width": "10", + "collapse": false + }, + { + "id": "b5d61bc7.54fe48", + "type": "ui_group", + "name": "Statistics", + "tab": "c9194f02.9d5e9", + "order": 4, + "disp": true, + "width": "10", + "collapse": false + }, + { + "id": "8dc3722c.06efa8", + "type": "mqtt-broker", + "name": "", + "broker": "0.0.0.0", + "port": "1883", + "clientid": "Client_node", + "autoConnect": true, + "usetls": false, + "compatmode": false, + "protocolVersion": 4, + "keepalive": "60", + "cleansession": true, + "birthTopic": "", + "birthQos": "0", + "birthPayload": "", + "closeTopic": "", + "closeQos": "0", + "closePayload": "", + "willTopic": "", + "willQos": "0", + "willPayload": "" + }, + { + "id": "abeb6dad.635a2", + "type": "ui_group", + "name": "Control", + "tab": "8d16beb8.9b3fb", + "order": 1, + "disp": true, + "width": 10, + "collapse": false + }, + { + "id": "cf5d9f0e.d57e7", + "type": "ui_group", + "name": "Net Metadata", + "tab": "737ec584.2eea2c", + "order": 4, + "disp": false, + "width": "10", + "collapse": false + }, + { + "id": "ce9e278.781eed8", + "type": "ui_group", + "name": "Information", + "tab": "d9cd733b.ab73d", + "order": 5, + "disp": true, + "width": 6, + "collapse": false + }, + { + "id": "70de8209.68416c", + "type": "ui_group", + "name": "Status", + "tab": "c9194f02.9d5e9", + "order": 5, + "disp": true, + "width": 10, + "collapse": false + }, + { + "id": "46be9c86.dea684", + "type": "ui_group", + "name": "Status", + "tab": "8d16beb8.9b3fb", + "order": 2, + "disp": true, + "width": 10, + "collapse": false + }, + { + "id": "8c38a81e.9897a8", + "type": "ui_group", + "name": "Camera Settings", + "tab": "181bb236.1e94be", + "order": 3, + "disp": true, + "width": 6, + "collapse": false + }, + { + "id": "2489e51c.eed77a", + "type": "ui_tab", + "name": "Administration", + "icon": "dashboard", + "order": 9, + "disabled": false, + "hidden": false + }, + { + "id": "b0fb559a.6966a8", + "type": "ui_tab", + "name": "Hardware Settings", + "icon": "fa-cogs", + "disabled": false, + "hidden": false + }, + { + "id": "6be36295.0ab324", + "type": "ui_group", + "name": "Settings", + "tab": "b0fb559a.6966a8", + "order": 1, + "disp": false, + "width": "8", + "collapse": false, + "className": "" + }, + { + "id": "f3ca28ef.4df0a8", + "type": "ui_group", + "name": "Shutdown", + "tab": "3a6bb13f.c9703e", + "order": 8, + "disp": true, + "width": 4, + "collapse": false + }, + { + "id": "3dfd8a69.69ed56", + "type": "ui_spacer", + "name": "spacer", + "group": "f3ca28ef.4df0a8", + "order": 3, + "width": 4, + "height": 1 + }, + { + "id": "72a9216.2ff48e", + "type": "ui_spacer", + "name": "spacer", + "group": "4322c187.e73e5", + "order": 8, + "width": 10, + "height": 1 + }, + { + "id": "1b664927.c91d1f", + "type": "ui_spacer", + "name": "spacer", + "group": "b5d61bc7.54fe48", + "order": 2, + "width": 2, + "height": 1 + }, + { + "id": "1a663b6a.ab5805", + "type": "ui_spacer", + "name": "spacer", + "group": "b5d61bc7.54fe48", + "order": 4, + "width": 2, + "height": 1 + }, + { + "id": "8eeed8d8.ad9098", + "type": "ui_spacer", + "name": "spacer", + "group": "b5d61bc7.54fe48", + "order": 5, + "width": 2, + "height": 1 + }, + { + "id": "be1c5ce7.004e", + "type": "ui_spacer", + "name": "spacer", + "group": "b5d61bc7.54fe48", + "order": 6, + "width": 2, + "height": 1 + }, + { + "id": "c2fe38e9.555e3", + "type": "ui_spacer", + "name": "spacer", + "group": "b5d61bc7.54fe48", + "order": 7, + "width": 2, + "height": 1 + }, + { + "id": "89bd18b7.c779a8", + "type": "ui_spacer", + "name": "spacer", + "group": "b5d61bc7.54fe48", + "order": 8, + "width": 2, + "height": 1 + }, + { + "id": "3cbbfa5d.efa636", + "type": "ui_spacer", + "name": "spacer", + "group": "b7919ae2.c01788", + "order": 2, + "width": 5, + "height": 1 + }, + { + "id": "97148e8d8e298f1a", + "type": "ui_spacer", + "z": "cb95299c.2817c8", + "name": "spacer", + "group": "abeb6dad.635a2", + "order": 7, + "width": 10, + "height": 1 + }, + { + "id": "3b2eccc574e6a9ae", + "type": "ui_spacer", + "z": "cb95299c.2817c8", + "name": "spacer", + "group": "abeb6dad.635a2", + "order": 11, + "width": 1, + "height": 1 + }, + { + "id": "bbd6431d97c86f97", + "type": "ui_spacer", + "z": "cb95299c.2817c8", + "name": "spacer", + "group": "46be9c86.dea684", + "order": 4, + "width": 3, + "height": 1 + }, + { + "id": "5f98f5f140f0ecde", + "type": "ui_spacer", + "z": "cb95299c.2817c8", + "name": "spacer", + "group": "46be9c86.dea684", + "order": 6, + "width": 3, + "height": 1 + }, + { + "id": "7bc0a4c416e4545c", + "type": "ui_group", + "name": "Culture Date and Time", + "tab": "737ec584.2eea2c", + "order": 2, + "disp": true, + "width": "10", + "collapse": false, + "className": "" + }, + { + "id": "6c31ad948a9d62fd", + "type": "ui_spacer", + "z": "b771c342.49603", + "name": "spacer", + "group": "3e1ba03d.f01d8", + "order": 5, + "width": 10, + "height": 1 + }, + { + "id": "0035a03e1490cd8c", + "type": "ui_group", + "name": "Setup", + "tab": "3a6bb13f.c9703e", + "order": 1, + "disp": true, + "width": "8", + "collapse": false, + "className": "" + }, + { + "id": "833bc5bb.217ba8", + "type": "ui_group", + "name": "Preview", + "tab": "181bb236.1e94be", + "order": 1, + "disp": true, + "width": 18, + "collapse": false + }, + { + "id": "a7d64879.38298", + "type": "ui_group", + "name": "Logs", + "tab": "2489e51c.eed77a", + "order": 1, + "disp": true, + "width": "12", + "collapse": true, + "className": "" + }, + { + "id": "6465bdd5.15eb8c", + "type": "file in", + "z": "1c24ad9c.bebec2", + "name": "", + "filename": "/home/pi/PlanktoScope/config.json", + "filenameType": "str", + "format": "utf8", + "chunk": false, + "sendError": false, + "encoding": "none", + "x": 560, + "y": 60, + "wires": [ + [ + "15ceb135.6628bf" + ] + ], + "info": "# PlanktoScope Help\nThis Node will read the content of the file named **config.txt** containing all the input placeholders.\n" + }, + { + "id": "15ceb135.6628bf", + "type": "json", + "z": "1c24ad9c.bebec2", + "name": "config.json", + "property": "payload", + "action": "", + "pretty": false, + "x": 730, + "y": 60, + "wires": [ + [ + "ad541674.4791c8" + ] + ] + }, + { + "id": "7205d267.36adcc", + "type": "file", + "z": "1c24ad9c.bebec2", + "name": "", + "filename": "/home/pi/PlanktoScope/config.json", + "appendNewline": true, + "createDir": true, + "overwriteFile": "true", + "encoding": "none", + "x": 990, "y": 160, "wires": [ - { - "id": "3ad9835.08c937c" - } + [] ] - } - ], - "out": [ - { - "x": 1040, + }, + { + "id": "2e6ddf51.c0dba", + "type": "json", + "z": "1c24ad9c.bebec2", + "name": "config.json", + "property": "payload", + "action": "str", + "pretty": true, + "x": 730, + "y": 160, + "wires": [ + [ + "7205d267.36adcc" + ] + ] + }, + { + "id": "ad541674.4791c8", + "type": "function", + "z": "1c24ad9c.bebec2", + "name": "Global Set", + "func": "global.set(\"config_keys\", Object.keys(msg.payload));\n\nfor (const key in msg.payload) {\n global.set(key, msg.payload[key]);\n}\n\nreturn msg;", + "outputs": 1, + "timeout": "", + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 910, + "y": 60, + "wires": [ + [] + ] + }, + { + "id": "3e9a33c.141384c", + "type": "inject", + "z": "1c24ad9c.bebec2", + "name": "Load config", + "props": [ + { + "p": "topic", + "vt": "str" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "payloadType": "str", + "x": 230, "y": 60, "wires": [ - { - "id": "ad541674.4791c8", - "port": 0 - } - ] - } - ], - "env": [], - "color": "#DDAA99" - }, - { - "id": "4ed26b8b.253504", - "type": "subflow", - "name": "Save hardware config", - "info": "", - "category": "", - "in": [ - { - "x": 40, + [ + "6465bdd5.15eb8c" + ] + ] + }, + { + "id": "3ad9835.08c937c", + "type": "function", + "z": "1c24ad9c.bebec2", + "name": "get config payload", + "func": "keys = global.get(\"config_keys\")\n\nvar payload = {}\n\nkeys.forEach(function(item, index, array) {\n payload[item] = global.get(item);\n})\n\nreturn {\"payload\": payload};", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 410, + "y": 160, + "wires": [ + [ + "2e6ddf51.c0dba" + ] + ] + }, + { + "id": "f439663c.8abd3", + "type": "ui_ui_control", + "z": "1c24ad9c.bebec2", + "name": "Connect Event", + "events": "connect", + "x": 220, + "y": 100, + "wires": [ + [ + "6465bdd5.15eb8c" + ] + ] + }, + { + "id": "82099021.9ceb08", + "type": "file", + "z": "4ed26b8b.253504", + "name": "", + "filename": "/home/pi/PlanktoScope/hardware.json", + "appendNewline": true, + "createDir": true, + "overwriteFile": "true", + "encoding": "none", + "x": 660, "y": 40, "wires": [ - { - "id": "53d163be.47cf24" - } - ] - } - ], - "out": [], - "env": [], - "meta": {}, - "color": "#DDAA99" - }, - { - "id": "b7861ce703215a01", - "type": "subflow", - "name": "Load hardware config", - "info": "", - "category": "", - "in": [ - { - "x": 40, + [] + ] + }, + { + "id": "bb0a8725.a1849", + "type": "json", + "z": "4ed26b8b.253504", + "name": "Create JSON", + "property": "payload", + "action": "str", + "pretty": true, + "x": 490, "y": 40, "wires": [ - { - "id": "0f16258953fae292" - } + [ + "82099021.9ceb08" + ] ] - } - ], - "out": [ - { - "x": 900, + }, + { + "id": "53d163be.47cf24", + "type": "function", + "z": "4ed26b8b.253504", + "name": "Update and retrieve hardware_conf", + "func": "// change global\nhardware_conf = global.get(\"hardware_conf\");\n\nif (msg.topic == \"process_pixel_fixed\" && msg.payload == 0){\n delete hardware_conf[msg.topic]\n delete msg.topic\n}\n\nif (msg.topic !== null && msg.topic !== undefined){\n hardware_conf[msg.topic] = msg.payload;\n global.set(\"hardware_conf\", hardware_conf);\n}\n\nreturn {\"payload\": hardware_conf};", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 240, "y": 40, "wires": [ - { - "id": "d0fbcd200cd09981", - "port": 0 - } - ] - } - ], - "env": [], - "meta": {}, - "color": "#DDAA99" - }, - { - "id": "3a6bb13f.c9703e", - "type": "ui_tab", - "name": "Home", - "icon": "home", - "order": 1, - "disabled": false, - "hidden": false - }, - { - "id": "181bb236.1e94be", - "type": "ui_tab", - "name": "Optic Configuration", - "icon": "fa-eye", - "order": 3, - "disabled": false, - "hidden": false - }, - { - "id": "c9194f02.9d5e9", - "type": "ui_tab", - "name": "Fluidic Acquisition", - "icon": "fa-flask", - "order": 4, - "disabled": false, - "hidden": false - }, - { - "id": "8d16beb8.9b3fb", - "type": "ui_tab", - "name": "Segmentation", - "icon": "fa-crop", - "order": 5, - "disabled": false, - "hidden": false - }, - { - "id": "d9cd733b.ab73d", - "type": "ui_tab", - "name": "System Monitoring", - "icon": "fa-thermometer-full", - "order": 7, - "disabled": false, - "hidden": false - }, - { - "id": "4248342d.e55fac", - "type": "ui_group", - "name": "Optic Characterization", - "tab": "181bb236.1e94be", - "order": 4, - "disp": true, - "width": "6", - "collapse": false - }, - { - "id": "858a0e3c.987fe", - "type": "ui_group", - "name": "Preview", - "tab": "c9194f02.9d5e9", - "order": 1, - "disp": true, - "width": 10, - "collapse": false - }, - { - "id": "64903b47.4034e4", - "type": "ui_group", - "name": "Navigation", - "tab": "8d16beb8.9b3fb", - "order": 3, - "disp": false, - "width": "6", - "collapse": false - }, - { - "id": "3da7da8f.179606", - "type": "ui_group", - "name": "Metrics", - "tab": "d9cd733b.ab73d", - "order": 1, - "disp": true, - "width": "24", - "collapse": true, - "className": "" - }, - { - "id": "cc8bc4eb.651868", - "type": "ui_base", - "theme": { - "name": "theme-dark", - "lightTheme": { - "default": "#0094CE", - "baseColor": "#5900ce", - "baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif", - "edited": false, - "reset": false - }, - "darkTheme": { - "default": "#097479", - "baseColor": "#097479", - "baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif", - "edited": true, - "reset": false - }, - "customTheme": { - "name": "Untitled Theme 1", - "default": "#4B7930", - "baseColor": "#4B7930", - "baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif" - }, - "themeState": { - "base-color": { - "default": "#097479", - "value": "#097479", - "edited": true - }, - "page-titlebar-backgroundColor": { - "value": "#097479", - "edited": false - }, - "page-backgroundColor": { - "value": "#111111", - "edited": false - }, - "page-sidebar-backgroundColor": { - "value": "#333333", - "edited": false - }, - "group-textColor": { - "value": "#0eb8c0", - "edited": false - }, - "group-borderColor": { - "value": "#555555", - "edited": false - }, - "group-backgroundColor": { - "value": "#333333", - "edited": false - }, - "widget-textColor": { - "value": "#eeeeee", - "edited": false - }, - "widget-backgroundColor": { - "value": "#097479", - "edited": false - }, - "widget-borderColor": { - "value": "#333333", - "edited": false - }, - "base-font": { - "value": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif" - } - }, - "angularTheme": { - "primary": "indigo", - "accents": "blue", - "warn": "red", - "background": "grey", - "palette": "light" - } - }, - "site": { - "name": "PlanktoScope", - "hideToolbar": "false", - "allowSwipe": "false", - "lockMenu": "false", - "allowTempTheme": "true", - "dateFormat": "Y-MM-DD", - "sizes": { - "sx": 55, - "sy": 55, - "gx": 4, - "gy": 4, - "cx": 4, - "cy": 4, - "px": 4, - "py": 4 - } - } - }, - { - "id": "36739a35.7cce36", - "type": "ui_tab", - "name": "Gallery", - "icon": "fa-file-image-o", - "order": 6, - "disabled": false, - "hidden": false - }, - { - "id": "c0ebfc57.42527", - "type": "ui_group", - "name": "Group 1", - "tab": "36739a35.7cce36", - "order": 1, - "disp": false, - "width": "24", - "collapse": false, - "className": "" - }, - { - "id": "737ec584.2eea2c", - "type": "ui_tab", - "name": "Sample", - "icon": "fa-eyedropper", - "order": 2, - "disabled": false, - "hidden": false - }, - { - "id": "6f97e7ae.270c48", - "type": "ui_group", - "name": "Group 1", - "tab": "3a6bb13f.c9703e", - "order": 2, - "disp": false, - "width": "4", - "collapse": false, - "className": "" - }, - { - "id": "3e1ba03d.f01d8", - "type": "ui_group", - "name": "Sample Identification", - "tab": "737ec584.2eea2c", - "order": 1, - "disp": true, - "width": "10", - "collapse": false - }, - { - "id": "4e0cd5ea.17e59c", - "type": "ui_group", - "name": "Group 2", - "tab": "3a6bb13f.c9703e", - "order": 3, - "disp": false, - "width": "4", - "collapse": false - }, - { - "id": "ef590206.24f6", - "type": "ui_group", - "name": "Group 3", - "tab": "3a6bb13f.c9703e", - "order": 4, - "disp": false, - "width": "4", - "collapse": false - }, - { - "id": "ae8f6620.073358", - "type": "ui_group", - "name": "Group 4", - "tab": "3a6bb13f.c9703e", - "order": 5, - "disp": false, - "width": "4", - "collapse": false - }, - { - "id": "196518b2.4d53b7", - "type": "ui_group", - "name": "Group 5", - "tab": "3a6bb13f.c9703e", - "order": 6, - "disp": false, - "width": "4", - "collapse": false - }, - { - "id": "777a7c33.fcd804", - "type": "ui_group", - "name": "Group 6", - "tab": "3a6bb13f.c9703e", - "order": 7, - "disp": false, - "width": "4", - "collapse": false - }, - { - "id": "cef1e703.bcf3c8", - "type": "ui_group", - "name": "Sample Location", - "tab": "737ec584.2eea2c", - "order": 3, - "disp": false, - "width": "10", - "collapse": false - }, - { - "id": "5517c651.b2f668", - "type": "ui_group", - "name": "Validation", - "tab": "737ec584.2eea2c", - "order": 5, - "disp": false, - "width": 10, - "collapse": false - }, - { - "id": "fbd92986.1028c8", - "type": "ui_group", - "name": "Focus Adjustment", - "tab": "181bb236.1e94be", - "order": 2, - "disp": true, - "width": 4, - "collapse": false - }, - { - "id": "707d9797.c8e798", - "type": "ui_group", - "name": "Fluidic Manual Manipulation", - "tab": "181bb236.1e94be", - "order": 5, - "disp": true, - "width": 4, - "collapse": false - }, - { - "id": "7a0b4877.a5d268", - "type": "ui_group", - "name": "Navigation", - "tab": "181bb236.1e94be", - "order": 6, - "disp": false, - "width": 4, - "collapse": false - }, - { - "id": "4322c187.e73e5", - "type": "ui_group", - "name": "Acquisition", - "tab": "c9194f02.9d5e9", - "order": 3, - "disp": true, - "width": 10, - "collapse": false - }, - { - "id": "b7919ae2.c01788", - "type": "ui_group", - "name": "Navigation", - "tab": "c9194f02.9d5e9", - "order": 6, - "disp": false, - "width": "10", - "collapse": false - }, - { - "id": "b5d61bc7.54fe48", - "type": "ui_group", - "name": "Statistics", - "tab": "c9194f02.9d5e9", - "order": 4, - "disp": true, - "width": "10", - "collapse": false - }, - { - "id": "8dc3722c.06efa8", - "type": "mqtt-broker", - "name": "", - "broker": "0.0.0.0", - "port": "1883", - "clientid": "Client_node", - "autoConnect": true, - "usetls": false, - "compatmode": false, - "protocolVersion": 4, - "keepalive": "60", - "cleansession": true, - "birthTopic": "", - "birthQos": "0", - "birthPayload": "", - "closeTopic": "", - "closeQos": "0", - "closePayload": "", - "willTopic": "", - "willQos": "0", - "willPayload": "" - }, - { - "id": "abeb6dad.635a2", - "type": "ui_group", - "name": "Control", - "tab": "8d16beb8.9b3fb", - "order": 1, - "disp": true, - "width": 10, - "collapse": false - }, - { - "id": "cf5d9f0e.d57e7", - "type": "ui_group", - "name": "Net Metadata", - "tab": "737ec584.2eea2c", - "order": 4, - "disp": false, - "width": "10", - "collapse": false - }, - { - "id": "ce9e278.781eed8", - "type": "ui_group", - "name": "Information", - "tab": "d9cd733b.ab73d", - "order": 5, - "disp": true, - "width": 6, - "collapse": false - }, - { - "id": "70de8209.68416c", - "type": "ui_group", - "name": "Status", - "tab": "c9194f02.9d5e9", - "order": 5, - "disp": true, - "width": 10, - "collapse": false - }, - { - "id": "46be9c86.dea684", - "type": "ui_group", - "name": "Status", - "tab": "8d16beb8.9b3fb", - "order": 2, - "disp": true, - "width": 10, - "collapse": false - }, - { - "id": "8c38a81e.9897a8", - "type": "ui_group", - "name": "Camera Settings", - "tab": "181bb236.1e94be", - "order": 3, - "disp": true, - "width": 6, - "collapse": false - }, - { - "id": "2489e51c.eed77a", - "type": "ui_tab", - "name": "Administration", - "icon": "dashboard", - "order": 9, - "disabled": false, - "hidden": false - }, - { - "id": "b0fb559a.6966a8", - "type": "ui_tab", - "name": "Hardware Settings", - "icon": "fa-cogs", - "disabled": false, - "hidden": false - }, - { - "id": "6be36295.0ab324", - "type": "ui_group", - "name": "Settings", - "tab": "b0fb559a.6966a8", - "order": 1, - "disp": false, - "width": "8", - "collapse": false, - "className": "" - }, - { - "id": "f3ca28ef.4df0a8", - "type": "ui_group", - "name": "Shutdown", - "tab": "3a6bb13f.c9703e", - "order": 8, - "disp": true, - "width": 4, - "collapse": false - }, - { - "id": "3dfd8a69.69ed56", - "type": "ui_spacer", - "name": "spacer", - "group": "f3ca28ef.4df0a8", - "order": 3, - "width": 4, - "height": 1 - }, - { - "id": "72a9216.2ff48e", - "type": "ui_spacer", - "name": "spacer", - "group": "4322c187.e73e5", - "order": 8, - "width": 10, - "height": 1 - }, - { - "id": "1b664927.c91d1f", - "type": "ui_spacer", - "name": "spacer", - "group": "b5d61bc7.54fe48", - "order": 2, - "width": 2, - "height": 1 - }, - { - "id": "1a663b6a.ab5805", - "type": "ui_spacer", - "name": "spacer", - "group": "b5d61bc7.54fe48", - "order": 4, - "width": 2, - "height": 1 - }, - { - "id": "8eeed8d8.ad9098", - "type": "ui_spacer", - "name": "spacer", - "group": "b5d61bc7.54fe48", - "order": 5, - "width": 2, - "height": 1 - }, - { - "id": "be1c5ce7.004e", - "type": "ui_spacer", - "name": "spacer", - "group": "b5d61bc7.54fe48", - "order": 6, - "width": 2, - "height": 1 - }, - { - "id": "c2fe38e9.555e3", - "type": "ui_spacer", - "name": "spacer", - "group": "b5d61bc7.54fe48", - "order": 7, - "width": 2, - "height": 1 - }, - { - "id": "89bd18b7.c779a8", - "type": "ui_spacer", - "name": "spacer", - "group": "b5d61bc7.54fe48", - "order": 8, - "width": 2, - "height": 1 - }, - { - "id": "3cbbfa5d.efa636", - "type": "ui_spacer", - "name": "spacer", - "group": "b7919ae2.c01788", - "order": 2, - "width": 5, - "height": 1 - }, - { - "id": "97148e8d8e298f1a", - "type": "ui_spacer", - "z": "cb95299c.2817c8", - "name": "spacer", - "group": "abeb6dad.635a2", - "order": 7, - "width": 10, - "height": 1 - }, - { - "id": "3b2eccc574e6a9ae", - "type": "ui_spacer", - "z": "cb95299c.2817c8", - "name": "spacer", - "group": "abeb6dad.635a2", - "order": 11, - "width": 1, - "height": 1 - }, - { - "id": "bbd6431d97c86f97", - "type": "ui_spacer", - "z": "cb95299c.2817c8", - "name": "spacer", - "group": "46be9c86.dea684", - "order": 4, - "width": 3, - "height": 1 - }, - { - "id": "5f98f5f140f0ecde", - "type": "ui_spacer", - "z": "cb95299c.2817c8", - "name": "spacer", - "group": "46be9c86.dea684", - "order": 6, - "width": 3, - "height": 1 - }, - { - "id": "7bc0a4c416e4545c", - "type": "ui_group", - "name": "Culture Date and Time", - "tab": "737ec584.2eea2c", - "order": 2, - "disp": true, - "width": "10", - "collapse": false, - "className": "" - }, - { - "id": "6c31ad948a9d62fd", - "type": "ui_spacer", - "z": "b771c342.49603", - "name": "spacer", - "group": "3e1ba03d.f01d8", - "order": 5, - "width": 10, - "height": 1 - }, - { - "id": "0035a03e1490cd8c", - "type": "ui_group", - "name": "Setup", - "tab": "3a6bb13f.c9703e", - "order": 1, - "disp": true, - "width": "8", - "collapse": false, - "className": "" - }, - { - "id": "833bc5bb.217ba8", - "type": "ui_group", - "name": "Preview", - "tab": "181bb236.1e94be", - "order": 1, - "disp": true, - "width": 18, - "collapse": false - }, - { - "id": "a7d64879.38298", - "type": "ui_group", - "name": "Logs", - "tab": "2489e51c.eed77a", - "order": 1, - "disp": true, - "width": "12", - "collapse": true, - "className": "" - }, - { - "id": "6465bdd5.15eb8c", - "type": "file in", - "z": "1c24ad9c.bebec2", - "name": "", - "filename": "/home/pi/PlanktoScope/config.json", - "filenameType": "str", - "format": "utf8", - "chunk": false, - "sendError": false, - "encoding": "none", - "x": 560, - "y": 60, - "wires": [["15ceb135.6628bf"]], - "info": "# PlanktoScope Help\nThis Node will read the content of the file named **config.txt** containing all the input placeholders.\n" - }, - { - "id": "15ceb135.6628bf", - "type": "json", - "z": "1c24ad9c.bebec2", - "name": "config.json", - "property": "payload", - "action": "", - "pretty": false, - "x": 730, - "y": 60, - "wires": [["ad541674.4791c8"]] - }, - { - "id": "7205d267.36adcc", - "type": "file", - "z": "1c24ad9c.bebec2", - "name": "", - "filename": "/home/pi/PlanktoScope/config.json", - "appendNewline": true, - "createDir": true, - "overwriteFile": "true", - "encoding": "none", - "x": 990, - "y": 160, - "wires": [[]] - }, - { - "id": "2e6ddf51.c0dba", - "type": "json", - "z": "1c24ad9c.bebec2", - "name": "config.json", - "property": "payload", - "action": "str", - "pretty": true, - "x": 730, - "y": 160, - "wires": [["7205d267.36adcc"]] - }, - { - "id": "ad541674.4791c8", - "type": "function", - "z": "1c24ad9c.bebec2", - "name": "Global Set", - "func": "global.set(\"config_keys\", Object.keys(msg.payload));\n\nfor (const key in msg.payload) {\n global.set(key, msg.payload[key]);\n}\n\nreturn msg;", - "outputs": 1, - "timeout": "", - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 910, - "y": 60, - "wires": [[]] - }, - { - "id": "3e9a33c.141384c", - "type": "inject", - "z": "1c24ad9c.bebec2", - "name": "Load config", - "props": [ - { - "p": "topic", - "vt": "str" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "", - "payloadType": "str", - "x": 230, - "y": 60, - "wires": [["6465bdd5.15eb8c"]] - }, - { - "id": "3ad9835.08c937c", - "type": "function", - "z": "1c24ad9c.bebec2", - "name": "get config payload", - "func": "keys = global.get(\"config_keys\")\n\nvar payload = {}\n\nkeys.forEach(function(item, index, array) {\n payload[item] = global.get(item);\n})\n\nreturn {\"payload\": payload};", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 410, - "y": 160, - "wires": [["2e6ddf51.c0dba"]] - }, - { - "id": "f439663c.8abd3", - "type": "ui_ui_control", - "z": "1c24ad9c.bebec2", - "name": "Connect Event", - "events": "connect", - "x": 220, - "y": 100, - "wires": [["6465bdd5.15eb8c"]] - }, - { - "id": "82099021.9ceb08", - "type": "file", - "z": "4ed26b8b.253504", - "name": "", - "filename": "/home/pi/PlanktoScope/hardware.json", - "appendNewline": true, - "createDir": true, - "overwriteFile": "true", - "encoding": "none", - "x": 660, - "y": 40, - "wires": [[]] - }, - { - "id": "bb0a8725.a1849", - "type": "json", - "z": "4ed26b8b.253504", - "name": "Create JSON", - "property": "payload", - "action": "str", - "pretty": true, - "x": 490, - "y": 40, - "wires": [["82099021.9ceb08"]] - }, - { - "id": "53d163be.47cf24", - "type": "function", - "z": "4ed26b8b.253504", - "name": "Update and retrieve hardware_conf", - "func": "// change global\nhardware_conf = global.get(\"hardware_conf\");\n\nif (msg.topic == \"process_pixel_fixed\" && msg.payload == 0){\n delete hardware_conf[msg.topic]\n delete msg.topic\n}\n\nif (msg.topic !== null && msg.topic !== undefined){\n hardware_conf[msg.topic] = msg.payload;\n global.set(\"hardware_conf\", hardware_conf);\n}\n\nreturn {\"payload\": hardware_conf};", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 240, - "y": 40, - "wires": [["bb0a8725.a1849"]] - }, - { - "id": "0f16258953fae292", - "type": "file in", - "z": "b7861ce703215a01", - "name": "", - "filename": "/home/pi/PlanktoScope/hardware.json", - "filenameType": "str", - "format": "utf8", - "chunk": false, - "sendError": false, - "encoding": "none", - "allProps": false, - "x": 250, - "y": 40, - "wires": [["81c516291ab19acd"]], - "info": "# PlanktoScope Help\nThis Node will read the content of the file named **config.txt** containing all the input placeholders.\n" - }, - { - "id": "81c516291ab19acd", - "type": "json", - "z": "b7861ce703215a01", - "name": "Parse JSON", - "property": "payload", - "action": "", - "pretty": false, - "x": 510, - "y": 40, - "wires": [["d0fbcd200cd09981"]] - }, - { - "id": "d0fbcd200cd09981", - "type": "change", - "z": "b7861ce703215a01", - "name": "", - "rules": [ - { - "t": "set", - "p": "hardware_conf", - "pt": "global", - "to": "payload", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 730, - "y": 40, - "wires": [[]] - }, - { - "id": "4e78af2d.90be7", - "type": "ui_ui_control", - "z": "eaae323a.31b3", - "name": "", - "events": "change", - "x": 440, - "y": 160, - "wires": [[]] - }, - { - "id": "7789839d.69b48c", - "type": "ui_template", - "z": "eaae323a.31b3", - "group": "4e0cd5ea.17e59c", - "name": "Optic Configuration", - "order": 1, - "width": 4, - "height": 4, - "format": "\n \n
Optic Configuration
\n
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "className": "", - "x": 130, - "y": 100, - "wires": [["4e78af2d.90be7"]] - }, - { - "id": "6ea6c306.f9c12c", - "type": "ui_template", - "z": "eaae323a.31b3", - "group": "ef590206.24f6", - "name": "Fluidic Acquisition", - "order": 1, - "width": 4, - "height": 4, - "format": "\n \n
Fluidic Acquisition
\n
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "className": "", - "x": 130, - "y": 140, - "wires": [["4e78af2d.90be7"]] - }, - { - "id": "bb9eb153.9e36c", - "type": "ui_template", - "z": "eaae323a.31b3", - "group": "ae8f6620.073358", - "name": "Segmentation", - "order": 1, - "width": 4, - "height": 4, - "format": "\n \n
Segmentation
\n
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "className": "", - "x": 140, - "y": 180, - "wires": [["4e78af2d.90be7"]] - }, - { - "id": "eaf8ee7f.96f44", - "type": "ui_template", - "z": "eaae323a.31b3", - "group": "196518b2.4d53b7", - "name": "Gallery", - "order": 1, - "width": 4, - "height": 4, - "format": "\n \n
Gallery
\n
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "className": "", - "x": 160, - "y": 220, - "wires": [["4e78af2d.90be7"]] - }, - { - "id": "c1b1469.9650eb8", - "type": "ui_template", - "z": "eaae323a.31b3", - "group": "777a7c33.fcd804", - "name": "System Monitoring", - "order": 1, - "width": 4, - "height": 4, - "format": "\n \n
System Monitoring
\n
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "className": "", - "x": 130, - "y": 260, - "wires": [["4e78af2d.90be7"]] - }, - { - "id": "abafd6e6.04a5f8", - "type": "ui_template", - "z": "eaae323a.31b3", - "group": "6f97e7ae.270c48", - "name": "Sample", - "order": 1, - "width": 4, - "height": 4, - "format": "\n \n
Sample
\n
\n In doubt? Start Here!\n
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "className": "", - "x": 160, - "y": 60, - "wires": [["4e78af2d.90be7"]] - }, - { - "id": "dab82064.26a8d", - "type": "ui_button", - "z": "eaae323a.31b3", - "name": "Unlock button", - "group": "f3ca28ef.4df0a8", - "order": 2, - "width": 0, - "height": 0, - "passthru": false, - "label": "Unlock button", - "tooltip": "", - "color": "", - "bgcolor": "", - "icon": "", - "payload": "shutdown", - "payloadType": "flow", - "topic": "", - "x": 120, - "y": 380, - "wires": [["6c3a3b4.78cad44"]] - }, - { - "id": "1c658761.b852a1", - "type": "ui_toast", - "z": "eaae323a.31b3", - "position": "dialog", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 1, - "ok": "YES PLEASE", - "cancel": "NO!", - "raw": false, - "topic": "Are you sure?", - "name": "Confirmation message", - "x": 800, - "y": 380, - "wires": [["8f1b8e23.daafe"]] - }, - { - "id": "a48ff63f.db5e18", - "type": "inject", - "z": "eaae323a.31b3", - "name": "disabled", - "props": [ - { - "p": "enabled", - "v": "false", - "vt": "bool" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "", - "x": 140, - "y": 420, - "wires": [["d58039a9.6e7928"]] - }, - { - "id": "b67a7147.65fcd8", - "type": "ui_button", - "z": "eaae323a.31b3", - "name": "Shutdown button", - "group": "f3ca28ef.4df0a8", - "order": 4, - "width": 0, - "height": 0, - "passthru": false, - "label": "Shutdown", - "tooltip": "", - "color": "", - "bgcolor": "#AD1625", - "icon": "fa-power-off fa-2x", - "payload": "Do you want to turn the machine off now?", - "payloadType": "str", - "topic": "", - "x": 550, - "y": 380, - "wires": [["1c658761.b852a1"]] - }, - { - "id": "d58039a9.6e7928", - "type": "change", - "z": "eaae323a.31b3", - "name": "", - "rules": [ - { - "t": "set", - "p": "shutdown", - "pt": "flow", - "to": "false", - "tot": "bool" - }, - { - "t": "set", - "p": "enabled", - "pt": "msg", - "to": "shutdown", - "tot": "flow" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 320, - "y": 420, - "wires": [["b67a7147.65fcd8"]] - }, - { - "id": "6c3a3b4.78cad44", - "type": "function", - "z": "eaae323a.31b3", - "name": "Toggle", - "func": "flow.set(\"shutdown\", !flow.get(\"shutdown\"))\nmsg.enabled = flow.get(\"shutdown\")\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 290, - "y": 380, - "wires": [["b67a7147.65fcd8"]] - }, - { - "id": "d1153ad6.40d738", - "type": "ui_template", - "z": "eaae323a.31b3", - "group": "f3ca28ef.4df0a8", - "name": "Shutdown information", - "order": 1, - "width": 0, - "height": 0, - "format": "
To prevent data corruption, please always shutdown the machine before unplugging the unit.\n

\nRemember to first unlock the shutdown button.\n
", - "storeOutMessages": true, - "fwdInMessages": false, - "resendOnRefresh": true, - "templateScope": "local", - "x": 120, - "y": 320, - "wires": [[]] - }, - { - "id": "e08cfcb8.2a67e8", - "type": "link out", - "z": "eaae323a.31b3", - "name": "Home shutdown button", - "links": ["b81b990a.d4dca"], - "x": 715, - "y": 500, - "wires": [] - }, - { - "id": "ce7087fc.dcc9e8", - "type": "ui_toast", - "z": "eaae323a.31b3", - "position": "dialog", - "displayTime": "10", - "highlight": "", - "sendall": true, - "outputs": 1, - "ok": "OK", - "cancel": "", - "raw": false, - "topic": "Turning off now!", - "name": "Shutdown message", - "x": 580, - "y": 540, - "wires": [[]] - }, - { - "id": "7d1626a0.deb85", - "type": "change", - "z": "eaae323a.31b3", - "name": "shutdown!", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "shutdown", - "tot": "str" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 310, - "y": 500, - "wires": [["e08cfcb8.2a67e8"]] - }, - { - "id": "8f1b8e23.daafe", - "type": "switch", - "z": "eaae323a.31b3", - "name": "", - "property": "payload", - "propertyType": "msg", - "rules": [ - { - "t": "eq", - "v": "NO!", - "vt": "str" - }, - { - "t": "else" - } - ], - "checkall": "true", - "repair": false, - "outputs": 2, - "x": 150, - "y": 500, - "wires": [["d58039a9.6e7928"], ["7d1626a0.deb85", "281a56c9.ec7902"]] - }, - { - "id": "281a56c9.ec7902", - "type": "change", - "z": "eaae323a.31b3", - "name": "Shutdown message", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "Please wait a minute before disconnecting the machine from its power supply!", - "tot": "str" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 340, - "y": 540, - "wires": [["ce7087fc.dcc9e8"]] - }, - { - "id": "57db4f6279b5afe0", - "type": "comment", - "z": "eaae323a.31b3", - "name": "LICENSE", - "info": "Copyright 2022 Thibaut Pollina and Romain Bazile\nLicensed under GPL v3.0", - "x": 140, - "y": 600, - "wires": [] - }, - { - "id": "6af85f0e0fc21b11", - "type": "ui_ui_control", - "z": "eaae323a.31b3", - "name": "", - "events": "all", - "x": 700, - "y": 720, - "wires": [[]] - }, - { - "id": "382f8fcc81f904f1", - "type": "ui_dropdown", - "z": "eaae323a.31b3", - "name": "", - "label": "Hardware version", - "tooltip": "", - "place": "Select option", - "group": "0035a03e1490cd8c", - "order": 2, - "width": 0, - "height": 0, - "passthru": false, - "multiple": false, - "options": [ - { - "label": "", - "value": "PlanktoScope v2.3", - "type": "str" - }, - { - "label": "", - "value": "PlanktoScope v2.5", - "type": "str" - }, - { - "label": "", - "value": "PlanktoScope v2.6", - "type": "str" - }, - { - "label": "", - "value": "PlanktoScope v3.0", - "type": "str" - } - ], - "payload": "", - "topic": "acq_instrument", - "topicType": "str", - "className": "", - "x": 490, - "y": 640, - "wires": [["9f34e4a2f33c4022"]] - }, - { - "id": "9f34e4a2f33c4022", - "type": "link out", - "z": "eaae323a.31b3", - "name": "Set hardware version", - "mode": "link", - "links": ["cb9009e8a49e93cc"], - "x": 655, - "y": 640, - "wires": [] - }, - { - "id": "e954204b947a0c70", - "type": "switch", - "z": "eaae323a.31b3", - "name": "", - "property": "payload", - "propertyType": "msg", - "rules": [ - { - "t": "null" - }, - { - "t": "else" - } - ], - "checkall": "true", - "repair": false, - "outputs": 2, - "x": 290, - "y": 680, - "wires": [["382f8fcc81f904f1", "e3736dd7be4b7522"], ["f80babd43aa7cce4"]] - }, - { - "id": "e3736dd7be4b7522", - "type": "change", - "z": "eaae323a.31b3", - "name": "Show setup panel", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "{\"group\":{\"show\":[\"Home_Setup\"],\"hide\":[\"Home_Group_1\",\"Home_Group_2\",\"Home_Group_3\",\"Home_Group_4\",\"Home_Group_5\",\"Home_Group_6\"]}}", - "tot": "json" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 490, - "y": 680, - "wires": [["6af85f0e0fc21b11"]] - }, - { - "id": "f80babd43aa7cce4", - "type": "change", - "z": "eaae323a.31b3", - "name": "Show home buttons", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "{\"group\":{\"hide\":[\"Home_Setup\"],\"show\":[\"Home_Group_1\",\"Home_Group_2\",\"Home_Group_3\",\"Home_Group_4\",\"Home_Group_5\",\"Home_Group_6\"]}}", - "tot": "json" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 500, - "y": 720, - "wires": [["6af85f0e0fc21b11"]] - }, - { - "id": "438439b4ae62444c", - "type": "ui_template", - "z": "eaae323a.31b3", - "group": "0035a03e1490cd8c", - "name": "Information", - "order": 1, - "width": "0", - "height": "0", - "format": "
\n

\n To start using your PlanktoScope, please indicate the version of your PlanktoScope hardware:\n

\n
\n", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": true, - "templateScope": "local", - "className": "", - "x": 710, - "y": 680, - "wires": [[]] - }, - { - "id": "a2f2a4c7cbae4446", - "type": "link in", - "z": "eaae323a.31b3", - "name": "Load hardware version", - "links": ["3973b999ee7b3b1d", "56dd3f82c45717f0"], - "x": 185, - "y": 680, - "wires": [["e954204b947a0c70"]] - }, - { - "id": "4557d689.a4fa88", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "sample_ship", - "label": "Name of the ship", - "tooltip": "", - "group": "3e1ba03d.f01d8", - "order": 2, - "width": 0, - "height": 0, - "passthru": true, - "mode": "text", - "delay": "300", - "topic": "sample_ship", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 670, - "y": 80, - "wires": [["9f501f49.45645"]] - }, - { - "id": "fcfc31ae.af3af", - "type": "ui_dropdown", - "z": "b771c342.49603", - "name": "sample_sampling_gear", - "label": "Sampling gear*", - "tooltip": "", - "place": "Choose from list", - "group": "3e1ba03d.f01d8", - "order": 6, - "width": 0, - "height": 0, - "passthru": true, - "multiple": false, - "options": [ - { - "label": "High Speed Net", - "value": "net_hsn", - "type": "str" - }, - { - "label": "Tara Decknet", - "value": "net_decknet", - "type": "str" - }, - { - "label": "Plankton net", - "value": "net", - "type": "str" - }, - { - "label": "Niskin bottle 12L", - "value": "niskin_12L", - "type": "str" - }, - { - "label": "Niskin bottle 24L", - "value": "niskin_24L", - "type": "str" - }, - { - "label": "Pass Hull", - "value": "pass_hull", - "type": "str" - }, - { - "label": "Single location (with net or bucket)", - "value": "single_location", - "type": "str" - }, - { - "label": "Lab culture", - "value": "culture", - "type": "str" - }, - { - "label": "Test", - "value": "test", - "type": "str" - } - ], - "payload": "", - "topic": "sample_sampling_gear", - "topicType": "str", - "className": "", - "x": 630, - "y": 200, - "wires": [["9f501f49.45645", "46eb1bf8.3dc5f4", "3ac7b631f5d8ef90"]] - }, - { - "id": "82c5fc77.59c97", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "sample_operator", - "label": "Name of the operator*", - "tooltip": "", - "group": "3e1ba03d.f01d8", - "order": 3, - "width": 0, - "height": 0, - "passthru": true, - "mode": "text", - "delay": "300", - "topic": "sample_operator", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 650, - "y": 160, - "wires": [["9f501f49.45645"]] - }, - { - "id": "9c882b37.fde668", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "sample_project", - "label": "Name of the project*", - "tooltip": "", - "group": "3e1ba03d.f01d8", - "order": 1, - "width": 0, - "height": 0, - "passthru": true, - "mode": "text", - "delay": "300", - "topic": "sample_project", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 660, - "y": 40, - "wires": [["9f501f49.45645"]] - }, - { - "id": "94eb4221.9b92c", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "sample_id", - "label": "Station ID*", - "tooltip": "", - "group": "3e1ba03d.f01d8", - "order": 4, - "width": 0, - "height": 0, - "passthru": true, - "mode": "text", - "delay": "300", - "topic": "sample_id", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 670, - "y": 120, - "wires": [["9f501f49.45645"]] - }, - { - "id": "9f501f49.45645", - "type": "function", - "z": "b771c342.49603", - "name": "set global", - "func": "global.set(msg.topic,msg.payload);", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 1080, - "y": 200, - "wires": [[]] - }, - { - "id": "222c851d.5d0a3a", - "type": "ui_ui_control", - "z": "b771c342.49603", - "name": "", - "events": "change", - "x": 400, - "y": 880, - "wires": [[]] - }, - { - "id": "52f6b103.1efb6", - "type": "ui_toast", - "z": "b771c342.49603", - "position": "dialog", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 1, - "ok": "OK", - "cancel": "", - "raw": false, - "topic": "", - "name": "", - "x": 710, - "y": 980, - "wires": [[]] - }, - { - "id": "986d960a.c75908", - "type": "function", - "z": "b771c342.49603", - "name": "Check form", - "func": "var sample_project= global.get(\"sample_project\");\nvar sample_id= global.get(\"sample_id\");\nvar sample_operator= global.get(\"sample_operator\");\nvar sample_sampling_gear= global.get(\"sample_sampling_gear\");\nvar object_lat= global.get(\"object_lat\");\nvar object_lon= global.get(\"object_lon\");\nvar object_date= global.get(\"object_date\");\nvar object_time= global.get(\"object_time\");\nif (sample_project === undefined || sample_project === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Sample project\"\n return [null, msg];\n}\n\nelse if (sample_id === undefined || sample_id === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Sample ID\"\n return [null, msg];\n}\n\nelse if (sample_operator === undefined || sample_operator === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Sample operator\"\n return [null, msg];\n}\n\nelse if (sample_sampling_gear === undefined || sample_sampling_gear === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Sample sampling gear\"\n return [null, msg];\n}\n\nelse if (object_lat === undefined || object_lat === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Latitude of sample\"\n return [null, msg];\n}\n\nelse if (object_lon === undefined || object_lon === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Longitude of sample\"\n return [null, msg];\n}\n\nelse if (object_date === undefined || object_date === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Date of sample\"\n return [null, msg];\n}\n\nelse if (object_time === undefined || object_time === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Time of sample\"\n return [null, msg];\n}\nelse if (sample_sampling_gear.startsWith(\"net\")){\n var object_lat_end = global.get(\"object_lat_end\");\n var object_lon_end = global.get(\"object_lon_end\");\n var object_date_end = global.get(\"object_date_end\");\n var object_time_end = global.get(\"object_time_end\");\n var sample_gear_net_opening = global.get(\"sample_gear_net_opening\");\n\n if (object_lat_end === undefined || object_lat_end === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Latitude of retrieval\"\n return [null, msg];\n }\n \n else if (object_lon_end === undefined || object_lon_end === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Longitude of retrieval\"\n return [null, msg];\n }\n \n else if (object_date_end === undefined || object_date_end === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Date of retrieval\"\n return [null, msg];\n }\n \n else if (object_time_end === undefined || object_time_end === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Time of retrieval\"\n return [null, msg];\n }\n \n else if (sample_gear_net_opening === undefined || sample_gear_net_opening === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Net opening dimension\"\n return [null, msg];\n }\n \n if (sample_sampling_gear == \"net_decknet\"){\n var sample_total_volume = global.get(\"sample_total_volume\");\n if (sample_total_volume === undefined || sample_total_volume === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Decknet flowmeter readings\"\n return [null, msg];\n }\n }\n}\nmsg.topic = \"config_save\"\nmsg.payload={\"tab\":\"Optic Configuration\"};\n\nreturn [msg, null];", - "outputs": 2, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 470, - "y": 940, - "wires": [["726a7822.cd6298", "e2b277c1.07283"], ["52f6b103.1efb6"]], - "outputLabels": ["message", "error"] - }, - { - "id": "726a7822.cd6298", - "type": "ui_ui_control", - "z": "b771c342.49603", - "name": "", - "events": "change", - "x": 700, - "y": 900, - "wires": [[]] - }, - { - "id": "16de754c.cc969b", - "type": "ui_button", - "z": "b771c342.49603", - "name": "", - "group": "5517c651.b2f668", - "order": 1, - "width": 5, - "height": 1, - "passthru": false, - "label": "Previous", - "tooltip": "", - "color": "#097479", - "bgcolor": "white", - "icon": "keyboard_return", - "payload": "{\"tab\":\"Home\"}", - "payloadType": "json", - "topic": "", - "x": 240, - "y": 880, - "wires": [["222c851d.5d0a3a"]] - }, - { - "id": "84f3d040.5f7ea", - "type": "ui_button", - "z": "b771c342.49603", - "name": "", - "group": "5517c651.b2f668", - "order": 2, - "width": 5, - "height": 1, - "passthru": false, - "label": "Continue", - "tooltip": "", - "color": "#097479", - "bgcolor": "white", - "icon": "keyboard_tab", - "payload": "{\"tab\":\"Home\"}", - "payloadType": "json", - "topic": "", - "x": 240, - "y": 940, - "wires": [["986d960a.c75908"]] - }, - { - "id": "d027a6bf.7049e8", - "type": "function", - "z": "b771c342.49603", - "name": "get sample_projet", - "func": "msg.payload = msg.payload.sample_project;\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 310, - "y": 40, - "wires": [["9c882b37.fde668"]] - }, - { - "id": "5a811caf.0f3144", - "type": "function", - "z": "b771c342.49603", - "name": "get sample_ship", - "func": "msg.payload = msg.payload.sample_ship;\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 300, - "y": 80, - "wires": [["4557d689.a4fa88"]] - }, - { - "id": "45911c98.2bd83c", - "type": "function", - "z": "b771c342.49603", - "name": "get sample_id", - "func": "msg.payload = msg.payload.sample_id;\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 300, - "y": 120, - "wires": [["94eb4221.9b92c"]] - }, - { - "id": "1e09a4ab.72996b", - "type": "function", - "z": "b771c342.49603", - "name": "get sample_operator", - "func": "msg.payload = msg.payload.sample_operator;\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 320, - "y": 160, - "wires": [["82c5fc77.59c97"]] - }, - { - "id": "a3272681.f271c8", - "type": "function", - "z": "b771c342.49603", - "name": "get sample_sampling_gear", - "func": "msg.topic = \"sample_sampling_gear\"\nif (msg.payload.sample_sampling_gear === undefined){\n msg.payload = \"net\";\n}\nelse\n{\n msg.payload = msg.payload.sample_sampling_gear;\n}\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 340, - "y": 200, - "wires": [["fcfc31ae.af3af"]] - }, - { - "id": "a6907a38.f6611", - "type": "subflow:1c24ad9c.bebec2", - "z": "b771c342.49603", - "name": "", - "env": [], - "x": 70, - "y": 220, - "wires": [ - [ - "d027a6bf.7049e8", - "5a811caf.0f3144", - "45911c98.2bd83c", - "1e09a4ab.72996b", - "8dff1648.82e42", - "9f04c5ec.75f3d8", - "f408a273.4fb538", - "e73fd87d.d24e4", - "489c8e06.cc7d6", - "a3272681.f271c8" - ] - ] - }, - { - "id": "e2b277c1.07283", - "type": "subflow:1c24ad9c.bebec2", - "z": "b771c342.49603", - "name": "", - "env": [], - "x": 690, - "y": 940, - "wires": [[]] - }, - { - "id": "9c7f7fc9.c8d3a", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "object_depth_max", - "label": "Max sampling depth (m)", - "tooltip": "in m", - "group": "3e1ba03d.f01d8", - "order": 10, - "width": 5, - "height": 1, - "passthru": true, - "mode": "number", - "delay": "300", - "topic": "object_depth_max", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 650, - "y": 240, - "wires": [["9f501f49.45645"]] - }, - { - "id": "317eeeb7.8d3042", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "object_depth_min", - "label": "Min sampling depth (m)", - "tooltip": "in m", - "group": "3e1ba03d.f01d8", - "order": 9, - "width": 5, - "height": 1, - "passthru": true, - "mode": "number", - "delay": "300", - "topic": "object_depth_min", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 650, - "y": 280, - "wires": [["9f501f49.45645"]] - }, - { - "id": "cbb123ab.fd3428", - "type": "ui_ui_control", - "z": "b771c342.49603", - "name": "show/hide net groups", - "events": "change", - "x": 1320, - "y": 300, - "wires": [[]] - }, - { - "id": "642ff403.1ed91c", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "sample_concentrated_sample_volume", - "label": "Concentrated sample volume (mL)", - "tooltip": "Volume extracted from the net codend (in mL)", - "group": "3e1ba03d.f01d8", - "order": 12, - "width": 10, - "height": 1, - "passthru": true, - "mode": "number", - "delay": "300", - "topic": "sample_concentrated_sample_volume", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 590, - "y": 440, - "wires": [["9f501f49.45645"]] - }, - { - "id": "e967b844.46aa48", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "sample_gear_net_opening", - "label": "Net opening dimension (mm)", - "tooltip": "Size of the net mouth opening (in mm)", - "group": "cf5d9f0e.d57e7", - "order": 1, - "width": 10, - "height": 1, - "passthru": true, - "mode": "number", - "delay": "300", - "topic": "sample_gear_net_opening", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 620, - "y": 320, - "wires": [["9f501f49.45645"]] - }, - { - "id": "c0ce5626.b6c5", - "type": "ui_toast", - "z": "b771c342.49603", - "position": "dialog", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 1, - "ok": "OK", - "cancel": "", - "raw": false, - "topic": "", - "name": "", - "x": 1230, - "y": 620, - "wires": [[]] - }, - { - "id": "c33f1124.af6688", - "type": "ui_form", - "z": "b771c342.49603", - "name": "sample_location", - "label": "Sample Location", - "group": "cef1e703.bcf3c8", - "order": 1, - "width": 0, - "height": 0, - "options": [ - { - "label": "Latitude (36.574439°N or 36°57.4439'N)", - "value": "object_lat", - "type": "text", - "required": true, - "rows": null - }, - { - "label": "Longitude (110.42100°W or 110°4.2100'W)", - "value": "object_lon", - "type": "text", - "required": true, - "rows": null - }, - { - "label": "Date (YYYY-MM-DD, UTC)", - "value": "object_date", - "type": "text", - "required": true, - "rows": null - }, - { - "label": "Time (HH:MM(:SS), UTC 24h)", - "value": "object_time", - "type": "text", - "required": true, - "rows": null - } - ], - "formValue": { - "object_lat": "", - "object_lon": "", - "object_date": "", - "object_time": "" - }, - "payload": "", - "submit": "Validate", - "cancel": "Reset", - "topic": "sample_location", - "x": 660, - "y": 580, - "wires": [["14658615.47c862", "a9fb1f4b83fc25a7"]] - }, - { - "id": "358908cd.416ab", - "type": "ui_form", - "z": "b771c342.49603", - "name": "net_throw_location", - "label": "Net Throw Location", - "group": "cf5d9f0e.d57e7", - "order": 3, - "width": 0, - "height": 0, - "options": [ - { - "label": "Latitude (36.574439°N or 36°57.4439'N)", - "value": "object_lat", - "type": "text", - "required": true, - "rows": null - }, - { - "label": "Longitude (110.42100°W or 110°4.2100'W)", - "value": "object_lon", - "type": "text", - "required": true, - "rows": null - }, - { - "label": "Date (YYYY-MM-DD UTC)", - "value": "object_date", - "type": "text", - "required": true, - "rows": null - }, - { - "label": "Time (HH:MM, UTC 24h)", - "value": "object_time", - "type": "text", - "required": true, - "rows": null - } - ], - "formValue": { - "object_lat": "", - "object_lon": "", - "object_date": "", - "object_time": "" - }, - "payload": "", - "submit": "Validate", - "cancel": "", - "topic": "net_throw_location", - "topicType": "str", - "splitLayout": false, - "className": "", - "x": 650, - "y": 620, - "wires": [["14658615.47c862", "ad54b89540460d27"]] - }, - { - "id": "56d40584.eff4e4", - "type": "ui_form", - "z": "b771c342.49603", - "name": "net_retrieval_location", - "label": "Net Retrieval Location", - "group": "cf5d9f0e.d57e7", - "order": 4, - "width": 0, - "height": 0, - "options": [ - { - "label": "Latitude (36.574439°N or 36°57.4439'N)", - "value": "object_lat_end", - "type": "text", - "required": true, - "rows": null - }, - { - "label": "Longitude (110.42100°W or 110°4.2100'W)", - "value": "object_lon_end", - "type": "text", - "required": true, - "rows": null - }, - { - "label": "Date (YYYY-MM-DD UTC)", - "value": "object_date_end", - "type": "text", - "required": true, - "rows": null - }, - { - "label": "Time (HH:MM, UTC 24h)", - "value": "object_time_end", - "type": "text", - "required": true, - "rows": null - } - ], - "formValue": { - "object_lat_end": "", - "object_lon_end": "", - "object_date_end": "", - "object_time_end": "" - }, - "payload": "", - "submit": "Validate", - "cancel": "", - "topic": "net_retrieval_location", - "topicType": "str", - "splitLayout": false, - "x": 640, - "y": 660, - "wires": [["14658615.47c862", "c21bf0244e67e40a"]] - }, - { - "id": "14658615.47c862", - "type": "function", - "z": "b771c342.49603", - "name": "Validate Location / Timestamp", - "func": "// Code added here will be run once\n// whenever the node is started.\nfunction ConvertDDMMToDD(input) {\n // Input Format 36°57.4439'N, 110°4.2100'W\n // From https://stackoverflow.com/questions/1140189/converting-latitude-and-longitude-to-decimal-values\n if (!input.match(/\\d+°\\d+\\.*\\d*\\'[NSEW]/)){\n \treturn \"parsing error\"\n }\n var parts = input.split(/[^\\d.\\w]+/)\n if (parts.length != 3){\n \treturn \"parsing error\"\n }\n var dd = Number(parts[0]) + Number(parts[1])/60\n return dd.toFixed(6) + parts[2]\n}\n\nfunction ValidateCoordinates(input, lat){\n // Input Format 36.574439°N, 110.42100°W\n // Or 36°57.4439'N, 110°4.2100'W\n if (input.match(\"'\")){\n input = ConvertDDMMToDD(input)\n }\n \n var error = {}\n\n if (input.startsWith(\"parsing error\")){\n error.topic = \"Error with the \"\n error.payload = \"You need to respect the format example, 36.574439°N or 36°57.4439'N\"\n return [null, error]\n }\n \n var direction = input.match(/[NSEW]/)\n var position = input.match(/[\\+\\-\\d\\.]+/)\n \n if (direction === null){\n error.topic = \"Error with the \"\n error.payload = \"You need to explicitely enter N/S/E/W\"\n return [null, error]\n }\n \n // Test that position is only made of digits!\n if(/^[\\+\\-]/.test(position)){\n error.topic = \"Error with the \"\n error.payload = \"Use of +/- sign is inconsistent with N/S/E/W letter! Please only use N/S/E/W!\"\n return [null, error]\n }\n \n var dd = Number(position)\n if (lat){\n // Check latitude\n if (direction == \"S\" || direction == \"N\") {\n if (dd>90.0){\n error.topic = \"Error with the \"\n error.payload = \"Latitude is more than 90°\"\n return [null, error]\n }\n }\n if (direction == \"W\" || direction == \"E\") {\n error.topic = \"Error with the \"\n error.payload = \"This is not a Latitude!\"\n return [null, error]\n }\n }\n else{\n // Check longitude\n if (direction == \"W\" || direction == \"E\") {\n if (dd>180.0){\n error.topic = \"Error with the \"\n error.payload = \"Longitude is more than 180°\"\n return [null, error]\n }\n }\n if (direction == \"N\" || direction == \"S\") {\n error.topic = \"Error with the \"\n error.payload = \"This is not a Longitude!\"\n return [null, error]\n }\n }\n \n if (direction == \"S\" || direction == \"W\") {\n dd = dd * -1\n } // Don't do anything for N or E\n return [dd.toFixed(4), null]\n \n}\n\nfunction ValidateDate(input){\n // Input Format 2020-12-25\n var error = {};\n \n if (! /20\\d{2}-[0-1]\\d-[0-3]\\d/.test(input)){\n error.topic = \"Error with the date\";\n error.payload = \"The date should respect the ISO format YYYY-MM-DD\";\n return [null, error];\n }\n else {\n var date = input.match(/\\d+/g);\n if (!((2000 < date[0]) && (date[0] < 2100))){\n error.topic = \"Error with the date\"\n error.payload = \"The year should be between 2000 and 2100\"\n return [null, error]\n }\n else if (!((0 < date[1]) && (date[1] <= 12))){\n error.topic = \"Error with the date\"\n error.payload = \"The month should be between 01 and 12\"\n return [null, error]\n }\n else if (!((0 < date[2]) && (date[2] <= 31))){\n error.topic = \"Error with the date\"\n error.payload = \"The day should be between 01 and 31\"\n return [null, error]\n }\n }\n return [input.replace(/-/g, ''), null]\n}\n\nfunction ValidateTime(input){\n // Input Format 12:00\n var error = {}\n \n if (! /[0-2]?\\d:[0-5]\\d/.test(input)){\n error.topic = \"Error with the time\"\n error.payload = \"The date should respect the ISO format HH:MM\"\n return [null, error]\n }\n else {\n var time = input.match(/\\d+/g)\n \n if (!((0 <= time[0]) && (time[0] < 24))){\n error.topic = \"Error with the time\"\n error.payload = \"The hours should be 0 and 23.\"\n return [null, error]\n }\n else if (!((0 <= time[1]) && (time[1] < 60))){\n error.topic = \"Error with the time\"\n error.payload = \"The minutes should be between 0 and 59\"\n return [null, error]\n }\n }\n return [input.replace(/:/g, ''), null]\n}\n\n\nvar ret\nvar payload_for_form = {payload:{}}\nmsg.valid = false\n\nif (msg.topic == \"culture_timestamp\"){\n ret = ValidateDate(msg.payload.object_date)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_date\", ret[0])\n \n ret = ValidateTime(msg.payload.object_time)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_time\", ret[0])\n return [{topic: \"Date and time format valid!\", payload: \"All good!\", valid: true}, payload_for_form]\n}\nelse if (msg.topic == \"net_retrieval_location\"){\n ret = ValidateCoordinates(msg.payload.object_lat_end, true);\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" Latitude\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_lat_end\", ret[0])\n ret = ValidateCoordinates(msg.payload.object_lon_end, false)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" Longitude\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_lon_end\", ret[0]);\n \n ret = ValidateDate(msg.payload.object_date_end)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample retrieval\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_date_end\", ret[0])\n \n ret = ValidateTime(msg.payload.object_time_end)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample retrieval\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_time_end\", ret[0])\n}\nelse{\n ret = ValidateCoordinates(msg.payload.object_lat, true);\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" Latitude\";\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_lat\", ret[0]);\n payload_for_form.payload[\"object_lat_end\"] = msg.payload.object_lat;\n \n ret = ValidateCoordinates(msg.payload.object_lon, false);\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" Longitude\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_lon\", ret[0])\n payload_for_form.payload[\"object_lon_end\"] = msg.payload.object_lon;\n\n ret = ValidateDate(msg.payload.object_date)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_date\", ret[0])\n payload_for_form.payload[\"object_date_end\"] = msg.payload.object_date;\n \n ret = ValidateTime(msg.payload.object_time)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_time\", ret[0])\n payload_for_form.payload[\"object_time_end\"] = msg.payload.object_time;\n}\nreturn [{topic: \"Coordinates valid!\", payload: \"All good!\", valid: true}, payload_for_form]\n", - "outputs": 2, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 930, - "y": 620, - "wires": [["c0ce5626.b6c5", "9a18a4b4.178448"], ["56d40584.eff4e4"]], - "inputLabels": ["Location form data"], - "outputLabels": ["Message", "Location validated"] - }, - { - "id": "46eb1bf8.3dc5f4", - "type": "function", - "z": "b771c342.49603", - "name": "Net check", - "func": "var decknet = {}\nvar activation_msg = {}\n\nif (msg.payload.startsWith(\"net_decknet\")){\n decknet.enabled = true;\n}\nelse {\n decknet.enabled = false;\n}\n\nif (msg.payload.startsWith(\"net\")){\n activation_msg.payload = {\"group\":{\"show\":[\"Sample_Net_Metadata\"],\"hide\":[\"Sample_Sample_Location\",\"Sample_Culture_Date_and_Time\"]}};\n}\nelse if (msg.payload != \"culture\" && msg.payload != \"test\"){\n activation_msg.payload = {\"group\":{\"show\":[\"Sample_Sample_Location\"], \"hide\":[\"Sample_Net_Metadata\",\"Sample_Culture_Date_and_Time\"]}};\n}\n\n\nreturn [decknet, activation_msg];", - "outputs": 2, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 1080, - "y": 240, - "wires": [ - ["516375fd.2ed61c", "470e382a.25691", "fbe32ac8.ff6a38"], - ["cbb123ab.fd3428"] - ], - "outputLabels": ["decknet activation", "group display control"] - }, - { - "id": "516375fd.2ed61c", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "sample_total_flowmeter_start", - "label": "Decknet flowmeter start", - "tooltip": "in L", - "group": "cf5d9f0e.d57e7", - "order": 6, - "width": 5, - "height": 1, - "passthru": false, - "mode": "text", - "delay": "300", - "topic": "sample_total_flowmeter_start", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 1340, - "y": 220, - "wires": [["e9bc112c.eb75f8"]] - }, - { - "id": "470e382a.25691", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "sample_total_flowmeter_end", - "label": "Decknet flowmeter end", - "tooltip": "in L", - "group": "cf5d9f0e.d57e7", - "order": 7, - "width": 5, - "height": 1, - "passthru": false, - "mode": "text", - "delay": "300", - "topic": "sample_total_flowmeter_end", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 1340, - "y": 260, - "wires": [["e9bc112c.eb75f8"]] - }, - { - "id": "fbe32ac8.ff6a38", - "type": "ui_template", - "z": "b771c342.49603", - "group": "cf5d9f0e.d57e7", - "name": "Decknet flowmeter read", - "order": 5, - "width": 10, - "height": 1, - "format": "
\n

Decknet flowmeter readings

\n

Those values are used to calculate sample_total_volume. Values are in L.

\n
\n", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": true, - "templateScope": "local", - "x": 1330, - "y": 180, - "wires": [[]] - }, - { - "id": "f408a273.4fb538", - "type": "function", - "z": "b771c342.49603", - "name": "get sample_gear_net_opening", - "func": "if (msg.payload.sample_gear_net_opening === null){\n msg.payload = 0;\n global.set(\"sample_gear_net_opening\",msg.payload);\n}\nelse\n{\n msg.payload = msg.payload.sample_gear_net_opening;\n}\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 350, - "y": 320, - "wires": [["e967b844.46aa48"]] - }, - { - "id": "8dff1648.82e42", - "type": "function", - "z": "b771c342.49603", - "name": "get object_depth_max", - "func": "if (msg.payload.object_depth_max === null){\n msg.payload = 0;\n global.set(\"object_depth_max\",msg.payload);\n}\nelse\n{\n msg.payload = msg.payload.object_depth_max;\n}\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 320, - "y": 240, - "wires": [["9c7f7fc9.c8d3a"]] - }, - { - "id": "9f04c5ec.75f3d8", - "type": "function", - "z": "b771c342.49603", - "name": "get object_depth_min", - "func": "if (msg.payload.object_depth_min === null){\n msg.payload = 0;\n global.set(\"object_depth_min\",msg.payload);\n}\nelse\n{\n msg.payload = msg.payload.object_depth_min;\n}\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 320, - "y": 280, - "wires": [["317eeeb7.8d3042"]] - }, - { - "id": "9a18a4b4.178448", - "type": "function", - "z": "b771c342.49603", - "name": "calculate sample_total_volume", - "func": "\n/*object_lat = 33.95 \nobject_lon = 118.4 \nobject_lat_end = 40.6333 \nobject_lon_end = 73.78333\nsample_gear_net_opening = 40*/\n\n// Copyright 1997 Ed Williams. All rights reserved\n// Adapted by Romain Bazile - Ocean Trotter - 01-2021\n\ndecpl=4 // Dec places of minutes output\n\nellipse = {\"name\":\"WSG84\", \"a\":6378.137/1.852, \"invf\":298.257223563}\n\nfunction ComputeDistance(lat1, lon1, lat2, lon2){\n var d,crs12,crs21\n var argacos\n var a,invf\n \n // lat and lon in radian\n lat1=(Math.PI/180)*lat1\n lat2=(Math.PI/180)*lat2\n lon1=(Math.PI/180)*lon1\n lon2=(Math.PI/180)*lon2\n \n //alert(\"lat1=\" + lat1 + \"lon1=\" + lon1 +\"\\nlat2=\" +lat2+ \"lon2=\"+lon2)\n \n /* get distance conversion factor */\n dc=1.852 //km\n //alert(\"dc=\" +dc)\n \n //showProps(ellipse,\"ellipse\")\n \n // elliptic code\n d=crsdist_ell(lat1,-lon1,lat2,-lon2,ellipse) // ellipse uses East negative\n d=d*dc // go to physical units\n \n //alert(\"d=\"+d+\" crs12=\"+crs12+\" crs21=\"+crs21)\n return d\n}\n\nfunction crsdist(lat1,lon1,lat2,lon2){ // radian args\n /* compute course and distance (spherical) */\n if ((lat1+lat2===0) && (Math.abs(lon1-lon2)==Math.PI) && \n (Math.abs(lat1) != (Math.PI/180)*90)){\t\n \talert(\"Course between antipodal points is undefined\")\n }\n \n d = Math.acos(Math.sin(lat1)*Math.sin(lat2)+Math.cos(lat1)*Math.cos(lat2)*Math.cos(lon1-lon2))\n return d\n}\n\nfunction crsdist_ell(glat1,glon1,glat2,glon2,ellipse){\n // glat1 initial geodetic latitude in radians N positive \n // glon1 initial geodetic longitude in radians E positive \n // glat2 final geodetic latitude in radians N positive \n // glon2 final geodetic longitude in radians E positive \n a=ellipse.a\n f=1/ellipse.invf\n //alert(\"a=\"+a+\" f=\"+f)\n var r, tu1, tu2, cu1, su1, cu2, s1, b1, f1\n var x, sx, cx, sy, cy,y, sa, c2a, cz, e, c, d\n var EPS= 0.00000000005\n var faz, baz, s\n var iter=1\n var MAXITER=100\n if ((glat1+glat2===0) && (Math.abs(glon1-glon2)==Math.PI)){\n alert(\"Course and distance between antipodal points is undefined\")\n glat1=glat1+0.00001 // allow algorithm to complete\n }\n if (glat1==glat2 && (glon1==glon2 || Math.abs(Math.abs(glon1-glon2)-2*Math.PI) < EPS)){\n alert(\"Points 1 and 2 are identical- course undefined\")\n out=new MakeArray(0)\n out.d=0\n out.crs12=0\n out.crs21=Math.PI\n return out\n }\n r = 1 - f\n tu1 = r * Math.tan (glat1)\n tu2 = r * Math.tan (glat2)\n cu1 = 1 / Math.sqrt (1 + tu1 * tu1)\n su1 = cu1 * tu1\n cu2 = 1 / Math.sqrt (1 + tu2 * tu2)\n s1 = cu1 * cu2\n b1 = s1 * tu2\n f1 = b1 * tu1\n x = glon2 - glon1\n d = x + 1 // force one pass\n while ((Math.abs(d - x) > EPS) && (iter < MAXITER))\n {\n iter=iter+1\n sx = Math.sin (x)\n // alert(\"sx=\"+sx)\n cx = Math.cos (x)\n tu1 = cu2 * sx\n tu2 = b1 - su1 * cu2 * cx\n sy = Math.sqrt(tu1 * tu1 + tu2 * tu2)\n cy = s1 * cx + f1\n y = atan2 (sy, cy)\n sa = s1 * sx / sy\n c2a = 1 - sa * sa\n cz = f1 + f1\n if (c2a > 0)\n cz = cy - cz / c2a\n e = cz * cz * 2 - 1\n c = ((-3 * c2a + 4) * f + 4) * c2a * f / 16\n d = x\n x = ((e * cy * c + cz) * sy * c + y) * sa\n x = (1 - c) * x * f + glon2 - glon1\n }\n x = Math.sqrt ((1 / (r * r) - 1) * c2a + 1)\n x +=1\n x = (x - 2) / x\n c = 1 - x\n c = (x * x / 4 + 1) / c\n d = (0.375 * x * x - 1) * x\n x = e * cy\n d = ((((sy*sy*4-3)*(1-e-e)*cz*d/6-x)*d/4+cz)*sy*d+y)*c*a*r\n if (Math.abs(iter-MAXITER)0) && (y>=0)){ out= Math.atan(y/x)}\n if ((x >0) && (y<0)) { out= Math.atan(y/x)+2*Math.PI}\n if ((x===0) && (y>0)) { out= Math.PI/2}\n if ((x===0) && (y<0)) { out= 3*Math.PI/2} \n if ((x===0) && (y===0)) {\n alert(\"atan2(0,0) undefined\")\n out= 0\n } \n return out\n}\n\nfunction showProps(obj,objName){\n var result=\"\"\n for (var i in obj){\n result +=objName + \".\" + i + \" = \" + obj[i] + \"\\n\"\n }\n alert(result)\n}\n\n\nif (msg.valid){\n msg.topic=\"sample_total_volume\"\n \n var object_lat_end = global.get(\"object_lat_end\")\n var object_lon_end = global.get(\"object_lon_end\")\n var sample_sampling_gear = global.get(\"sample_sampling_gear\")\n \n if (sample_sampling_gear.startsWith(\"net\") && sample_sampling_gear != \"net_decknet\") {\n if (!(isNaN(object_lat_end) && isNaN(object_lon_end))){\n var object_lat = global.get(\"object_lat\")\n var object_lon = global.get(\"object_lon\")\n var sample_gear_net_opening = global.get(\"sample_gear_net_opening\");\n\n distance_km = ComputeDistance(object_lat, object_lon, object_lat_end, object_lon_end)\n\n sample_total_volume = distance_km*(Math.PI*(sample_gear_net_opening/2)*(sample_gear_net_opening/2)) // liters\n sample_total_volume = Math.round(sample_total_volume + Number.EPSILON)\n msg.payload = sample_total_volume\n return msg\n }\n }\n}", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 930, - "y": 760, - "wires": [["4f6afc5a.81e454"]] - }, - { - "id": "e73fd87d.d24e4", - "type": "function", - "z": "b771c342.49603", - "name": "get acq_minimum_mesh", - "func": "msg.payload = msg.payload.acq_minimum_mesh;\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 330, - "y": 360, - "wires": [["1aad56b31b5647ce"]] - }, - { - "id": "489c8e06.cc7d6", - "type": "function", - "z": "b771c342.49603", - "name": "get acq_maximum_mesh", - "func": "msg.payload = msg.payload.acq_maximum_mesh;\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 330, - "y": 400, - "wires": [["10eb31a2d7a6590c"]] - }, - { - "id": "58de1340.3cc354", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "sample_dilution_factor", - "label": "Concentration Factor", - "tooltip": "0.5 if diluted by two; 2 if concentrated by a factor 2", - "group": "3e1ba03d.f01d8", - "order": 13, - "width": 10, - "height": 1, - "passthru": true, - "mode": "number", - "delay": "300", - "topic": "sample_dilution_factor", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 640, - "y": 480, - "wires": [["9f501f49.45645"]] - }, - { - "id": "4f6afc5a.81e454", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "sample_total_volume", - "label": "Filtered volume (in L)", - "tooltip": "Calculated or hand filled", - "group": "3e1ba03d.f01d8", - "order": 11, - "width": 0, - "height": 0, - "passthru": true, - "mode": "text", - "delay": "300", - "topic": "sample_total_volume", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 1220, - "y": 760, - "wires": [["e1f2f6eb.fe1dd"]] - }, - { - "id": "e1f2f6eb.fe1dd", - "type": "function", - "z": "b771c342.49603", - "name": "set global", - "func": "global.set(msg.topic,msg.payload);", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 1420, - "y": 760, - "wires": [[]] - }, - { - "id": "e9bc112c.eb75f8", - "type": "function", - "z": "b771c342.49603", - "name": "Calculate volume", - "func": "if (msg.topic == \"sample_total_flowmeter_start\"){\n context.set(\"sample_total_flowmeter_start\", msg.payload);\n}\nif (msg.topic == \"sample_total_flowmeter_end\"){\n context.set(\"sample_total_flowmeter_end\", msg.payload);\n}\n\nif (context.keys().length == 2){\n sample_total_volume = context.get(\"sample_total_flowmeter_end\") - context.get(\"sample_total_flowmeter_start\");\n msg.topic=\"sample_total_volume\"\n msg.payload=sample_total_volume\n return msg\n}\n", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 1610, - "y": 240, - "wires": [["4f6afc5a.81e454"]] - }, - { - "id": "cdd4181922eecf11", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "sample_speed_through_water", - "label": "Speed Through Water (kts)", - "tooltip": "in knots", - "group": "cf5d9f0e.d57e7", - "order": 2, - "width": 10, - "height": 1, - "passthru": true, - "mode": "number", - "delay": "300", - "topic": "sample_speed_through_water", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 610, - "y": 520, - "wires": [["9f501f49.45645"]] - }, - { - "id": "1aad56b31b5647ce", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "acq_minimum_mesh", - "label": "Minimal fraction size (μm)", - "tooltip": "Net mesh pore size or minimal filtration mesh pore size", - "group": "3e1ba03d.f01d8", - "order": 7, - "width": 5, - "height": 1, - "passthru": true, - "mode": "number", - "delay": "300", - "topic": "acq_minimum_mesh", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 640, - "y": 360, - "wires": [["9f501f49.45645"]] - }, - { - "id": "10eb31a2d7a6590c", - "type": "ui_text_input", - "z": "b771c342.49603", - "name": "acq_maximum_mesh", - "label": "Maximal fraction size (μm)", - "tooltip": "Maximal filtration mesh pore size", - "group": "3e1ba03d.f01d8", - "order": 8, - "width": 5, - "height": 1, - "passthru": true, - "mode": "number", - "delay": "300", - "topic": "acq_maximum_mesh", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 640, - "y": 400, - "wires": [["9f501f49.45645"]] - }, - { - "id": "3ac7b631f5d8ef90", - "type": "function", - "z": "b771c342.49603", - "name": "Culture check", - "func": "var activation_msg = {}\nvar date_msg = {}\nvar timestamp=new Date().toISOString();\n\nif (msg.payload === \"culture\"){\n activation_msg.payload = {\"group\":{\"show\":[\"Sample_Culture_Date_and_Time\"],\"hide\":[\"Sample_Sample_Location\", \"Sample_Net_Metadata\"]}};\n global.set(\"object_lat\", \"-90.0000\")\n global.set(\"object_lon\", \"0.0000\")\n date_msg.payload = {\"object_date\": timestamp.split('T')[0],\n \"object_time\": timestamp.split('T')[1].split('.')[0]}\n return [activation_msg, date_msg];\n}\nelse if (msg.payload === \"test\"){\n activation_msg.payload = {\"group\":{\"hide\":[\"Sample_Culture_Date_and_Time\", \"Sample_Sample_Location\", \"Sample_Net_Metadata\"]}};\n global.set(\"object_lat\", \"-90.0000\")\n global.set(\"object_lon\", \"0.0000\")\n global.set(\"object_date\", timestamp.split('T')[0])\n global.set(\"object_time\", timestamp.split('T')[1].split('.')[0])\n return [activation_msg, null];\n}\nelse{\n return [null, null]\n}\n\n", - "outputs": 2, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 1100, - "y": 320, - "wires": [["cbb123ab.fd3428"], ["05c6aff2afbd69cf"]], - "outputLabels": ["decknet activation", ""] - }, - { - "id": "05c6aff2afbd69cf", - "type": "ui_form", - "z": "b771c342.49603", - "name": "culture_timestamp", - "label": "Culture timestamp", - "group": "7bc0a4c416e4545c", - "order": 1, - "width": 0, - "height": 0, - "options": [ - { - "label": "Date (YYYY-MM-DD, UTC)", - "value": "object_date", - "type": "text", - "required": true, - "rows": null - }, - { - "label": "Time (HH:MM(:SS), UTC 24h)", - "value": "object_time", - "type": "text", - "required": true, - "rows": null - } - ], - "formValue": { - "object_date": "", - "object_time": "" - }, - "payload": "", - "submit": "Validate", - "cancel": "Reset", - "topic": "culture_timestamp", - "topicType": "str", - "splitLayout": false, - "className": "", - "x": 650, - "y": 700, - "wires": [["14658615.47c862", "f8044c35996322e6"]] - }, - { - "id": "a9fb1f4b83fc25a7", - "type": "change", - "z": "b771c342.49603", - "name": "Repopulate input fields", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 400, - "y": 580, - "wires": [["c33f1124.af6688"]] - }, - { - "id": "ad54b89540460d27", - "type": "change", - "z": "b771c342.49603", - "name": "Repopulate input fields", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 400, - "y": 620, - "wires": [["358908cd.416ab"]] - }, - { - "id": "c21bf0244e67e40a", - "type": "change", - "z": "b771c342.49603", - "name": "Repopulate input fields", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 400, - "y": 660, - "wires": [["56d40584.eff4e4"]] - }, - { - "id": "f8044c35996322e6", - "type": "change", - "z": "b771c342.49603", - "name": "Repopulate input fields", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 400, - "y": 700, - "wires": [["05c6aff2afbd69cf"]] - }, - { - "id": "8b48a02877b7b6d6", - "type": "inject", - "z": "b771c342.49603", - "name": "", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "", - "payload": "1", - "payloadType": "num", - "x": 270, - "y": 480, - "wires": [["58de1340.3cc354"]] - }, - { - "id": "6a84252a.d52a0c", - "type": "ui_template", - "z": "bccd1f23.87219", - "group": "833bc5bb.217ba8", - "name": "Stream Pi Camera", - "order": 1, - "width": 18, - "height": 14, - "format": "
\n \"If\n
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "className": "", - "x": 610, - "y": 40, - "wires": [[]] - }, - { - "id": "dc48dc42.98d18", - "type": "function", - "z": "bccd1f23.87219", - "name": "set global", - "func": "global.set(msg.topic,msg.payload);", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 880, - "y": 440, - "wires": [[]] - }, - { - "id": "811cd88c.daf528", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "down", - "group": "fbd92986.1028c8", - "order": 8, - "width": 4, - "height": 1, - "passthru": true, - "label": "", - "tooltip": "", - "color": "", - "bgcolor": "", - "icon": "fa-angle-double-down fa-3x", - "payload": "DOWN", - "payloadType": "str", - "topic": "actuator/focus", - "x": 550, - "y": 800, - "wires": [["65ad39d.b6d4d48"]] - }, - { - "id": "edda4df4.76de2", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "up", - "group": "fbd92986.1028c8", - "order": 1, - "width": 4, - "height": 1, - "passthru": false, - "label": "", - "tooltip": "", - "color": "", - "bgcolor": "", - "icon": "fa-angle-double-up fa-3x", - "payload": "UP", - "payloadType": "str", - "topic": "actuator/focus", - "x": 550, - "y": 760, - "wires": [["65ad39d.b6d4d48"]] - }, - { - "id": "68962547.34a67c", - "type": "ui_text_input", - "z": "bccd1f23.87219", - "name": "pump_manual_volume", - "label": "Volume to pass (ml)", - "tooltip": "Tiny values are accepted down to 0.001mL", - "group": "707d9797.c8e798", - "order": 3, - "width": 2, - "height": 1, - "passthru": true, - "mode": "text", - "delay": "300", - "topic": "pump_manual_volume", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 600, - "y": 420, - "wires": [["dc48dc42.98d18"]] - }, - { - "id": "6c792043.b6ff9", - "type": "ui_ui_control", - "z": "bccd1f23.87219", - "name": "", - "events": "change", - "x": 560, - "y": 1140, - "wires": [[]] - }, - { - "id": "902429eb.ceacb8", - "type": "ui_toast", - "z": "bccd1f23.87219", - "position": "dialog", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 1, - "ok": "OK", - "cancel": "", - "raw": false, - "topic": "", - "name": "", - "x": 570, - "y": 1220, - "wires": [[]] - }, - { - "id": "fe840e05.b46f3", - "type": "function", - "z": "bccd1f23.87219", - "name": "Check form", - "func": "var acq_fnumber_objective= global.get(\"acq_fnumber_objective\");\n\nif (acq_fnumber_objective === undefined || acq_fnumber_objective === \"\") {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Focal Length of the objective\";\n return [null, msg];\n}\n\nmsg.topic = \"Change Tab\";\nmsg.payload={\"tab\":\"Fluidic Acquisition\"};\nreturn [msg, null];", - "outputs": 2, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 330, - "y": 1180, - "wires": [["6c792043.b6ff9", "326a1d95.ca21aa"], ["902429eb.ceacb8"]], - "outputLabels": ["message", "error"] - }, - { - "id": "5846b1d4.7971b", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "Backward", - "group": "707d9797.c8e798", - "order": 2, - "width": 1, - "height": 1, - "passthru": false, - "label": "", - "tooltip": "", - "color": "", - "bgcolor": "", - "icon": "fa-rotate-left fa-2x", - "payload": "BACKWARD", - "payloadType": "str", - "topic": "actuator/pump", - "x": 560, - "y": 280, - "wires": [["3cb96380.e575ec"]] - }, - { - "id": "2cab680b.baf888", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "Forward", - "group": "707d9797.c8e798", - "order": 4, - "width": 1, - "height": 1, - "passthru": true, - "label": "", - "tooltip": "", - "color": "", - "bgcolor": "", - "icon": "fa-rotate-right fa-2x", - "payload": "FORWARD", - "payloadType": "str", - "topic": "actuator/pump", - "x": 560, - "y": 320, - "wires": [["3cb96380.e575ec"]] - }, - { - "id": "8038414a.34461", - "type": "function", - "z": "bccd1f23.87219", - "name": "Calculate optics", - "func": "var acq_fnumber_objective = String(global.get(\"acq_fnumber_objective\"));\nvar acq_camera = global.get(\"acq_camera\")\n\n// Those values needs to be recalculated, they are not good!\nif (acq_camera == \"HQ Camera\"){\n switch(acq_fnumber_objective) {\n case \"25\":\n acq_magnification= 0.6;\n process_pixel= 1.56;\n sug_min= 60;\n sug_max= 670;\n sug_flowrate= 3;\n break;\n case \"16\":\n acq_magnification= 1.6;\n process_pixel= 1.01;\n sug_min= 40;\n sug_max= 430;\n sug_flowrate= 2.4;\n break;\n case \"12\":\n acq_magnification= 1.20;\n process_pixel= 0.79;\n sug_min= 30;\n sug_max= 340;\n sug_flowrate= 1.25;\n break;\n case \"8\":\n acq_magnification= 1.78;\n process_pixel= 0.53;\n sug_min= 20;\n sug_max= 230;\n sug_flowrate= 0.42;\n break;\n case \"6\":\n acq_magnification= 2.36;\n process_pixel= 0.41;\n sug_min= 15;\n sug_max= 170;\n sug_flowrate= 0.32;\n break;\n }\n}\nelse if (acq_camera == \"Camera v2.1\"){\n switch(acq_fnumber_objective) {\n case \"25\":\n acq_magnification= 0.6;\n process_pixel= 1.86;\n sug_min= 60;\n sug_max= 670;\n sug_flowrate= 3;\n break;\n case \"16\":\n acq_magnification= 1.6;\n process_pixel= 0.7;\n sug_min= 40;\n sug_max= 430;\n sug_flowrate= 2.4;\n break;\n case \"12\":\n acq_magnification= 1.20;\n process_pixel= 0.94;\n sug_min= 30;\n sug_max= 340;\n sug_flowrate= 1.25;\n break;\n case \"8\":\n acq_magnification= 1.78;\n process_pixel= 0.63;\n sug_min= 20;\n sug_max= 230;\n sug_flowrate= 0.42;\n break;\n case \"6\":\n acq_magnification= 2.36;\n process_pixel= 0.48;\n sug_min= 15;\n sug_max= 170;\n sug_flowrate= 0.32;\n break;\n }\n}else {\n acq_magnification= \"ERROR\";\n process_pixel= \"ERROR\";\n sug_min= \"ERROR\";\n sug_max= \"ERROR\";\n sug_flowrate= \"ERROR\";\n}\n\nvar process_pixel_fixed = global.get(\"process_pixel_fixed\")\n\nif (process_pixel_fixed !== undefined && process_pixel_fixed !== \"\") {\n process_pixel = process_pixel_fixed\n}\n\nglobal.set(\"process_pixel\",process_pixel);\n\nglobal.set(\"acq_magnification\",acq_magnification);\n\n\nreturn [{payload: acq_fnumber_objective}, {payload: acq_magnification}, {payload: process_pixel}, {payload: sug_min}, {payload: sug_max}];", - "outputs": 5, - "timeout": "", - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 1080, - "y": 120, - "wires": [[], [], [], [], []], - "inputLabels": ["acq_fnumber_objective"], - "outputLabels": [ - "acq_magnification", - "process_pixel", - "sug_min", - "sug_max", - "" - ] - }, - { - "id": "f61aaed5.1e64", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "", - "group": "7a0b4877.a5d268", - "order": 1, - "width": 2, - "height": 1, - "passthru": false, - "label": "Previous", - "tooltip": "", - "color": "#097479", - "bgcolor": "white", - "icon": "keyboard_return", - "payload": "{\"tab\":\"Sample\"}", - "payloadType": "json", - "topic": "", - "x": 140, - "y": 1140, - "wires": [["6c792043.b6ff9"]] - }, - { - "id": "9ba6ec0a.22c96", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "", - "group": "7a0b4877.a5d268", - "order": 2, - "width": 2, - "height": 1, - "passthru": false, - "label": "Continue", - "tooltip": "", - "color": "#097479", - "bgcolor": "white", - "icon": "keyboard_tab", - "payload": "{\"tab\":\"Home\"}", - "payloadType": "json", - "topic": "", - "x": 140, - "y": 1180, - "wires": [["fe840e05.b46f3"]] - }, - { - "id": "3cb96380.e575ec", - "type": "function", - "z": "bccd1f23.87219", - "name": "pump", - "func": "var manual_volume= global.get(\"pump_manual_volume\");\nvar flowrate= global.get(\"pump_flowrate\");\n\nif (manual_volume === undefined || manual_volume === \"\" || manual_volume === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Volume to pass\";\n return [null, msg];\n}\nelse if (flowrate === undefined || flowrate === \"\" || flowrate === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Flowrate\";\n return [null, msg];\n}\nelse {\n msg.topic = \"actuator/pump\";\n // msg.payload is FORWARD or BACKWARD here\n msg.payload={\"action\":\"move\", \n \"direction\":msg.payload,\n \"volume\":manual_volume,\n \"flowrate\":flowrate};\n}\nreturn [msg, null];", - "outputs": 2, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 750, - "y": 300, - "wires": [["bdc8ce57.de1f08"], ["8bcce348.efc1a"]], - "inputLabels": ["direction"], - "outputLabels": ["message", "error"] - }, - { - "id": "8bcce348.efc1a", - "type": "ui_toast", - "z": "bccd1f23.87219", - "position": "dialog", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 1, - "ok": "OK", - "cancel": "", - "raw": false, - "topic": "", - "name": "", - "x": 1090, - "y": 300, - "wires": [[]] - }, - { - "id": "bdc8ce57.de1f08", - "type": "mqtt out", - "z": "bccd1f23.87219", - "name": "", - "topic": "", - "qos": "", - "retain": "", - "broker": "8dc3722c.06efa8", - "x": 1210, - "y": 260, - "wires": [] - }, - { - "id": "d71d224f.0585d8", - "type": "ui_toast", - "z": "bccd1f23.87219", - "position": "dialog", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 1, - "ok": "OK", - "cancel": "", - "raw": false, - "topic": "", - "name": "", - "x": 1090, - "y": 800, - "wires": [[]] - }, - { - "id": "65ad39d.b6d4d48", - "type": "function", - "z": "bccd1f23.87219", - "name": "focus", - "func": "var distance = global.get(\"focus_distance\");\nvar speed = global.get(\"focus_speed\");\n\nif (distance === undefined || distance === \"\" || distance === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Distance\";\n return [null, msg]\n}\nif (speed === undefined || speed === \"\" || speed === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Speed\";\n return [null, msg]\n}\n// msg.payload is UP or DOWN here\nmsg.payload={\"action\":\"move\", \n \"direction\":msg.payload,\n \"distance\":(distance/1000),\n \"speed\": (speed/1000)\n};\nreturn [msg, null];", - "outputs": 2, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 850, - "y": 780, - "wires": [["62030521.88317c"], ["d71d224f.0585d8"]], - "inputLabels": ["direction"], - "outputLabels": ["message", "error"] - }, - { - "id": "1962d999.4a97e6", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "stop focus", - "group": "fbd92986.1028c8", - "order": 9, - "width": 0, - "height": 0, - "passthru": true, - "label": " STOP FOCUS", - "tooltip": "", - "color": "", - "bgcolor": "#AD1625", - "icon": "fa-pause fa-2x", - "payload": "{\"action\":\"stop\"}", - "payloadType": "json", - "topic": "actuator/focus", - "x": 570, - "y": 560, - "wires": [["62030521.88317c"]] - }, - { - "id": "62030521.88317c", - "type": "mqtt out", - "z": "bccd1f23.87219", - "name": "", - "topic": "", - "qos": "", - "retain": "", - "broker": "8dc3722c.06efa8", - "x": 1210, - "y": 720, - "wires": [] - }, - { - "id": "3bd43039.bc5fb8", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "", - "group": "fbd92986.1028c8", - "order": 2, - "width": 4, - "height": 1, - "passthru": false, - "label": "UP 1mm", - "tooltip": "", - "color": "", - "bgcolor": "", - "icon": "fa-angle-up fa-3x", - "payload": "{\"action\":\"move\",\"direction\":\"UP\",\"distance\":1}", - "payloadType": "json", - "topic": "actuator/focus", - "topicType": "str", - "x": 560, - "y": 600, - "wires": [["62030521.88317c"]] - }, - { - "id": "c0663029.2d03b", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "", - "group": "fbd92986.1028c8", - "order": 7, - "width": 4, - "height": 1, - "passthru": false, - "label": "DOWN 1mm", - "tooltip": "", - "color": "", - "bgcolor": "", - "icon": "fa-angle-down fa-3x", - "payload": "{\"action\":\"move\",\"direction\":\"DOWN\",\"distance\":1}", - "payloadType": "json", - "topic": "actuator/focus", - "topicType": "str", - "x": 570, - "y": 720, - "wires": [["62030521.88317c"]] - }, - { - "id": "71f55a58.d7eaf4", - "type": "inject", - "z": "bccd1f23.87219", - "name": "Default: 500µm", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": "0.5", - "topic": "", - "payload": "500", - "payloadType": "num", - "x": 120, - "y": 460, - "wires": [["be33e564.029358"]] - }, - { - "id": "9a1d0e7c.2d5a1", - "type": "inject", - "z": "bccd1f23.87219", - "name": "Default: OFF", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "", - "payload": "off", - "payloadType": "str", - "x": 130, - "y": 120, - "wires": [["f0775525.cf806"]] - }, - { - "id": "f782a471.447748", - "type": "inject", - "z": "bccd1f23.87219", - "name": "Default: 2mL/min", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": "0.5", - "topic": "", - "payload": "2", - "payloadType": "num", - "x": 130, - "y": 380, - "wires": [["cb2d5174.cfe9f"]] - }, - { - "id": "73b8252a.5ca754", - "type": "inject", - "z": "bccd1f23.87219", - "name": "Default: 2mL", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": "0.5", - "topic": "", - "payload": "2", - "payloadType": "num", - "x": 110, - "y": 420, - "wires": [["68962547.34a67c"]] - }, - { - "id": "6451f991.aaac1", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "stop pump", - "group": "707d9797.c8e798", - "order": 5, - "width": 4, - "height": 1, - "passthru": true, - "label": " STOP PUMP", - "tooltip": "", - "color": "", - "bgcolor": "#AD1625", - "icon": "fa-pause fa-2x", - "payload": "{\"action\":\"stop\"}", - "payloadType": "json", - "topic": "actuator/pump", - "x": 570, - "y": 240, - "wires": [["bdc8ce57.de1f08"]] - }, - { - "id": "cfc783d7.d6ceb", - "type": "link in", - "z": "bccd1f23.87219", - "name": "Optics recalculation", - "links": ["559a8085.1d6b9", "5d5ad36d2c50dcc2"], - "x": 915, - "y": 120, - "wires": [["8038414a.34461"]] - }, - { - "id": "326a1d95.ca21aa", - "type": "subflow:1c24ad9c.bebec2", - "z": "bccd1f23.87219", - "name": "", - "x": 550, - "y": 1180, - "wires": [[]] - }, - { - "id": "2d371e59.b0e50a", - "type": "inject", - "z": "bccd1f23.87219", - "name": "Default: 1000µm/s", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": "0.5", - "topic": "", - "payload": "1000", - "payloadType": "num", - "x": 130, - "y": 500, - "wires": [["3a86de51.765b9a"]] - }, - { - "id": "167cda35.c9b6ae", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "", - "group": "fbd92986.1028c8", - "order": 3, - "width": 4, - "height": 1, - "passthru": false, - "label": "UP 100um", - "tooltip": "", - "color": "", - "bgcolor": "", - "icon": "fa-angle-up fa-3x", - "payload": "{\"action\":\"move\",\"direction\":\"UP\",\"distance\":0.1}", - "payloadType": "json", - "topic": "actuator/focus", - "topicType": "str", - "x": 570, - "y": 640, - "wires": [["62030521.88317c"]] - }, - { - "id": "72a7c597.9374fc", - "type": "ui_button", - "z": "bccd1f23.87219", - "name": "", - "group": "fbd92986.1028c8", - "order": 6, - "width": 4, - "height": 1, - "passthru": false, - "label": "DOWN 100um", - "tooltip": "", - "color": "", - "bgcolor": "", - "icon": "fa-angle-down fa-3x", - "payload": "{\"action\":\"move\",\"direction\":\"DOWN\",\"distance\":0.1}", - "payloadType": "json", - "topic": "actuator/focus", - "topicType": "str", - "x": 580, - "y": 680, - "wires": [["62030521.88317c"]] - }, - { - "id": "f0775525.cf806", - "type": "ui_multistate_switch", - "z": "bccd1f23.87219", - "name": "light_control", - "group": "4248342d.e55fac", - "order": 1, - "width": 6, - "height": 1, - "label": "Light ", - "stateField": "payload", - "enableField": "enable", - "passthroughField": "passthrough", - "inputMsgField": "inputmsg", - "rounded": true, - "useThemeColors": true, - "hideSelectedLabel": false, - "multilineLabel": false, - "passThrough": "never", - "inputMsg": "all", - "userInput": "enabled_show", - "options": [ - { - "label": "Off", - "value": "off", - "valueType": "str", - "color": "#009933" - }, - { - "label": "On", - "value": "on", - "valueType": "str", - "color": "#999999" - } - ], - "topic": "", - "x": 310, - "y": 120, - "wires": [["99ae4886.8d43c"]] - }, - { - "id": "99ae4886.8d43c", - "type": "function", - "z": "bccd1f23.87219", - "name": "Prepare message", - "func": "msg.topic = \"light\"\nmsg.payload = {\"action\":msg.payload}\n\nreturn msg;", - "outputs": 1, - "timeout": "", - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 490, - "y": 120, - "wires": [["d31fcead.7e2ef"]] - }, - { - "id": "d31fcead.7e2ef", - "type": "mqtt out", - "z": "bccd1f23.87219", - "name": "", - "topic": "", - "qos": "", - "retain": "", - "respTopic": "", - "contentType": "", - "userProps": "", - "correl": "", - "expiry": "", - "broker": "8dc3722c.06efa8", - "x": 650, - "y": 120, - "wires": [] - }, - { - "id": "8ea9dc9a.c7d87", - "type": "function", - "z": "bccd1f23.87219", - "name": "Encapsulate settings", - "func": "msg.payload = {\n \"action\":\"settings\", \n \"settings\":{[msg.topic]:msg.payload}\n}\n\nmsg.topic = \"imager/image\"\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 1120, - "y": 940, - "wires": [["845e06e1.0d812"]] - }, - { - "id": "5765a825.a595c8", - "type": "ui_slider", - "z": "bccd1f23.87219", - "name": "Shutter speed slider", - "label": "Shutter Speed", - "tooltip": "In microseconds, up to 1000µs, 125µs by default", - "group": "8c38a81e.9897a8", - "order": 4, - "width": 0, - "height": 0, - "passthru": true, - "outs": "end", - "topic": "shutter_speed", - "topicType": "str", - "min": "125", - "max": "1000", - "step": "1", - "className": "", - "x": 600, - "y": 880, - "wires": [["8ea9dc9a.c7d87"]] - }, - { - "id": "845e06e1.0d812", - "type": "mqtt out", - "z": "bccd1f23.87219", - "name": "", - "topic": "", - "qos": "", - "retain": "", - "broker": "8dc3722c.06efa8", - "x": 1390, - "y": 980, - "wires": [] - }, - { - "id": "2350e507.d4e302", - "type": "inject", - "z": "bccd1f23.87219", - "name": "Default: 125µs", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": "1", - "topic": "", - "payload": "125", - "payloadType": "num", - "x": 120, - "y": 880, - "wires": [["5765a825.a595c8"]] - }, - { - "id": "5e147425.7666ec", - "type": "function", - "z": "bccd1f23.87219", - "name": "Encapsulate wb gain settings", - "func": "msg.payload = {\n \"action\":\"settings\", \n \"settings\":{\"white_balance_gain\":{\n [msg.topic]:Math.round(msg.payload*100)\n }\n }\n}\nmsg.topic = \"imager/image\"\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 1100, - "y": 1060, - "wires": [["845e06e1.0d812"]] - }, - { - "id": "82722a3c.846b3", - "type": "inject", - "z": "bccd1f23.87219", - "name": "Default: OFF", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": "1", - "topic": "", - "payload": "false", - "payloadType": "bool", - "x": 110, - "y": 920, - "wires": [["60e44330.50bdec"]] - }, - { - "id": "60e44330.50bdec", - "type": "ui_switch", - "z": "bccd1f23.87219", - "name": "AWB", - "label": "Auto White Balance", - "tooltip": "", - "group": "8c38a81e.9897a8", - "order": 5, - "width": 2, - "height": 2, - "passthru": true, - "decouple": "false", - "topic": "white_balance", - "topicType": "str", - "style": "", - "onvalue": "auto", - "onvalueType": "str", - "onicon": "", - "oncolor": "", - "offvalue": "off", - "offvalueType": "str", - "officon": "", - "offcolor": "", - "animate": true, - "className": "", - "x": 550, - "y": 920, - "wires": [["8ea9dc9a.c7d87"]] - }, - { - "id": "6be64480.7e7e24", - "type": "change", - "z": "bccd1f23.87219", - "name": "Get red_gain", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.red_gain", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 370, - "y": 1040, - "wires": [["d5415af6.e06cc"]] - }, - { - "id": "6d49d161.13628", - "type": "change", - "z": "bccd1f23.87219", - "name": "Get blue_gain", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.blue_gain", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 380, - "y": 1080, - "wires": [["dba68c1f.e3144"]] - }, - { - "id": "56835fa1.2fe538", - "type": "subflow:4ed26b8b.253504", - "z": "bccd1f23.87219", - "name": "", - "env": [], - "x": 1160, - "y": 1020, - "wires": [] - }, - { - "id": "8ef294ba.12213", - "type": "change", - "z": "bccd1f23.87219", - "name": "Get analog_gain", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "1", - "tot": "num" - }, - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.analog_gain", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 380, - "y": 960, - "wires": [["a6c7eec4.f7a918"]] - }, - { - "id": "8e336e58.14722", - "type": "change", - "z": "bccd1f23.87219", - "name": "Get digital_gain", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "1", - "tot": "num" - }, - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.digital_gain", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 380, - "y": 1000, - "wires": [["66b37eef.f3f9e"]] - }, - { - "id": "a6c7eec4.f7a918", - "type": "ui_text_input", - "z": "bccd1f23.87219", - "d": true, - "name": "Analog gain field", - "label": "Analog Gain", - "tooltip": "From 1.0 to 12.0", - "group": "8c38a81e.9897a8", - "order": 2, - "width": 0, - "height": 0, - "passthru": true, - "mode": "number", - "delay": 300, - "topic": "analog", - "topicType": "str", - "x": 580, - "y": 960, - "wires": [["44e02933.a66688", "d361a2c4.0990f8"]] - }, - { - "id": "66b37eef.f3f9e", - "type": "ui_text_input", - "z": "bccd1f23.87219", - "d": true, - "name": "Digital gain field", - "label": "Digital Gain", - "tooltip": "From 1.0 to 64.0. Overexpose starting at 4.0", - "group": "8c38a81e.9897a8", - "order": 3, - "width": 0, - "height": 0, - "passthru": true, - "mode": "number", - "delay": 300, - "topic": "digital", - "topicType": "str", - "x": 580, - "y": 1000, - "wires": [["44e02933.a66688", "d361a2c4.0990f8"]] - }, - { - "id": "44e02933.a66688", - "type": "function", - "z": "bccd1f23.87219", - "name": "Encapsulate image gain settings", - "func": "msg.payload = {\n \"action\":\"settings\", \n \"settings\":{\"image_gain\":{\n [msg.topic]:Math.round(msg.payload*100)\n }\n }\n}\nmsg.topic = \"imager/image\"\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 1090, - "y": 980, - "wires": [["845e06e1.0d812"]] - }, - { - "id": "d361a2c4.0990f8", - "type": "change", - "z": "bccd1f23.87219", - "name": "topic *_gain", - "rules": [ - { - "t": "set", - "p": "topic", - "pt": "msg", - "to": "topic&'_gain'", - "tot": "jsonata" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 970, - "y": 1020, - "wires": [["56835fa1.2fe538"]] - }, - { - "id": "d8d006bf.2947f", - "type": "inject", - "z": "bccd1f23.87219", - "name": "Default: ISO 150", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": "1", - "topic": "", - "payload": "150", - "payloadType": "num", - "x": 130, - "y": 840, - "wires": [["f62c3241bd753f24"]] - }, - { - "id": "eb9966de.cf13c8", - "type": "change", - "z": "bccd1f23.87219", - "name": "", - "rules": [ - { - "t": "set", - "p": "topic", - "pt": "msg", - "to": "iso", - "tot": "str" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 740, - "y": 840, - "wires": [["8ea9dc9a.c7d87"]] - }, - { - "id": "be33e564.029358", - "type": "ui_text_input", - "z": "bccd1f23.87219", - "name": "focus_distance", - "label": "Focus Distance (in µm)", - "tooltip": "in µm, 25µm resolution", - "group": "fbd92986.1028c8", - "order": 4, - "width": 0, - "height": 0, - "passthru": true, - "mode": "number", - "delay": 300, - "topic": "focus_distance", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 580, - "y": 460, - "wires": [["dc48dc42.98d18"]] - }, - { - "id": "3a86de51.765b9a", - "type": "ui_text_input", - "z": "bccd1f23.87219", - "name": "focus_speed", - "label": "Focus Speed (in µm/sec)", - "tooltip": "in µm/sec", - "group": "fbd92986.1028c8", - "order": 5, - "width": 0, - "height": 0, - "passthru": true, - "mode": "number", - "delay": 300, - "topic": "focus_speed", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 570, - "y": 500, - "wires": [["dc48dc42.98d18"]] - }, - { - "id": "cb2d5174.cfe9f", - "type": "ui_text_input", - "z": "bccd1f23.87219", - "name": "pump_flowrate", - "label": "Flowrate (ml/min)*", - "tooltip": "", - "group": "707d9797.c8e798", - "order": 1, - "width": 0, - "height": 0, - "passthru": true, - "mode": "text", - "delay": 300, - "topic": "pump_flowrate", - "topicType": "str", - "x": 580, - "y": 380, - "wires": [["dc48dc42.98d18"]] - }, - { - "id": "dba68c1f.e3144", - "type": "ui_text_input", - "z": "bccd1f23.87219", - "name": "WB Blue input", - "label": "WB: Blue", - "tooltip": "From 0.0 to 64.0", - "group": "8c38a81e.9897a8", - "order": 7, - "width": 4, - "height": 1, - "passthru": true, - "mode": "number", - "delay": "0", - "topic": "blue", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 580, - "y": 1080, - "wires": [["3ece53716a02e09e"]] - }, - { - "id": "33ef60a6a80aa3a7", - "type": "subflow:b7861ce703215a01", - "z": "bccd1f23.87219", - "name": "", - "x": 160, - "y": 1020, - "wires": [ - ["8ef294ba.12213", "8e336e58.14722", "6be64480.7e7e24", "6d49d161.13628"] - ] - }, - { - "id": "a3d034643b56796f", - "type": "inject", - "z": "bccd1f23.87219", - "name": "Once", - "props": [], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "", - "x": 70, - "y": 1080, - "wires": [["33ef60a6a80aa3a7"]] - }, - { - "id": "5984b086eddc9311", - "type": "link in", - "z": "bccd1f23.87219", - "name": "Load hardware config", - "links": ["3973b999ee7b3b1d", "5d3df1564b9af89c"], - "x": 25, - "y": 1000, - "wires": [["33ef60a6a80aa3a7"]] - }, - { - "id": "d5415af6.e06cc", - "type": "ui_text_input", - "z": "bccd1f23.87219", - "name": "WB Red input", - "label": "WB: Red", - "tooltip": "From 0.0 to 32.0", - "group": "8c38a81e.9897a8", - "order": 6, - "width": 4, - "height": 1, - "passthru": true, - "mode": "number", - "delay": "0", - "topic": "red", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 580, - "y": 1040, - "wires": [["01c2b633558b0b02"]] - }, - { - "id": "01c2b633558b0b02", - "type": "switch", - "z": "bccd1f23.87219", - "name": "Validate", - "property": "payload", - "propertyType": "msg", - "rules": [ - { - "t": "btwn", - "v": "0.0", - "vt": "num", - "v2": "32.0", - "v2t": "num" - }, - { - "t": "else" - } - ], - "checkall": "false", - "repair": false, - "outputs": 2, - "x": 740, - "y": 1040, - "wires": [ - ["d361a2c4.0990f8", "5e147425.7666ec"], - ["cbfaf049d92be90e", "5d3df1564b9af89c"] - ] - }, - { - "id": "3ece53716a02e09e", - "type": "switch", - "z": "bccd1f23.87219", - "name": "Validate", - "property": "payload", - "propertyType": "msg", - "rules": [ - { - "t": "btwn", - "v": "0.0", - "vt": "num", - "v2": "32.0", - "v2t": "num" - }, - { - "t": "else" - } - ], - "checkall": "false", - "repair": false, - "outputs": 2, - "x": 740, - "y": 1080, - "wires": [ - ["d361a2c4.0990f8", "5e147425.7666ec"], - ["cbfaf049d92be90e", "5d3df1564b9af89c"] - ] - }, - { - "id": "cbfaf049d92be90e", - "type": "ui_toast", - "z": "bccd1f23.87219", - "position": "top right", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 0, - "ok": "OK", - "cancel": "", - "raw": false, - "className": "", - "topic": "Invalid white balance value", - "name": "", - "x": 990, - "y": 1100, - "wires": [] - }, - { - "id": "5d3df1564b9af89c", - "type": "link out", - "z": "bccd1f23.87219", - "name": "Reload hardware config", - "mode": "link", - "links": ["5984b086eddc9311"], - "x": 915, - "y": 1140, - "wires": [] - }, - { - "id": "f62c3241bd753f24", - "type": "ui_slider", - "z": "bccd1f23.87219", - "name": "ISO selector", - "label": "ISO", - "tooltip": "", - "group": "8c38a81e.9897a8", - "order": 1, - "width": 0, - "height": 0, - "passthru": true, - "outs": "end", - "topic": "topic", - "topicType": "msg", - "min": "50", - "max": "650", - "step": "50", - "className": "", - "x": 570, - "y": 840, - "wires": [["eb9966de.cf13c8"]] - }, - { - "id": "6b34c456.83178c", - "type": "ui_text_input", - "z": "baa1e3d9.cb29d", - "name": "acq_id", - "label": "Acquisition unique ID*", - "tooltip": "", - "group": "4322c187.e73e5", - "order": 1, - "width": 5, - "height": 1, - "passthru": true, - "mode": "text", - "delay": 300, - "topic": "acq_id", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 690, - "y": 180, - "wires": [["fb887036.12429"]] - }, - { - "id": "cc0ca68b.4263a8", - "type": "ui_dropdown", - "z": "baa1e3d9.cb29d", - "name": "acq_celltype", - "label": "Flowcell thickness*", - "tooltip": "", - "place": "Select option", - "group": "4322c187.e73e5", - "order": 6, - "width": 5, - "height": 1, - "passthru": true, - "multiple": false, - "options": [ - { - "label": "200 μm µ-Slide I Luer", - "value": 200, - "type": "num" - }, - { - "label": "300 µm capillary", - "value": 300, - "type": "num" - }, - { - "label": "400 μm µ-Slide I Luer", - "value": 400, - "type": "num" - }, - { - "label": "600 μm µ-Slide I Luer", - "value": 600, - "type": "num" - }, - { - "label": "800 μm µ-Slide I Luer", - "value": 800, - "type": "num" - } - ], - "payload": "", - "topic": "acq_celltype", - "topicType": "str", - "className": "", - "x": 670, - "y": 100, - "wires": [["fb887036.12429", "99b11fe4.2795d"]] - }, - { - "id": "fb887036.12429", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "set global", - "func": "global.set(msg.topic, msg.payload);\nreturn msg", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 920, - "y": 180, - "wires": [["52ea7d01.711034"]] - }, - { - "id": "bb2bb7ce.1d1458", - "type": "ui_template", - "z": "baa1e3d9.cb29d", - "group": "858a0e3c.987fe", - "name": "Stream Pi Camera", - "order": 1, - "width": 10, - "height": 8, - "format": "
\n \"If\n
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "className": "", - "x": 550, - "y": 40, - "wires": [[]] - }, - { - "id": "d0c5b57d.590818", - "type": "ui_ui_control", - "z": "baa1e3d9.cb29d", - "name": "", - "events": "change", - "x": 1280, - "y": 660, - "wires": [[]] - }, - { - "id": "c72f8fae.23bd4", - "type": "ui_button", - "z": "baa1e3d9.cb29d", - "name": "", - "group": "b7919ae2.c01788", - "order": 1, - "width": 5, - "height": 1, - "passthru": false, - "label": "Previous", - "tooltip": "", - "color": "#097479", - "bgcolor": "white", - "icon": "keyboard_return", - "payload": "{\"tab\":\"Optic Configuration\"}", - "payloadType": "json", - "topic": "", - "x": 1140, - "y": 660, - "wires": [["d0c5b57d.590818"]] - }, - { - "id": "29be525e.0c87fe", - "type": "ui_template", - "z": "baa1e3d9.cb29d", - "group": "b5d61bc7.54fe48", - "name": "Show Metadata", - "order": 9, - "width": 0, - "height": 0, - "format": "
\n \n \n \n \n \n \n \n \n \n
\n

Sample

\n

id:

\n

project:\n

\n

ship:

\n

operator:\n

\n

sampling gear:\n

\n

concentrated volume:\n

\n

gear net opening:\n

\n

total volume filtered:\n

\n
\n

Acquisition

\n

id:

\n

instrument:\n

\n

instrument id:\n

\n

camera:

\n

celltype: \n

\n

minimum mesh:\n

\n

maximum mesh:\n

\n

min esd: \n

\n

max esd: \n

\n

volume:

\n

magnification:\n

\n

fnumber objective:\n

\n

software: \n

\n
\n

Object

\n

latitude: \n

\n

longitude: \n

\n

latitude end:\n

\n

longitude end:\n

\n

date:

\n

time:

\n

date end:\n

\n

time end:\n

\n

depth min:\n

\n

depth max:\n

\n
\n

Process

\n

pixel: \n

\n

id:

\n
\n
", - "storeOutMessages": false, - "fwdInMessages": false, - "resendOnRefresh": false, - "templateScope": "local", - "className": "", - "x": 1160, - "y": 380, - "wires": [[]] - }, - { - "id": "c9f510c0.7d1328", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "Image control", - "func": "// Reset the number of images taken\nflow.set('img_counter', 0);\n\nvar acq_celltype = global.get(\"acq_celltype\");\nvar acq_minimum_mesh = global.get(\"acq_minimum_mesh\");\nvar acq_maximum_mesh = global.get(\"acq_maximum_mesh\");\nvar imaging_pump_volume = global.get(\"imaging_pump_volume\");\nvar acq_id = global.get(\"acq_id\");\nvar nb_frame = global.get(\"nb_frame\");\nvar pump_direction = global.get(\"pump_direction\");\nvar sleep_before = global.get(\"sleep_before\");\nvar object_date = global.get(\"object_date\");\n\nif (acq_celltype === undefined || acq_celltype === \"\") {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Type of the flowcell\";\n return [null, msg];\n} else if (acq_minimum_mesh === undefined || acq_minimum_mesh === \"\") {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Lower fraction size\";\n return [null, msg];\n} else if (acq_maximum_mesh === undefined || acq_maximum_mesh === \"\") {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Upper fraction size\";\n return [null, msg];\n} else if (imaging_pump_volume === undefined || imaging_pump_volume === \"\" || imaging_pump_volume === null) {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Volume inbetween images\";\n return [null, msg];\n} else if (acq_id === undefined || acq_id === \"\") {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Acquisition ID\";\n return [null, msg];\n} else if (nb_frame === undefined || nb_frame === \"\" || nb_frame === null) {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Number of image to save\";\n return [null, msg];\n} else if (pump_direction === undefined || pump_direction === \"\" || pump_direction === null) {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Pump direction\";\n return [null, msg];\n} else if (sleep_before === undefined || sleep_before === \"\" || sleep_before === null) {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Delay before image\";\n return [null, msg];\n}else if (object_date === undefined || object_date === \"\" || object_date === null) {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Object date\";\n return [null, msg];\n}\n\nmsg.payload = {\n \"action\": \"image\",\n \"sleep\": sleep_before,\n \"pump_direction\": pump_direction,\n \"volume\": imaging_pump_volume,\n \"nb_frame\": nb_frame,\n}\nmsg.send = true\n\nreturn [msg, null];", - "outputs": 2, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 640, - "y": 440, - "wires": [ - ["52ea7d01.711034", "40c12463.a1f84c", "a4abb1ae.2ae418"], - ["20e0a8c8.edbeb"] - ] - }, - { - "id": "20e0a8c8.edbeb", - "type": "ui_toast", - "z": "baa1e3d9.cb29d", - "position": "dialog", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 1, - "ok": "OK", - "cancel": "", - "raw": false, - "topic": "", - "name": "", - "x": 890, - "y": 520, - "wires": [[]] - }, - { - "id": "c3e50240.82aa58", - "type": "mqtt out", - "z": "baa1e3d9.cb29d", - "name": "", - "topic": "", - "qos": "", - "retain": "", - "broker": "8dc3722c.06efa8", - "x": 1130, - "y": 420, - "wires": [] - }, - { - "id": "3a4450b1.4459a8", - "type": "ui_button", - "z": "baa1e3d9.cb29d", - "name": "Stop Acquisition", - "group": "4322c187.e73e5", - "order": 11, - "width": 5, - "height": 1, - "passthru": true, - "label": "STOP ACQUISITION", - "tooltip": "", - "color": "", - "bgcolor": "#AD1625", - "icon": "cancel", - "payload": "{\"action\":\"stop\"}", - "payloadType": "json", - "topic": "imager/image", - "x": 420, - "y": 480, - "wires": [["d74210ef.edc15"]] - }, - { - "id": "d74210ef.edc15", - "type": "mqtt out", - "z": "baa1e3d9.cb29d", - "name": "", - "topic": "", - "qos": "", - "retain": "", - "broker": "8dc3722c.06efa8", - "x": 610, - "y": 480, - "wires": [] - }, - { - "id": "bb62da8a.ebc328", - "type": "ui_switch", - "z": "baa1e3d9.cb29d", - "name": "Pump direction", - "label": "Pump direction", - "tooltip": "BACKWARD / FORWARD", - "group": "4322c187.e73e5", - "order": 9, - "width": 5, - "height": 1, - "passthru": true, - "decouple": "false", - "topic": "pump_direction", - "style": "", - "onvalue": "FORWARD", - "onvalueType": "str", - "onicon": "", - "oncolor": "", - "offvalue": "BACKWARD", - "offvalueType": "str", - "officon": "", - "offcolor": "", - "x": 420, - "y": 520, - "wires": [["6b2239f3.41fa3"]] - }, - { - "id": "52ea7d01.711034", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "Encapsulate config", - "func": "msg.payload = {\n\t\"action\": \"update_config\",\n\t\"config\": {\n \t\"description\": {\n \t\t\"sample_project\": \"Project's name\",\n \t\t\"sample_id\": \"Sample ID\",\n \t\t\"sample_uuid\": \"Sample UUID (Autogenerated)\",\n \t\t\"sample_ship\": \"Ship's name\",\n \t\t\"sample_operator\": \"Operator's name\",\n \t\t\"sample_sampling_gear\": \"Sampling gear used\",\n \t\t\"sample_concentrated_sample_volume\": \"Volume of concentrated sample, in mL\",\n \t\t\"sample_total_volume\": \"Total volume filtered by the net used, in L\",\n \t\t\"sample_dilution_factor\": \"Dilution factor of the sample, 0.5 if diluted by 2, 2 if concentrated by 2\",\n \t\t\"sample_speed_through_water\": \"Speed of the boat through water when sampling, in kts\",\n \t\t\"acq_id\": \"Acquisition ID\",\n \t\t\"acq_uuid\": \"Acquisition UUID (Autogenerated)\",\n \t\t\"acq_instrument\": \"Instrument type\",\n \t\t\"acq_instrument_id\": \"Instrument ID\",\n \t\t\"acq_celltype\": \"Flow cell dimension thickness, in µm\",\n \t\t\"acq_minimum_mesh\": \"Minimum filtration mesh size, in µm\",\n \t\t\"acq_maximum_mesh\": \"Maximum filtration mesh size, in µm\",\n \t\t\"acq_min_esd\": \"\",\n \t\t\"acq_max_esd\": \"\",\n \t\t\"acq_volume\": \"Pumped volume, in mL\",\n\t\t \"acq_imaged_volume\": \"Total imaged volume, in mL\",\n \t\t\"acq_magnification\": \"Optical magnification\",\n \t\t\"acq_fnumber_objective\": \"Focal length of the objective, in mm\",\n \t\t\"acq_camera_name\": \"Name of the camera used\",\n \t\t\"acq_nb_frame\": \"Number of picture taken\",\n \"acq_local_datetime\": \"Instrument local datetime\",\n \"acq_camera_resolution\": \"Resolution of the images\",\n \"acq_camera_iso\": \"ISO Number of the images\",\n \"acq_camera_shutter_speed\": \"Shutter speed of the images, in µs\",\n \"acq_software\": \"Software version number\",\n \t\t\"object_date\": \"Sample collection date (or beginning if using a net)\",\n \t\t\"object_time\": \"Sample collection time (or beginning if using a net)\",\n \t\t\"object_lat\": \"Sample collection latitude (or beginning if using a net)\",\n \t\t\"object_lon\": \"Sample collection longitude (or beginning if using a net)\",\n \t\t\"object_depth_min\": \"Sample collection minimal depth, in m\",\n \t\t\"object_depth_max\": \"Sample collection maximum depth, in m\",\n \t\t\"process_pixel\": \"Pixel imaging resolution, in µm/pixel\",\n \t\t\"process_datetime\": \"Segmentation timestamp\",\n \t\t\"process_id\": \"Segmentation ID\",\n \t\t\"process_uuid\": \"Segmentation UUID (Autogenerated)\",\n \t\t\"process_source\": \"Code source link of the executed code\",\n \t\t\"process_commit\": \"Version reference of the executed code\",\n \t\t\"sample_gear_net_opening\": \"Sample mouth opening dimension, in mm\",\n \t\t\"object_date_end\": \"Sample end collection date when using a net\",\n \t\t\"object_time_end\": \"Sample end collection time when using a net\",\n \t\t\"object_lat_end\": \"Sample end collection latitude when using a net\",\n \t\t\"object_lon_end\": \"Sample end collection longitude when using a net\",\n \t},\n\t\t\"sample_project\": global.get(\"sample_project\"),\n\t\t\"sample_id\": global.get(\"sample_project\") + \"_\" + global.get(\"sample_id\"),\n\t\t\"sample_ship\": global.get(\"sample_ship\"),\n\t\t\"sample_operator\": global.get(\"sample_operator\"),\n\t\t\"sample_sampling_gear\": global.get(\"sample_sampling_gear\"),\n\t\t\"sample_concentrated_sample_volume\": global.get(\"sample_concentrated_sample_volume\"),\n\t\t\"sample_total_volume\": global.get(\"sample_total_volume\"),\n\t\t\"sample_dilution_factor\": global.get(\"sample_dilution_factor\"),\n\t\t\"sample_speed_through_water\": global.get(\"sample_speed_through_water\"),\n\n\t\t\"acq_id\": global.get(\"sample_project\") + \"_\" + global.get(\"sample_id\")+ \"_\" + global.get(\"acq_id\"),\n\t\t\"acq_instrument\": global.get(\"acq_instrument\"),\n\t\t\"acq_instrument_id\": global.get(\"acq_instrument_id\"),\n\t\t\"acq_celltype\": global.get(\"acq_celltype\"),\n\t\t\"acq_minimum_mesh\": global.get(\"acq_minimum_mesh\"),\n\t\t\"acq_maximum_mesh\": global.get(\"acq_maximum_mesh\"),\n\t\t\"acq_min_esd\": global.get(\"acq_min_esd\"),\n\t\t\"acq_max_esd\": global.get(\"acq_max_esd\"),\n\t\t\"acq_volume\": global.get(\"acq_volume\"),\n\t\t\"acq_imaged_volume\": global.get(\"acq_imaged_volume\"),\n\t\t\"acq_magnification\": global.get(\"acq_magnification\"),\n\t\t\"acq_fnumber_objective\": global.get(\"acq_fnumber_objective\"),\n\t\t\"acq_camera\": global.get(\"acq_camera\"),\n\t\t\"acq_nb_frame\": global.get(\"nb_frame\"),\n\t\t\"acq_software\": global.get(\"acq_software\"),\n\n\t\t\"object_date\": global.get(\"object_date\"),\n\t\t\"object_time\": global.get(\"object_time\"),\n\t\t\"object_lat\": global.get(\"object_lat\"),\n\t\t\"object_lon\": global.get(\"object_lon\"),\n\t\t\"object_depth_min\": global.get(\"object_depth_min\"),\n\t\t\"object_depth_max\": global.get(\"object_depth_max\"),\n\n\t\t\"process_pixel\": global.get(\"process_pixel\"),\n\t\t\"process_source\": global.get(\"process_source\"),\n\t\t\"process_commit\": global.get(\"process_commit\")\n\t}\n};\n\nif (msg.payload.config.sample_sampling_gear.startsWith(\"net\")) {\n\tmsg.payload.config[\"sample_gear_net_opening\"] = global.get(\"sample_gear_net_opening\")\n\tmsg.payload.config[\"object_date_end\"] = global.get(\"object_date_end\")\n\tmsg.payload.config[\"object_time_end\"] = global.get(\"object_time_end\")\n\tmsg.payload.config[\"object_lat_end\"] = global.get(\"object_lat_end\")\n\tmsg.payload.config[\"object_lon_end\"] = global.get(\"object_lon_end\")\n}\n\nif ( msg.send == true){\n\treturn [msg, msg]\n}\nelse{\n\treturn [msg, null]\n}", - "outputs": 2, - "timeout": "", - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 870, - "y": 400, - "wires": [["29be525e.0c87fe"], ["c3e50240.82aa58"]] - }, - { - "id": "40c12463.a1f84c", - "type": "delay", - "z": "baa1e3d9.cb29d", - "name": "", - "pauseType": "delay", - "timeout": "1", - "timeoutUnits": "seconds", - "rate": "1", - "nbRateUnits": "1", - "rateUnits": "second", - "randomFirst": "1", - "randomLast": "5", - "randomUnits": "seconds", - "drop": false, - "outputs": 1, - "x": 900, - "y": 440, - "wires": [["c3e50240.82aa58"]] - }, - { - "id": "4d1b02cb.83b51c", - "type": "ui_button", - "z": "baa1e3d9.cb29d", - "name": "", - "group": "4322c187.e73e5", - "order": 10, - "width": 5, - "height": 1, - "passthru": false, - "label": "Update config", - "tooltip": "", - "color": "", - "bgcolor": "", - "className": "", - "icon": "save", - "payload": "", - "payloadType": "str", - "topic": "imager/image", - "topicType": "str", - "x": 420, - "y": 400, - "wires": [["52ea7d01.711034"]] - }, - { - "id": "5921d0d0.a3d568", - "type": "subflow:1c24ad9c.bebec2", - "z": "baa1e3d9.cb29d", - "name": "", - "env": [], - "x": 110, - "y": 180, - "wires": [ - [ - "f3658d30.b8448", - "de2c90cf.b73b08", - "4be09c97f86897d9", - "f573206abefa9518", - "f948151ab4031df4" - ] - ] - }, - { - "id": "f3658d30.b8448", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "get acq_id", - "func": "msg.payload = msg.payload.acq_id;\nreturn msg;", - "outputs": 1, - "timeout": "", - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 330, - "y": 180, - "wires": [["6b34c456.83178c"]] - }, - { - "id": "de2c90cf.b73b08", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "get acq_celltype", - "func": "msg.topic = 'acq_celltype';\nmsg.payload = msg.payload.acq_celltype;\nreturn msg;", - "outputs": 1, - "timeout": "", - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 340, - "y": 100, - "wires": [["cc0ca68b.4263a8"]] - }, - { - "id": "b402f719.55bc98", - "type": "inject", - "z": "baa1e3d9.cb29d", - "name": "Default: FORWARD", - "props": [ - { - "p": "payload" - }, - { - "p": "topic", - "vt": "str" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "pump_direction", - "payload": "FORWARD", - "payloadType": "str", - "x": 180, - "y": 520, - "wires": [["bb62da8a.ebc328"]] - }, - { - "id": "6b2239f3.41fa3", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "set global", - "func": "global.set(msg.topic, msg.payload);", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 620, - "y": 520, - "wires": [[]] - }, - { - "id": "51b4d0df.d70a88", - "type": "ui_text_input", - "z": "baa1e3d9.cb29d", - "name": "nb_frame", - "label": "Number of images to acquire", - "tooltip": "", - "group": "4322c187.e73e5", - "order": 2, - "width": 5, - "height": 1, - "passthru": true, - "mode": "number", - "delay": 300, - "topic": "nb_frame", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 680, - "y": 220, - "wires": [["fb887036.12429", "67091ac0.8f9f6c", "99b11fe4.2795d"]] - }, - { - "id": "999065ca.27edb8", - "type": "switch", - "z": "baa1e3d9.cb29d", - "name": "topic filter", - "property": "topic", - "propertyType": "msg", - "rules": [ - { - "t": "eq", - "v": "status/pump", - "vt": "str" - }, - { - "t": "eq", - "v": "status/focus", - "vt": "str" - }, - { - "t": "eq", - "v": "status/light", - "vt": "str" - }, - { - "t": "eq", - "v": "status/imager", - "vt": "str" - } - ], - "checkall": "true", - "repair": false, - "outputs": 4, - "x": 320, - "y": 800, - "wires": [ - ["a46a1e7f.88a92", "6742014e.1bb238"], - ["c516d9ea.f7f6e", "6742014e.1bb238"], - ["6742014e.1bb238"], - ["307c851e.fb0f7a", "2b9d6988.d84836"] - ] - }, - { - "id": "2b009bd7.c07004", - "type": "ui_text", - "z": "baa1e3d9.cb29d", - "group": "70de8209.68416c", - "order": 3, - "width": 10, - "height": 2, - "name": "imager", - "label": "Imager status:", - "format": "{{msg.payload.status}}", - "layout": "col-center", - "x": 770, - "y": 740, - "wires": [] - }, - { - "id": "c516d9ea.f7f6e", - "type": "ui_text", - "z": "baa1e3d9.cb29d", - "group": "70de8209.68416c", - "order": 1, - "width": 5, - "height": 1, - "name": "focus", - "label": "Focus status:", - "format": "{{msg.payload.status}}", - "layout": "col-center", - "x": 770, - "y": 700, - "wires": [] - }, - { - "id": "a46a1e7f.88a92", - "type": "ui_text", - "z": "baa1e3d9.cb29d", - "group": "70de8209.68416c", - "order": 2, - "width": 5, - "height": 1, - "name": "pump", - "label": "Pump status:", - "format": "{{msg.payload.status}}", - "layout": "col-center", - "x": 770, - "y": 660, - "wires": [] - }, - { - "id": "bb628f8d.98f108", - "type": "link in", - "z": "baa1e3d9.cb29d", - "name": "Status for fluidic module", - "links": ["58f2e0f.4e8b12"], - "x": 175, - "y": 800, - "wires": [["999065ca.27edb8"]] - }, - { - "id": "307c851e.fb0f7a", - "type": "switch", - "z": "baa1e3d9.cb29d", - "name": "Imaging state", - "property": "payload", - "propertyType": "msg", - "rules": [ - { - "t": "jsonata_exp", - "v": "$contains(msg.payload.status, \"jpg\")\t", - "vt": "jsonata" - }, - { - "t": "else" - } - ], - "checkall": "false", - "repair": false, - "outputs": 2, - "x": 540, - "y": 880, - "wires": [["db8e3dde.44efb8"], ["6742014e.1bb238"]] - }, - { - "id": "db8e3dde.44efb8", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "img_counter", - "func": "img_counter=flow.get('img_counter')\nif (img_counter === undefined || img_counter === \"\"){\n img_counter = 0\n}\nimg_counter=img_counter+1\nflow.set('img_counter',img_counter)\nmsg.payload = img_counter\nmsg.payload = (100 * img_counter/global.get('nb_frame')).toFixed(2)\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 770, - "y": 860, - "wires": [["1a2e721a.f5e876"]] - }, - { - "id": "59164d65.e7993c", - "type": "ui_toast", - "z": "baa1e3d9.cb29d", - "position": "top right", - "displayTime": "5", - "highlight": "", - "sendall": true, - "outputs": 0, - "ok": "OK", - "cancel": "", - "raw": false, - "topic": "", - "name": "", - "x": 1270, - "y": 900, - "wires": [] - }, - { - "id": "8c7348aa.1962e8", - "type": "template", - "z": "baa1e3d9.cb29d", - "name": "Create sentence", - "field": "payload", - "fieldType": "msg", - "format": "handlebars", - "syntax": "mustache", - "template": "The {{topic}} is {{payload.status}}", - "output": "str", - "x": 1050, - "y": 900, - "wires": [["59164d65.e7993c"]] - }, - { - "id": "6742014e.1bb238", - "type": "change", - "z": "baa1e3d9.cb29d", - "name": "Remove high-level topic", - "rules": [ - { - "t": "change", - "p": "topic", - "pt": "msg", - "from": "status/", - "fromt": "str", + [ + "bb0a8725.a1849" + ] + ] + }, + { + "id": "0f16258953fae292", + "type": "file in", + "z": "b7861ce703215a01", + "name": "", + "filename": "/home/pi/PlanktoScope/hardware.json", + "filenameType": "str", + "format": "utf8", + "chunk": false, + "sendError": false, + "encoding": "none", + "allProps": false, + "x": 250, + "y": 40, + "wires": [ + [ + "81c516291ab19acd" + ] + ], + "info": "# PlanktoScope Help\nThis Node will read the content of the file named **config.txt** containing all the input placeholders.\n" + }, + { + "id": "81c516291ab19acd", + "type": "json", + "z": "b7861ce703215a01", + "name": "Parse JSON", + "property": "payload", + "action": "", + "pretty": false, + "x": 510, + "y": 40, + "wires": [ + [ + "d0fbcd200cd09981" + ] + ] + }, + { + "id": "d0fbcd200cd09981", + "type": "change", + "z": "b7861ce703215a01", + "name": "", + "rules": [ + { + "t": "set", + "p": "hardware_conf", + "pt": "global", + "to": "payload", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", "to": "", - "tot": "str" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 810, - "y": 900, - "wires": [["8c7348aa.1962e8"]] - }, - { - "id": "1a2e721a.f5e876", - "type": "ui_gauge", - "z": "baa1e3d9.cb29d", - "name": "progress donut", - "group": "b5d61bc7.54fe48", - "order": 3, - "width": 6, - "height": 3, - "gtype": "donut", - "title": "", - "label": "%", - "format": "{{value}}", - "min": 0, - "max": "100", - "colors": ["#ffa83f", "#e6ff02", "#00dfe9"], - "seg1": "50", - "seg2": "75", - "x": 1260, - "y": 860, - "wires": [] - }, - { - "id": "9bd72495.a8a098", - "type": "ui_text", - "z": "baa1e3d9.cb29d", - "group": "4322c187.e73e5", - "order": 5, - "width": 5, - "height": 1, - "name": "Total imaged volume", - "label": "Total imaged volume", - "format": "{{msg.payload}}", - "layout": "col-center", - "x": 1200, - "y": 100, - "wires": [] - }, - { - "id": "99b11fe4.2795d", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "imaged volume calc", - "func": "camera = global.get(\"acq_camera\");\ncell = global.get(\"acq_celltype\");\nnb_frame = global.get(\"nb_frame\");\nprocess_pixel = global.get(\"process_pixel\");\n\nvar volume = 0\nif (camera == \"HQ Camera\"){\n volume = nb_frame * (process_pixel*4056*process_pixel*3040*cell/1000000000) / 1000;\n}\nelse if (camera == \"Camera v2.1\"){\n volume = nb_frame * (process_pixel*3280*process_pixel*2464*cell/1000000000) / 1000;\n}\nelse{\n msg.payload = \"The camera is not known to this system\";\n return msg;\n}\n\nglobal.set(\"acq_imaged_volume\", volume.toFixed(4))\n\nmsg.payload = volume.toFixed(2) + \" mL\"\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 960, - "y": 100, - "wires": [["9bd72495.a8a098"]], - "info": "### Focusing\n##### focus.py `nb_step` `orientation`\n\n- `nb_step` : **integer** (from 1 to 100000) - number of step to perform by the stage (about 31um/step)\n- `orientation` : **string** - orientation of the focus either `up` or `down`\n\nExample:\n\n python3.7 $HOME/PlanktoScope/scripts/focus.py 650 up\n" - }, - { - "id": "8e16aa2f.e40398", - "type": "ui_text", - "z": "baa1e3d9.cb29d", - "group": "4322c187.e73e5", - "order": 7, - "width": 5, - "height": 1, - "name": "Total pumped volume", - "label": "Total pumped volume", - "format": "{{msg.payload}} mL", - "layout": "col-center", - "x": 1200, - "y": 260, - "wires": [] - }, - { - "id": "67091ac0.8f9f6c", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "acq_volume calc", - "func": "var imaging_pump_volume = global.get(\"imaging_pump_volume\");\nvar nb_frame = global.get(\"nb_frame\");\nvar acq_volume = 0\n\nacq_volume = (Number(nb_frame)*Number(imaging_pump_volume)).toFixed(2)\nglobal.set(\"acq_volume\", acq_volume)\n\nmsg.payload = acq_volume\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 950, - "y": 260, - "wires": [["8e16aa2f.e40398"]], - "info": "### Focusing\n##### focus.py `nb_step` `orientation`\n\n- `nb_step` : **integer** (from 1 to 100000) - number of step to perform by the stage (about 31um/step)\n- `orientation` : **string** - orientation of the focus either `up` or `down`\n\nExample:\n\n python3.7 $HOME/PlanktoScope/scripts/focus.py 650 up\n" - }, - { - "id": "2b9d6988.d84836", - "type": "switch", - "z": "baa1e3d9.cb29d", - "name": "", - "property": "payload", - "propertyType": "msg", - "rules": [ - { - "t": "hask", - "v": "status", - "vt": "str" - }, - { - "t": "hask", - "v": "camera_name", - "vt": "str" - } - ], - "checkall": "true", - "repair": false, - "outputs": 2, - "x": 650, - "y": 760, - "wires": [["2b009bd7.c07004"], ["3bbb756a.84190a"]] - }, - { - "id": "3bbb756a.84190a", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "set camera name", - "func": "global.set(\"acq_camera\", msg.payload.camera_name);\n\nmsg.payload = msg.payload.camera_name;\n\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 810, - "y": 780, - "wires": [["559a8085.1d6b9"]] - }, - { - "id": "559a8085.1d6b9", - "type": "link out", - "z": "baa1e3d9.cb29d", - "name": "Camera Name", - "links": ["30067f35.532f2", "572a6daa.6004c4"], - "x": 965, - "y": 780, - "wires": [] - }, - { - "id": "49ea1123.ee1768", - "type": "ui_numeric", - "z": "baa1e3d9.cb29d", - "name": "sleep_before", - "label": "Delay to stabilize image (s)", - "tooltip": "Happens before every capture", - "group": "4322c187.e73e5", - "order": 4, - "width": 5, - "height": 1, - "wrap": false, - "passthru": true, - "topic": "sleep_before", - "topicType": "str", - "format": "{{value}}", - "min": "0.1", - "max": "5", - "step": "0.1", - "className": "", - "x": 670, - "y": 140, - "wires": [["fb887036.12429"]] - }, - { - "id": "572a6daa.6004c4", - "type": "link in", - "z": "baa1e3d9.cb29d", - "name": "", - "links": ["559a8085.1d6b9"], - "x": 735, - "y": 60, - "wires": [["99b11fe4.2795d"]] - }, - { - "id": "8032ea50.1b57f", - "type": "ui_template", - "z": "baa1e3d9.cb29d", - "group": "b5d61bc7.54fe48", - "name": "progress header", - "order": 1, - "width": 0, - "height": 0, - "format": "

Capture progress

", - "storeOutMessages": false, - "fwdInMessages": false, - "resendOnRefresh": false, - "templateScope": "local", - "x": 1270, - "y": 820, - "wires": [[]] - }, - { - "id": "a4abb1ae.2ae418", - "type": "subflow:1c24ad9c.bebec2", - "z": "baa1e3d9.cb29d", - "name": "", - "env": [], - "x": 890, - "y": 480, - "wires": [[]] - }, - { - "id": "4be09c97f86897d9", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "get nb_frame", - "func": "msg.payload = msg.payload.nb_frame;\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 330, - "y": 220, - "wires": [["51b4d0df.d70a88"]] - }, - { - "id": "f573206abefa9518", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "get imaging_pump_volume", - "func": "msg.payload = msg.payload.imaging_pump_volume;\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 380, - "y": 260, - "wires": [["0df8d1d86af6455a"]] - }, - { - "id": "f948151ab4031df4", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "get sleep_before", - "func": "msg.payload = msg.payload.sleep_before;\nreturn msg;", - "outputs": 1, - "timeout": "", - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 340, - "y": 140, - "wires": [["49ea1123.ee1768"]] - }, - { - "id": "ad153212312f0347", - "type": "ui_ui_control", - "z": "baa1e3d9.cb29d", - "name": "onTab", - "events": "all", - "x": 310, - "y": 340, - "wires": [["9b69ea945b587192"]] - }, - { - "id": "9b69ea945b587192", - "type": "function", - "z": "baa1e3d9.cb29d", - "name": "check tab", - "func": "if (msg.name == \"Fluidic Acquisition\"){\n return { \"topic\": \"imager/ image\" }\n}", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 460, - "y": 340, - "wires": [["52ea7d01.711034"]], - "outputLabels": ["interface"] - }, - { - "id": "0df8d1d86af6455a", - "type": "ui_text_input", - "z": "baa1e3d9.cb29d", - "name": "imaging_pump_volume", - "label": "Pumped volume (mL)", - "tooltip": "between frames", - "group": "4322c187.e73e5", - "order": 3, - "width": 0, - "height": 0, - "passthru": true, - "mode": "number", - "delay": 300, - "topic": "imaging_pump_volume", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 630, - "y": 260, - "wires": [["fb887036.12429", "67091ac0.8f9f6c"]] - }, - { - "id": "37116281279b9b82", - "type": "ui_template", - "z": "baa1e3d9.cb29d", - "group": "4322c187.e73e5", - "name": "Start Acquisition", - "order": 12, - "width": "5", - "height": "1", - "format": "\n\n", - "storeOutMessages": false, - "fwdInMessages": false, - "resendOnRefresh": false, - "templateScope": "local", - "className": "", - "x": 420, - "y": 440, - "wires": [["c9f510c0.7d1328"]] - }, - { - "id": "9d6abe67.6bb3d", - "type": "ui_button", - "z": "cb95299c.2817c8", - "name": "", - "group": "64903b47.4034e4", - "order": 1, - "width": 0, - "height": 0, - "passthru": false, - "label": "Home", - "tooltip": "", - "color": "", - "bgcolor": "", - "icon": "home", - "payload": "{\"tab\":\"Home\"}", - "payloadType": "json", - "topic": "", - "x": 430, - "y": 600, - "wires": [["f0fb77cf.8f1c28"]] - }, - { - "id": "f0fb77cf.8f1c28", - "type": "ui_ui_control", - "z": "cb95299c.2817c8", - "name": "", - "events": "change", - "x": 740, - "y": 600, - "wires": [[]] - }, - { - "id": "8ec68b82.17e3d8", - "type": "ui_button", - "z": "cb95299c.2817c8", - "name": "Start segmentation", - "group": "abeb6dad.635a2", - "order": 10, - "width": 5, - "height": 1, - "passthru": false, - "label": "Start segmentation", - "tooltip": "", - "color": "", - "bgcolor": "", - "icon": "", - "payload": "{\"action\":\"segment\"}", - "payloadType": "json", - "topic": "segmenter/segment", - "x": 370, - "y": 460, - "wires": [["33c28dc1.238002", "c72a1064.1ec388"]] - }, - { - "id": "27be7971.b3fbce", - "type": "ui_button", - "z": "cb95299c.2817c8", - "d": true, - "name": "Stop segmentation", - "group": "abeb6dad.635a2", - "order": 12, - "width": 4, - "height": 1, - "passthru": true, - "label": "Stop segmentation", - "tooltip": "", - "color": "", - "bgcolor": "#AD1625", - "icon": "", - "payload": "{\"action\":\"stop\"}", - "payloadType": "json", - "topic": "segmenter/segment", - "x": 370, - "y": 520, - "wires": [["16f3cef4.0acac9"]] - }, - { - "id": "16f3cef4.0acac9", - "type": "mqtt out", - "z": "cb95299c.2817c8", - "name": "", - "topic": "", - "qos": "", - "retain": "", - "broker": "8dc3722c.06efa8", - "x": 850, - "y": 520, - "wires": [] - }, - { - "id": "8f3788f6.ddcf98", - "type": "function", - "z": "cb95299c.2817c8", - "name": "obj_counter", - "func": "obj_counter = flow.get('obj_counter')\nobj_counter = obj_counter + 1\nflow.set('obj_counter', obj_counter)\nmsg.payload = obj_counter\nmsg.topic = \"object count\"\nreturn msg", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 810, - "y": 800, - "wires": [["fa3b7929.ac7da8", "9d53dbe2.dbffe8"]] - }, - { - "id": "aa38dbbc.cf0a9", - "type": "switch", - "z": "cb95299c.2817c8", - "name": "Segmenter", - "property": "topic", - "propertyType": "msg", - "rules": [ - { - "t": "eq", - "v": "status/segmenter", - "vt": "str" - }, - { - "t": "eq", - "v": "status/segmenter/name", - "vt": "str" - }, - { - "t": "eq", - "v": "status/segmenter/object_id", - "vt": "str" - }, - { - "t": "eq", - "v": "status/segmenter/metric", - "vt": "str" - } - ], - "checkall": "true", - "repair": false, - "outputs": 4, - "x": 490, - "y": 740, - "wires": [ - ["b9a23b91.93638", "6919465f.332e5"], - ["49af3d24.1799e4"], - ["8f3788f6.ddcf98"], - [] - ] - }, - { - "id": "9d53dbe2.dbffe8", - "type": "ui_chart", - "z": "cb95299c.2817c8", - "name": "counter graph", - "group": "46be9c86.dea684", - "order": 7, - "width": 10, - "height": 2, - "label": "", - "chartType": "horizontalBar", - "legend": "false", - "xformat": "HH:mm:ss", - "interpolate": "linear", - "nodata": "Objects count will be shown here once the segmentation is started", - "dot": false, - "ymin": "", - "ymax": "", - "removeOlder": 1, - "removeOlderPoints": "", - "removeOlderUnit": "3600", - "cutout": 0, - "useOneColor": true, - "useUTC": false, - "colors": [ - "#1f77b4", - "#aec7e8", - "#ff7f0e", - "#2ca02c", - "#98df8a", - "#d62728", - "#ff9896", - "#9467bd", - "#c5b0d5" - ], - "outputs": 1, - "x": 1340, - "y": 840, - "wires": [[]] - }, - { - "id": "a4f0f0d1.3aca88", - "type": "ui_toast", - "z": "cb95299c.2817c8", - "position": "top right", - "displayTime": "5", - "highlight": "", - "sendall": true, - "outputs": 0, - "ok": "OK", - "cancel": "", - "raw": false, - "topic": "", - "name": "", - "x": 1350, - "y": 680, - "wires": [] - }, - { - "id": "49af3d24.1799e4", - "type": "debug", - "z": "cb95299c.2817c8", - "name": "segmentation name", - "active": true, - "tosidebar": true, - "console": false, - "tostatus": false, - "complete": "true", - "targetType": "full", - "statusVal": "", - "statusType": "auto", - "x": 840, - "y": 760, - "wires": [] - }, - { - "id": "7088a5be.0c79a4", - "type": "template", - "z": "cb95299c.2817c8", - "name": "Create sentence", - "field": "payload", - "fieldType": "msg", - "format": "handlebars", - "syntax": "mustache", - "template": "The {{topic}} is {{payload.status}}", - "output": "str", - "x": 1100, - "y": 680, - "wires": [["a4f0f0d1.3aca88"]] - }, - { - "id": "b9a23b91.93638", - "type": "change", - "z": "cb95299c.2817c8", - "name": "Remove high-level topic", - "rules": [ - { - "t": "change", - "p": "topic", - "pt": "msg", - "from": "status/", - "fromt": "str", + "reg": false, + "x": 730, + "y": 40, + "wires": [ + [] + ] + }, + { + "id": "4e78af2d.90be7", + "type": "ui_ui_control", + "z": "eaae323a.31b3", + "name": "", + "events": "change", + "x": 440, + "y": 160, + "wires": [ + [] + ] + }, + { + "id": "7789839d.69b48c", + "type": "ui_template", + "z": "eaae323a.31b3", + "group": "4e0cd5ea.17e59c", + "name": "Optic Configuration", + "order": 1, + "width": 4, + "height": 4, + "format": "\n \n
Optic Configuration
\n
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "className": "", + "x": 130, + "y": 100, + "wires": [ + [ + "4e78af2d.90be7" + ] + ] + }, + { + "id": "6ea6c306.f9c12c", + "type": "ui_template", + "z": "eaae323a.31b3", + "group": "ef590206.24f6", + "name": "Fluidic Acquisition", + "order": 1, + "width": 4, + "height": 4, + "format": "\n \n
Fluidic Acquisition
\n
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "className": "", + "x": 130, + "y": 140, + "wires": [ + [ + "4e78af2d.90be7" + ] + ] + }, + { + "id": "bb9eb153.9e36c", + "type": "ui_template", + "z": "eaae323a.31b3", + "group": "ae8f6620.073358", + "name": "Segmentation", + "order": 1, + "width": 4, + "height": 4, + "format": "\n \n
Segmentation
\n
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "className": "", + "x": 140, + "y": 180, + "wires": [ + [ + "4e78af2d.90be7" + ] + ] + }, + { + "id": "eaf8ee7f.96f44", + "type": "ui_template", + "z": "eaae323a.31b3", + "group": "196518b2.4d53b7", + "name": "Gallery", + "order": 1, + "width": 4, + "height": 4, + "format": "\n \n
Gallery
\n
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "className": "", + "x": 160, + "y": 220, + "wires": [ + [ + "4e78af2d.90be7" + ] + ] + }, + { + "id": "c1b1469.9650eb8", + "type": "ui_template", + "z": "eaae323a.31b3", + "group": "777a7c33.fcd804", + "name": "System Monitoring", + "order": 1, + "width": 4, + "height": 4, + "format": "\n \n
System Monitoring
\n
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "className": "", + "x": 130, + "y": 260, + "wires": [ + [ + "4e78af2d.90be7" + ] + ] + }, + { + "id": "abafd6e6.04a5f8", + "type": "ui_template", + "z": "eaae323a.31b3", + "group": "6f97e7ae.270c48", + "name": "Sample", + "order": 1, + "width": 4, + "height": 4, + "format": "\n \n
Sample
\n
\n In doubt? Start Here!\n
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "className": "", + "x": 160, + "y": 60, + "wires": [ + [ + "4e78af2d.90be7" + ] + ] + }, + { + "id": "dab82064.26a8d", + "type": "ui_button", + "z": "eaae323a.31b3", + "name": "Unlock button", + "group": "f3ca28ef.4df0a8", + "order": 2, + "width": 0, + "height": 0, + "passthru": false, + "label": "Unlock button", + "tooltip": "", + "color": "", + "bgcolor": "", + "icon": "", + "payload": "shutdown", + "payloadType": "flow", + "topic": "", + "x": 120, + "y": 380, + "wires": [ + [ + "6c3a3b4.78cad44" + ] + ] + }, + { + "id": "1c658761.b852a1", + "type": "ui_toast", + "z": "eaae323a.31b3", + "position": "dialog", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 1, + "ok": "YES PLEASE", + "cancel": "NO!", + "raw": false, + "topic": "Are you sure?", + "name": "Confirmation message", + "x": 800, + "y": 380, + "wires": [ + [ + "8f1b8e23.daafe" + ] + ] + }, + { + "id": "a48ff63f.db5e18", + "type": "inject", + "z": "eaae323a.31b3", + "name": "disabled", + "props": [ + { + "p": "enabled", + "v": "false", + "vt": "bool" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "x": 140, + "y": 420, + "wires": [ + [ + "d58039a9.6e7928" + ] + ] + }, + { + "id": "b67a7147.65fcd8", + "type": "ui_button", + "z": "eaae323a.31b3", + "name": "Shutdown button", + "group": "f3ca28ef.4df0a8", + "order": 4, + "width": 0, + "height": 0, + "passthru": false, + "label": "Shutdown", + "tooltip": "", + "color": "", + "bgcolor": "#AD1625", + "icon": "fa-power-off fa-2x", + "payload": "Do you want to turn the machine off now?", + "payloadType": "str", + "topic": "", + "x": 550, + "y": 380, + "wires": [ + [ + "1c658761.b852a1" + ] + ] + }, + { + "id": "d58039a9.6e7928", + "type": "change", + "z": "eaae323a.31b3", + "name": "", + "rules": [ + { + "t": "set", + "p": "shutdown", + "pt": "flow", + "to": "false", + "tot": "bool" + }, + { + "t": "set", + "p": "enabled", + "pt": "msg", + "to": "shutdown", + "tot": "flow" + } + ], + "action": "", + "property": "", + "from": "", "to": "", - "tot": "str" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 850, - "y": 680, - "wires": [["7088a5be.0c79a4"]] - }, - { - "id": "6919465f.332e5", - "type": "ui_text", - "z": "cb95299c.2817c8", - "group": "46be9c86.dea684", - "order": 1, - "width": 10, - "height": 1, - "name": "segmenter", - "label": "Segmenter status:", - "format": "{{msg.payload.status}}", - "layout": "row-spread", - "x": 810, - "y": 720, - "wires": [] - }, - { - "id": "fa3b7929.ac7da8", - "type": "ui_text", - "z": "cb95299c.2817c8", - "group": "46be9c86.dea684", - "order": 5, - "width": 4, - "height": 1, - "name": "counter", - "label": "", - "format": "{{msg.payload}}", - "layout": "col-center", - "x": 1320, - "y": 800, - "wires": [] - }, - { - "id": "640ece83.88cab", - "type": "inject", - "z": "cb95299c.2817c8", - "name": "Init graphs", - "props": [ - { - "p": "payload" - }, - { - "p": "topic", - "vt": "str" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "object count", - "payload": "0", - "payloadType": "num", - "x": 810, - "y": 880, - "wires": [["4f3f7c4a.cb21c4"]] - }, - { - "id": "25867454.a8e334", - "type": "link in", - "z": "cb95299c.2817c8", - "name": "Segmenter module status", - "links": ["dcf5bd45.16a8d"], - "x": 295, - "y": 740, - "wires": [["aa38dbbc.cf0a9"]] - }, - { - "id": "c8749cbb.55254", - "type": "function", - "z": "cb95299c.2817c8", - "name": "set global", - "func": "global.set(msg.topic, msg.payload);", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 960, - "y": 380, - "wires": [[]] - }, - { - "id": "d43c3ed9.e6cb1", - "type": "ui_template", - "z": "cb95299c.2817c8", - "group": "46be9c86.dea684", - "name": "Object counts", - "order": 3, - "width": 0, - "height": 0, - "format": "

Object counts

", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": true, - "templateScope": "local", - "x": 1340, - "y": 760, - "wires": [[]] - }, - { - "id": "33c28dc1.238002", - "type": "function", - "z": "cb95299c.2817c8", - "name": "prepare segmentation", - "func": "global.set('obj_counter', 0);\n\nvar segmentation_list = flow.get('segmentation_list')\nif (segmentation_list !== undefined && segmentation_list !== \"\") {\n msg.payload['path'] = segmentation_list\n}\n\n\nvar force = flow.get('force')\nif (force !== undefined && force !== \"\") {\n msg.payload['settings'] = {\"force\":Boolean(force)}\n}\n\n\nvar recursive = flow.get('recursive')\nif (recursive !== undefined && recursive !== \"\") {\n if (\"settings\" in msg.payload){\n msg.payload.settings[\"recursive\"] = Boolean(recursive)\n }\n else{\n msg.payload['settings'] = {\"recursive\": Boolean(recursive)}\n }\n}\n\nvar ecotaxa = flow.get('ecotaxa')\nif (ecotaxa !== undefined && ecotaxa !== \"\") {\n if (\"settings\" in msg.payload){\n msg.payload.settings[\"ecotaxa\"] = Boolean(ecotaxa)\n }\n else{\n msg.payload['settings'] = {\"ecotaxa\": Boolean(ecotaxa)}\n }\n}\n\nvar keep = flow.get('keep')\nif (keep !== undefined && keep !== \"\") {\n if (\"settings\" in msg.payload){\n msg.payload.settings[\"keep\"] = Boolean(keep)\n }\n else{\n msg.payload['settings'] = {\"keep\": Boolean(keep)}\n }\n}\n\nvar process_id = global.get('process_id')\nif (process_id !== undefined && process_id !== \"\") {\n if (\"settings\" in msg.payload){\n msg.payload.settings[\"process_id\"] = process_id\n }\n else{\n msg.payload['settings'] = {\"process_id\": process_id}\n }\n}\n\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 620, - "y": 460, - "wires": [["16f3cef4.0acac9"]] - }, - { - "id": "fa12f9f8.00cfa8", - "type": "subflow:1c24ad9c.bebec2", - "z": "cb95299c.2817c8", - "name": "", - "env": [], - "x": 430, - "y": 380, - "wires": [["3b72d11c.86e9e6"]] - }, - { - "id": "3b72d11c.86e9e6", - "type": "function", - "z": "cb95299c.2817c8", - "name": "get process_id", - "func": "msg.payload = msg.payload.process_id;\nmsg.topic = \"process_id\";\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 600, - "y": 380, - "wires": [["56971109c8be3b54"]] - }, - { - "id": "3ea12061.ce62c", - "type": "ui_list", - "z": "cb95299c.2817c8", - "group": "abeb6dad.635a2", - "name": "", - "order": 9, - "width": 10, - "height": 11, - "lineType": "one", - "actionType": "check", - "allowHTML": false, - "outputs": 1, - "topic": "", - "x": 770, - "y": 140, - "wires": [["cb3b87b5.63c4"]] - }, - { - "id": "8bd8fb2c.53fa4", - "type": "dir2files", - "z": "cb95299c.2817c8", - "name": "", - "dirname": "/home/pi/data/img/", - "pathRegex": "", - "isRecursive": true, - "findDir": true, - "isArray": true, - "x": 460, - "y": 140, - "wires": [["ba2947.c854deb8"]] - }, - { - "id": "127d4ee.f8ad1b1", - "type": "ui_button", - "z": "cb95299c.2817c8", - "name": "Refresh", - "group": "abeb6dad.635a2", - "order": 8, - "width": 0, - "height": 0, - "passthru": false, - "label": "Update acquisition's folder list", - "tooltip": "Refresh the list of previous acquisitions", - "color": "", - "bgcolor": "", - "icon": "mi-find_replace", - "payload": "", - "payloadType": "date", - "topic": "update", - "x": 260, - "y": 140, - "wires": [["8bd8fb2c.53fa4", "56f845f5.e7c054"]] - }, - { - "id": "946ce9ee.092cf", - "type": "inject", - "z": "cb95299c.2817c8", - "name": "Init", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "", - "payload": "", - "payloadType": "date", - "x": 270, - "y": 100, - "wires": [["8bd8fb2c.53fa4", "56f845f5.e7c054"]] - }, - { - "id": "cb3b87b5.63c4", - "type": "function", - "z": "cb95299c.2817c8", - "name": "update segmentation_list", - "func": "var segmentation_list = flow.get('segmentation_list');\n\nif (segmentation_list === undefined || segmentation_list === \"\") {\n segmentation_list = []\n console.log(\"error\")\n}\n\npath = \"/home/pi/data/img/\" + msg.payload.title\n\nif (msg.payload.isChecked){\n if (segmentation_list.includes(path) === false){\n segmentation_list.push(path)\n }\n // Element already in list, don't push it more than once\n //segmentation_list.push(msg.payload[\"title\"])\n}\nelse {\n var pos = segmentation_list.indexOf(path)\n segmentation_list.splice(pos, 1)\n}\n\nflow.set('segmentation_list', segmentation_list)", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 950, - "y": 140, - "wires": [[]] - }, - { - "id": "56f845f5.e7c054", - "type": "change", - "z": "cb95299c.2817c8", - "name": "Reset segmentation_list", - "rules": [ - { - "t": "set", - "p": "segmentation_list", - "pt": "flow", - "to": "[]", - "tot": "json" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 510, - "y": 100, - "wires": [[]] - }, - { - "id": "7fc72364.8f038c", - "type": "ui_template", - "z": "cb95299c.2817c8", - "group": "abeb6dad.635a2", - "name": "Update message", - "order": 1, - "width": 10, - "height": 3, - "format": "
You can choose here in which folder(s) you want the segmentation script to run. A few details though:\n
The segmentation is run recursively in all folders. So if you select a top level folder, the segmentation will be run in all subfolders.\n
Also, you will be able to chose wether for force the segmentation for folders in which it has run already.
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": true, - "templateScope": "local", - "x": 270, - "y": 40, - "wires": [[]] - }, - { - "id": "ba2947.c854deb8", - "type": "function", - "z": "cb95299c.2817c8", - "name": "remove common", - "func": "function remove_path(item, index, array) {\n array[index] = item.replace(\"/home/pi/data/img/\", \"\")\n} \n\nmsg.payload.forEach(remove_path)\n\nreturn msg", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "x": 620, - "y": 140, - "wires": [["3ea12061.ce62c"]] - }, - { - "id": "21af0db1.c2c182", - "type": "ui_multistate_switch", - "z": "cb95299c.2817c8", - "name": "recursive toggle", - "group": "abeb6dad.635a2", - "order": 4, - "width": 5, - "height": 1, - "label": "Recursive folder", - "stateField": "payload", - "enableField": "enable", - "rounded": true, - "useThemeColors": true, - "hideSelectedLabel": false, - "options": [ - { - "label": "No", - "value": "0", - "valueType": "num", - "color": "#009933" - }, - { - "label": "Yes", - "value": "1", - "valueType": "num", - "color": "#999999" - } - ], - "x": 480, - "y": 220, - "wires": [["880b192a.88e2d"]] - }, - { - "id": "dffb9881.feef8", - "type": "ui_multistate_switch", - "z": "cb95299c.2817c8", - "name": "force toggle", - "group": "abeb6dad.635a2", - "order": 3, - "width": 5, - "height": 1, - "label": "Force rework", - "stateField": "payload", - "enableField": "enable", - "rounded": true, - "useThemeColors": true, - "hideSelectedLabel": false, - "options": [ - { - "label": "No", - "value": "0", - "valueType": "num", - "color": "#009933" - }, - { - "label": "Yes", - "value": "1", - "valueType": "num", - "color": "#999999" - } - ], - "x": 470, - "y": 300, - "wires": [["a4f68fa6.5d77f8"]] - }, - { - "id": "880b192a.88e2d", - "type": "change", - "z": "cb95299c.2817c8", - "name": "", - "rules": [ - { - "t": "set", - "p": "recursive", - "pt": "flow", - "to": "payload", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 690, - "y": 240, - "wires": [[]] - }, - { - "id": "a4f68fa6.5d77f8", - "type": "change", - "z": "cb95299c.2817c8", - "name": "", - "rules": [ - { - "t": "set", - "p": "force", - "pt": "flow", - "to": "payload", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 670, - "y": 280, - "wires": [[]] - }, - { - "id": "1ef1b43b.b0f064", - "type": "inject", - "z": "cb95299c.2817c8", - "name": "0", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "", - "payload": "0", - "payloadType": "num", - "x": 270, - "y": 280, - "wires": [["dffb9881.feef8", "a4f68fa6.5d77f8"]] - }, - { - "id": "f078c068.eacf58", - "type": "ui_template", - "z": "cb95299c.2817c8", - "group": "46be9c86.dea684", - "name": "Stream Segmented object", - "order": 2, - "width": 10, - "height": 8, - "format": "
\n Latest object segmented:
\n \"If\n
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "className": "", - "x": 1380, - "y": 600, - "wires": [[]] - }, - { - "id": "43f97b93.b76294", - "type": "inject", - "z": "cb95299c.2817c8", - "name": "1", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "", - "payload": "1", - "payloadType": "num", - "x": 270, - "y": 240, - "wires": [["21af0db1.c2c182", "880b192a.88e2d"]] - }, - { - "id": "4f3f7c4a.cb21c4", - "type": "change", - "z": "cb95299c.2817c8", - "name": "", - "rules": [ - { - "t": "set", - "p": "obj_counter", - "pt": "flow", - "to": "0", - "tot": "num" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 1020, - "y": 840, - "wires": [["fa3b7929.ac7da8", "9d53dbe2.dbffe8"]] - }, - { - "id": "6bce0f60.f48998", - "type": "link in", - "z": "cb95299c.2817c8", - "name": "", - "links": ["596fc9d4.46c75"], - "x": 855, - "y": 840, - "wires": [["4f3f7c4a.cb21c4"]] - }, - { - "id": "596fc9d4.46c75", - "type": "link out", - "z": "cb95299c.2817c8", - "name": "", - "links": ["6bce0f60.f48998"], - "x": 715, - "y": 500, - "wires": [] - }, - { - "id": "c72a1064.1ec388", - "type": "change", - "z": "cb95299c.2817c8", - "name": "Reset counters", - "rules": [ - { - "t": "set", - "p": "topic", - "pt": "msg", - "to": "object count", - "tot": "str" - }, - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "0", - "tot": "num" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 600, - "y": 500, - "wires": [["596fc9d4.46c75"]] - }, - { - "id": "9367534a.fb8568", - "type": "ui_multistate_switch", - "z": "cb95299c.2817c8", - "name": "Ecotaxa archive", - "group": "abeb6dad.635a2", - "order": 6, - "width": 5, - "height": 1, - "label": "Ecotaxa archive", - "stateField": "payload", - "enableField": "enable", - "rounded": true, - "useThemeColors": true, - "hideSelectedLabel": false, - "options": [ - { - "label": "No", - "value": "0", - "valueType": "num", - "color": "#009933" - }, - { - "label": "Yes", - "value": "1", - "valueType": "num", - "color": "#999999" - } - ], - "x": 1080, - "y": 220, - "wires": [["25ac4f9a.5b05c8"]] - }, - { - "id": "25ac4f9a.5b05c8", - "type": "change", - "z": "cb95299c.2817c8", - "name": "", - "rules": [ - { - "t": "set", - "p": "ecotaxa", - "pt": "flow", - "to": "payload", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 1280, - "y": 240, - "wires": [[]] - }, - { - "id": "bef78886.8f0b98", - "type": "inject", - "z": "cb95299c.2817c8", - "name": "1", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "", - "payload": "1", - "payloadType": "num", - "x": 910, - "y": 240, - "wires": [["9367534a.fb8568", "25ac4f9a.5b05c8"]] - }, - { - "id": "32465a4e.8fcac6", - "type": "ui_multistate_switch", - "z": "cb95299c.2817c8", - "name": "Keep objects", - "group": "abeb6dad.635a2", - "order": 5, - "width": 5, - "height": 1, - "label": "Keep objects", - "stateField": "payload", - "enableField": "enable", - "rounded": true, - "useThemeColors": true, - "hideSelectedLabel": false, - "options": [ - { - "label": "No", - "value": "0", - "valueType": "num", - "color": "#009933" - }, - { - "label": "Yes", - "value": "1", - "valueType": "num", - "color": "#999999" - } - ], - "x": 1070, - "y": 300, - "wires": [["8dd6f57f.b77f98"]] - }, - { - "id": "8dd6f57f.b77f98", - "type": "change", - "z": "cb95299c.2817c8", - "name": "", - "rules": [ - { - "t": "set", - "p": "keep", - "pt": "flow", - "to": "payload", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 1270, - "y": 280, - "wires": [[]] - }, - { - "id": "8090df89.c029e", - "type": "inject", - "z": "cb95299c.2817c8", - "name": "1", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "", - "payload": "1", - "payloadType": "num", - "x": 910, - "y": 280, - "wires": [["32465a4e.8fcac6", "8dd6f57f.b77f98"]] - }, - { - "id": "56971109c8be3b54", - "type": "ui_text_input", - "z": "cb95299c.2817c8", - "name": "process_id", - "label": "Process unique ID*", - "tooltip": "", - "group": "abeb6dad.635a2", - "order": 2, - "width": 10, - "height": 1, - "passthru": true, - "mode": "text", - "delay": 300, - "topic": "process_id", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 790, - "y": 380, - "wires": [["c8749cbb.55254"]] - }, - { - "id": "2911fbc6.d28c24", - "type": "ui_template", - "z": "c1660bc.e7ff7f8", - "group": "c0ebfc57.42527", - "name": "Image browser", - "order": 1, - "width": "0", - "height": "0", - "format": "
\n\n
", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "className": "", - "x": 400, - "y": 100, - "wires": [[]] - }, - { - "id": "4f02c726.de69b8", - "type": "ui_button", - "z": "9daf9e2b.019fc", - "name": "", - "group": "a7d64879.38298", - "order": 4, - "width": "6", - "height": 1, - "passthru": false, - "label": "Reboot", - "tooltip": "", - "color": "", - "bgcolor": "#AD1625", - "className": "", - "icon": "fa-repeat fa-2x", - "payload": "reboot", - "payloadType": "str", - "topic": "reboot", - "topicType": "str", - "x": 160, - "y": 240, - "wires": [["611a8b1c.a829b4"]] - }, - { - "id": "611a8b1c.a829b4", - "type": "exec", - "z": "9daf9e2b.019fc", - "command": "sudo", - "addpay": "payload", - "append": "now", - "useSpawn": "false", - "timer": "2", - "winHide": false, - "oldrc": false, - "name": "sudo cmd now", - "x": 480, - "y": 280, - "wires": [[], [], []] - }, - { - "id": "bc76c4d6.a7ad28", - "type": "ui_button", - "z": "9daf9e2b.019fc", - "name": "", - "group": "a7d64879.38298", - "order": 5, - "width": "6", - "height": 1, - "passthru": false, - "label": "Shutdown", - "tooltip": "", - "color": "", - "bgcolor": "#AD1625", - "className": "", - "icon": "fa-power-off fa-2x", - "payload": "shutdown", - "payloadType": "str", - "topic": "shutdown", - "topicType": "str", - "x": 160, - "y": 320, - "wires": [["611a8b1c.a829b4"]] - }, - { - "id": "b81b990a.d4dca", - "type": "link in", - "z": "9daf9e2b.019fc", - "name": "Shutdown", - "links": ["e08cfcb8.2a67e8"], - "x": 195, - "y": 280, - "wires": [["611a8b1c.a829b4"]] - }, - { - "id": "ea4fae012404854c", - "type": "ui_button", - "z": "9daf9e2b.019fc", - "name": "", - "group": "a7d64879.38298", - "order": 2, - "width": "6", - "height": 1, - "passthru": true, - "label": "Restart Hardware Controller", - "tooltip": "", - "color": "", - "bgcolor": "#AD1625", - "className": "", - "icon": "fa-refresh fa-2x", - "payload": "Restarting hardware controller...", - "payloadType": "str", - "topic": "", - "topicType": "str", - "x": 440, - "y": 420, - "wires": [["c54d948575dbcff8", "d10f3ffd98055447"]] - }, - { - "id": "438febd245a9f73c", - "type": "link in", - "z": "9daf9e2b.019fc", - "name": "Restart Hardware Controller", - "links": ["e41870d7.300eb8", "3973b999ee7b3b1d"], - "x": 195, - "y": 420, - "wires": [["ea4fae012404854c"]] - }, - { - "id": "c54d948575dbcff8", - "type": "exec", - "z": "9daf9e2b.019fc", - "command": "sudo systemctl restart planktoscope-org.device-backend.controller.service", - "addpay": false, - "append": "", - "useSpawn": "false", - "timer": "", - "winHide": false, - "oldrc": false, - "name": "Restart hardware controller", - "x": 780, - "y": 420, - "wires": [[], [], []] - }, - { - "id": "e2e5ce0351a6cc11", - "type": "ui_button", - "z": "9daf9e2b.019fc", - "name": "", - "group": "a7d64879.38298", - "order": 3, - "width": "6", - "height": 1, - "passthru": true, - "label": "Restart Segmenter", - "tooltip": "", - "color": "", - "bgcolor": "#AD1625", - "className": "", - "icon": "fa-refresh fa-2x", - "payload": "Restarting segmenter...", - "payloadType": "str", - "topic": "", - "topicType": "str", - "x": 410, - "y": 500, - "wires": [["2cdbadb65d0e1b20", "9c1629488b02fdba"]] - }, - { - "id": "2cdbadb65d0e1b20", - "type": "exec", - "z": "9daf9e2b.019fc", - "command": "docker restart apps_ps_backend_proc-segmenter-server-1", - "addpay": false, - "append": "", - "useSpawn": "false", - "timer": "", - "winHide": false, - "oldrc": false, - "name": "Restart segmenter", - "x": 750, - "y": 500, - "wires": [[], [], []] - }, - { - "id": "7b64209d734e4e2c", - "type": "ui_template", - "z": "9daf9e2b.019fc", - "group": "a7d64879.38298", - "name": "Logs", - "order": 1, - "width": "0", - "height": "0", - "format": "

\n The PlanktoScope software application consists of three components: a Node-RED dashboard which provides the user interface you're using; a Hardware Controller\n which executes commands sent from the Node-RED dashboard for hardware control and image acquisition; and a Segmenter which processes an acquired dataset of\n images and isolates objects from those images. Each component has its own independent log of messages, managed separately from the logs for the other components.\n

\n

\n All three components have live-updating logs which you can monitor. Additionally, the Hardware Controller and the Segmenter also save all of their log messages\n to files which you can browse and download. Those software components create a new log file each time they start, and the name of the log file includes the time\n in the PlanktoScope's clock when the software component started. However, if your PlanktoScope's clock is usually wrong, it makes the log files difficult to navigate.\n This will be fixed in a future version of the software.\n

\n

\n If you need to share your logs with other people (e.g. on Slack or GitHub), you should open the \"Downloadable Logs\" links, and then you can select one file or multiple\n log files for downloading as a zip archive.\n

\n", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": true, - "templateScope": "local", - "className": "", - "x": 630, - "y": 180, - "wires": [[]] - }, - { - "id": "d10f3ffd98055447", - "type": "ui_toast", - "z": "9daf9e2b.019fc", - "position": "top right", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 0, - "ok": "OK", - "cancel": "", - "raw": false, - "className": "", - "topic": "", - "name": "", - "x": 750, - "y": 380, - "wires": [] - }, - { - "id": "9c1629488b02fdba", - "type": "ui_toast", - "z": "9daf9e2b.019fc", - "position": "top right", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 0, - "ok": "OK", - "cancel": "", - "raw": false, - "className": "", - "topic": "", - "name": "", - "x": 750, - "y": 460, - "wires": [] - }, - { - "id": "3910d662.fa1f7a", - "type": "exec", - "z": "1371dec5.76e671", - "command": "df -h | grep /dev/root | awk -F ' ' '{print $5}' | tr -d % | tr \"\\n$\" \"\\ \" | sed 's/,/./' | tr -d \" \"", - "addpay": false, - "append": "", - "useSpawn": "", - "timer": "", - "name": "Disk Usage", - "x": 330, - "y": 120, - "wires": [["eaf74a43.fa27d"], [], []] - }, - { - "id": "1cd5b4c0.46af9b", - "type": "inject", - "z": "1371dec5.76e671", - "name": "update: 5s", - "props": [ - { - "p": "payload" - }, - { - "p": "topic", - "vt": "str" - } - ], - "repeat": "5", - "crontab": "", - "once": false, - "onceDelay": "", - "topic": "", - "payload": "", - "payloadType": "date", - "x": 110, - "y": 160, - "wires": [ - [ - "3910d662.fa1f7a", - "aa2e4cd182dbc776", - "797675a937dc1629", - "f6f570b10c675854" - ] - ] - }, - { - "id": "569154a.b53182c", - "type": "inject", - "z": "1371dec5.76e671", - "name": "once", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": "", - "topic": "", - "payload": "start", - "payloadType": "str", - "x": 130, - "y": 700, - "wires": [["5883e629f5d546ed"]] - }, - { - "id": "4828d2f4.7c712c", - "type": "function", - "z": "1371dec5.76e671", - "name": "set global", - "func": "global.set(\"acq_instrument_id\",msg.payload);\n", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 580, - "y": 720, - "wires": [[]] - }, - { - "id": "e2f39a35.f57298", - "type": "subflow:1c24ad9c.bebec2", - "z": "1371dec5.76e671", - "name": "", - "env": [], - "x": 130, - "y": 640, - "wires": [["9b64f397101c2762"]] - }, - { - "id": "3e64877a.9684b", - "type": "function", - "z": "1371dec5.76e671", - "name": "set global", - "func": "global.set(\"acq_software\", \"PlanktoScope \" + msg.payload);\n", - "outputs": 1, - "timeout": "", - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 820, - "y": 520, - "wires": [[]] - }, - { - "id": "bdc6718a.dd5d48", - "type": "ui_text", - "z": "1371dec5.76e671", - "group": "ce9e278.781eed8", - "order": 2, - "width": 0, - "height": 0, - "name": "", - "label": "Instrument Type", - "format": "{{msg.payload}}", - "layout": "row-spread", - "className": "", - "style": false, - "font": "", - "fontSize": "", - "color": "#000000", - "x": 600, - "y": 640, - "wires": [] - }, - { - "id": "a400a97e.e333a8", - "type": "ui_text", - "z": "1371dec5.76e671", - "group": "ce9e278.781eed8", - "order": 1, - "width": 0, - "height": 0, - "name": "", - "label": "Instrument Name", - "format": "{{msg.payload}}", - "layout": "row-spread", - "x": 610, - "y": 680, - "wires": [] - }, - { - "id": "8343fa69.49339", - "type": "ui_text", - "z": "1371dec5.76e671", - "group": "ce9e278.781eed8", - "order": 3, - "width": 0, - "height": 0, - "name": "", - "label": "Software Version", - "format": "{{msg.payload}}", - "layout": "row-spread", - "className": "", - "style": false, - "font": "", - "fontSize": "", - "color": "#000000", - "x": 850, - "y": 560, - "wires": [] - }, - { - "id": "f783aefd.c3bfd8", - "type": "ui_text", - "z": "1371dec5.76e671", - "group": "ce9e278.781eed8", - "order": 4, - "width": 0, - "height": 0, - "name": "", - "label": "Camera Name", - "format": "{{msg.payload}}", - "layout": "row-spread", - "x": 600, - "y": 760, - "wires": [] - }, - { - "id": "30067f35.532f2", - "type": "link in", - "z": "1371dec5.76e671", - "name": "Camera Name", - "links": ["559a8085.1d6b9"], - "x": 155, - "y": 760, - "wires": [["f783aefd.c3bfd8"]] - }, - { - "id": "eaf74a43.fa27d", - "type": "switch", - "z": "1371dec5.76e671", - "name": "if disk > 90%", - "property": "payload", - "propertyType": "msg", - "rules": [ - { - "t": "gte", - "v": "90", - "vt": "num" - } - ], - "checkall": "true", - "repair": false, - "outputs": 1, - "x": 590, - "y": 120, - "wires": [["6d09f428.930bcc"]] - }, - { - "id": "46d5e78b.15f998", - "type": "ui_toast", - "z": "1371dec5.76e671", - "position": "dialog", - "displayTime": "10", - "highlight": "", - "sendall": true, - "outputs": 1, - "ok": "OK", - "cancel": "", - "raw": false, - "topic": "", - "name": "", - "x": 1090, - "y": 120, - "wires": [[]] - }, - { - "id": "24df077a.cb252", - "type": "change", - "z": "1371dec5.76e671", - "name": "full disk msg", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "\"Your drive has reached 90% capacity, you should do a backup to an external drive and a purge.\"", - "tot": "str" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 930, - "y": 120, - "wires": [["46d5e78b.15f998"]] - }, - { - "id": "6d09f428.930bcc", - "type": "delay", - "z": "1371dec5.76e671", - "name": "", - "pauseType": "rate", - "timeout": "5", - "timeoutUnits": "seconds", - "rate": "1", - "nbRateUnits": "5", - "rateUnits": "minute", - "randomFirst": "1", - "randomLast": "5", - "randomUnits": "seconds", - "drop": true, - "allowrate": false, - "outputs": 1, - "x": 760, - "y": 120, - "wires": [["24df077a.cb252"]] - }, - { - "id": "5883e629f5d546ed", - "type": "file in", - "z": "1371dec5.76e671", - "name": "Get machine name", - "filename": "/run/machine-name", - "filenameType": "str", - "format": "utf8", - "chunk": false, - "sendError": false, - "encoding": "none", - "allProps": false, - "x": 350, - "y": 700, - "wires": [["a400a97e.e333a8", "4828d2f4.7c712c"]] - }, - { - "id": "9b64f397101c2762", - "type": "change", - "z": "1371dec5.76e671", - "name": "Get acq_instrument", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.acq_instrument", - "tot": "msg" - }, - { - "t": "set", - "p": "topic", - "pt": "msg", - "to": "acq_instrument", - "tot": "str" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 350, - "y": 640, - "wires": [["bdc6718a.dd5d48"]] - }, - { - "id": "99725e1437cc390b", - "type": "file in", - "z": "1371dec5.76e671", - "name": "Versioning File", - "filename": "/usr/share/planktoscope/installer-versioning.yml", - "filenameType": "str", - "format": "utf8", - "chunk": false, - "sendError": false, - "encoding": "none", - "allProps": false, - "x": 240, - "y": 540, - "wires": [["f4e21e28bd903f6d"]], - "info": "# PlanktoScope Help\nThis Node will read the content of the file named **config.txt** containing all the input placeholders.\n" - }, - { - "id": "6a0fa173874c3ddd", - "type": "inject", - "z": "1371dec5.76e671", - "name": "once", - "props": [ - { - "p": "payload" - } - ], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": "", - "topic": "", - "payload": "start", - "payloadType": "str", - "x": 90, - "y": 540, - "wires": [["99725e1437cc390b"]] - }, - { - "id": "f4e21e28bd903f6d", - "type": "yaml", - "z": "1371dec5.76e671", - "property": "payload", - "name": "", - "x": 390, - "y": 540, - "wires": [["d6264e3e29b68c6e", "aa84b912c996c69e", "fba22dc2c16b3ec8"]] - }, - { - "id": "d6264e3e29b68c6e", - "type": "change", - "z": "1371dec5.76e671", - "name": "Get version", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.version", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 590, - "y": 540, - "wires": [["3e64877a.9684b", "8343fa69.49339"]] - }, - { - "id": "aa84b912c996c69e", - "type": "change", - "z": "1371dec5.76e671", - "name": "Get repo", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.repo", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 580, - "y": 500, - "wires": [["fd55e7a43d9bdbbb"]] - }, - { - "id": "fd55e7a43d9bdbbb", - "type": "function", - "z": "1371dec5.76e671", - "name": "set global", - "func": "global.set(\"process_source\", msg.payload);\n", - "outputs": 1, - "timeout": "", - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 820, - "y": 480, - "wires": [[]] - }, - { - "id": "fba22dc2c16b3ec8", - "type": "change", - "z": "1371dec5.76e671", - "name": "Get commit", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.commit", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 590, - "y": 580, - "wires": [["2ddc75a4ac38a17f"]] - }, - { - "id": "2ddc75a4ac38a17f", - "type": "function", - "z": "1371dec5.76e671", - "name": "set global", - "func": "global.set(\"process_commit\", msg.payload);\n", - "outputs": 1, - "timeout": "", - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 820, - "y": 600, - "wires": [[]] - }, - { - "id": "797675a937dc1629", - "type": "ui_template", - "z": "1371dec5.76e671", - "group": "3da7da8f.179606", - "name": "Metrics panel", - "order": 2, - "width": "0", - "height": "0", - "format": "
\n

\n The instrument's system time is different from your web browser's time by {{drift}}.\n As a result, timestamps in your datasets will be incorrect.\n Additionally, system metrics will not be recorded or shown correctly.\n Additionally, you will see incorrectly-aligned graphs in the metrics below.\n

\n

Please change the instrument's system time or your web browser's time to accurate values.

\n

\n \n

\n
\n\n
\n

Loading system metrics, please wait...

\n
\n\n
\n \n
\n\n\n", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "className": "", - "x": 330, - "y": 280, - "wires": [[]] - }, - { - "id": "aa2e4cd182dbc776", - "type": "function", - "z": "1371dec5.76e671", - "name": "Get system time", - "func": "var date = new Date();\ndate.setSeconds(0, 0);\nmsg.payload = (\n date.toISOString().replace('T', ' ').replace(/:\\d+\\.\\d+Z/,' UTC')\n);\nreturn msg", - "outputs": 1, - "timeout": "", - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 340, - "y": 240, - "wires": [["7c9ee522f6dbd3b0"]] - }, - { - "id": "7c9ee522f6dbd3b0", - "type": "ui_text", - "z": "1371dec5.76e671", - "group": "ce9e278.781eed8", - "order": 5, - "width": 0, - "height": 0, - "name": "", - "label": "System Time", - "format": "{{msg.payload}}", - "layout": "row-spread", - "className": "", - "style": false, - "font": "", - "fontSize": "", - "color": "#000000", - "x": 590, - "y": 240, - "wires": [] - }, - { - "id": "6dc9862f2eebe935", - "type": "http in", - "z": "1371dec5.76e671", - "name": "POST /api/system-time", - "url": "/api/system-time", - "method": "post", - "upload": false, - "swaggerDoc": "", - "x": 120, - "y": 360, - "wires": [["a7994a561866dc94", "dea222e9a6553cac"]] - }, - { - "id": "1c4113d4c933fd4b", - "type": "ui_toast", - "z": "1371dec5.76e671", - "position": "top right", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 0, - "ok": "OK", - "cancel": "", - "raw": false, - "className": "", - "topic": "Setting system time", - "name": "", - "x": 610, - "y": 340, - "wires": [] - }, - { - "id": "a7994a561866dc94", - "type": "function", - "z": "1371dec5.76e671", - "name": "Get system time", - "func": "var date = new Date(msg.payload.timestamp);\nmsg.payload = (\n date.toISOString().replace('T', ' ').replace(/:\\d+\\.\\d+Z/,' UTC')\n);\nreturn msg", - "outputs": 1, - "timeout": "", - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 340, - "y": 340, - "wires": [["1c4113d4c933fd4b", "423659c62bae0524"]] - }, - { - "id": "814ce40bfc413777", - "type": "exec", - "z": "1371dec5.76e671", - "command": "sudo date -s", - "addpay": "payload", - "append": "", - "useSpawn": "", - "timer": "", - "winHide": false, - "name": "Set system time", - "x": 600, - "y": 380, - "wires": [[], [], []] - }, - { - "id": "dea222e9a6553cac", - "type": "function", - "z": "1371dec5.76e671", - "name": "Prepare timestamp", - "func": "msg.payload = ('@' + msg.payload.timestamp).slice(0, -3);\nreturn msg;", - "outputs": 1, - "timeout": "", - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 350, - "y": 380, - "wires": [["814ce40bfc413777"]] - }, - { - "id": "f6f570b10c675854", - "type": "ui_template", - "z": "1371dec5.76e671", - "group": "ce9e278.781eed8", - "name": "Browser time", - "order": 6, - "width": "6", - "height": "1", - "format": "
\n

Browser Time

\n

{{time}}

\n
\n\n", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": false, - "templateScope": "local", - "className": "", - "x": 330, - "y": 200, - "wires": [[]] - }, - { - "id": "3822b843fda94733", - "type": "http in", - "z": "1371dec5.76e671", - "name": "GET /api/system-time", - "url": "/api/system-time", - "method": "get", - "upload": false, - "swaggerDoc": "", - "x": 120, - "y": 420, - "wires": [["5b0a65d3fe187424"]] - }, - { - "id": "5b0a65d3fe187424", - "type": "function", - "z": "1371dec5.76e671", - "name": "Get system time", - "func": "var date = new Date();\nmsg.payload = {'timestamp': date.getTime()};\nreturn msg", - "outputs": 1, - "timeout": "", - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 340, - "y": 420, - "wires": [["312a15407574b38e"]] - }, - { - "id": "423659c62bae0524", - "type": "http response", - "z": "1371dec5.76e671", - "name": "Send POST response", - "statusCode": "", - "headers": {}, - "x": 620, - "y": 300, - "wires": [] - }, - { - "id": "312a15407574b38e", - "type": "http response", - "z": "1371dec5.76e671", - "name": "Send GET response", - "statusCode": "", - "headers": { - "Content-Type": "application/json; charset=UTF-8" - }, - "x": 620, - "y": 420, - "wires": [] - }, - { - "id": "1fdf77b5.24e4e", - "type": "mqtt in", - "z": "9a22e67a.378818", - "name": "", - "topic": "status/#", - "qos": "0", - "datatype": "json", - "broker": "8dc3722c.06efa8", - "nl": false, - "rap": false, - "inputs": 0, - "x": 290, - "y": 340, - "wires": [["fa73983d.318188"]] - }, - { - "id": "4a1e9e3e.27506", - "type": "switch", - "z": "9a22e67a.378818", - "name": "Filter segmenter out", - "property": "topic", - "propertyType": "msg", - "rules": [ - { - "t": "else" - }, - { - "t": "cont", - "v": "status/segmenter", - "vt": "str" - } - ], - "checkall": "true", - "repair": false, - "outputs": 2, - "x": 620, - "y": 340, - "wires": [["58f2e0f.4e8b12"], ["dcf5bd45.16a8d"]] - }, - { - "id": "fa73983d.318188", - "type": "json", - "z": "9a22e67a.378818", - "name": "", - "property": "payload", - "action": "obj", - "pretty": true, - "x": 430, - "y": 340, - "wires": [["4a1e9e3e.27506"]] - }, - { - "id": "58f2e0f.4e8b12", - "type": "link out", - "z": "9a22e67a.378818", - "name": "Fluidic module status", - "links": ["bb628f8d.98f108"], - "x": 795, - "y": 320, - "wires": [] - }, - { - "id": "dcf5bd45.16a8d", - "type": "link out", - "z": "9a22e67a.378818", - "name": "Segmenter module status", - "links": ["25867454.a8e334"], - "x": 795, - "y": 360, - "wires": [] - }, - { - "id": "e41870d7.300eb8", - "type": "link out", - "z": "1eaf21c8.f7a21e", - "name": "Stepper config change", - "mode": "link", - "links": ["438febd245a9f73c"], - "x": 1495, - "y": 380, - "wires": [] - }, - { - "id": "2068e7f.f4efb18", - "type": "delay", - "z": "1eaf21c8.f7a21e", - "name": "", - "pauseType": "delay", - "timeout": "1", - "timeoutUnits": "seconds", - "rate": "1", - "nbRateUnits": "1", - "rateUnits": "second", - "randomFirst": "1", - "randomLast": "5", - "randomUnits": "seconds", - "drop": false, - "outputs": 1, - "x": 1180, - "y": 380, - "wires": [["e41870d7.300eb8"]] - }, - { - "id": "8e3b3d3c.955148", - "type": "subflow:4ed26b8b.253504", - "z": "1eaf21c8.f7a21e", - "name": "", - "env": [], - "x": 1220, - "y": 420, - "wires": [] - }, - { - "id": "54ba7f16.709ad8", - "type": "change", - "z": "1eaf21c8.f7a21e", - "name": "Get pump_steps_per_ml", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.pump_steps_per_ml", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 670, - "y": 400, - "wires": [["ee58b91c.396108"]] - }, - { - "id": "ee58b91c.396108", - "type": "ui_text_input", - "z": "1eaf21c8.f7a21e", - "name": "pump_steps_per_ml", - "label": "Pump: steps per mL", - "tooltip": "", - "group": "6be36295.0ab324", - "order": 6, - "width": 0, - "height": 0, - "passthru": false, - "mode": "number", - "delay": "2000", - "topic": "pump_steps_per_ml", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 940, - "y": 400, - "wires": [["2068e7f.f4efb18", "8e3b3d3c.955148"]] - }, - { - "id": "7534dfd9.8cf3e8", - "type": "ui_template", - "z": "1eaf21c8.f7a21e", - "group": "6be36295.0ab324", - "name": "Information", - "order": 1, - "width": "8", - "height": "3", - "format": "
\n

\n Changing one of these values will cause the Python hardware controller to restart, to reload the new hardware configuration.\n

\n

\n Warning: selecting a hardware version from the dropdown menu below will also overwrite all of your hardware settings, including your camera white balance settings.\n

\n

\n If you are not sure, you probably should not be touching anything here!\n

\n
\n", - "storeOutMessages": true, - "fwdInMessages": true, - "resendOnRefresh": true, - "templateScope": "local", - "className": "", - "x": 610, - "y": 40, - "wires": [[]] - }, - { - "id": "a7e5c7f4.644678", - "type": "ui_dropdown", - "z": "1eaf21c8.f7a21e", - "name": "", - "label": "Hardware version", - "tooltip": "", - "place": "Select option", - "group": "6be36295.0ab324", - "order": 2, - "width": 0, - "height": 0, - "passthru": false, - "multiple": false, - "options": [ - { - "label": "", - "value": "PlanktoScope v2.1", - "type": "str" - }, - { - "label": "", - "value": "PlanktoScope v2.3", - "type": "str" - }, - { - "label": "", - "value": "PlanktoScope v2.5", - "type": "str" - }, - { - "label": "", - "value": "PlanktoScope v2.6", - "type": "str" - }, - { - "label": "", - "value": "PlanktoScope v3.0", - "type": "str" - } - ], - "payload": "", - "topic": "acq_instrument", - "topicType": "str", - "className": "", - "x": 670, - "y": 160, - "wires": [["08d177136bd18281", "56dd3f82c45717f0"]] - }, - { - "id": "1cfadc66.3cde8c", - "type": "subflow:1c24ad9c.bebec2", - "z": "1eaf21c8.f7a21e", - "name": "", - "env": [], - "x": 510, - "y": 300, - "wires": [[]] - }, - { - "id": "3e2c5c1c.4c57b4", - "type": "function", - "z": "1eaf21c8.f7a21e", - "name": "Save global", - "func": "global.set(msg.topic,msg.payload);\nreturn msg;", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 350, - "y": 300, - "wires": [["1cfadc66.3cde8c"]] - }, - { - "id": "427c312.fc5e65", - "type": "subflow:1c24ad9c.bebec2", - "z": "1eaf21c8.f7a21e", - "name": "", - "env": [], - "x": 170, - "y": 140, - "wires": [["c00c6732b9f36adb"]] - }, - { - "id": "c67c305004f87e39", - "type": "change", - "z": "1eaf21c8.f7a21e", - "name": "Get process_pixel_fixed", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.process_pixel_fixed", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 670, - "y": 480, - "wires": [["244ca5dd62df2bcd"]] - }, - { - "id": "244ca5dd62df2bcd", - "type": "ui_text_input", - "z": "1eaf21c8.f7a21e", - "name": "process_pixel_fixed", - "label": "Pixel size calibration: um per pixel", - "tooltip": "Object size in µm / pixel. 0 will remove this calibration.", - "group": "6be36295.0ab324", - "order": 8, - "width": 0, - "height": 0, - "passthru": true, - "mode": "number", - "delay": "1000", - "topic": "process_pixel_fixed", - "sendOnBlur": true, - "className": "", - "topicType": "str", - "x": 940, - "y": 480, - "wires": [["8e3b3d3c.955148", "f9b47f4b1da15778"]] - }, - { - "id": "f9b47f4b1da15778", - "type": "function", - "z": "1eaf21c8.f7a21e", - "name": "Set or remove if null", - "func": "if (msg.payload == 0){\n global.set(msg.topic,undefined)\n}\nelse {\n global.set(msg.topic,msg.payload);\n}\n\nreturn msg", - "outputs": 1, - "noerr": 0, - "initialize": "", - "finalize": "", - "libs": [], - "x": 1220, - "y": 480, - "wires": [["5d5ad36d2c50dcc2"]] - }, - { - "id": "5d5ad36d2c50dcc2", - "type": "link out", - "z": "1eaf21c8.f7a21e", - "name": "Process_pixel calibration", - "links": [], - "x": 1495, - "y": 500, - "wires": [] - }, - { - "id": "6146ba22df928516", - "type": "ui_dropdown", - "z": "1eaf21c8.f7a21e", - "name": "acq_fnumber_objective", - "label": "M12 Lens", - "tooltip": "", - "place": "Select option", - "group": "6be36295.0ab324", - "order": 7, - "width": 0, - "height": 0, - "passthru": true, - "multiple": false, - "options": [ - { - "label": "f 25mm 1/2\" 5MP IR", - "value": 25, - "type": "num" - }, - { - "label": "f 16mm 1/2.5\" 5MP IR", - "value": 16, - "type": "num" - }, - { - "label": "f 12mm 1/2.5\" 5MP IR", - "value": 12, - "type": "num" - }, - { - "label": "f 8mm 1/2.5\" 5MP IR", - "value": 8, - "type": "num" - }, - { - "label": "f 6mm 1/2.5\" 5MP IR", - "value": 6, - "type": "num" - } - ], - "payload": "", - "topic": "acq_fnumber_objective", - "topicType": "str", - "x": 930, - "y": 520, - "wires": [["a6983d3232b570a7", "8e3b3d3c.955148"]] - }, - { - "id": "a6983d3232b570a7", - "type": "change", - "z": "1eaf21c8.f7a21e", - "name": "", - "rules": [ - { - "t": "set", - "p": "acq_fnumber_objective", - "pt": "global", - "to": "payload", - "tot": "msg" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 1260, - "y": 520, - "wires": [["5d5ad36d2c50dcc2"]] - }, - { - "id": "11955bbeefc29ab4", - "type": "change", - "z": "1eaf21c8.f7a21e", - "name": "Get acq_fnumber_objective", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.acq_fnumber_objective", - "tot": "msg" - }, - { - "t": "set", - "p": "topic", - "pt": "msg", - "to": "acq_fnumber_objective", - "tot": "str" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 680, - "y": 520, - "wires": [["6146ba22df928516"]] - }, - { - "id": "d276ce894f483bcf", - "type": "ui_toast", - "z": "1eaf21c8.f7a21e", - "position": "top right", - "displayTime": "3", - "highlight": "", - "sendall": true, - "outputs": 0, - "ok": "OK", - "cancel": "", - "raw": false, - "className": "", - "topic": "Resetting hardware configuration to version-specific default", - "name": "", - "x": 370, - "y": 260, - "wires": [] - }, - { - "id": "68703ef63da2f081", - "type": "change", - "z": "1eaf21c8.f7a21e", - "name": "Choose default hardware config", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "$join([\"/home/pi/PlanktoScope/device-backend/default-configs/\", $substringAfter(msg.payload, \"PlanktoScope \"), \".hardware.json\"])", - "tot": "jsonata" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 410, - "y": 220, - "wires": [["e3ba6ac89221b17b"]] - }, - { - "id": "e3ba6ac89221b17b", - "type": "exec", - "z": "1eaf21c8.f7a21e", - "command": "cp", - "addpay": "payload", - "append": "/home/pi/PlanktoScope/hardware.json", - "useSpawn": "false", - "timer": "", - "winHide": false, - "oldrc": false, - "name": "Copy default hardware config", - "x": 700, - "y": 220, - "wires": [["97e582080deae888"], [], []] - }, - { - "id": "97e582080deae888", - "type": "delay", - "z": "1eaf21c8.f7a21e", - "name": "", - "pauseType": "delay", - "timeout": "500", - "timeoutUnits": "milliseconds", - "rate": "1", - "nbRateUnits": "1", - "rateUnits": "second", - "randomFirst": "1", - "randomLast": "5", - "randomUnits": "seconds", - "drop": false, - "allowrate": false, - "outputs": 1, - "x": 930, - "y": 220, - "wires": [["3973b999ee7b3b1d"]] - }, - { - "id": "3973b999ee7b3b1d", - "type": "link out", - "z": "1eaf21c8.f7a21e", - "name": "Reload hardware config", - "mode": "link", - "links": [ - "438febd245a9f73c", - "4ebc0345e63a78e9", - "5984b086eddc9311", - "a2f2a4c7cbae4446" - ], - "x": 1095, - "y": 220, - "wires": [] - }, - { - "id": "3bcaf757cbc77fbe", - "type": "subflow:b7861ce703215a01", - "z": "1eaf21c8.f7a21e", - "name": "", - "x": 380, - "y": 440, - "wires": [["54ba7f16.709ad8", "c67c305004f87e39", "11955bbeefc29ab4"]] - }, - { - "id": "862235d10aae5b83", - "type": "inject", - "z": "1eaf21c8.f7a21e", - "name": "Once", - "props": [], - "repeat": "", - "crontab": "", - "once": true, - "onceDelay": 0.1, - "topic": "", - "x": 170, - "y": 460, - "wires": [["3bcaf757cbc77fbe"]] - }, - { - "id": "c00c6732b9f36adb", - "type": "change", - "z": "1eaf21c8.f7a21e", - "name": "Get acq_instrument", - "rules": [ - { - "t": "set", - "p": "payload", - "pt": "msg", - "to": "payload.acq_instrument", - "tot": "msg" - }, - { - "t": "set", - "p": "topic", - "pt": "msg", - "to": "acq_instrument", - "tot": "str" - } - ], - "action": "", - "property": "", - "from": "", - "to": "", - "reg": false, - "x": 370, - "y": 140, - "wires": [["a7e5c7f4.644678", "56dd3f82c45717f0"]] - }, - { - "id": "4ebc0345e63a78e9", - "type": "link in", - "z": "1eaf21c8.f7a21e", - "name": "Load hardware config", - "links": ["3973b999ee7b3b1d"], - "x": 205, - "y": 420, - "wires": [["3bcaf757cbc77fbe"]] - }, - { - "id": "cb9009e8a49e93cc", - "type": "link in", - "z": "1eaf21c8.f7a21e", - "name": "Set hardware version", - "links": ["08d177136bd18281", "9f34e4a2f33c4022"], - "x": 205, - "y": 260, - "wires": [ - [ - "68703ef63da2f081", - "d276ce894f483bcf", - "3e2c5c1c.4c57b4", - "a7e5c7f4.644678" - ] - ] - }, - { - "id": "08d177136bd18281", - "type": "link out", - "z": "1eaf21c8.f7a21e", - "name": "Set hardware version", - "mode": "link", - "links": ["cb9009e8a49e93cc"], - "x": 875, - "y": 160, - "wires": [] - }, - { - "id": "56dd3f82c45717f0", - "type": "link out", - "z": "1eaf21c8.f7a21e", - "name": "Hardware version loaded", - "mode": "link", - "links": ["a2f2a4c7cbae4446"], - "x": 875, - "y": 120, - "wires": [] - } + "reg": false, + "x": 320, + "y": 420, + "wires": [ + [ + "b67a7147.65fcd8" + ] + ] + }, + { + "id": "6c3a3b4.78cad44", + "type": "function", + "z": "eaae323a.31b3", + "name": "Toggle", + "func": "flow.set(\"shutdown\", !flow.get(\"shutdown\"))\nmsg.enabled = flow.get(\"shutdown\")\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 290, + "y": 380, + "wires": [ + [ + "b67a7147.65fcd8" + ] + ] + }, + { + "id": "d1153ad6.40d738", + "type": "ui_template", + "z": "eaae323a.31b3", + "group": "f3ca28ef.4df0a8", + "name": "Shutdown information", + "order": 1, + "width": 0, + "height": 0, + "format": "
To prevent data corruption, please always shutdown the machine before unplugging the unit.\n

\nRemember to first unlock the shutdown button.\n
", + "storeOutMessages": true, + "fwdInMessages": false, + "resendOnRefresh": true, + "templateScope": "local", + "x": 120, + "y": 320, + "wires": [ + [] + ] + }, + { + "id": "e08cfcb8.2a67e8", + "type": "link out", + "z": "eaae323a.31b3", + "name": "Home shutdown button", + "links": [ + "b81b990a.d4dca" + ], + "x": 715, + "y": 500, + "wires": [] + }, + { + "id": "ce7087fc.dcc9e8", + "type": "ui_toast", + "z": "eaae323a.31b3", + "position": "dialog", + "displayTime": "10", + "highlight": "", + "sendall": true, + "outputs": 1, + "ok": "OK", + "cancel": "", + "raw": false, + "topic": "Turning off now!", + "name": "Shutdown message", + "x": 580, + "y": 540, + "wires": [ + [] + ] + }, + { + "id": "7d1626a0.deb85", + "type": "change", + "z": "eaae323a.31b3", + "name": "shutdown!", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "shutdown", + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 310, + "y": 500, + "wires": [ + [ + "e08cfcb8.2a67e8" + ] + ] + }, + { + "id": "8f1b8e23.daafe", + "type": "switch", + "z": "eaae323a.31b3", + "name": "", + "property": "payload", + "propertyType": "msg", + "rules": [ + { + "t": "eq", + "v": "NO!", + "vt": "str" + }, + { + "t": "else" + } + ], + "checkall": "true", + "repair": false, + "outputs": 2, + "x": 150, + "y": 500, + "wires": [ + [ + "d58039a9.6e7928" + ], + [ + "7d1626a0.deb85", + "281a56c9.ec7902" + ] + ] + }, + { + "id": "281a56c9.ec7902", + "type": "change", + "z": "eaae323a.31b3", + "name": "Shutdown message", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "Please wait a minute before disconnecting the machine from its power supply!", + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 340, + "y": 540, + "wires": [ + [ + "ce7087fc.dcc9e8" + ] + ] + }, + { + "id": "57db4f6279b5afe0", + "type": "comment", + "z": "eaae323a.31b3", + "name": "LICENSE", + "info": "Copyright 2022 Thibaut Pollina and Romain Bazile\nLicensed under GPL v3.0", + "x": 140, + "y": 600, + "wires": [] + }, + { + "id": "6af85f0e0fc21b11", + "type": "ui_ui_control", + "z": "eaae323a.31b3", + "name": "", + "events": "all", + "x": 700, + "y": 720, + "wires": [ + [] + ] + }, + { + "id": "382f8fcc81f904f1", + "type": "ui_dropdown", + "z": "eaae323a.31b3", + "name": "", + "label": "Hardware version", + "tooltip": "", + "place": "Select option", + "group": "0035a03e1490cd8c", + "order": 2, + "width": 0, + "height": 0, + "passthru": false, + "multiple": false, + "options": [ + { + "label": "", + "value": "PlanktoScope v2.3", + "type": "str" + }, + { + "label": "", + "value": "PlanktoScope v2.5", + "type": "str" + }, + { + "label": "", + "value": "PlanktoScope v2.6", + "type": "str" + }, + { + "label": "", + "value": "PlanktoScope v3.0", + "type": "str" + } + ], + "payload": "", + "topic": "acq_instrument", + "topicType": "str", + "className": "", + "x": 490, + "y": 640, + "wires": [ + [ + "9f34e4a2f33c4022" + ] + ] + }, + { + "id": "9f34e4a2f33c4022", + "type": "link out", + "z": "eaae323a.31b3", + "name": "Set hardware version", + "mode": "link", + "links": [ + "cb9009e8a49e93cc" + ], + "x": 655, + "y": 640, + "wires": [] + }, + { + "id": "e954204b947a0c70", + "type": "switch", + "z": "eaae323a.31b3", + "name": "", + "property": "payload", + "propertyType": "msg", + "rules": [ + { + "t": "null" + }, + { + "t": "else" + } + ], + "checkall": "true", + "repair": false, + "outputs": 2, + "x": 290, + "y": 680, + "wires": [ + [ + "382f8fcc81f904f1", + "e3736dd7be4b7522" + ], + [ + "f80babd43aa7cce4" + ] + ] + }, + { + "id": "e3736dd7be4b7522", + "type": "change", + "z": "eaae323a.31b3", + "name": "Show setup panel", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "{\"group\":{\"show\":[\"Home_Setup\"],\"hide\":[\"Home_Group_1\",\"Home_Group_2\",\"Home_Group_3\",\"Home_Group_4\",\"Home_Group_5\",\"Home_Group_6\"]}}", + "tot": "json" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 490, + "y": 680, + "wires": [ + [ + "6af85f0e0fc21b11" + ] + ] + }, + { + "id": "f80babd43aa7cce4", + "type": "change", + "z": "eaae323a.31b3", + "name": "Show home buttons", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "{\"group\":{\"hide\":[\"Home_Setup\"],\"show\":[\"Home_Group_1\",\"Home_Group_2\",\"Home_Group_3\",\"Home_Group_4\",\"Home_Group_5\",\"Home_Group_6\"]}}", + "tot": "json" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 500, + "y": 720, + "wires": [ + [ + "6af85f0e0fc21b11" + ] + ] + }, + { + "id": "438439b4ae62444c", + "type": "ui_template", + "z": "eaae323a.31b3", + "group": "0035a03e1490cd8c", + "name": "Information", + "order": 1, + "width": "0", + "height": "0", + "format": "
\n

\n To start using your PlanktoScope, please indicate the version of your PlanktoScope hardware:\n

\n
\n", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": true, + "templateScope": "local", + "className": "", + "x": 710, + "y": 680, + "wires": [ + [] + ] + }, + { + "id": "a2f2a4c7cbae4446", + "type": "link in", + "z": "eaae323a.31b3", + "name": "Load hardware version", + "links": [ + "3973b999ee7b3b1d", + "56dd3f82c45717f0" + ], + "x": 185, + "y": 680, + "wires": [ + [ + "e954204b947a0c70" + ] + ] + }, + { + "id": "4557d689.a4fa88", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "sample_ship", + "label": "Name of the ship", + "tooltip": "", + "group": "3e1ba03d.f01d8", + "order": 2, + "width": 0, + "height": 0, + "passthru": true, + "mode": "text", + "delay": "300", + "topic": "sample_ship", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 670, + "y": 80, + "wires": [ + [ + "9f501f49.45645" + ] + ] + }, + { + "id": "fcfc31ae.af3af", + "type": "ui_dropdown", + "z": "b771c342.49603", + "name": "sample_sampling_gear", + "label": "Sampling gear*", + "tooltip": "", + "place": "Choose from list", + "group": "3e1ba03d.f01d8", + "order": 6, + "width": 0, + "height": 0, + "passthru": true, + "multiple": false, + "options": [ + { + "label": "High Speed Net", + "value": "net_hsn", + "type": "str" + }, + { + "label": "Tara Decknet", + "value": "net_decknet", + "type": "str" + }, + { + "label": "Plankton net", + "value": "net", + "type": "str" + }, + { + "label": "Niskin bottle 12L", + "value": "niskin_12L", + "type": "str" + }, + { + "label": "Niskin bottle 24L", + "value": "niskin_24L", + "type": "str" + }, + { + "label": "Pass Hull", + "value": "pass_hull", + "type": "str" + }, + { + "label": "Single location (with net or bucket)", + "value": "single_location", + "type": "str" + }, + { + "label": "Lab culture", + "value": "culture", + "type": "str" + }, + { + "label": "Test", + "value": "test", + "type": "str" + } + ], + "payload": "", + "topic": "sample_sampling_gear", + "topicType": "str", + "className": "", + "x": 630, + "y": 200, + "wires": [ + [ + "9f501f49.45645", + "46eb1bf8.3dc5f4", + "3ac7b631f5d8ef90" + ] + ] + }, + { + "id": "82c5fc77.59c97", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "sample_operator", + "label": "Name of the operator*", + "tooltip": "", + "group": "3e1ba03d.f01d8", + "order": 3, + "width": 0, + "height": 0, + "passthru": true, + "mode": "text", + "delay": "300", + "topic": "sample_operator", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 650, + "y": 160, + "wires": [ + [ + "9f501f49.45645" + ] + ] + }, + { + "id": "9c882b37.fde668", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "sample_project", + "label": "Name of the project*", + "tooltip": "", + "group": "3e1ba03d.f01d8", + "order": 1, + "width": 0, + "height": 0, + "passthru": true, + "mode": "text", + "delay": "300", + "topic": "sample_project", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 660, + "y": 40, + "wires": [ + [ + "9f501f49.45645" + ] + ] + }, + { + "id": "94eb4221.9b92c", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "sample_id", + "label": "Station ID*", + "tooltip": "", + "group": "3e1ba03d.f01d8", + "order": 4, + "width": 0, + "height": 0, + "passthru": true, + "mode": "text", + "delay": "300", + "topic": "sample_id", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 670, + "y": 120, + "wires": [ + [ + "9f501f49.45645" + ] + ] + }, + { + "id": "9f501f49.45645", + "type": "function", + "z": "b771c342.49603", + "name": "set global", + "func": "global.set(msg.topic,msg.payload);", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 1080, + "y": 200, + "wires": [ + [] + ] + }, + { + "id": "222c851d.5d0a3a", + "type": "ui_ui_control", + "z": "b771c342.49603", + "name": "", + "events": "change", + "x": 400, + "y": 880, + "wires": [ + [] + ] + }, + { + "id": "52f6b103.1efb6", + "type": "ui_toast", + "z": "b771c342.49603", + "position": "dialog", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 1, + "ok": "OK", + "cancel": "", + "raw": false, + "topic": "", + "name": "", + "x": 710, + "y": 980, + "wires": [ + [] + ] + }, + { + "id": "986d960a.c75908", + "type": "function", + "z": "b771c342.49603", + "name": "Check form", + "func": "var sample_project= global.get(\"sample_project\");\nvar sample_id= global.get(\"sample_id\");\nvar sample_operator= global.get(\"sample_operator\");\nvar sample_sampling_gear= global.get(\"sample_sampling_gear\");\nvar object_lat= global.get(\"object_lat\");\nvar object_lon= global.get(\"object_lon\");\nvar object_date= global.get(\"object_date\");\nvar object_time= global.get(\"object_time\");\nif (sample_project === undefined || sample_project === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Sample project\"\n return [null, msg];\n}\n\nelse if (sample_id === undefined || sample_id === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Sample ID\"\n return [null, msg];\n}\n\nelse if (sample_operator === undefined || sample_operator === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Sample operator\"\n return [null, msg];\n}\n\nelse if (sample_sampling_gear === undefined || sample_sampling_gear === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Sample sampling gear\"\n return [null, msg];\n}\n\nelse if (object_lat === undefined || object_lat === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Latitude of sample\"\n return [null, msg];\n}\n\nelse if (object_lon === undefined || object_lon === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Longitude of sample\"\n return [null, msg];\n}\n\nelse if (object_date === undefined || object_date === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Date of sample\"\n return [null, msg];\n}\n\nelse if (object_time === undefined || object_time === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Time of sample\"\n return [null, msg];\n}\nelse if (sample_sampling_gear.startsWith(\"net\")){\n var object_lat_end = global.get(\"object_lat_end\");\n var object_lon_end = global.get(\"object_lon_end\");\n var object_date_end = global.get(\"object_date_end\");\n var object_time_end = global.get(\"object_time_end\");\n var sample_gear_net_opening = global.get(\"sample_gear_net_opening\");\n\n if (object_lat_end === undefined || object_lat_end === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Latitude of retrieval\"\n return [null, msg];\n }\n \n else if (object_lon_end === undefined || object_lon_end === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Longitude of retrieval\"\n return [null, msg];\n }\n \n else if (object_date_end === undefined || object_date_end === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Date of retrieval\"\n return [null, msg];\n }\n \n else if (object_time_end === undefined || object_time_end === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Time of retrieval\"\n return [null, msg];\n }\n \n else if (sample_gear_net_opening === undefined || sample_gear_net_opening === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Net opening dimension\"\n return [null, msg];\n }\n \n if (sample_sampling_gear == \"net_decknet\"){\n var sample_total_volume = global.get(\"sample_total_volume\");\n if (sample_total_volume === undefined || sample_total_volume === \"\") {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Decknet flowmeter readings\"\n return [null, msg];\n }\n }\n}\nmsg.topic = \"config_save\"\nmsg.payload={\"tab\":\"Optic Configuration\"};\n\nreturn [msg, null];", + "outputs": 2, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 470, + "y": 940, + "wires": [ + [ + "726a7822.cd6298", + "e2b277c1.07283" + ], + [ + "52f6b103.1efb6" + ] + ], + "outputLabels": [ + "message", + "error" + ] + }, + { + "id": "726a7822.cd6298", + "type": "ui_ui_control", + "z": "b771c342.49603", + "name": "", + "events": "change", + "x": 700, + "y": 900, + "wires": [ + [] + ] + }, + { + "id": "16de754c.cc969b", + "type": "ui_button", + "z": "b771c342.49603", + "name": "", + "group": "5517c651.b2f668", + "order": 1, + "width": 5, + "height": 1, + "passthru": false, + "label": "Previous", + "tooltip": "", + "color": "#097479", + "bgcolor": "white", + "icon": "keyboard_return", + "payload": "{\"tab\":\"Home\"}", + "payloadType": "json", + "topic": "", + "x": 240, + "y": 880, + "wires": [ + [ + "222c851d.5d0a3a" + ] + ] + }, + { + "id": "84f3d040.5f7ea", + "type": "ui_button", + "z": "b771c342.49603", + "name": "", + "group": "5517c651.b2f668", + "order": 2, + "width": 5, + "height": 1, + "passthru": false, + "label": "Continue", + "tooltip": "", + "color": "#097479", + "bgcolor": "white", + "icon": "keyboard_tab", + "payload": "{\"tab\":\"Home\"}", + "payloadType": "json", + "topic": "", + "x": 240, + "y": 940, + "wires": [ + [ + "986d960a.c75908" + ] + ] + }, + { + "id": "d027a6bf.7049e8", + "type": "function", + "z": "b771c342.49603", + "name": "get sample_projet", + "func": "msg.payload = msg.payload.sample_project;\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 310, + "y": 40, + "wires": [ + [ + "9c882b37.fde668" + ] + ] + }, + { + "id": "5a811caf.0f3144", + "type": "function", + "z": "b771c342.49603", + "name": "get sample_ship", + "func": "msg.payload = msg.payload.sample_ship;\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 300, + "y": 80, + "wires": [ + [ + "4557d689.a4fa88" + ] + ] + }, + { + "id": "45911c98.2bd83c", + "type": "function", + "z": "b771c342.49603", + "name": "get sample_id", + "func": "msg.payload = msg.payload.sample_id;\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 300, + "y": 120, + "wires": [ + [ + "94eb4221.9b92c" + ] + ] + }, + { + "id": "1e09a4ab.72996b", + "type": "function", + "z": "b771c342.49603", + "name": "get sample_operator", + "func": "msg.payload = msg.payload.sample_operator;\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 320, + "y": 160, + "wires": [ + [ + "82c5fc77.59c97" + ] + ] + }, + { + "id": "a3272681.f271c8", + "type": "function", + "z": "b771c342.49603", + "name": "get sample_sampling_gear", + "func": "msg.topic = \"sample_sampling_gear\"\nif (msg.payload.sample_sampling_gear === undefined){\n msg.payload = \"net\";\n}\nelse\n{\n msg.payload = msg.payload.sample_sampling_gear;\n}\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 340, + "y": 200, + "wires": [ + [ + "fcfc31ae.af3af" + ] + ] + }, + { + "id": "a6907a38.f6611", + "type": "subflow:1c24ad9c.bebec2", + "z": "b771c342.49603", + "name": "", + "env": [], + "x": 70, + "y": 220, + "wires": [ + [ + "d027a6bf.7049e8", + "5a811caf.0f3144", + "45911c98.2bd83c", + "1e09a4ab.72996b", + "8dff1648.82e42", + "9f04c5ec.75f3d8", + "f408a273.4fb538", + "e73fd87d.d24e4", + "489c8e06.cc7d6", + "a3272681.f271c8" + ] + ] + }, + { + "id": "e2b277c1.07283", + "type": "subflow:1c24ad9c.bebec2", + "z": "b771c342.49603", + "name": "", + "env": [], + "x": 690, + "y": 940, + "wires": [ + [] + ] + }, + { + "id": "9c7f7fc9.c8d3a", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "object_depth_max", + "label": "Max sampling depth (m)", + "tooltip": "in m", + "group": "3e1ba03d.f01d8", + "order": 10, + "width": 5, + "height": 1, + "passthru": true, + "mode": "number", + "delay": "300", + "topic": "object_depth_max", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 650, + "y": 240, + "wires": [ + [ + "9f501f49.45645" + ] + ] + }, + { + "id": "317eeeb7.8d3042", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "object_depth_min", + "label": "Min sampling depth (m)", + "tooltip": "in m", + "group": "3e1ba03d.f01d8", + "order": 9, + "width": 5, + "height": 1, + "passthru": true, + "mode": "number", + "delay": "300", + "topic": "object_depth_min", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 650, + "y": 280, + "wires": [ + [ + "9f501f49.45645" + ] + ] + }, + { + "id": "cbb123ab.fd3428", + "type": "ui_ui_control", + "z": "b771c342.49603", + "name": "show/hide net groups", + "events": "change", + "x": 1320, + "y": 300, + "wires": [ + [] + ] + }, + { + "id": "642ff403.1ed91c", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "sample_concentrated_sample_volume", + "label": "Concentrated sample volume (mL)", + "tooltip": "Volume extracted from the net codend (in mL)", + "group": "3e1ba03d.f01d8", + "order": 12, + "width": 10, + "height": 1, + "passthru": true, + "mode": "number", + "delay": "300", + "topic": "sample_concentrated_sample_volume", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 590, + "y": 440, + "wires": [ + [ + "9f501f49.45645" + ] + ] + }, + { + "id": "e967b844.46aa48", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "sample_gear_net_opening", + "label": "Net opening dimension (mm)", + "tooltip": "Size of the net mouth opening (in mm)", + "group": "cf5d9f0e.d57e7", + "order": 1, + "width": 10, + "height": 1, + "passthru": true, + "mode": "number", + "delay": "300", + "topic": "sample_gear_net_opening", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 620, + "y": 320, + "wires": [ + [ + "9f501f49.45645" + ] + ] + }, + { + "id": "c0ce5626.b6c5", + "type": "ui_toast", + "z": "b771c342.49603", + "position": "dialog", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 1, + "ok": "OK", + "cancel": "", + "raw": false, + "topic": "", + "name": "", + "x": 1230, + "y": 620, + "wires": [ + [] + ] + }, + { + "id": "c33f1124.af6688", + "type": "ui_form", + "z": "b771c342.49603", + "name": "sample_location", + "label": "Sample Location", + "group": "cef1e703.bcf3c8", + "order": 1, + "width": 0, + "height": 0, + "options": [ + { + "label": "Latitude (36.574439°N or 36°57.4439'N)", + "value": "object_lat", + "type": "text", + "required": true, + "rows": null + }, + { + "label": "Longitude (110.42100°W or 110°4.2100'W)", + "value": "object_lon", + "type": "text", + "required": true, + "rows": null + }, + { + "label": "Date (YYYY-MM-DD, UTC)", + "value": "object_date", + "type": "text", + "required": true, + "rows": null + }, + { + "label": "Time (HH:MM(:SS), UTC 24h)", + "value": "object_time", + "type": "text", + "required": true, + "rows": null + } + ], + "formValue": { + "object_lat": "", + "object_lon": "", + "object_date": "", + "object_time": "" + }, + "payload": "", + "submit": "Validate", + "cancel": "Reset", + "topic": "sample_location", + "x": 660, + "y": 580, + "wires": [ + [ + "14658615.47c862", + "a9fb1f4b83fc25a7" + ] + ] + }, + { + "id": "358908cd.416ab", + "type": "ui_form", + "z": "b771c342.49603", + "name": "net_throw_location", + "label": "Net Throw Location", + "group": "cf5d9f0e.d57e7", + "order": 3, + "width": 0, + "height": 0, + "options": [ + { + "label": "Latitude (36.574439°N or 36°57.4439'N)", + "value": "object_lat", + "type": "text", + "required": true, + "rows": null + }, + { + "label": "Longitude (110.42100°W or 110°4.2100'W)", + "value": "object_lon", + "type": "text", + "required": true, + "rows": null + }, + { + "label": "Date (YYYY-MM-DD UTC)", + "value": "object_date", + "type": "text", + "required": true, + "rows": null + }, + { + "label": "Time (HH:MM, UTC 24h)", + "value": "object_time", + "type": "text", + "required": true, + "rows": null + } + ], + "formValue": { + "object_lat": "", + "object_lon": "", + "object_date": "", + "object_time": "" + }, + "payload": "", + "submit": "Validate", + "cancel": "", + "topic": "net_throw_location", + "topicType": "str", + "splitLayout": false, + "className": "", + "x": 650, + "y": 620, + "wires": [ + [ + "14658615.47c862", + "ad54b89540460d27" + ] + ] + }, + { + "id": "56d40584.eff4e4", + "type": "ui_form", + "z": "b771c342.49603", + "name": "net_retrieval_location", + "label": "Net Retrieval Location", + "group": "cf5d9f0e.d57e7", + "order": 4, + "width": 0, + "height": 0, + "options": [ + { + "label": "Latitude (36.574439°N or 36°57.4439'N)", + "value": "object_lat_end", + "type": "text", + "required": true, + "rows": null + }, + { + "label": "Longitude (110.42100°W or 110°4.2100'W)", + "value": "object_lon_end", + "type": "text", + "required": true, + "rows": null + }, + { + "label": "Date (YYYY-MM-DD UTC)", + "value": "object_date_end", + "type": "text", + "required": true, + "rows": null + }, + { + "label": "Time (HH:MM, UTC 24h)", + "value": "object_time_end", + "type": "text", + "required": true, + "rows": null + } + ], + "formValue": { + "object_lat_end": "", + "object_lon_end": "", + "object_date_end": "", + "object_time_end": "" + }, + "payload": "", + "submit": "Validate", + "cancel": "", + "topic": "net_retrieval_location", + "topicType": "str", + "splitLayout": false, + "x": 640, + "y": 660, + "wires": [ + [ + "14658615.47c862", + "c21bf0244e67e40a" + ] + ] + }, + { + "id": "14658615.47c862", + "type": "function", + "z": "b771c342.49603", + "name": "Validate Location / Timestamp", + "func": "// Code added here will be run once\n// whenever the node is started.\nfunction ConvertDDMMToDD(input) {\n // Input Format 36°57.4439'N, 110°4.2100'W\n // From https://stackoverflow.com/questions/1140189/converting-latitude-and-longitude-to-decimal-values\n if (!input.match(/\\d+°\\d+\\.*\\d*\\'[NSEW]/)){\n \treturn \"parsing error\"\n }\n var parts = input.split(/[^\\d.\\w]+/)\n if (parts.length != 3){\n \treturn \"parsing error\"\n }\n var dd = Number(parts[0]) + Number(parts[1])/60\n return dd.toFixed(6) + parts[2]\n}\n\nfunction ValidateCoordinates(input, lat){\n // Input Format 36.574439°N, 110.42100°W\n // Or 36°57.4439'N, 110°4.2100'W\n if (input.match(\"'\")){\n input = ConvertDDMMToDD(input)\n }\n \n var error = {}\n\n if (input.startsWith(\"parsing error\")){\n error.topic = \"Error with the \"\n error.payload = \"You need to respect the format example, 36.574439°N or 36°57.4439'N\"\n return [null, error]\n }\n \n var direction = input.match(/[NSEW]/)\n var position = input.match(/[\\+\\-\\d\\.]+/)\n \n if (direction === null){\n error.topic = \"Error with the \"\n error.payload = \"You need to explicitely enter N/S/E/W\"\n return [null, error]\n }\n \n // Test that position is only made of digits!\n if(/^[\\+\\-]/.test(position)){\n error.topic = \"Error with the \"\n error.payload = \"Use of +/- sign is inconsistent with N/S/E/W letter! Please only use N/S/E/W!\"\n return [null, error]\n }\n \n var dd = Number(position)\n if (lat){\n // Check latitude\n if (direction == \"S\" || direction == \"N\") {\n if (dd>90.0){\n error.topic = \"Error with the \"\n error.payload = \"Latitude is more than 90°\"\n return [null, error]\n }\n }\n if (direction == \"W\" || direction == \"E\") {\n error.topic = \"Error with the \"\n error.payload = \"This is not a Latitude!\"\n return [null, error]\n }\n }\n else{\n // Check longitude\n if (direction == \"W\" || direction == \"E\") {\n if (dd>180.0){\n error.topic = \"Error with the \"\n error.payload = \"Longitude is more than 180°\"\n return [null, error]\n }\n }\n if (direction == \"N\" || direction == \"S\") {\n error.topic = \"Error with the \"\n error.payload = \"This is not a Longitude!\"\n return [null, error]\n }\n }\n \n if (direction == \"S\" || direction == \"W\") {\n dd = dd * -1\n } // Don't do anything for N or E\n return [dd.toFixed(4), null]\n \n}\n\nfunction ValidateDate(input){\n // Input Format 2020-12-25\n var error = {};\n \n if (! /20\\d{2}-[0-1]\\d-[0-3]\\d/.test(input)){\n error.topic = \"Error with the date\";\n error.payload = \"The date should respect the ISO format YYYY-MM-DD\";\n return [null, error];\n }\n else {\n var date = input.match(/\\d+/g);\n if (!((2000 < date[0]) && (date[0] < 2100))){\n error.topic = \"Error with the date\"\n error.payload = \"The year should be between 2000 and 2100\"\n return [null, error]\n }\n else if (!((0 < date[1]) && (date[1] <= 12))){\n error.topic = \"Error with the date\"\n error.payload = \"The month should be between 01 and 12\"\n return [null, error]\n }\n else if (!((0 < date[2]) && (date[2] <= 31))){\n error.topic = \"Error with the date\"\n error.payload = \"The day should be between 01 and 31\"\n return [null, error]\n }\n }\n return [input.replace(/-/g, ''), null]\n}\n\nfunction ValidateTime(input){\n // Input Format 12:00\n var error = {}\n \n if (! /[0-2]?\\d:[0-5]\\d/.test(input)){\n error.topic = \"Error with the time\"\n error.payload = \"The date should respect the ISO format HH:MM\"\n return [null, error]\n }\n else {\n var time = input.match(/\\d+/g)\n \n if (!((0 <= time[0]) && (time[0] < 24))){\n error.topic = \"Error with the time\"\n error.payload = \"The hours should be 0 and 23.\"\n return [null, error]\n }\n else if (!((0 <= time[1]) && (time[1] < 60))){\n error.topic = \"Error with the time\"\n error.payload = \"The minutes should be between 0 and 59\"\n return [null, error]\n }\n }\n return [input.replace(/:/g, ''), null]\n}\n\n\nvar ret\nvar payload_for_form = {payload:{}}\nmsg.valid = false\n\nif (msg.topic == \"culture_timestamp\"){\n ret = ValidateDate(msg.payload.object_date)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_date\", ret[0])\n \n ret = ValidateTime(msg.payload.object_time)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_time\", ret[0])\n return [{topic: \"Date and time format valid!\", payload: \"All good!\", valid: true}, payload_for_form]\n}\nelse if (msg.topic == \"net_retrieval_location\"){\n ret = ValidateCoordinates(msg.payload.object_lat_end, true);\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" Latitude\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_lat_end\", ret[0])\n ret = ValidateCoordinates(msg.payload.object_lon_end, false)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" Longitude\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_lon_end\", ret[0]);\n \n ret = ValidateDate(msg.payload.object_date_end)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample retrieval\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_date_end\", ret[0])\n \n ret = ValidateTime(msg.payload.object_time_end)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample retrieval\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_time_end\", ret[0])\n}\nelse{\n ret = ValidateCoordinates(msg.payload.object_lat, true);\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" Latitude\";\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_lat\", ret[0]);\n payload_for_form.payload[\"object_lat_end\"] = msg.payload.object_lat;\n \n ret = ValidateCoordinates(msg.payload.object_lon, false);\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" Longitude\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_lon\", ret[0])\n payload_for_form.payload[\"object_lon_end\"] = msg.payload.object_lon;\n\n ret = ValidateDate(msg.payload.object_date)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_date\", ret[0])\n payload_for_form.payload[\"object_date_end\"] = msg.payload.object_date;\n \n ret = ValidateTime(msg.payload.object_time)\n if (ret[1] !== null){\n msg.topic = ret[1].topic + \" of the sample\"\n msg.payload = ret[1].payload\n return [msg, null]\n }\n global.set(\"object_time\", ret[0])\n payload_for_form.payload[\"object_time_end\"] = msg.payload.object_time;\n}\nreturn [{topic: \"Coordinates valid!\", payload: \"All good!\", valid: true}, payload_for_form]\n", + "outputs": 2, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 930, + "y": 620, + "wires": [ + [ + "c0ce5626.b6c5", + "9a18a4b4.178448" + ], + [ + "56d40584.eff4e4" + ] + ], + "inputLabels": [ + "Location form data" + ], + "outputLabels": [ + "Message", + "Location validated" + ] + }, + { + "id": "46eb1bf8.3dc5f4", + "type": "function", + "z": "b771c342.49603", + "name": "Net check", + "func": "var decknet = {}\nvar activation_msg = {}\n\nif (msg.payload.startsWith(\"net_decknet\")){\n decknet.enabled = true;\n}\nelse {\n decknet.enabled = false;\n}\n\nif (msg.payload.startsWith(\"net\")){\n activation_msg.payload = {\"group\":{\"show\":[\"Sample_Net_Metadata\"],\"hide\":[\"Sample_Sample_Location\",\"Sample_Culture_Date_and_Time\"]}};\n}\nelse if (msg.payload != \"culture\" && msg.payload != \"test\"){\n activation_msg.payload = {\"group\":{\"show\":[\"Sample_Sample_Location\"], \"hide\":[\"Sample_Net_Metadata\",\"Sample_Culture_Date_and_Time\"]}};\n}\n\n\nreturn [decknet, activation_msg];", + "outputs": 2, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 1080, + "y": 240, + "wires": [ + [ + "516375fd.2ed61c", + "470e382a.25691", + "fbe32ac8.ff6a38" + ], + [ + "cbb123ab.fd3428" + ] + ], + "outputLabels": [ + "decknet activation", + "group display control" + ] + }, + { + "id": "516375fd.2ed61c", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "sample_total_flowmeter_start", + "label": "Decknet flowmeter start", + "tooltip": "in L", + "group": "cf5d9f0e.d57e7", + "order": 6, + "width": 5, + "height": 1, + "passthru": false, + "mode": "text", + "delay": "300", + "topic": "sample_total_flowmeter_start", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 1340, + "y": 220, + "wires": [ + [ + "e9bc112c.eb75f8" + ] + ] + }, + { + "id": "470e382a.25691", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "sample_total_flowmeter_end", + "label": "Decknet flowmeter end", + "tooltip": "in L", + "group": "cf5d9f0e.d57e7", + "order": 7, + "width": 5, + "height": 1, + "passthru": false, + "mode": "text", + "delay": "300", + "topic": "sample_total_flowmeter_end", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 1340, + "y": 260, + "wires": [ + [ + "e9bc112c.eb75f8" + ] + ] + }, + { + "id": "fbe32ac8.ff6a38", + "type": "ui_template", + "z": "b771c342.49603", + "group": "cf5d9f0e.d57e7", + "name": "Decknet flowmeter read", + "order": 5, + "width": 10, + "height": 1, + "format": "
\n

Decknet flowmeter readings

\n

Those values are used to calculate sample_total_volume. Values are in L.

\n
\n", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": true, + "templateScope": "local", + "x": 1330, + "y": 180, + "wires": [ + [] + ] + }, + { + "id": "f408a273.4fb538", + "type": "function", + "z": "b771c342.49603", + "name": "get sample_gear_net_opening", + "func": "if (msg.payload.sample_gear_net_opening === null){\n msg.payload = 0;\n global.set(\"sample_gear_net_opening\",msg.payload);\n}\nelse\n{\n msg.payload = msg.payload.sample_gear_net_opening;\n}\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 350, + "y": 320, + "wires": [ + [ + "e967b844.46aa48" + ] + ] + }, + { + "id": "8dff1648.82e42", + "type": "function", + "z": "b771c342.49603", + "name": "get object_depth_max", + "func": "if (msg.payload.object_depth_max === null){\n msg.payload = 0;\n global.set(\"object_depth_max\",msg.payload);\n}\nelse\n{\n msg.payload = msg.payload.object_depth_max;\n}\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 320, + "y": 240, + "wires": [ + [ + "9c7f7fc9.c8d3a" + ] + ] + }, + { + "id": "9f04c5ec.75f3d8", + "type": "function", + "z": "b771c342.49603", + "name": "get object_depth_min", + "func": "if (msg.payload.object_depth_min === null){\n msg.payload = 0;\n global.set(\"object_depth_min\",msg.payload);\n}\nelse\n{\n msg.payload = msg.payload.object_depth_min;\n}\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 320, + "y": 280, + "wires": [ + [ + "317eeeb7.8d3042" + ] + ] + }, + { + "id": "9a18a4b4.178448", + "type": "function", + "z": "b771c342.49603", + "name": "calculate sample_total_volume", + "func": "\n/*object_lat = 33.95 \nobject_lon = 118.4 \nobject_lat_end = 40.6333 \nobject_lon_end = 73.78333\nsample_gear_net_opening = 40*/\n\n// Copyright 1997 Ed Williams. All rights reserved\n// Adapted by Romain Bazile - Ocean Trotter - 01-2021\n\ndecpl=4 // Dec places of minutes output\n\nellipse = {\"name\":\"WSG84\", \"a\":6378.137/1.852, \"invf\":298.257223563}\n\nfunction ComputeDistance(lat1, lon1, lat2, lon2){\n var d,crs12,crs21\n var argacos\n var a,invf\n \n // lat and lon in radian\n lat1=(Math.PI/180)*lat1\n lat2=(Math.PI/180)*lat2\n lon1=(Math.PI/180)*lon1\n lon2=(Math.PI/180)*lon2\n \n //alert(\"lat1=\" + lat1 + \"lon1=\" + lon1 +\"\\nlat2=\" +lat2+ \"lon2=\"+lon2)\n \n /* get distance conversion factor */\n dc=1.852 //km\n //alert(\"dc=\" +dc)\n \n //showProps(ellipse,\"ellipse\")\n \n // elliptic code\n d=crsdist_ell(lat1,-lon1,lat2,-lon2,ellipse) // ellipse uses East negative\n d=d*dc // go to physical units\n \n //alert(\"d=\"+d+\" crs12=\"+crs12+\" crs21=\"+crs21)\n return d\n}\n\nfunction crsdist(lat1,lon1,lat2,lon2){ // radian args\n /* compute course and distance (spherical) */\n if ((lat1+lat2===0) && (Math.abs(lon1-lon2)==Math.PI) && \n (Math.abs(lat1) != (Math.PI/180)*90)){\t\n \talert(\"Course between antipodal points is undefined\")\n }\n \n d = Math.acos(Math.sin(lat1)*Math.sin(lat2)+Math.cos(lat1)*Math.cos(lat2)*Math.cos(lon1-lon2))\n return d\n}\n\nfunction crsdist_ell(glat1,glon1,glat2,glon2,ellipse){\n // glat1 initial geodetic latitude in radians N positive \n // glon1 initial geodetic longitude in radians E positive \n // glat2 final geodetic latitude in radians N positive \n // glon2 final geodetic longitude in radians E positive \n a=ellipse.a\n f=1/ellipse.invf\n //alert(\"a=\"+a+\" f=\"+f)\n var r, tu1, tu2, cu1, su1, cu2, s1, b1, f1\n var x, sx, cx, sy, cy,y, sa, c2a, cz, e, c, d\n var EPS= 0.00000000005\n var faz, baz, s\n var iter=1\n var MAXITER=100\n if ((glat1+glat2===0) && (Math.abs(glon1-glon2)==Math.PI)){\n alert(\"Course and distance between antipodal points is undefined\")\n glat1=glat1+0.00001 // allow algorithm to complete\n }\n if (glat1==glat2 && (glon1==glon2 || Math.abs(Math.abs(glon1-glon2)-2*Math.PI) < EPS)){\n alert(\"Points 1 and 2 are identical- course undefined\")\n out=new MakeArray(0)\n out.d=0\n out.crs12=0\n out.crs21=Math.PI\n return out\n }\n r = 1 - f\n tu1 = r * Math.tan (glat1)\n tu2 = r * Math.tan (glat2)\n cu1 = 1 / Math.sqrt (1 + tu1 * tu1)\n su1 = cu1 * tu1\n cu2 = 1 / Math.sqrt (1 + tu2 * tu2)\n s1 = cu1 * cu2\n b1 = s1 * tu2\n f1 = b1 * tu1\n x = glon2 - glon1\n d = x + 1 // force one pass\n while ((Math.abs(d - x) > EPS) && (iter < MAXITER))\n {\n iter=iter+1\n sx = Math.sin (x)\n // alert(\"sx=\"+sx)\n cx = Math.cos (x)\n tu1 = cu2 * sx\n tu2 = b1 - su1 * cu2 * cx\n sy = Math.sqrt(tu1 * tu1 + tu2 * tu2)\n cy = s1 * cx + f1\n y = atan2 (sy, cy)\n sa = s1 * sx / sy\n c2a = 1 - sa * sa\n cz = f1 + f1\n if (c2a > 0)\n cz = cy - cz / c2a\n e = cz * cz * 2 - 1\n c = ((-3 * c2a + 4) * f + 4) * c2a * f / 16\n d = x\n x = ((e * cy * c + cz) * sy * c + y) * sa\n x = (1 - c) * x * f + glon2 - glon1\n }\n x = Math.sqrt ((1 / (r * r) - 1) * c2a + 1)\n x +=1\n x = (x - 2) / x\n c = 1 - x\n c = (x * x / 4 + 1) / c\n d = (0.375 * x * x - 1) * x\n x = e * cy\n d = ((((sy*sy*4-3)*(1-e-e)*cz*d/6-x)*d/4+cz)*sy*d+y)*c*a*r\n if (Math.abs(iter-MAXITER)0) && (y>=0)){ out= Math.atan(y/x)}\n if ((x >0) && (y<0)) { out= Math.atan(y/x)+2*Math.PI}\n if ((x===0) && (y>0)) { out= Math.PI/2}\n if ((x===0) && (y<0)) { out= 3*Math.PI/2} \n if ((x===0) && (y===0)) {\n alert(\"atan2(0,0) undefined\")\n out= 0\n } \n return out\n}\n\nfunction showProps(obj,objName){\n var result=\"\"\n for (var i in obj){\n result +=objName + \".\" + i + \" = \" + obj[i] + \"\\n\"\n }\n alert(result)\n}\n\n\nif (msg.valid){\n msg.topic=\"sample_total_volume\"\n \n var object_lat_end = global.get(\"object_lat_end\")\n var object_lon_end = global.get(\"object_lon_end\")\n var sample_sampling_gear = global.get(\"sample_sampling_gear\")\n \n if (sample_sampling_gear.startsWith(\"net\") && sample_sampling_gear != \"net_decknet\") {\n if (!(isNaN(object_lat_end) && isNaN(object_lon_end))){\n var object_lat = global.get(\"object_lat\")\n var object_lon = global.get(\"object_lon\")\n var sample_gear_net_opening = global.get(\"sample_gear_net_opening\");\n\n distance_km = ComputeDistance(object_lat, object_lon, object_lat_end, object_lon_end)\n\n sample_total_volume = distance_km*(Math.PI*(sample_gear_net_opening/2)*(sample_gear_net_opening/2)) // liters\n sample_total_volume = Math.round(sample_total_volume + Number.EPSILON)\n msg.payload = sample_total_volume\n return msg\n }\n }\n}", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 930, + "y": 760, + "wires": [ + [ + "4f6afc5a.81e454" + ] + ] + }, + { + "id": "e73fd87d.d24e4", + "type": "function", + "z": "b771c342.49603", + "name": "get acq_minimum_mesh", + "func": "msg.payload = msg.payload.acq_minimum_mesh;\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 330, + "y": 360, + "wires": [ + [ + "1aad56b31b5647ce" + ] + ] + }, + { + "id": "489c8e06.cc7d6", + "type": "function", + "z": "b771c342.49603", + "name": "get acq_maximum_mesh", + "func": "msg.payload = msg.payload.acq_maximum_mesh;\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 330, + "y": 400, + "wires": [ + [ + "10eb31a2d7a6590c" + ] + ] + }, + { + "id": "58de1340.3cc354", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "sample_dilution_factor", + "label": "Concentration Factor", + "tooltip": "0.5 if diluted by two; 2 if concentrated by a factor 2", + "group": "3e1ba03d.f01d8", + "order": 13, + "width": 10, + "height": 1, + "passthru": true, + "mode": "number", + "delay": "300", + "topic": "sample_dilution_factor", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 640, + "y": 480, + "wires": [ + [ + "9f501f49.45645" + ] + ] + }, + { + "id": "4f6afc5a.81e454", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "sample_total_volume", + "label": "Filtered volume (in L)", + "tooltip": "Calculated or hand filled", + "group": "3e1ba03d.f01d8", + "order": 11, + "width": 0, + "height": 0, + "passthru": true, + "mode": "text", + "delay": "300", + "topic": "sample_total_volume", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 1220, + "y": 760, + "wires": [ + [ + "e1f2f6eb.fe1dd" + ] + ] + }, + { + "id": "e1f2f6eb.fe1dd", + "type": "function", + "z": "b771c342.49603", + "name": "set global", + "func": "global.set(msg.topic,msg.payload);", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 1420, + "y": 760, + "wires": [ + [] + ] + }, + { + "id": "e9bc112c.eb75f8", + "type": "function", + "z": "b771c342.49603", + "name": "Calculate volume", + "func": "if (msg.topic == \"sample_total_flowmeter_start\"){\n context.set(\"sample_total_flowmeter_start\", msg.payload);\n}\nif (msg.topic == \"sample_total_flowmeter_end\"){\n context.set(\"sample_total_flowmeter_end\", msg.payload);\n}\n\nif (context.keys().length == 2){\n sample_total_volume = context.get(\"sample_total_flowmeter_end\") - context.get(\"sample_total_flowmeter_start\");\n msg.topic=\"sample_total_volume\"\n msg.payload=sample_total_volume\n return msg\n}\n", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 1610, + "y": 240, + "wires": [ + [ + "4f6afc5a.81e454" + ] + ] + }, + { + "id": "cdd4181922eecf11", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "sample_speed_through_water", + "label": "Speed Through Water (kts)", + "tooltip": "in knots", + "group": "cf5d9f0e.d57e7", + "order": 2, + "width": 10, + "height": 1, + "passthru": true, + "mode": "number", + "delay": "300", + "topic": "sample_speed_through_water", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 610, + "y": 520, + "wires": [ + [ + "9f501f49.45645" + ] + ] + }, + { + "id": "1aad56b31b5647ce", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "acq_minimum_mesh", + "label": "Minimal fraction size (μm)", + "tooltip": "Net mesh pore size or minimal filtration mesh pore size", + "group": "3e1ba03d.f01d8", + "order": 7, + "width": 5, + "height": 1, + "passthru": true, + "mode": "number", + "delay": "300", + "topic": "acq_minimum_mesh", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 640, + "y": 360, + "wires": [ + [ + "9f501f49.45645" + ] + ] + }, + { + "id": "10eb31a2d7a6590c", + "type": "ui_text_input", + "z": "b771c342.49603", + "name": "acq_maximum_mesh", + "label": "Maximal fraction size (μm)", + "tooltip": "Maximal filtration mesh pore size", + "group": "3e1ba03d.f01d8", + "order": 8, + "width": 5, + "height": 1, + "passthru": true, + "mode": "number", + "delay": "300", + "topic": "acq_maximum_mesh", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 640, + "y": 400, + "wires": [ + [ + "9f501f49.45645" + ] + ] + }, + { + "id": "3ac7b631f5d8ef90", + "type": "function", + "z": "b771c342.49603", + "name": "Culture check", + "func": "var activation_msg = {}\nvar date_msg = {}\nvar timestamp=new Date().toISOString();\n\nif (msg.payload === \"culture\"){\n activation_msg.payload = {\"group\":{\"show\":[\"Sample_Culture_Date_and_Time\"],\"hide\":[\"Sample_Sample_Location\", \"Sample_Net_Metadata\"]}};\n global.set(\"object_lat\", \"-90.0000\")\n global.set(\"object_lon\", \"0.0000\")\n date_msg.payload = {\"object_date\": timestamp.split('T')[0],\n \"object_time\": timestamp.split('T')[1].split('.')[0]}\n return [activation_msg, date_msg];\n}\nelse if (msg.payload === \"test\"){\n activation_msg.payload = {\"group\":{\"hide\":[\"Sample_Culture_Date_and_Time\", \"Sample_Sample_Location\", \"Sample_Net_Metadata\"]}};\n global.set(\"object_lat\", \"-90.0000\")\n global.set(\"object_lon\", \"0.0000\")\n global.set(\"object_date\", timestamp.split('T')[0])\n global.set(\"object_time\", timestamp.split('T')[1].split('.')[0])\n return [activation_msg, null];\n}\nelse{\n return [null, null]\n}\n\n", + "outputs": 2, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 1100, + "y": 320, + "wires": [ + [ + "cbb123ab.fd3428" + ], + [ + "05c6aff2afbd69cf" + ] + ], + "outputLabels": [ + "decknet activation", + "" + ] + }, + { + "id": "05c6aff2afbd69cf", + "type": "ui_form", + "z": "b771c342.49603", + "name": "culture_timestamp", + "label": "Culture timestamp", + "group": "7bc0a4c416e4545c", + "order": 1, + "width": 0, + "height": 0, + "options": [ + { + "label": "Date (YYYY-MM-DD, UTC)", + "value": "object_date", + "type": "text", + "required": true, + "rows": null + }, + { + "label": "Time (HH:MM(:SS), UTC 24h)", + "value": "object_time", + "type": "text", + "required": true, + "rows": null + } + ], + "formValue": { + "object_date": "", + "object_time": "" + }, + "payload": "", + "submit": "Validate", + "cancel": "Reset", + "topic": "culture_timestamp", + "topicType": "str", + "splitLayout": false, + "className": "", + "x": 650, + "y": 700, + "wires": [ + [ + "14658615.47c862", + "f8044c35996322e6" + ] + ] + }, + { + "id": "a9fb1f4b83fc25a7", + "type": "change", + "z": "b771c342.49603", + "name": "Repopulate input fields", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 400, + "y": 580, + "wires": [ + [ + "c33f1124.af6688" + ] + ] + }, + { + "id": "ad54b89540460d27", + "type": "change", + "z": "b771c342.49603", + "name": "Repopulate input fields", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 400, + "y": 620, + "wires": [ + [ + "358908cd.416ab" + ] + ] + }, + { + "id": "c21bf0244e67e40a", + "type": "change", + "z": "b771c342.49603", + "name": "Repopulate input fields", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 400, + "y": 660, + "wires": [ + [ + "56d40584.eff4e4" + ] + ] + }, + { + "id": "f8044c35996322e6", + "type": "change", + "z": "b771c342.49603", + "name": "Repopulate input fields", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 400, + "y": 700, + "wires": [ + [ + "05c6aff2afbd69cf" + ] + ] + }, + { + "id": "8b48a02877b7b6d6", + "type": "inject", + "z": "b771c342.49603", + "name": "", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "payload": "1", + "payloadType": "num", + "x": 270, + "y": 480, + "wires": [ + [ + "58de1340.3cc354" + ] + ] + }, + { + "id": "6a84252a.d52a0c", + "type": "ui_template", + "z": "bccd1f23.87219", + "group": "833bc5bb.217ba8", + "name": "Stream Pi Camera", + "order": 1, + "width": 18, + "height": 14, + "format": "
\n \"If\n
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "className": "", + "x": 610, + "y": 40, + "wires": [ + [] + ] + }, + { + "id": "dc48dc42.98d18", + "type": "function", + "z": "bccd1f23.87219", + "name": "set global", + "func": "global.set(msg.topic,msg.payload);", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 880, + "y": 440, + "wires": [ + [] + ] + }, + { + "id": "811cd88c.daf528", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "down", + "group": "fbd92986.1028c8", + "order": 8, + "width": 4, + "height": 1, + "passthru": true, + "label": "", + "tooltip": "", + "color": "", + "bgcolor": "", + "icon": "fa-angle-double-down fa-3x", + "payload": "DOWN", + "payloadType": "str", + "topic": "actuator/focus", + "x": 550, + "y": 800, + "wires": [ + [ + "65ad39d.b6d4d48" + ] + ] + }, + { + "id": "edda4df4.76de2", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "up", + "group": "fbd92986.1028c8", + "order": 1, + "width": 4, + "height": 1, + "passthru": false, + "label": "", + "tooltip": "", + "color": "", + "bgcolor": "", + "icon": "fa-angle-double-up fa-3x", + "payload": "UP", + "payloadType": "str", + "topic": "actuator/focus", + "x": 550, + "y": 760, + "wires": [ + [ + "65ad39d.b6d4d48" + ] + ] + }, + { + "id": "68962547.34a67c", + "type": "ui_text_input", + "z": "bccd1f23.87219", + "name": "pump_manual_volume", + "label": "Volume to pass (ml)", + "tooltip": "Tiny values are accepted down to 0.001mL", + "group": "707d9797.c8e798", + "order": 3, + "width": 2, + "height": 1, + "passthru": true, + "mode": "text", + "delay": "300", + "topic": "pump_manual_volume", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 600, + "y": 420, + "wires": [ + [ + "dc48dc42.98d18" + ] + ] + }, + { + "id": "6c792043.b6ff9", + "type": "ui_ui_control", + "z": "bccd1f23.87219", + "name": "", + "events": "change", + "x": 560, + "y": 1140, + "wires": [ + [] + ] + }, + { + "id": "902429eb.ceacb8", + "type": "ui_toast", + "z": "bccd1f23.87219", + "position": "dialog", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 1, + "ok": "OK", + "cancel": "", + "raw": false, + "topic": "", + "name": "", + "x": 570, + "y": 1220, + "wires": [ + [] + ] + }, + { + "id": "fe840e05.b46f3", + "type": "function", + "z": "bccd1f23.87219", + "name": "Check form", + "func": "var acq_fnumber_objective= global.get(\"acq_fnumber_objective\");\n\nif (acq_fnumber_objective === undefined || acq_fnumber_objective === \"\") {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Focal Length of the objective\";\n return [null, msg];\n}\n\nmsg.topic = \"Change Tab\";\nmsg.payload={\"tab\":\"Fluidic Acquisition\"};\nreturn [msg, null];", + "outputs": 2, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 330, + "y": 1180, + "wires": [ + [ + "6c792043.b6ff9", + "326a1d95.ca21aa" + ], + [ + "902429eb.ceacb8" + ] + ], + "outputLabels": [ + "message", + "error" + ] + }, + { + "id": "5846b1d4.7971b", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "Backward", + "group": "707d9797.c8e798", + "order": 2, + "width": 1, + "height": 1, + "passthru": false, + "label": "", + "tooltip": "", + "color": "", + "bgcolor": "", + "icon": "fa-rotate-left fa-2x", + "payload": "BACKWARD", + "payloadType": "str", + "topic": "actuator/pump", + "x": 560, + "y": 280, + "wires": [ + [ + "3cb96380.e575ec" + ] + ] + }, + { + "id": "2cab680b.baf888", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "Forward", + "group": "707d9797.c8e798", + "order": 4, + "width": 1, + "height": 1, + "passthru": true, + "label": "", + "tooltip": "", + "color": "", + "bgcolor": "", + "icon": "fa-rotate-right fa-2x", + "payload": "FORWARD", + "payloadType": "str", + "topic": "actuator/pump", + "x": 560, + "y": 320, + "wires": [ + [ + "3cb96380.e575ec" + ] + ] + }, + { + "id": "8038414a.34461", + "type": "function", + "z": "bccd1f23.87219", + "name": "Calculate optics", + "func": "var acq_fnumber_objective = String(global.get(\"acq_fnumber_objective\"));\nvar acq_camera = global.get(\"acq_camera\")\n\n// Those values needs to be recalculated, they are not good!\nif (acq_camera == \"HQ Camera\"){\n switch(acq_fnumber_objective) {\n case \"25\":\n acq_magnification= 0.6;\n process_pixel= 1.56;\n sug_min= 60;\n sug_max= 670;\n sug_flowrate= 3;\n break;\n case \"16\":\n acq_magnification= 1.6;\n process_pixel= 1.01;\n sug_min= 40;\n sug_max= 430;\n sug_flowrate= 2.4;\n break;\n case \"12\":\n acq_magnification= 1.20;\n process_pixel= 0.79;\n sug_min= 30;\n sug_max= 340;\n sug_flowrate= 1.25;\n break;\n case \"8\":\n acq_magnification= 1.78;\n process_pixel= 0.53;\n sug_min= 20;\n sug_max= 230;\n sug_flowrate= 0.42;\n break;\n case \"6\":\n acq_magnification= 2.36;\n process_pixel= 0.41;\n sug_min= 15;\n sug_max= 170;\n sug_flowrate= 0.32;\n break;\n }\n}\nelse if (acq_camera == \"Camera v2.1\"){\n switch(acq_fnumber_objective) {\n case \"25\":\n acq_magnification= 0.6;\n process_pixel= 1.86;\n sug_min= 60;\n sug_max= 670;\n sug_flowrate= 3;\n break;\n case \"16\":\n acq_magnification= 1.6;\n process_pixel= 0.7;\n sug_min= 40;\n sug_max= 430;\n sug_flowrate= 2.4;\n break;\n case \"12\":\n acq_magnification= 1.20;\n process_pixel= 0.94;\n sug_min= 30;\n sug_max= 340;\n sug_flowrate= 1.25;\n break;\n case \"8\":\n acq_magnification= 1.78;\n process_pixel= 0.63;\n sug_min= 20;\n sug_max= 230;\n sug_flowrate= 0.42;\n break;\n case \"6\":\n acq_magnification= 2.36;\n process_pixel= 0.48;\n sug_min= 15;\n sug_max= 170;\n sug_flowrate= 0.32;\n break;\n }\n}else {\n acq_magnification= \"ERROR\";\n process_pixel= \"ERROR\";\n sug_min= \"ERROR\";\n sug_max= \"ERROR\";\n sug_flowrate= \"ERROR\";\n}\n\nvar process_pixel_fixed = global.get(\"process_pixel_fixed\")\n\nif (process_pixel_fixed !== undefined && process_pixel_fixed !== \"\") {\n process_pixel = process_pixel_fixed\n}\n\nglobal.set(\"process_pixel\",process_pixel);\n\nglobal.set(\"acq_magnification\",acq_magnification);\n\n\nreturn [{payload: acq_fnumber_objective}, {payload: acq_magnification}, {payload: process_pixel}, {payload: sug_min}, {payload: sug_max}];", + "outputs": 5, + "timeout": "", + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 1080, + "y": 120, + "wires": [ + [], + [], + [], + [], + [] + ], + "inputLabels": [ + "acq_fnumber_objective" + ], + "outputLabels": [ + "acq_magnification", + "process_pixel", + "sug_min", + "sug_max", + "" + ] + }, + { + "id": "f61aaed5.1e64", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "", + "group": "7a0b4877.a5d268", + "order": 1, + "width": 2, + "height": 1, + "passthru": false, + "label": "Previous", + "tooltip": "", + "color": "#097479", + "bgcolor": "white", + "icon": "keyboard_return", + "payload": "{\"tab\":\"Sample\"}", + "payloadType": "json", + "topic": "", + "x": 140, + "y": 1140, + "wires": [ + [ + "6c792043.b6ff9" + ] + ] + }, + { + "id": "9ba6ec0a.22c96", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "", + "group": "7a0b4877.a5d268", + "order": 2, + "width": 2, + "height": 1, + "passthru": false, + "label": "Continue", + "tooltip": "", + "color": "#097479", + "bgcolor": "white", + "icon": "keyboard_tab", + "payload": "{\"tab\":\"Home\"}", + "payloadType": "json", + "topic": "", + "x": 140, + "y": 1180, + "wires": [ + [ + "fe840e05.b46f3" + ] + ] + }, + { + "id": "3cb96380.e575ec", + "type": "function", + "z": "bccd1f23.87219", + "name": "pump", + "func": "var manual_volume= global.get(\"pump_manual_volume\");\nvar flowrate= global.get(\"pump_flowrate\");\n\nif (manual_volume === undefined || manual_volume === \"\" || manual_volume === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Volume to pass\";\n return [null, msg];\n}\nelse if (flowrate === undefined || flowrate === \"\" || flowrate === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Flowrate\";\n return [null, msg];\n}\nelse {\n msg.topic = \"actuator/pump\";\n // msg.payload is FORWARD or BACKWARD here\n msg.payload={\"action\":\"move\", \n \"direction\":msg.payload,\n \"volume\":manual_volume,\n \"flowrate\":flowrate};\n}\nreturn [msg, null];", + "outputs": 2, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 750, + "y": 300, + "wires": [ + [ + "bdc8ce57.de1f08" + ], + [ + "8bcce348.efc1a" + ] + ], + "inputLabels": [ + "direction" + ], + "outputLabels": [ + "message", + "error" + ] + }, + { + "id": "8bcce348.efc1a", + "type": "ui_toast", + "z": "bccd1f23.87219", + "position": "dialog", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 1, + "ok": "OK", + "cancel": "", + "raw": false, + "topic": "", + "name": "", + "x": 1090, + "y": 300, + "wires": [ + [] + ] + }, + { + "id": "bdc8ce57.de1f08", + "type": "mqtt out", + "z": "bccd1f23.87219", + "name": "", + "topic": "", + "qos": "", + "retain": "", + "broker": "8dc3722c.06efa8", + "x": 1210, + "y": 260, + "wires": [] + }, + { + "id": "d71d224f.0585d8", + "type": "ui_toast", + "z": "bccd1f23.87219", + "position": "dialog", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 1, + "ok": "OK", + "cancel": "", + "raw": false, + "topic": "", + "name": "", + "x": 1090, + "y": 800, + "wires": [ + [] + ] + }, + { + "id": "65ad39d.b6d4d48", + "type": "function", + "z": "bccd1f23.87219", + "name": "focus", + "func": "var distance = global.get(\"focus_distance\");\nvar speed = global.get(\"focus_speed\");\n\nif (distance === undefined || distance === \"\" || distance === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Distance\";\n return [null, msg]\n}\nif (speed === undefined || speed === \"\" || speed === null) {\n msg.topic = \"Missing entry :\"\n msg.payload = \"Speed\";\n return [null, msg]\n}\n// msg.payload is UP or DOWN here\nmsg.payload={\"action\":\"move\", \n \"direction\":msg.payload,\n \"distance\":(distance/1000),\n \"speed\": (speed/1000)\n};\nreturn [msg, null];", + "outputs": 2, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 850, + "y": 780, + "wires": [ + [ + "62030521.88317c" + ], + [ + "d71d224f.0585d8" + ] + ], + "inputLabels": [ + "direction" + ], + "outputLabels": [ + "message", + "error" + ] + }, + { + "id": "1962d999.4a97e6", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "stop focus", + "group": "fbd92986.1028c8", + "order": 9, + "width": 0, + "height": 0, + "passthru": true, + "label": " STOP FOCUS", + "tooltip": "", + "color": "", + "bgcolor": "#AD1625", + "icon": "fa-pause fa-2x", + "payload": "{\"action\":\"stop\"}", + "payloadType": "json", + "topic": "actuator/focus", + "x": 570, + "y": 560, + "wires": [ + [ + "62030521.88317c" + ] + ] + }, + { + "id": "62030521.88317c", + "type": "mqtt out", + "z": "bccd1f23.87219", + "name": "", + "topic": "", + "qos": "", + "retain": "", + "broker": "8dc3722c.06efa8", + "x": 1210, + "y": 720, + "wires": [] + }, + { + "id": "3bd43039.bc5fb8", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "", + "group": "fbd92986.1028c8", + "order": 2, + "width": 4, + "height": 1, + "passthru": false, + "label": "UP 1mm", + "tooltip": "", + "color": "", + "bgcolor": "", + "icon": "fa-angle-up fa-3x", + "payload": "{\"action\":\"move\",\"direction\":\"UP\",\"distance\":1}", + "payloadType": "json", + "topic": "actuator/focus", + "topicType": "str", + "x": 560, + "y": 600, + "wires": [ + [ + "62030521.88317c" + ] + ] + }, + { + "id": "c0663029.2d03b", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "", + "group": "fbd92986.1028c8", + "order": 7, + "width": 4, + "height": 1, + "passthru": false, + "label": "DOWN 1mm", + "tooltip": "", + "color": "", + "bgcolor": "", + "icon": "fa-angle-down fa-3x", + "payload": "{\"action\":\"move\",\"direction\":\"DOWN\",\"distance\":1}", + "payloadType": "json", + "topic": "actuator/focus", + "topicType": "str", + "x": 570, + "y": 720, + "wires": [ + [ + "62030521.88317c" + ] + ] + }, + { + "id": "71f55a58.d7eaf4", + "type": "inject", + "z": "bccd1f23.87219", + "name": "Default: 500µm", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": "0.5", + "topic": "", + "payload": "500", + "payloadType": "num", + "x": 120, + "y": 460, + "wires": [ + [ + "be33e564.029358" + ] + ] + }, + { + "id": "9a1d0e7c.2d5a1", + "type": "inject", + "z": "bccd1f23.87219", + "name": "Default: OFF", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "payload": "off", + "payloadType": "str", + "x": 130, + "y": 120, + "wires": [ + [ + "f0775525.cf806" + ] + ] + }, + { + "id": "f782a471.447748", + "type": "inject", + "z": "bccd1f23.87219", + "name": "Default: 2mL/min", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": "0.5", + "topic": "", + "payload": "2", + "payloadType": "num", + "x": 130, + "y": 380, + "wires": [ + [ + "cb2d5174.cfe9f" + ] + ] + }, + { + "id": "73b8252a.5ca754", + "type": "inject", + "z": "bccd1f23.87219", + "name": "Default: 2mL", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": "0.5", + "topic": "", + "payload": "2", + "payloadType": "num", + "x": 110, + "y": 420, + "wires": [ + [ + "68962547.34a67c" + ] + ] + }, + { + "id": "6451f991.aaac1", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "stop pump", + "group": "707d9797.c8e798", + "order": 5, + "width": 4, + "height": 1, + "passthru": true, + "label": " STOP PUMP", + "tooltip": "", + "color": "", + "bgcolor": "#AD1625", + "icon": "fa-pause fa-2x", + "payload": "{\"action\":\"stop\"}", + "payloadType": "json", + "topic": "actuator/pump", + "x": 570, + "y": 240, + "wires": [ + [ + "bdc8ce57.de1f08" + ] + ] + }, + { + "id": "cfc783d7.d6ceb", + "type": "link in", + "z": "bccd1f23.87219", + "name": "Optics recalculation", + "links": [ + "559a8085.1d6b9", + "5d5ad36d2c50dcc2" + ], + "x": 915, + "y": 120, + "wires": [ + [ + "8038414a.34461" + ] + ] + }, + { + "id": "326a1d95.ca21aa", + "type": "subflow:1c24ad9c.bebec2", + "z": "bccd1f23.87219", + "name": "", + "x": 550, + "y": 1180, + "wires": [ + [] + ] + }, + { + "id": "2d371e59.b0e50a", + "type": "inject", + "z": "bccd1f23.87219", + "name": "Default: 1000µm/s", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": "0.5", + "topic": "", + "payload": "1000", + "payloadType": "num", + "x": 130, + "y": 500, + "wires": [ + [ + "3a86de51.765b9a" + ] + ] + }, + { + "id": "167cda35.c9b6ae", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "", + "group": "fbd92986.1028c8", + "order": 3, + "width": 4, + "height": 1, + "passthru": false, + "label": "UP 100um", + "tooltip": "", + "color": "", + "bgcolor": "", + "icon": "fa-angle-up fa-3x", + "payload": "{\"action\":\"move\",\"direction\":\"UP\",\"distance\":0.1}", + "payloadType": "json", + "topic": "actuator/focus", + "topicType": "str", + "x": 570, + "y": 640, + "wires": [ + [ + "62030521.88317c" + ] + ] + }, + { + "id": "72a7c597.9374fc", + "type": "ui_button", + "z": "bccd1f23.87219", + "name": "", + "group": "fbd92986.1028c8", + "order": 6, + "width": 4, + "height": 1, + "passthru": false, + "label": "DOWN 100um", + "tooltip": "", + "color": "", + "bgcolor": "", + "icon": "fa-angle-down fa-3x", + "payload": "{\"action\":\"move\",\"direction\":\"DOWN\",\"distance\":0.1}", + "payloadType": "json", + "topic": "actuator/focus", + "topicType": "str", + "x": 580, + "y": 680, + "wires": [ + [ + "62030521.88317c" + ] + ] + }, + { + "id": "f0775525.cf806", + "type": "ui_multistate_switch", + "z": "bccd1f23.87219", + "name": "light_control", + "group": "4248342d.e55fac", + "order": 1, + "width": 6, + "height": 1, + "label": "Light ", + "stateField": "payload", + "enableField": "enable", + "passthroughField": "passthrough", + "inputMsgField": "inputmsg", + "rounded": true, + "useThemeColors": true, + "hideSelectedLabel": false, + "multilineLabel": false, + "passThrough": "never", + "inputMsg": "all", + "userInput": "enabled_show", + "options": [ + { + "label": "Off", + "value": "off", + "valueType": "str", + "color": "#009933" + }, + { + "label": "On", + "value": "on", + "valueType": "str", + "color": "#999999" + } + ], + "topic": "", + "x": 310, + "y": 120, + "wires": [ + [ + "99ae4886.8d43c" + ] + ] + }, + { + "id": "99ae4886.8d43c", + "type": "function", + "z": "bccd1f23.87219", + "name": "Prepare message", + "func": "msg.topic = \"light\"\nmsg.payload = {\"action\":msg.payload}\n\nreturn msg;", + "outputs": 1, + "timeout": "", + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 490, + "y": 120, + "wires": [ + [ + "d31fcead.7e2ef" + ] + ] + }, + { + "id": "d31fcead.7e2ef", + "type": "mqtt out", + "z": "bccd1f23.87219", + "name": "", + "topic": "", + "qos": "", + "retain": "", + "respTopic": "", + "contentType": "", + "userProps": "", + "correl": "", + "expiry": "", + "broker": "8dc3722c.06efa8", + "x": 650, + "y": 120, + "wires": [] + }, + { + "id": "8ea9dc9a.c7d87", + "type": "function", + "z": "bccd1f23.87219", + "name": "Encapsulate settings", + "func": "msg.payload = {\n \"action\":\"settings\", \n \"settings\":{[msg.topic]:msg.payload}\n}\n\nmsg.topic = \"imager/image\"\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 1120, + "y": 940, + "wires": [ + [ + "845e06e1.0d812" + ] + ] + }, + { + "id": "5765a825.a595c8", + "type": "ui_slider", + "z": "bccd1f23.87219", + "name": "Shutter speed slider", + "label": "Shutter Speed", + "tooltip": "In microseconds, up to 1000µs, 125µs by default", + "group": "8c38a81e.9897a8", + "order": 4, + "width": 0, + "height": 0, + "passthru": true, + "outs": "end", + "topic": "shutter_speed", + "topicType": "str", + "min": "125", + "max": "1000", + "step": "1", + "className": "", + "x": 600, + "y": 880, + "wires": [ + [ + "8ea9dc9a.c7d87" + ] + ] + }, + { + "id": "845e06e1.0d812", + "type": "mqtt out", + "z": "bccd1f23.87219", + "name": "", + "topic": "", + "qos": "", + "retain": "", + "broker": "8dc3722c.06efa8", + "x": 1390, + "y": 980, + "wires": [] + }, + { + "id": "2350e507.d4e302", + "type": "inject", + "z": "bccd1f23.87219", + "name": "Default: 125µs", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": "1", + "topic": "", + "payload": "125", + "payloadType": "num", + "x": 120, + "y": 880, + "wires": [ + [ + "5765a825.a595c8" + ] + ] + }, + { + "id": "5e147425.7666ec", + "type": "function", + "z": "bccd1f23.87219", + "name": "Encapsulate wb gain settings", + "func": "msg.payload = {\n \"action\":\"settings\", \n \"settings\":{\"white_balance_gain\":{\n [msg.topic]:Math.round(msg.payload*100)\n }\n }\n}\nmsg.topic = \"imager/image\"\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 1100, + "y": 1060, + "wires": [ + [ + "845e06e1.0d812" + ] + ] + }, + { + "id": "82722a3c.846b3", + "type": "inject", + "z": "bccd1f23.87219", + "name": "Default: OFF", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": "1", + "topic": "", + "payload": "false", + "payloadType": "bool", + "x": 110, + "y": 920, + "wires": [ + [ + "60e44330.50bdec" + ] + ] + }, + { + "id": "60e44330.50bdec", + "type": "ui_switch", + "z": "bccd1f23.87219", + "name": "AWB", + "label": "Auto White Balance", + "tooltip": "", + "group": "8c38a81e.9897a8", + "order": 5, + "width": 2, + "height": 2, + "passthru": true, + "decouple": "false", + "topic": "white_balance", + "topicType": "str", + "style": "", + "onvalue": "auto", + "onvalueType": "str", + "onicon": "", + "oncolor": "", + "offvalue": "off", + "offvalueType": "str", + "officon": "", + "offcolor": "", + "animate": true, + "className": "", + "x": 550, + "y": 920, + "wires": [ + [ + "8ea9dc9a.c7d87" + ] + ] + }, + { + "id": "6be64480.7e7e24", + "type": "change", + "z": "bccd1f23.87219", + "name": "Get red_gain", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.red_gain", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 370, + "y": 1040, + "wires": [ + [ + "d5415af6.e06cc" + ] + ] + }, + { + "id": "6d49d161.13628", + "type": "change", + "z": "bccd1f23.87219", + "name": "Get blue_gain", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.blue_gain", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 380, + "y": 1080, + "wires": [ + [ + "dba68c1f.e3144" + ] + ] + }, + { + "id": "56835fa1.2fe538", + "type": "subflow:4ed26b8b.253504", + "z": "bccd1f23.87219", + "name": "", + "env": [], + "x": 1160, + "y": 1020, + "wires": [] + }, + { + "id": "8ef294ba.12213", + "type": "change", + "z": "bccd1f23.87219", + "name": "Get analog_gain", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "1", + "tot": "num" + }, + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.analog_gain", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 380, + "y": 960, + "wires": [ + [ + "a6c7eec4.f7a918" + ] + ] + }, + { + "id": "8e336e58.14722", + "type": "change", + "z": "bccd1f23.87219", + "name": "Get digital_gain", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "1", + "tot": "num" + }, + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.digital_gain", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 380, + "y": 1000, + "wires": [ + [ + "66b37eef.f3f9e" + ] + ] + }, + { + "id": "a6c7eec4.f7a918", + "type": "ui_text_input", + "z": "bccd1f23.87219", + "d": true, + "name": "Analog gain field", + "label": "Analog Gain", + "tooltip": "From 1.0 to 12.0", + "group": "8c38a81e.9897a8", + "order": 2, + "width": 0, + "height": 0, + "passthru": true, + "mode": "number", + "delay": 300, + "topic": "analog", + "topicType": "str", + "x": 580, + "y": 960, + "wires": [ + [ + "44e02933.a66688", + "d361a2c4.0990f8" + ] + ] + }, + { + "id": "66b37eef.f3f9e", + "type": "ui_text_input", + "z": "bccd1f23.87219", + "d": true, + "name": "Digital gain field", + "label": "Digital Gain", + "tooltip": "From 1.0 to 64.0. Overexpose starting at 4.0", + "group": "8c38a81e.9897a8", + "order": 3, + "width": 0, + "height": 0, + "passthru": true, + "mode": "number", + "delay": 300, + "topic": "digital", + "topicType": "str", + "x": 580, + "y": 1000, + "wires": [ + [ + "44e02933.a66688", + "d361a2c4.0990f8" + ] + ] + }, + { + "id": "44e02933.a66688", + "type": "function", + "z": "bccd1f23.87219", + "name": "Encapsulate image gain settings", + "func": "msg.payload = {\n \"action\":\"settings\", \n \"settings\":{\"image_gain\":{\n [msg.topic]:Math.round(msg.payload*100)\n }\n }\n}\nmsg.topic = \"imager/image\"\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 1090, + "y": 980, + "wires": [ + [ + "845e06e1.0d812" + ] + ] + }, + { + "id": "d361a2c4.0990f8", + "type": "change", + "z": "bccd1f23.87219", + "name": "topic *_gain", + "rules": [ + { + "t": "set", + "p": "topic", + "pt": "msg", + "to": "topic&'_gain'", + "tot": "jsonata" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 970, + "y": 1020, + "wires": [ + [ + "56835fa1.2fe538" + ] + ] + }, + { + "id": "d8d006bf.2947f", + "type": "inject", + "z": "bccd1f23.87219", + "name": "Default: ISO 150", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": "1", + "topic": "", + "payload": "150", + "payloadType": "num", + "x": 130, + "y": 840, + "wires": [ + [ + "f62c3241bd753f24" + ] + ] + }, + { + "id": "eb9966de.cf13c8", + "type": "change", + "z": "bccd1f23.87219", + "name": "", + "rules": [ + { + "t": "set", + "p": "topic", + "pt": "msg", + "to": "iso", + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 740, + "y": 840, + "wires": [ + [ + "8ea9dc9a.c7d87" + ] + ] + }, + { + "id": "be33e564.029358", + "type": "ui_text_input", + "z": "bccd1f23.87219", + "name": "focus_distance", + "label": "Focus Distance (in µm)", + "tooltip": "in µm, 25µm resolution", + "group": "fbd92986.1028c8", + "order": 4, + "width": 0, + "height": 0, + "passthru": true, + "mode": "number", + "delay": 300, + "topic": "focus_distance", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 580, + "y": 460, + "wires": [ + [ + "dc48dc42.98d18" + ] + ] + }, + { + "id": "3a86de51.765b9a", + "type": "ui_text_input", + "z": "bccd1f23.87219", + "name": "focus_speed", + "label": "Focus Speed (in µm/sec)", + "tooltip": "in µm/sec", + "group": "fbd92986.1028c8", + "order": 5, + "width": 0, + "height": 0, + "passthru": true, + "mode": "number", + "delay": 300, + "topic": "focus_speed", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 570, + "y": 500, + "wires": [ + [ + "dc48dc42.98d18" + ] + ] + }, + { + "id": "cb2d5174.cfe9f", + "type": "ui_text_input", + "z": "bccd1f23.87219", + "name": "pump_flowrate", + "label": "Flowrate (ml/min)*", + "tooltip": "", + "group": "707d9797.c8e798", + "order": 1, + "width": 0, + "height": 0, + "passthru": true, + "mode": "text", + "delay": 300, + "topic": "pump_flowrate", + "topicType": "str", + "x": 580, + "y": 380, + "wires": [ + [ + "dc48dc42.98d18" + ] + ] + }, + { + "id": "dba68c1f.e3144", + "type": "ui_text_input", + "z": "bccd1f23.87219", + "name": "WB Blue input", + "label": "WB: Blue", + "tooltip": "From 0.0 to 64.0", + "group": "8c38a81e.9897a8", + "order": 7, + "width": 4, + "height": 1, + "passthru": true, + "mode": "number", + "delay": "0", + "topic": "blue", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 580, + "y": 1080, + "wires": [ + [ + "3ece53716a02e09e" + ] + ] + }, + { + "id": "33ef60a6a80aa3a7", + "type": "subflow:b7861ce703215a01", + "z": "bccd1f23.87219", + "name": "", + "x": 160, + "y": 1020, + "wires": [ + [ + "8ef294ba.12213", + "8e336e58.14722", + "6be64480.7e7e24", + "6d49d161.13628" + ] + ] + }, + { + "id": "a3d034643b56796f", + "type": "inject", + "z": "bccd1f23.87219", + "name": "Once", + "props": [], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "x": 70, + "y": 1080, + "wires": [ + [ + "33ef60a6a80aa3a7" + ] + ] + }, + { + "id": "5984b086eddc9311", + "type": "link in", + "z": "bccd1f23.87219", + "name": "Load hardware config", + "links": [ + "3973b999ee7b3b1d", + "5d3df1564b9af89c" + ], + "x": 25, + "y": 1000, + "wires": [ + [ + "33ef60a6a80aa3a7" + ] + ] + }, + { + "id": "d5415af6.e06cc", + "type": "ui_text_input", + "z": "bccd1f23.87219", + "name": "WB Red input", + "label": "WB: Red", + "tooltip": "From 0.0 to 32.0", + "group": "8c38a81e.9897a8", + "order": 6, + "width": 4, + "height": 1, + "passthru": true, + "mode": "number", + "delay": "0", + "topic": "red", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 580, + "y": 1040, + "wires": [ + [ + "01c2b633558b0b02" + ] + ] + }, + { + "id": "01c2b633558b0b02", + "type": "switch", + "z": "bccd1f23.87219", + "name": "Validate", + "property": "payload", + "propertyType": "msg", + "rules": [ + { + "t": "btwn", + "v": "0.0", + "vt": "num", + "v2": "32.0", + "v2t": "num" + }, + { + "t": "else" + } + ], + "checkall": "false", + "repair": false, + "outputs": 2, + "x": 740, + "y": 1040, + "wires": [ + [ + "d361a2c4.0990f8", + "5e147425.7666ec" + ], + [ + "cbfaf049d92be90e", + "5d3df1564b9af89c" + ] + ] + }, + { + "id": "3ece53716a02e09e", + "type": "switch", + "z": "bccd1f23.87219", + "name": "Validate", + "property": "payload", + "propertyType": "msg", + "rules": [ + { + "t": "btwn", + "v": "0.0", + "vt": "num", + "v2": "32.0", + "v2t": "num" + }, + { + "t": "else" + } + ], + "checkall": "false", + "repair": false, + "outputs": 2, + "x": 740, + "y": 1080, + "wires": [ + [ + "d361a2c4.0990f8", + "5e147425.7666ec" + ], + [ + "cbfaf049d92be90e", + "5d3df1564b9af89c" + ] + ] + }, + { + "id": "cbfaf049d92be90e", + "type": "ui_toast", + "z": "bccd1f23.87219", + "position": "top right", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 0, + "ok": "OK", + "cancel": "", + "raw": false, + "className": "", + "topic": "Invalid white balance value", + "name": "", + "x": 990, + "y": 1100, + "wires": [] + }, + { + "id": "5d3df1564b9af89c", + "type": "link out", + "z": "bccd1f23.87219", + "name": "Reload hardware config", + "mode": "link", + "links": [ + "5984b086eddc9311" + ], + "x": 915, + "y": 1140, + "wires": [] + }, + { + "id": "f62c3241bd753f24", + "type": "ui_slider", + "z": "bccd1f23.87219", + "name": "ISO selector", + "label": "ISO", + "tooltip": "", + "group": "8c38a81e.9897a8", + "order": 1, + "width": 0, + "height": 0, + "passthru": true, + "outs": "end", + "topic": "topic", + "topicType": "msg", + "min": "50", + "max": "650", + "step": "50", + "className": "", + "x": 570, + "y": 840, + "wires": [ + [ + "eb9966de.cf13c8" + ] + ] + }, + { + "id": "6b34c456.83178c", + "type": "ui_text_input", + "z": "baa1e3d9.cb29d", + "name": "acq_id", + "label": "Acquisition unique ID*", + "tooltip": "", + "group": "4322c187.e73e5", + "order": 1, + "width": 5, + "height": 1, + "passthru": true, + "mode": "text", + "delay": 300, + "topic": "acq_id", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 690, + "y": 180, + "wires": [ + [ + "fb887036.12429" + ] + ] + }, + { + "id": "cc0ca68b.4263a8", + "type": "ui_dropdown", + "z": "baa1e3d9.cb29d", + "name": "acq_celltype", + "label": "Flowcell thickness*", + "tooltip": "", + "place": "Select option", + "group": "4322c187.e73e5", + "order": 6, + "width": 5, + "height": 1, + "passthru": true, + "multiple": false, + "options": [ + { + "label": "200 μm µ-Slide I Luer", + "value": 200, + "type": "num" + }, + { + "label": "300 µm capillary", + "value": 300, + "type": "num" + }, + { + "label": "400 μm µ-Slide I Luer", + "value": 400, + "type": "num" + }, + { + "label": "600 μm µ-Slide I Luer", + "value": 600, + "type": "num" + }, + { + "label": "800 μm µ-Slide I Luer", + "value": 800, + "type": "num" + } + ], + "payload": "", + "topic": "acq_celltype", + "topicType": "str", + "className": "", + "x": 670, + "y": 100, + "wires": [ + [ + "fb887036.12429", + "99b11fe4.2795d" + ] + ] + }, + { + "id": "fb887036.12429", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "set global", + "func": "global.set(msg.topic, msg.payload);\nreturn msg", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 920, + "y": 180, + "wires": [ + [ + "52ea7d01.711034" + ] + ] + }, + { + "id": "bb2bb7ce.1d1458", + "type": "ui_template", + "z": "baa1e3d9.cb29d", + "group": "858a0e3c.987fe", + "name": "Stream Pi Camera", + "order": 1, + "width": 10, + "height": 8, + "format": "
\n \"If\n
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "className": "", + "x": 550, + "y": 40, + "wires": [ + [] + ] + }, + { + "id": "d0c5b57d.590818", + "type": "ui_ui_control", + "z": "baa1e3d9.cb29d", + "name": "", + "events": "change", + "x": 1280, + "y": 660, + "wires": [ + [] + ] + }, + { + "id": "c72f8fae.23bd4", + "type": "ui_button", + "z": "baa1e3d9.cb29d", + "name": "", + "group": "b7919ae2.c01788", + "order": 1, + "width": 5, + "height": 1, + "passthru": false, + "label": "Previous", + "tooltip": "", + "color": "#097479", + "bgcolor": "white", + "icon": "keyboard_return", + "payload": "{\"tab\":\"Optic Configuration\"}", + "payloadType": "json", + "topic": "", + "x": 1140, + "y": 660, + "wires": [ + [ + "d0c5b57d.590818" + ] + ] + }, + { + "id": "29be525e.0c87fe", + "type": "ui_template", + "z": "baa1e3d9.cb29d", + "group": "b5d61bc7.54fe48", + "name": "Show Metadata", + "order": 9, + "width": 0, + "height": 0, + "format": "
\n \n \n \n \n \n \n \n \n \n
\n

Sample

\n

id:

\n

project:\n

\n

ship:

\n

operator:\n

\n

sampling gear:\n

\n

concentrated volume:\n

\n

gear net opening:\n

\n

total volume filtered:\n

\n
\n

Acquisition

\n

id:

\n

instrument:\n

\n

instrument id:\n

\n

camera:

\n

celltype: \n

\n

minimum mesh:\n

\n

maximum mesh:\n

\n

min esd: \n

\n

max esd: \n

\n

volume:

\n

magnification:\n

\n

fnumber objective:\n

\n

software: \n

\n
\n

Object

\n

latitude: \n

\n

longitude: \n

\n

latitude end:\n

\n

longitude end:\n

\n

date:

\n

time:

\n

date end:\n

\n

time end:\n

\n

depth min:\n

\n

depth max:\n

\n
\n

Process

\n

pixel: \n

\n

id:

\n
\n
", + "storeOutMessages": false, + "fwdInMessages": false, + "resendOnRefresh": false, + "templateScope": "local", + "className": "", + "x": 1160, + "y": 380, + "wires": [ + [] + ] + }, + { + "id": "c9f510c0.7d1328", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "Image control", + "func": "// Reset the number of images taken\nflow.set('img_counter', 0);\n\nvar acq_celltype = global.get(\"acq_celltype\");\nvar acq_minimum_mesh = global.get(\"acq_minimum_mesh\");\nvar acq_maximum_mesh = global.get(\"acq_maximum_mesh\");\nvar imaging_pump_volume = global.get(\"imaging_pump_volume\");\nvar acq_id = global.get(\"acq_id\");\nvar nb_frame = global.get(\"nb_frame\");\nvar pump_direction = global.get(\"pump_direction\");\nvar sleep_before = global.get(\"sleep_before\");\nvar object_date = global.get(\"object_date\");\n\nif (acq_celltype === undefined || acq_celltype === \"\") {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Type of the flowcell\";\n return [null, msg];\n} else if (acq_minimum_mesh === undefined || acq_minimum_mesh === \"\") {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Lower fraction size\";\n return [null, msg];\n} else if (acq_maximum_mesh === undefined || acq_maximum_mesh === \"\") {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Upper fraction size\";\n return [null, msg];\n} else if (imaging_pump_volume === undefined || imaging_pump_volume === \"\" || imaging_pump_volume === null) {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Volume inbetween images\";\n return [null, msg];\n} else if (acq_id === undefined || acq_id === \"\") {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Acquisition ID\";\n return [null, msg];\n} else if (nb_frame === undefined || nb_frame === \"\" || nb_frame === null) {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Number of image to save\";\n return [null, msg];\n} else if (pump_direction === undefined || pump_direction === \"\" || pump_direction === null) {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Pump direction\";\n return [null, msg];\n} else if (sleep_before === undefined || sleep_before === \"\" || sleep_before === null) {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Delay before image\";\n return [null, msg];\n}else if (object_date === undefined || object_date === \"\" || object_date === null) {\n msg.topic = \"Missing entry :\";\n msg.payload = \"Object date\";\n return [null, msg];\n}\n\nmsg.payload = {\n \"action\": \"image\",\n \"sleep\": sleep_before,\n \"pump_direction\": pump_direction,\n \"volume\": imaging_pump_volume,\n \"nb_frame\": nb_frame,\n}\nmsg.send = true\n\nreturn [msg, null];", + "outputs": 2, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 640, + "y": 440, + "wires": [ + [ + "52ea7d01.711034", + "40c12463.a1f84c", + "a4abb1ae.2ae418" + ], + [ + "20e0a8c8.edbeb" + ] + ] + }, + { + "id": "20e0a8c8.edbeb", + "type": "ui_toast", + "z": "baa1e3d9.cb29d", + "position": "dialog", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 1, + "ok": "OK", + "cancel": "", + "raw": false, + "topic": "", + "name": "", + "x": 890, + "y": 520, + "wires": [ + [] + ] + }, + { + "id": "c3e50240.82aa58", + "type": "mqtt out", + "z": "baa1e3d9.cb29d", + "name": "", + "topic": "", + "qos": "", + "retain": "", + "broker": "8dc3722c.06efa8", + "x": 1130, + "y": 420, + "wires": [] + }, + { + "id": "3a4450b1.4459a8", + "type": "ui_button", + "z": "baa1e3d9.cb29d", + "name": "Stop Acquisition", + "group": "4322c187.e73e5", + "order": 11, + "width": 5, + "height": 1, + "passthru": true, + "label": "STOP ACQUISITION", + "tooltip": "", + "color": "", + "bgcolor": "#AD1625", + "icon": "cancel", + "payload": "{\"action\":\"stop\"}", + "payloadType": "json", + "topic": "imager/image", + "x": 420, + "y": 480, + "wires": [ + [ + "d74210ef.edc15" + ] + ] + }, + { + "id": "d74210ef.edc15", + "type": "mqtt out", + "z": "baa1e3d9.cb29d", + "name": "", + "topic": "", + "qos": "", + "retain": "", + "broker": "8dc3722c.06efa8", + "x": 610, + "y": 480, + "wires": [] + }, + { + "id": "bb62da8a.ebc328", + "type": "ui_switch", + "z": "baa1e3d9.cb29d", + "name": "Pump direction", + "label": "Pump direction", + "tooltip": "BACKWARD / FORWARD", + "group": "4322c187.e73e5", + "order": 9, + "width": 5, + "height": 1, + "passthru": true, + "decouple": "false", + "topic": "pump_direction", + "style": "", + "onvalue": "FORWARD", + "onvalueType": "str", + "onicon": "", + "oncolor": "", + "offvalue": "BACKWARD", + "offvalueType": "str", + "officon": "", + "offcolor": "", + "x": 420, + "y": 520, + "wires": [ + [ + "6b2239f3.41fa3" + ] + ] + }, + { + "id": "52ea7d01.711034", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "Encapsulate config", + "func": "msg.payload = {\n\t\"action\": \"update_config\",\n\t\"config\": {\n \t\"description\": {\n \t\t\"sample_project\": \"Project's name\",\n \t\t\"sample_id\": \"Sample ID\",\n \t\t\"sample_uuid\": \"Sample UUID (Autogenerated)\",\n \t\t\"sample_ship\": \"Ship's name\",\n \t\t\"sample_operator\": \"Operator's name\",\n \t\t\"sample_sampling_gear\": \"Sampling gear used\",\n \t\t\"sample_concentrated_sample_volume\": \"Volume of concentrated sample, in mL\",\n \t\t\"sample_total_volume\": \"Total volume filtered by the net used, in L\",\n \t\t\"sample_dilution_factor\": \"Dilution factor of the sample, 0.5 if diluted by 2, 2 if concentrated by 2\",\n \t\t\"sample_speed_through_water\": \"Speed of the boat through water when sampling, in kts\",\n \t\t\"acq_id\": \"Acquisition ID\",\n \t\t\"acq_uuid\": \"Acquisition UUID (Autogenerated)\",\n \t\t\"acq_instrument\": \"Instrument type\",\n \t\t\"acq_instrument_id\": \"Instrument ID\",\n \t\t\"acq_celltype\": \"Flow cell dimension thickness, in µm\",\n \t\t\"acq_minimum_mesh\": \"Minimum filtration mesh size, in µm\",\n \t\t\"acq_maximum_mesh\": \"Maximum filtration mesh size, in µm\",\n \t\t\"acq_min_esd\": \"\",\n \t\t\"acq_max_esd\": \"\",\n \t\t\"acq_volume\": \"Pumped volume, in mL\",\n\t\t \"acq_imaged_volume\": \"Total imaged volume, in mL\",\n \t\t\"acq_magnification\": \"Optical magnification\",\n \t\t\"acq_fnumber_objective\": \"Focal length of the objective, in mm\",\n \t\t\"acq_camera_name\": \"Name of the camera used\",\n \t\t\"acq_nb_frame\": \"Number of picture taken\",\n \"acq_local_datetime\": \"Instrument local datetime\",\n \"acq_camera_resolution\": \"Resolution of the images\",\n \"acq_camera_iso\": \"ISO Number of the images\",\n \"acq_camera_shutter_speed\": \"Shutter speed of the images, in µs\",\n \"acq_software\": \"Software version number\",\n \t\t\"object_date\": \"Sample collection date (or beginning if using a net)\",\n \t\t\"object_time\": \"Sample collection time (or beginning if using a net)\",\n \t\t\"object_lat\": \"Sample collection latitude (or beginning if using a net)\",\n \t\t\"object_lon\": \"Sample collection longitude (or beginning if using a net)\",\n \t\t\"object_depth_min\": \"Sample collection minimal depth, in m\",\n \t\t\"object_depth_max\": \"Sample collection maximum depth, in m\",\n \t\t\"process_pixel\": \"Pixel imaging resolution, in µm/pixel\",\n \t\t\"process_datetime\": \"Segmentation timestamp\",\n \t\t\"process_id\": \"Segmentation ID\",\n \t\t\"process_uuid\": \"Segmentation UUID (Autogenerated)\",\n \t\t\"process_source\": \"Code source link of the executed code\",\n \t\t\"process_commit\": \"Version reference of the executed code\",\n \t\t\"sample_gear_net_opening\": \"Sample mouth opening dimension, in mm\",\n \t\t\"object_date_end\": \"Sample end collection date when using a net\",\n \t\t\"object_time_end\": \"Sample end collection time when using a net\",\n \t\t\"object_lat_end\": \"Sample end collection latitude when using a net\",\n \t\t\"object_lon_end\": \"Sample end collection longitude when using a net\",\n \t},\n\t\t\"sample_project\": global.get(\"sample_project\"),\n\t\t\"sample_id\": global.get(\"sample_project\") + \"_\" + global.get(\"sample_id\"),\n\t\t\"sample_ship\": global.get(\"sample_ship\"),\n\t\t\"sample_operator\": global.get(\"sample_operator\"),\n\t\t\"sample_sampling_gear\": global.get(\"sample_sampling_gear\"),\n\t\t\"sample_concentrated_sample_volume\": global.get(\"sample_concentrated_sample_volume\"),\n\t\t\"sample_total_volume\": global.get(\"sample_total_volume\"),\n\t\t\"sample_dilution_factor\": global.get(\"sample_dilution_factor\"),\n\t\t\"sample_speed_through_water\": global.get(\"sample_speed_through_water\"),\n\n\t\t\"acq_id\": global.get(\"sample_project\") + \"_\" + global.get(\"sample_id\")+ \"_\" + global.get(\"acq_id\"),\n\t\t\"acq_instrument\": global.get(\"acq_instrument\"),\n\t\t\"acq_instrument_id\": global.get(\"acq_instrument_id\"),\n\t\t\"acq_celltype\": global.get(\"acq_celltype\"),\n\t\t\"acq_minimum_mesh\": global.get(\"acq_minimum_mesh\"),\n\t\t\"acq_maximum_mesh\": global.get(\"acq_maximum_mesh\"),\n\t\t\"acq_min_esd\": global.get(\"acq_min_esd\"),\n\t\t\"acq_max_esd\": global.get(\"acq_max_esd\"),\n\t\t\"acq_volume\": global.get(\"acq_volume\"),\n\t\t\"acq_imaged_volume\": global.get(\"acq_imaged_volume\"),\n\t\t\"acq_magnification\": global.get(\"acq_magnification\"),\n\t\t\"acq_fnumber_objective\": global.get(\"acq_fnumber_objective\"),\n\t\t\"acq_camera\": global.get(\"acq_camera\"),\n\t\t\"acq_nb_frame\": global.get(\"nb_frame\"),\n\t\t\"acq_software\": global.get(\"acq_software\"),\n\n\t\t\"object_date\": global.get(\"object_date\"),\n\t\t\"object_time\": global.get(\"object_time\"),\n\t\t\"object_lat\": global.get(\"object_lat\"),\n\t\t\"object_lon\": global.get(\"object_lon\"),\n\t\t\"object_depth_min\": global.get(\"object_depth_min\"),\n\t\t\"object_depth_max\": global.get(\"object_depth_max\"),\n\n\t\t\"process_pixel\": global.get(\"process_pixel\"),\n\t\t\"process_source\": global.get(\"process_source\"),\n\t\t\"process_commit\": global.get(\"process_commit\")\n\t}\n};\n\nif (msg.payload.config.sample_sampling_gear.startsWith(\"net\")) {\n\tmsg.payload.config[\"sample_gear_net_opening\"] = global.get(\"sample_gear_net_opening\")\n\tmsg.payload.config[\"object_date_end\"] = global.get(\"object_date_end\")\n\tmsg.payload.config[\"object_time_end\"] = global.get(\"object_time_end\")\n\tmsg.payload.config[\"object_lat_end\"] = global.get(\"object_lat_end\")\n\tmsg.payload.config[\"object_lon_end\"] = global.get(\"object_lon_end\")\n}\n\nif ( msg.send == true){\n\treturn [msg, msg]\n}\nelse{\n\treturn [msg, null]\n}", + "outputs": 2, + "timeout": "", + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 870, + "y": 400, + "wires": [ + [ + "29be525e.0c87fe" + ], + [ + "c3e50240.82aa58" + ] + ] + }, + { + "id": "40c12463.a1f84c", + "type": "delay", + "z": "baa1e3d9.cb29d", + "name": "", + "pauseType": "delay", + "timeout": "1", + "timeoutUnits": "seconds", + "rate": "1", + "nbRateUnits": "1", + "rateUnits": "second", + "randomFirst": "1", + "randomLast": "5", + "randomUnits": "seconds", + "drop": false, + "outputs": 1, + "x": 900, + "y": 440, + "wires": [ + [ + "c3e50240.82aa58" + ] + ] + }, + { + "id": "4d1b02cb.83b51c", + "type": "ui_button", + "z": "baa1e3d9.cb29d", + "name": "", + "group": "4322c187.e73e5", + "order": 10, + "width": 5, + "height": 1, + "passthru": false, + "label": "Update config", + "tooltip": "", + "color": "", + "bgcolor": "", + "className": "", + "icon": "save", + "payload": "", + "payloadType": "str", + "topic": "imager/image", + "topicType": "str", + "x": 420, + "y": 400, + "wires": [ + [ + "52ea7d01.711034" + ] + ] + }, + { + "id": "5921d0d0.a3d568", + "type": "subflow:1c24ad9c.bebec2", + "z": "baa1e3d9.cb29d", + "name": "", + "env": [], + "x": 110, + "y": 180, + "wires": [ + [ + "f3658d30.b8448", + "de2c90cf.b73b08", + "4be09c97f86897d9", + "f573206abefa9518", + "f948151ab4031df4" + ] + ] + }, + { + "id": "f3658d30.b8448", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "get acq_id", + "func": "msg.payload = msg.payload.acq_id;\nreturn msg;", + "outputs": 1, + "timeout": "", + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 330, + "y": 180, + "wires": [ + [ + "6b34c456.83178c" + ] + ] + }, + { + "id": "de2c90cf.b73b08", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "get acq_celltype", + "func": "msg.topic = 'acq_celltype';\nmsg.payload = msg.payload.acq_celltype;\nreturn msg;", + "outputs": 1, + "timeout": "", + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 340, + "y": 100, + "wires": [ + [ + "cc0ca68b.4263a8" + ] + ] + }, + { + "id": "b402f719.55bc98", + "type": "inject", + "z": "baa1e3d9.cb29d", + "name": "Default: FORWARD", + "props": [ + { + "p": "payload" + }, + { + "p": "topic", + "vt": "str" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "pump_direction", + "payload": "FORWARD", + "payloadType": "str", + "x": 180, + "y": 520, + "wires": [ + [ + "bb62da8a.ebc328" + ] + ] + }, + { + "id": "6b2239f3.41fa3", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "set global", + "func": "global.set(msg.topic, msg.payload);", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 620, + "y": 520, + "wires": [ + [] + ] + }, + { + "id": "51b4d0df.d70a88", + "type": "ui_text_input", + "z": "baa1e3d9.cb29d", + "name": "nb_frame", + "label": "Number of images to acquire", + "tooltip": "", + "group": "4322c187.e73e5", + "order": 2, + "width": 5, + "height": 1, + "passthru": true, + "mode": "number", + "delay": 300, + "topic": "nb_frame", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 680, + "y": 220, + "wires": [ + [ + "fb887036.12429", + "67091ac0.8f9f6c", + "99b11fe4.2795d" + ] + ] + }, + { + "id": "999065ca.27edb8", + "type": "switch", + "z": "baa1e3d9.cb29d", + "name": "topic filter", + "property": "topic", + "propertyType": "msg", + "rules": [ + { + "t": "eq", + "v": "status/pump", + "vt": "str" + }, + { + "t": "eq", + "v": "status/focus", + "vt": "str" + }, + { + "t": "eq", + "v": "status/light", + "vt": "str" + }, + { + "t": "eq", + "v": "status/imager", + "vt": "str" + } + ], + "checkall": "true", + "repair": false, + "outputs": 4, + "x": 320, + "y": 800, + "wires": [ + [ + "a46a1e7f.88a92", + "6742014e.1bb238" + ], + [ + "c516d9ea.f7f6e", + "6742014e.1bb238" + ], + [ + "6742014e.1bb238" + ], + [ + "307c851e.fb0f7a", + "2b9d6988.d84836" + ] + ] + }, + { + "id": "2b009bd7.c07004", + "type": "ui_text", + "z": "baa1e3d9.cb29d", + "group": "70de8209.68416c", + "order": 3, + "width": 10, + "height": 2, + "name": "imager", + "label": "Imager status:", + "format": "{{msg.payload.status}}", + "layout": "col-center", + "x": 770, + "y": 740, + "wires": [] + }, + { + "id": "c516d9ea.f7f6e", + "type": "ui_text", + "z": "baa1e3d9.cb29d", + "group": "70de8209.68416c", + "order": 1, + "width": 5, + "height": 1, + "name": "focus", + "label": "Focus status:", + "format": "{{msg.payload.status}}", + "layout": "col-center", + "x": 770, + "y": 700, + "wires": [] + }, + { + "id": "a46a1e7f.88a92", + "type": "ui_text", + "z": "baa1e3d9.cb29d", + "group": "70de8209.68416c", + "order": 2, + "width": 5, + "height": 1, + "name": "pump", + "label": "Pump status:", + "format": "{{msg.payload.status}}", + "layout": "col-center", + "x": 770, + "y": 660, + "wires": [] + }, + { + "id": "bb628f8d.98f108", + "type": "link in", + "z": "baa1e3d9.cb29d", + "name": "Status for fluidic module", + "links": [ + "58f2e0f.4e8b12" + ], + "x": 175, + "y": 800, + "wires": [ + [ + "999065ca.27edb8" + ] + ] + }, + { + "id": "307c851e.fb0f7a", + "type": "switch", + "z": "baa1e3d9.cb29d", + "name": "Imaging state", + "property": "payload", + "propertyType": "msg", + "rules": [ + { + "t": "jsonata_exp", + "v": "$contains(msg.payload.status, \"jpg\")\t", + "vt": "jsonata" + }, + { + "t": "else" + } + ], + "checkall": "false", + "repair": false, + "outputs": 2, + "x": 540, + "y": 880, + "wires": [ + [ + "db8e3dde.44efb8" + ], + [ + "6742014e.1bb238" + ] + ] + }, + { + "id": "db8e3dde.44efb8", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "img_counter", + "func": "img_counter=flow.get('img_counter')\nif (img_counter === undefined || img_counter === \"\"){\n img_counter = 0\n}\nimg_counter=img_counter+1\nflow.set('img_counter',img_counter)\nmsg.payload = img_counter\nmsg.payload = (100 * img_counter/global.get('nb_frame')).toFixed(2)\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 770, + "y": 860, + "wires": [ + [ + "1a2e721a.f5e876" + ] + ] + }, + { + "id": "59164d65.e7993c", + "type": "ui_toast", + "z": "baa1e3d9.cb29d", + "position": "top right", + "displayTime": "5", + "highlight": "", + "sendall": true, + "outputs": 0, + "ok": "OK", + "cancel": "", + "raw": false, + "topic": "", + "name": "", + "x": 1270, + "y": 900, + "wires": [] + }, + { + "id": "8c7348aa.1962e8", + "type": "template", + "z": "baa1e3d9.cb29d", + "name": "Create sentence", + "field": "payload", + "fieldType": "msg", + "format": "handlebars", + "syntax": "mustache", + "template": "The {{topic}} is {{payload.status}}", + "output": "str", + "x": 1050, + "y": 900, + "wires": [ + [ + "59164d65.e7993c" + ] + ] + }, + { + "id": "6742014e.1bb238", + "type": "change", + "z": "baa1e3d9.cb29d", + "name": "Remove high-level topic", + "rules": [ + { + "t": "change", + "p": "topic", + "pt": "msg", + "from": "status/", + "fromt": "str", + "to": "", + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 810, + "y": 900, + "wires": [ + [ + "8c7348aa.1962e8" + ] + ] + }, + { + "id": "1a2e721a.f5e876", + "type": "ui_gauge", + "z": "baa1e3d9.cb29d", + "name": "progress donut", + "group": "b5d61bc7.54fe48", + "order": 3, + "width": 6, + "height": 3, + "gtype": "donut", + "title": "", + "label": "%", + "format": "{{value}}", + "min": 0, + "max": "100", + "colors": [ + "#ffa83f", + "#e6ff02", + "#00dfe9" + ], + "seg1": "50", + "seg2": "75", + "x": 1260, + "y": 860, + "wires": [] + }, + { + "id": "9bd72495.a8a098", + "type": "ui_text", + "z": "baa1e3d9.cb29d", + "group": "4322c187.e73e5", + "order": 5, + "width": 5, + "height": 1, + "name": "Total imaged volume", + "label": "Total imaged volume", + "format": "{{msg.payload}}", + "layout": "col-center", + "x": 1200, + "y": 100, + "wires": [] + }, + { + "id": "99b11fe4.2795d", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "imaged volume calc", + "func": "camera = global.get(\"acq_camera\");\ncell = global.get(\"acq_celltype\");\nnb_frame = global.get(\"nb_frame\");\nprocess_pixel = global.get(\"process_pixel\");\n\nvar volume = 0\nif (camera == \"HQ Camera\"){\n volume = nb_frame * (process_pixel*4056*process_pixel*3040*cell/1000000000) / 1000;\n}\nelse if (camera == \"Camera v2.1\"){\n volume = nb_frame * (process_pixel*3280*process_pixel*2464*cell/1000000000) / 1000;\n}\nelse{\n msg.payload = \"The camera is not known to this system\";\n return msg;\n}\n\nglobal.set(\"acq_imaged_volume\", volume.toFixed(4))\n\nmsg.payload = volume.toFixed(2) + \" mL\"\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 960, + "y": 100, + "wires": [ + [ + "9bd72495.a8a098" + ] + ], + "info": "### Focusing\n##### focus.py `nb_step` `orientation`\n\n- `nb_step` : **integer** (from 1 to 100000) - number of step to perform by the stage (about 31um/step)\n- `orientation` : **string** - orientation of the focus either `up` or `down`\n\nExample:\n\n python3.7 $HOME/PlanktoScope/scripts/focus.py 650 up\n" + }, + { + "id": "8e16aa2f.e40398", + "type": "ui_text", + "z": "baa1e3d9.cb29d", + "group": "4322c187.e73e5", + "order": 7, + "width": 5, + "height": 1, + "name": "Total pumped volume", + "label": "Total pumped volume", + "format": "{{msg.payload}} mL", + "layout": "col-center", + "x": 1200, + "y": 260, + "wires": [] + }, + { + "id": "67091ac0.8f9f6c", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "acq_volume calc", + "func": "var imaging_pump_volume = global.get(\"imaging_pump_volume\");\nvar nb_frame = global.get(\"nb_frame\");\nvar acq_volume = 0\n\nacq_volume = (Number(nb_frame)*Number(imaging_pump_volume)).toFixed(2)\nglobal.set(\"acq_volume\", acq_volume)\n\nmsg.payload = acq_volume\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 950, + "y": 260, + "wires": [ + [ + "8e16aa2f.e40398" + ] + ], + "info": "### Focusing\n##### focus.py `nb_step` `orientation`\n\n- `nb_step` : **integer** (from 1 to 100000) - number of step to perform by the stage (about 31um/step)\n- `orientation` : **string** - orientation of the focus either `up` or `down`\n\nExample:\n\n python3.7 $HOME/PlanktoScope/scripts/focus.py 650 up\n" + }, + { + "id": "2b9d6988.d84836", + "type": "switch", + "z": "baa1e3d9.cb29d", + "name": "", + "property": "payload", + "propertyType": "msg", + "rules": [ + { + "t": "hask", + "v": "status", + "vt": "str" + }, + { + "t": "hask", + "v": "camera_name", + "vt": "str" + } + ], + "checkall": "true", + "repair": false, + "outputs": 2, + "x": 650, + "y": 760, + "wires": [ + [ + "2b009bd7.c07004" + ], + [ + "3bbb756a.84190a" + ] + ] + }, + { + "id": "3bbb756a.84190a", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "set camera name", + "func": "global.set(\"acq_camera\", msg.payload.camera_name);\n\nmsg.payload = msg.payload.camera_name;\n\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 810, + "y": 780, + "wires": [ + [ + "559a8085.1d6b9" + ] + ] + }, + { + "id": "559a8085.1d6b9", + "type": "link out", + "z": "baa1e3d9.cb29d", + "name": "Camera Name", + "links": [ + "30067f35.532f2", + "572a6daa.6004c4" + ], + "x": 965, + "y": 780, + "wires": [] + }, + { + "id": "49ea1123.ee1768", + "type": "ui_numeric", + "z": "baa1e3d9.cb29d", + "name": "sleep_before", + "label": "Delay to stabilize image (s)", + "tooltip": "Happens before every capture", + "group": "4322c187.e73e5", + "order": 4, + "width": 5, + "height": 1, + "wrap": false, + "passthru": true, + "topic": "sleep_before", + "topicType": "str", + "format": "{{value}}", + "min": "0.1", + "max": "5", + "step": "0.1", + "className": "", + "x": 670, + "y": 140, + "wires": [ + [ + "fb887036.12429" + ] + ] + }, + { + "id": "572a6daa.6004c4", + "type": "link in", + "z": "baa1e3d9.cb29d", + "name": "", + "links": [ + "559a8085.1d6b9" + ], + "x": 735, + "y": 60, + "wires": [ + [ + "99b11fe4.2795d" + ] + ] + }, + { + "id": "8032ea50.1b57f", + "type": "ui_template", + "z": "baa1e3d9.cb29d", + "group": "b5d61bc7.54fe48", + "name": "progress header", + "order": 1, + "width": 0, + "height": 0, + "format": "

Capture progress

", + "storeOutMessages": false, + "fwdInMessages": false, + "resendOnRefresh": false, + "templateScope": "local", + "x": 1270, + "y": 820, + "wires": [ + [] + ] + }, + { + "id": "a4abb1ae.2ae418", + "type": "subflow:1c24ad9c.bebec2", + "z": "baa1e3d9.cb29d", + "name": "", + "env": [], + "x": 890, + "y": 480, + "wires": [ + [] + ] + }, + { + "id": "4be09c97f86897d9", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "get nb_frame", + "func": "msg.payload = msg.payload.nb_frame;\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 330, + "y": 220, + "wires": [ + [ + "51b4d0df.d70a88" + ] + ] + }, + { + "id": "f573206abefa9518", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "get imaging_pump_volume", + "func": "msg.payload = msg.payload.imaging_pump_volume;\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 380, + "y": 260, + "wires": [ + [ + "0df8d1d86af6455a" + ] + ] + }, + { + "id": "f948151ab4031df4", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "get sleep_before", + "func": "msg.payload = msg.payload.sleep_before;\nreturn msg;", + "outputs": 1, + "timeout": "", + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 340, + "y": 140, + "wires": [ + [ + "49ea1123.ee1768" + ] + ] + }, + { + "id": "ad153212312f0347", + "type": "ui_ui_control", + "z": "baa1e3d9.cb29d", + "name": "onTab", + "events": "all", + "x": 310, + "y": 340, + "wires": [ + [ + "9b69ea945b587192" + ] + ] + }, + { + "id": "9b69ea945b587192", + "type": "function", + "z": "baa1e3d9.cb29d", + "name": "check tab", + "func": "if (msg.name == \"Fluidic Acquisition\"){\n return { \"topic\": \"imager/ image\" }\n}", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 460, + "y": 340, + "wires": [ + [ + "52ea7d01.711034" + ] + ], + "outputLabels": [ + "interface" + ] + }, + { + "id": "0df8d1d86af6455a", + "type": "ui_text_input", + "z": "baa1e3d9.cb29d", + "name": "imaging_pump_volume", + "label": "Pumped volume (mL)", + "tooltip": "between frames", + "group": "4322c187.e73e5", + "order": 3, + "width": 0, + "height": 0, + "passthru": true, + "mode": "number", + "delay": 300, + "topic": "imaging_pump_volume", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 630, + "y": 260, + "wires": [ + [ + "fb887036.12429", + "67091ac0.8f9f6c" + ] + ] + }, + { + "id": "37116281279b9b82", + "type": "ui_template", + "z": "baa1e3d9.cb29d", + "group": "4322c187.e73e5", + "name": "Start Acquisition", + "order": 12, + "width": "5", + "height": "1", + "format": "\n\n", + "storeOutMessages": false, + "fwdInMessages": false, + "resendOnRefresh": false, + "templateScope": "local", + "className": "", + "x": 420, + "y": 440, + "wires": [ + [ + "c9f510c0.7d1328" + ] + ] + }, + { + "id": "9d6abe67.6bb3d", + "type": "ui_button", + "z": "cb95299c.2817c8", + "name": "", + "group": "64903b47.4034e4", + "order": 1, + "width": 0, + "height": 0, + "passthru": false, + "label": "Home", + "tooltip": "", + "color": "", + "bgcolor": "", + "icon": "home", + "payload": "{\"tab\":\"Home\"}", + "payloadType": "json", + "topic": "", + "x": 430, + "y": 600, + "wires": [ + [ + "f0fb77cf.8f1c28" + ] + ] + }, + { + "id": "f0fb77cf.8f1c28", + "type": "ui_ui_control", + "z": "cb95299c.2817c8", + "name": "", + "events": "change", + "x": 740, + "y": 600, + "wires": [ + [] + ] + }, + { + "id": "8ec68b82.17e3d8", + "type": "ui_button", + "z": "cb95299c.2817c8", + "name": "Start segmentation", + "group": "abeb6dad.635a2", + "order": 10, + "width": 5, + "height": 1, + "passthru": false, + "label": "Start segmentation", + "tooltip": "", + "color": "", + "bgcolor": "", + "icon": "", + "payload": "{\"action\":\"segment\"}", + "payloadType": "json", + "topic": "segmenter/segment", + "x": 370, + "y": 460, + "wires": [ + [ + "33c28dc1.238002", + "c72a1064.1ec388" + ] + ] + }, + { + "id": "27be7971.b3fbce", + "type": "ui_button", + "z": "cb95299c.2817c8", + "d": true, + "name": "Stop segmentation", + "group": "abeb6dad.635a2", + "order": 12, + "width": 4, + "height": 1, + "passthru": true, + "label": "Stop segmentation", + "tooltip": "", + "color": "", + "bgcolor": "#AD1625", + "icon": "", + "payload": "{\"action\":\"stop\"}", + "payloadType": "json", + "topic": "segmenter/segment", + "x": 370, + "y": 520, + "wires": [ + [ + "16f3cef4.0acac9" + ] + ] + }, + { + "id": "16f3cef4.0acac9", + "type": "mqtt out", + "z": "cb95299c.2817c8", + "name": "", + "topic": "", + "qos": "", + "retain": "", + "broker": "8dc3722c.06efa8", + "x": 850, + "y": 520, + "wires": [] + }, + { + "id": "8f3788f6.ddcf98", + "type": "function", + "z": "cb95299c.2817c8", + "name": "obj_counter", + "func": "obj_counter = flow.get('obj_counter')\nobj_counter = obj_counter + 1\nflow.set('obj_counter', obj_counter)\nmsg.payload = obj_counter\nmsg.topic = \"object count\"\nreturn msg", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 810, + "y": 800, + "wires": [ + [ + "fa3b7929.ac7da8", + "9d53dbe2.dbffe8" + ] + ] + }, + { + "id": "aa38dbbc.cf0a9", + "type": "switch", + "z": "cb95299c.2817c8", + "name": "Segmenter", + "property": "topic", + "propertyType": "msg", + "rules": [ + { + "t": "eq", + "v": "status/segmenter", + "vt": "str" + }, + { + "t": "eq", + "v": "status/segmenter/name", + "vt": "str" + }, + { + "t": "eq", + "v": "status/segmenter/object_id", + "vt": "str" + }, + { + "t": "eq", + "v": "status/segmenter/metric", + "vt": "str" + } + ], + "checkall": "true", + "repair": false, + "outputs": 4, + "x": 490, + "y": 740, + "wires": [ + [ + "b9a23b91.93638", + "6919465f.332e5" + ], + [ + "49af3d24.1799e4" + ], + [ + "8f3788f6.ddcf98" + ], + [] + ] + }, + { + "id": "9d53dbe2.dbffe8", + "type": "ui_chart", + "z": "cb95299c.2817c8", + "name": "counter graph", + "group": "46be9c86.dea684", + "order": 7, + "width": 10, + "height": 2, + "label": "", + "chartType": "horizontalBar", + "legend": "false", + "xformat": "HH:mm:ss", + "interpolate": "linear", + "nodata": "Objects count will be shown here once the segmentation is started", + "dot": false, + "ymin": "", + "ymax": "", + "removeOlder": 1, + "removeOlderPoints": "", + "removeOlderUnit": "3600", + "cutout": 0, + "useOneColor": true, + "useUTC": false, + "colors": [ + "#1f77b4", + "#aec7e8", + "#ff7f0e", + "#2ca02c", + "#98df8a", + "#d62728", + "#ff9896", + "#9467bd", + "#c5b0d5" + ], + "outputs": 1, + "x": 1340, + "y": 840, + "wires": [ + [] + ] + }, + { + "id": "a4f0f0d1.3aca88", + "type": "ui_toast", + "z": "cb95299c.2817c8", + "position": "top right", + "displayTime": "5", + "highlight": "", + "sendall": true, + "outputs": 0, + "ok": "OK", + "cancel": "", + "raw": false, + "topic": "", + "name": "", + "x": 1350, + "y": 680, + "wires": [] + }, + { + "id": "49af3d24.1799e4", + "type": "debug", + "z": "cb95299c.2817c8", + "name": "segmentation name", + "active": true, + "tosidebar": true, + "console": false, + "tostatus": false, + "complete": "true", + "targetType": "full", + "statusVal": "", + "statusType": "auto", + "x": 840, + "y": 760, + "wires": [] + }, + { + "id": "7088a5be.0c79a4", + "type": "template", + "z": "cb95299c.2817c8", + "name": "Create sentence", + "field": "payload", + "fieldType": "msg", + "format": "handlebars", + "syntax": "mustache", + "template": "The {{topic}} is {{payload.status}}", + "output": "str", + "x": 1100, + "y": 680, + "wires": [ + [ + "a4f0f0d1.3aca88" + ] + ] + }, + { + "id": "b9a23b91.93638", + "type": "change", + "z": "cb95299c.2817c8", + "name": "Remove high-level topic", + "rules": [ + { + "t": "change", + "p": "topic", + "pt": "msg", + "from": "status/", + "fromt": "str", + "to": "", + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 850, + "y": 680, + "wires": [ + [ + "7088a5be.0c79a4" + ] + ] + }, + { + "id": "6919465f.332e5", + "type": "ui_text", + "z": "cb95299c.2817c8", + "group": "46be9c86.dea684", + "order": 1, + "width": 10, + "height": 1, + "name": "segmenter", + "label": "Segmenter status:", + "format": "{{msg.payload.status}}", + "layout": "row-spread", + "x": 810, + "y": 720, + "wires": [] + }, + { + "id": "fa3b7929.ac7da8", + "type": "ui_text", + "z": "cb95299c.2817c8", + "group": "46be9c86.dea684", + "order": 5, + "width": 4, + "height": 1, + "name": "counter", + "label": "", + "format": "{{msg.payload}}", + "layout": "col-center", + "x": 1320, + "y": 800, + "wires": [] + }, + { + "id": "640ece83.88cab", + "type": "inject", + "z": "cb95299c.2817c8", + "name": "Init graphs", + "props": [ + { + "p": "payload" + }, + { + "p": "topic", + "vt": "str" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "object count", + "payload": "0", + "payloadType": "num", + "x": 810, + "y": 880, + "wires": [ + [ + "4f3f7c4a.cb21c4" + ] + ] + }, + { + "id": "25867454.a8e334", + "type": "link in", + "z": "cb95299c.2817c8", + "name": "Segmenter module status", + "links": [ + "dcf5bd45.16a8d" + ], + "x": 295, + "y": 740, + "wires": [ + [ + "aa38dbbc.cf0a9" + ] + ] + }, + { + "id": "c8749cbb.55254", + "type": "function", + "z": "cb95299c.2817c8", + "name": "set global", + "func": "global.set(msg.topic, msg.payload);", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 960, + "y": 380, + "wires": [ + [] + ] + }, + { + "id": "d43c3ed9.e6cb1", + "type": "ui_template", + "z": "cb95299c.2817c8", + "group": "46be9c86.dea684", + "name": "Object counts", + "order": 3, + "width": 0, + "height": 0, + "format": "

Object counts

", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": true, + "templateScope": "local", + "x": 1340, + "y": 760, + "wires": [ + [] + ] + }, + { + "id": "33c28dc1.238002", + "type": "function", + "z": "cb95299c.2817c8", + "name": "prepare segmentation", + "func": "global.set('obj_counter', 0);\n\nvar segmentation_list = flow.get('segmentation_list')\nif (segmentation_list !== undefined && segmentation_list !== \"\") {\n msg.payload['path'] = segmentation_list\n}\n\n\nvar force = flow.get('force')\nif (force !== undefined && force !== \"\") {\n msg.payload['settings'] = {\"force\":Boolean(force)}\n}\n\n\nvar recursive = flow.get('recursive')\nif (recursive !== undefined && recursive !== \"\") {\n if (\"settings\" in msg.payload){\n msg.payload.settings[\"recursive\"] = Boolean(recursive)\n }\n else{\n msg.payload['settings'] = {\"recursive\": Boolean(recursive)}\n }\n}\n\nvar ecotaxa = flow.get('ecotaxa')\nif (ecotaxa !== undefined && ecotaxa !== \"\") {\n if (\"settings\" in msg.payload){\n msg.payload.settings[\"ecotaxa\"] = Boolean(ecotaxa)\n }\n else{\n msg.payload['settings'] = {\"ecotaxa\": Boolean(ecotaxa)}\n }\n}\n\nvar keep = flow.get('keep')\nif (keep !== undefined && keep !== \"\") {\n if (\"settings\" in msg.payload){\n msg.payload.settings[\"keep\"] = Boolean(keep)\n }\n else{\n msg.payload['settings'] = {\"keep\": Boolean(keep)}\n }\n}\n\nvar process_id = global.get('process_id')\nif (process_id !== undefined && process_id !== \"\") {\n if (\"settings\" in msg.payload){\n msg.payload.settings[\"process_id\"] = process_id\n }\n else{\n msg.payload['settings'] = {\"process_id\": process_id}\n }\n}\n\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 620, + "y": 460, + "wires": [ + [ + "16f3cef4.0acac9" + ] + ] + }, + { + "id": "fa12f9f8.00cfa8", + "type": "subflow:1c24ad9c.bebec2", + "z": "cb95299c.2817c8", + "name": "", + "env": [], + "x": 430, + "y": 380, + "wires": [ + [ + "3b72d11c.86e9e6" + ] + ] + }, + { + "id": "3b72d11c.86e9e6", + "type": "function", + "z": "cb95299c.2817c8", + "name": "get process_id", + "func": "msg.payload = msg.payload.process_id;\nmsg.topic = \"process_id\";\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 600, + "y": 380, + "wires": [ + [ + "56971109c8be3b54" + ] + ] + }, + { + "id": "3ea12061.ce62c", + "type": "ui_list", + "z": "cb95299c.2817c8", + "group": "abeb6dad.635a2", + "name": "", + "order": 9, + "width": 10, + "height": 11, + "lineType": "one", + "actionType": "check", + "allowHTML": false, + "outputs": 1, + "topic": "", + "x": 770, + "y": 140, + "wires": [ + [ + "cb3b87b5.63c4" + ] + ] + }, + { + "id": "8bd8fb2c.53fa4", + "type": "dir2files", + "z": "cb95299c.2817c8", + "name": "", + "dirname": "/home/pi/data/img/", + "pathRegex": "", + "isRecursive": true, + "findDir": true, + "isArray": true, + "x": 460, + "y": 140, + "wires": [ + [ + "ba2947.c854deb8" + ] + ] + }, + { + "id": "127d4ee.f8ad1b1", + "type": "ui_button", + "z": "cb95299c.2817c8", + "name": "Refresh", + "group": "abeb6dad.635a2", + "order": 8, + "width": 0, + "height": 0, + "passthru": false, + "label": "Update acquisition's folder list", + "tooltip": "Refresh the list of previous acquisitions", + "color": "", + "bgcolor": "", + "icon": "mi-find_replace", + "payload": "", + "payloadType": "date", + "topic": "update", + "x": 260, + "y": 140, + "wires": [ + [ + "8bd8fb2c.53fa4", + "56f845f5.e7c054" + ] + ] + }, + { + "id": "946ce9ee.092cf", + "type": "inject", + "z": "cb95299c.2817c8", + "name": "Init", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "payload": "", + "payloadType": "date", + "x": 270, + "y": 100, + "wires": [ + [ + "8bd8fb2c.53fa4", + "56f845f5.e7c054" + ] + ] + }, + { + "id": "cb3b87b5.63c4", + "type": "function", + "z": "cb95299c.2817c8", + "name": "update segmentation_list", + "func": "var segmentation_list = flow.get('segmentation_list');\n\nif (segmentation_list === undefined || segmentation_list === \"\") {\n segmentation_list = []\n console.log(\"error\")\n}\n\npath = \"/home/pi/data/img/\" + msg.payload.title\n\nif (msg.payload.isChecked){\n if (segmentation_list.includes(path) === false){\n segmentation_list.push(path)\n }\n // Element already in list, don't push it more than once\n //segmentation_list.push(msg.payload[\"title\"])\n}\nelse {\n var pos = segmentation_list.indexOf(path)\n segmentation_list.splice(pos, 1)\n}\n\nflow.set('segmentation_list', segmentation_list)", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 950, + "y": 140, + "wires": [ + [] + ] + }, + { + "id": "56f845f5.e7c054", + "type": "change", + "z": "cb95299c.2817c8", + "name": "Reset segmentation_list", + "rules": [ + { + "t": "set", + "p": "segmentation_list", + "pt": "flow", + "to": "[]", + "tot": "json" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 510, + "y": 100, + "wires": [ + [] + ] + }, + { + "id": "7fc72364.8f038c", + "type": "ui_template", + "z": "cb95299c.2817c8", + "group": "abeb6dad.635a2", + "name": "Update message", + "order": 1, + "width": 10, + "height": 3, + "format": "
You can choose here in which folder(s) you want the segmentation script to run. A few details though:\n
The segmentation is run recursively in all folders. So if you select a top level folder, the segmentation will be run in all subfolders.\n
Also, you will be able to chose wether for force the segmentation for folders in which it has run already.
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": true, + "templateScope": "local", + "x": 270, + "y": 40, + "wires": [ + [] + ] + }, + { + "id": "ba2947.c854deb8", + "type": "function", + "z": "cb95299c.2817c8", + "name": "remove common", + "func": "function remove_path(item, index, array) {\n array[index] = item.replace(\"/home/pi/data/img/\", \"\")\n} \n\nmsg.payload.forEach(remove_path)\n\nreturn msg", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "x": 620, + "y": 140, + "wires": [ + [ + "3ea12061.ce62c" + ] + ] + }, + { + "id": "21af0db1.c2c182", + "type": "ui_multistate_switch", + "z": "cb95299c.2817c8", + "name": "recursive toggle", + "group": "abeb6dad.635a2", + "order": 4, + "width": 5, + "height": 1, + "label": "Recursive folder", + "stateField": "payload", + "enableField": "enable", + "rounded": true, + "useThemeColors": true, + "hideSelectedLabel": false, + "options": [ + { + "label": "No", + "value": "0", + "valueType": "num", + "color": "#009933" + }, + { + "label": "Yes", + "value": "1", + "valueType": "num", + "color": "#999999" + } + ], + "x": 480, + "y": 220, + "wires": [ + [ + "880b192a.88e2d" + ] + ] + }, + { + "id": "dffb9881.feef8", + "type": "ui_multistate_switch", + "z": "cb95299c.2817c8", + "name": "force toggle", + "group": "abeb6dad.635a2", + "order": 3, + "width": 5, + "height": 1, + "label": "Force rework", + "stateField": "payload", + "enableField": "enable", + "rounded": true, + "useThemeColors": true, + "hideSelectedLabel": false, + "options": [ + { + "label": "No", + "value": "0", + "valueType": "num", + "color": "#009933" + }, + { + "label": "Yes", + "value": "1", + "valueType": "num", + "color": "#999999" + } + ], + "x": 470, + "y": 300, + "wires": [ + [ + "a4f68fa6.5d77f8" + ] + ] + }, + { + "id": "880b192a.88e2d", + "type": "change", + "z": "cb95299c.2817c8", + "name": "", + "rules": [ + { + "t": "set", + "p": "recursive", + "pt": "flow", + "to": "payload", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 690, + "y": 240, + "wires": [ + [] + ] + }, + { + "id": "a4f68fa6.5d77f8", + "type": "change", + "z": "cb95299c.2817c8", + "name": "", + "rules": [ + { + "t": "set", + "p": "force", + "pt": "flow", + "to": "payload", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 670, + "y": 280, + "wires": [ + [] + ] + }, + { + "id": "1ef1b43b.b0f064", + "type": "inject", + "z": "cb95299c.2817c8", + "name": "0", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "payload": "0", + "payloadType": "num", + "x": 270, + "y": 280, + "wires": [ + [ + "dffb9881.feef8", + "a4f68fa6.5d77f8" + ] + ] + }, + { + "id": "f078c068.eacf58", + "type": "ui_template", + "z": "cb95299c.2817c8", + "group": "46be9c86.dea684", + "name": "Stream Segmented object", + "order": 2, + "width": 10, + "height": 8, + "format": "
\n Latest object segmented:
\n \"If\n
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "className": "", + "x": 1380, + "y": 600, + "wires": [ + [] + ] + }, + { + "id": "43f97b93.b76294", + "type": "inject", + "z": "cb95299c.2817c8", + "name": "1", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "payload": "1", + "payloadType": "num", + "x": 270, + "y": 240, + "wires": [ + [ + "21af0db1.c2c182", + "880b192a.88e2d" + ] + ] + }, + { + "id": "4f3f7c4a.cb21c4", + "type": "change", + "z": "cb95299c.2817c8", + "name": "", + "rules": [ + { + "t": "set", + "p": "obj_counter", + "pt": "flow", + "to": "0", + "tot": "num" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 1020, + "y": 840, + "wires": [ + [ + "fa3b7929.ac7da8", + "9d53dbe2.dbffe8" + ] + ] + }, + { + "id": "6bce0f60.f48998", + "type": "link in", + "z": "cb95299c.2817c8", + "name": "", + "links": [ + "596fc9d4.46c75" + ], + "x": 855, + "y": 840, + "wires": [ + [ + "4f3f7c4a.cb21c4" + ] + ] + }, + { + "id": "596fc9d4.46c75", + "type": "link out", + "z": "cb95299c.2817c8", + "name": "", + "links": [ + "6bce0f60.f48998" + ], + "x": 715, + "y": 500, + "wires": [] + }, + { + "id": "c72a1064.1ec388", + "type": "change", + "z": "cb95299c.2817c8", + "name": "Reset counters", + "rules": [ + { + "t": "set", + "p": "topic", + "pt": "msg", + "to": "object count", + "tot": "str" + }, + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "0", + "tot": "num" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 600, + "y": 500, + "wires": [ + [ + "596fc9d4.46c75" + ] + ] + }, + { + "id": "9367534a.fb8568", + "type": "ui_multistate_switch", + "z": "cb95299c.2817c8", + "name": "Ecotaxa archive", + "group": "abeb6dad.635a2", + "order": 6, + "width": 5, + "height": 1, + "label": "Ecotaxa archive", + "stateField": "payload", + "enableField": "enable", + "rounded": true, + "useThemeColors": true, + "hideSelectedLabel": false, + "options": [ + { + "label": "No", + "value": "0", + "valueType": "num", + "color": "#009933" + }, + { + "label": "Yes", + "value": "1", + "valueType": "num", + "color": "#999999" + } + ], + "x": 1080, + "y": 220, + "wires": [ + [ + "25ac4f9a.5b05c8" + ] + ] + }, + { + "id": "25ac4f9a.5b05c8", + "type": "change", + "z": "cb95299c.2817c8", + "name": "", + "rules": [ + { + "t": "set", + "p": "ecotaxa", + "pt": "flow", + "to": "payload", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 1280, + "y": 240, + "wires": [ + [] + ] + }, + { + "id": "bef78886.8f0b98", + "type": "inject", + "z": "cb95299c.2817c8", + "name": "1", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "payload": "1", + "payloadType": "num", + "x": 910, + "y": 240, + "wires": [ + [ + "9367534a.fb8568", + "25ac4f9a.5b05c8" + ] + ] + }, + { + "id": "32465a4e.8fcac6", + "type": "ui_multistate_switch", + "z": "cb95299c.2817c8", + "name": "Keep objects", + "group": "abeb6dad.635a2", + "order": 5, + "width": 5, + "height": 1, + "label": "Keep objects", + "stateField": "payload", + "enableField": "enable", + "rounded": true, + "useThemeColors": true, + "hideSelectedLabel": false, + "options": [ + { + "label": "No", + "value": "0", + "valueType": "num", + "color": "#009933" + }, + { + "label": "Yes", + "value": "1", + "valueType": "num", + "color": "#999999" + } + ], + "x": 1070, + "y": 300, + "wires": [ + [ + "8dd6f57f.b77f98" + ] + ] + }, + { + "id": "8dd6f57f.b77f98", + "type": "change", + "z": "cb95299c.2817c8", + "name": "", + "rules": [ + { + "t": "set", + "p": "keep", + "pt": "flow", + "to": "payload", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 1270, + "y": 280, + "wires": [ + [] + ] + }, + { + "id": "8090df89.c029e", + "type": "inject", + "z": "cb95299c.2817c8", + "name": "1", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "payload": "1", + "payloadType": "num", + "x": 910, + "y": 280, + "wires": [ + [ + "32465a4e.8fcac6", + "8dd6f57f.b77f98" + ] + ] + }, + { + "id": "56971109c8be3b54", + "type": "ui_text_input", + "z": "cb95299c.2817c8", + "name": "process_id", + "label": "Process unique ID*", + "tooltip": "", + "group": "abeb6dad.635a2", + "order": 2, + "width": 10, + "height": 1, + "passthru": true, + "mode": "text", + "delay": 300, + "topic": "process_id", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 790, + "y": 380, + "wires": [ + [ + "c8749cbb.55254" + ] + ] + }, + { + "id": "2911fbc6.d28c24", + "type": "ui_template", + "z": "c1660bc.e7ff7f8", + "group": "c0ebfc57.42527", + "name": "Image browser", + "order": 1, + "width": "0", + "height": "0", + "format": "
\n\n
", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "className": "", + "x": 400, + "y": 100, + "wires": [ + [] + ] + }, + { + "id": "4f02c726.de69b8", + "type": "ui_button", + "z": "9daf9e2b.019fc", + "name": "", + "group": "a7d64879.38298", + "order": 4, + "width": "6", + "height": 1, + "passthru": false, + "label": "Reboot", + "tooltip": "", + "color": "", + "bgcolor": "#AD1625", + "className": "", + "icon": "fa-repeat fa-2x", + "payload": "reboot", + "payloadType": "str", + "topic": "reboot", + "topicType": "str", + "x": 160, + "y": 240, + "wires": [ + [ + "611a8b1c.a829b4" + ] + ] + }, + { + "id": "611a8b1c.a829b4", + "type": "exec", + "z": "9daf9e2b.019fc", + "command": "sudo", + "addpay": "payload", + "append": "now", + "useSpawn": "false", + "timer": "2", + "winHide": false, + "oldrc": false, + "name": "sudo cmd now", + "x": 480, + "y": 280, + "wires": [ + [], + [], + [] + ] + }, + { + "id": "bc76c4d6.a7ad28", + "type": "ui_button", + "z": "9daf9e2b.019fc", + "name": "", + "group": "a7d64879.38298", + "order": 5, + "width": "6", + "height": 1, + "passthru": false, + "label": "Shutdown", + "tooltip": "", + "color": "", + "bgcolor": "#AD1625", + "className": "", + "icon": "fa-power-off fa-2x", + "payload": "shutdown", + "payloadType": "str", + "topic": "shutdown", + "topicType": "str", + "x": 160, + "y": 320, + "wires": [ + [ + "611a8b1c.a829b4" + ] + ] + }, + { + "id": "b81b990a.d4dca", + "type": "link in", + "z": "9daf9e2b.019fc", + "name": "Shutdown", + "links": [ + "e08cfcb8.2a67e8" + ], + "x": 195, + "y": 280, + "wires": [ + [ + "611a8b1c.a829b4" + ] + ] + }, + { + "id": "ea4fae012404854c", + "type": "ui_button", + "z": "9daf9e2b.019fc", + "name": "", + "group": "a7d64879.38298", + "order": 2, + "width": "6", + "height": 1, + "passthru": true, + "label": "Restart Hardware Controller", + "tooltip": "", + "color": "", + "bgcolor": "#AD1625", + "className": "", + "icon": "fa-refresh fa-2x", + "payload": "Restarting hardware controller...", + "payloadType": "str", + "topic": "", + "topicType": "str", + "x": 440, + "y": 420, + "wires": [ + [ + "c54d948575dbcff8", + "d10f3ffd98055447" + ] + ] + }, + { + "id": "438febd245a9f73c", + "type": "link in", + "z": "9daf9e2b.019fc", + "name": "Restart Hardware Controller", + "links": [ + "e41870d7.300eb8", + "3973b999ee7b3b1d" + ], + "x": 195, + "y": 420, + "wires": [ + [ + "ea4fae012404854c" + ] + ] + }, + { + "id": "c54d948575dbcff8", + "type": "exec", + "z": "9daf9e2b.019fc", + "command": "sudo systemctl restart planktoscope-org.device-backend.controller.service", + "addpay": false, + "append": "", + "useSpawn": "false", + "timer": "", + "winHide": false, + "oldrc": false, + "name": "Restart hardware controller", + "x": 780, + "y": 420, + "wires": [ + [], + [], + [] + ] + }, + { + "id": "e2e5ce0351a6cc11", + "type": "ui_button", + "z": "9daf9e2b.019fc", + "name": "", + "group": "a7d64879.38298", + "order": 3, + "width": "6", + "height": 1, + "passthru": true, + "label": "Restart Segmenter", + "tooltip": "", + "color": "", + "bgcolor": "#AD1625", + "className": "", + "icon": "fa-refresh fa-2x", + "payload": "Restarting segmenter...", + "payloadType": "str", + "topic": "", + "topicType": "str", + "x": 410, + "y": 500, + "wires": [ + [ + "2cdbadb65d0e1b20", + "9c1629488b02fdba" + ] + ] + }, + { + "id": "2cdbadb65d0e1b20", + "type": "exec", + "z": "9daf9e2b.019fc", + "command": "docker restart apps_ps_backend_proc-segmenter-server-1", + "addpay": false, + "append": "", + "useSpawn": "false", + "timer": "", + "winHide": false, + "oldrc": false, + "name": "Restart segmenter", + "x": 750, + "y": 500, + "wires": [ + [], + [], + [] + ] + }, + { + "id": "7b64209d734e4e2c", + "type": "ui_template", + "z": "9daf9e2b.019fc", + "group": "a7d64879.38298", + "name": "Logs", + "order": 1, + "width": "0", + "height": "0", + "format": "

\n The PlanktoScope software application consists of three components: a Node-RED dashboard which provides the user interface you're using; a Hardware Controller\n which executes commands sent from the Node-RED dashboard for hardware control and image acquisition; and a Segmenter which processes an acquired dataset of\n images and isolates objects from those images. Each component has its own independent log of messages, managed separately from the logs for the other components.\n

\n

\n All three components have live-updating logs which you can monitor. Additionally, the Hardware Controller and the Segmenter also save all of their log messages\n to files which you can browse and download. Those software components create a new log file each time they start, and the name of the log file includes the time\n in the PlanktoScope's clock when the software component started. However, if your PlanktoScope's clock is usually wrong, it makes the log files difficult to navigate.\n This will be fixed in a future version of the software.\n

\n

\n If you need to share your logs with other people (e.g. on Slack or GitHub), you should open the \"Downloadable Logs\" links, and then you can select one file or multiple\n log files for downloading as a zip archive.\n

\n", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": true, + "templateScope": "local", + "className": "", + "x": 630, + "y": 180, + "wires": [ + [] + ] + }, + { + "id": "d10f3ffd98055447", + "type": "ui_toast", + "z": "9daf9e2b.019fc", + "position": "top right", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 0, + "ok": "OK", + "cancel": "", + "raw": false, + "className": "", + "topic": "", + "name": "", + "x": 750, + "y": 380, + "wires": [] + }, + { + "id": "9c1629488b02fdba", + "type": "ui_toast", + "z": "9daf9e2b.019fc", + "position": "top right", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 0, + "ok": "OK", + "cancel": "", + "raw": false, + "className": "", + "topic": "", + "name": "", + "x": 750, + "y": 460, + "wires": [] + }, + { + "id": "3910d662.fa1f7a", + "type": "exec", + "z": "1371dec5.76e671", + "command": "df -h | grep /dev/root | awk -F ' ' '{print $5}' | tr -d % | tr \"\\n$\" \"\\ \" | sed 's/,/./' | tr -d \" \"", + "addpay": false, + "append": "", + "useSpawn": "", + "timer": "", + "name": "Disk Usage", + "x": 330, + "y": 120, + "wires": [ + [ + "eaf74a43.fa27d" + ], + [], + [] + ] + }, + { + "id": "1cd5b4c0.46af9b", + "type": "inject", + "z": "1371dec5.76e671", + "name": "update: 5s", + "props": [ + { + "p": "payload" + }, + { + "p": "topic", + "vt": "str" + } + ], + "repeat": "5", + "crontab": "", + "once": false, + "onceDelay": "", + "topic": "", + "payload": "", + "payloadType": "date", + "x": 110, + "y": 160, + "wires": [ + [ + "3910d662.fa1f7a", + "aa2e4cd182dbc776", + "797675a937dc1629", + "f6f570b10c675854" + ] + ] + }, + { + "id": "569154a.b53182c", + "type": "inject", + "z": "1371dec5.76e671", + "name": "once", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": "", + "topic": "", + "payload": "start", + "payloadType": "str", + "x": 130, + "y": 700, + "wires": [ + [ + "5883e629f5d546ed" + ] + ] + }, + { + "id": "4828d2f4.7c712c", + "type": "function", + "z": "1371dec5.76e671", + "name": "set global", + "func": "global.set(\"acq_instrument_id\",msg.payload);\n", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 580, + "y": 720, + "wires": [ + [] + ] + }, + { + "id": "e2f39a35.f57298", + "type": "subflow:1c24ad9c.bebec2", + "z": "1371dec5.76e671", + "name": "", + "env": [], + "x": 130, + "y": 640, + "wires": [ + [ + "9b64f397101c2762" + ] + ] + }, + { + "id": "3e64877a.9684b", + "type": "function", + "z": "1371dec5.76e671", + "name": "set global", + "func": "global.set(\"acq_software\", \"PlanktoScope \" + msg.payload);\n", + "outputs": 1, + "timeout": "", + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 820, + "y": 520, + "wires": [ + [] + ] + }, + { + "id": "bdc6718a.dd5d48", + "type": "ui_text", + "z": "1371dec5.76e671", + "group": "ce9e278.781eed8", + "order": 2, + "width": 0, + "height": 0, + "name": "", + "label": "Instrument Type", + "format": "{{msg.payload}}", + "layout": "row-spread", + "className": "", + "style": false, + "font": "", + "fontSize": "", + "color": "#000000", + "x": 600, + "y": 640, + "wires": [] + }, + { + "id": "a400a97e.e333a8", + "type": "ui_text", + "z": "1371dec5.76e671", + "group": "ce9e278.781eed8", + "order": 1, + "width": 0, + "height": 0, + "name": "", + "label": "Instrument Name", + "format": "{{msg.payload}}", + "layout": "row-spread", + "x": 610, + "y": 680, + "wires": [] + }, + { + "id": "8343fa69.49339", + "type": "ui_text", + "z": "1371dec5.76e671", + "group": "ce9e278.781eed8", + "order": 3, + "width": 0, + "height": 0, + "name": "", + "label": "Software Version", + "format": "{{msg.payload}}", + "layout": "row-spread", + "className": "", + "style": false, + "font": "", + "fontSize": "", + "color": "#000000", + "x": 850, + "y": 560, + "wires": [] + }, + { + "id": "f783aefd.c3bfd8", + "type": "ui_text", + "z": "1371dec5.76e671", + "group": "ce9e278.781eed8", + "order": 4, + "width": 0, + "height": 0, + "name": "", + "label": "Camera Name", + "format": "{{msg.payload}}", + "layout": "row-spread", + "x": 600, + "y": 760, + "wires": [] + }, + { + "id": "30067f35.532f2", + "type": "link in", + "z": "1371dec5.76e671", + "name": "Camera Name", + "links": [ + "559a8085.1d6b9" + ], + "x": 155, + "y": 760, + "wires": [ + [ + "f783aefd.c3bfd8" + ] + ] + }, + { + "id": "eaf74a43.fa27d", + "type": "switch", + "z": "1371dec5.76e671", + "name": "if disk > 90%", + "property": "payload", + "propertyType": "msg", + "rules": [ + { + "t": "gte", + "v": "90", + "vt": "num" + } + ], + "checkall": "true", + "repair": false, + "outputs": 1, + "x": 590, + "y": 120, + "wires": [ + [ + "6d09f428.930bcc" + ] + ] + }, + { + "id": "46d5e78b.15f998", + "type": "ui_toast", + "z": "1371dec5.76e671", + "position": "dialog", + "displayTime": "10", + "highlight": "", + "sendall": true, + "outputs": 1, + "ok": "OK", + "cancel": "", + "raw": false, + "topic": "", + "name": "", + "x": 1090, + "y": 120, + "wires": [ + [] + ] + }, + { + "id": "24df077a.cb252", + "type": "change", + "z": "1371dec5.76e671", + "name": "full disk msg", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "\"Your drive has reached 90% capacity, you should do a backup to an external drive and a purge.\"", + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 930, + "y": 120, + "wires": [ + [ + "46d5e78b.15f998" + ] + ] + }, + { + "id": "6d09f428.930bcc", + "type": "delay", + "z": "1371dec5.76e671", + "name": "", + "pauseType": "rate", + "timeout": "5", + "timeoutUnits": "seconds", + "rate": "1", + "nbRateUnits": "5", + "rateUnits": "minute", + "randomFirst": "1", + "randomLast": "5", + "randomUnits": "seconds", + "drop": true, + "allowrate": false, + "outputs": 1, + "x": 760, + "y": 120, + "wires": [ + [ + "24df077a.cb252" + ] + ] + }, + { + "id": "5883e629f5d546ed", + "type": "file in", + "z": "1371dec5.76e671", + "name": "Get machine name", + "filename": "/run/machine-name", + "filenameType": "str", + "format": "utf8", + "chunk": false, + "sendError": false, + "encoding": "none", + "allProps": false, + "x": 350, + "y": 700, + "wires": [ + [ + "a400a97e.e333a8", + "4828d2f4.7c712c" + ] + ] + }, + { + "id": "9b64f397101c2762", + "type": "change", + "z": "1371dec5.76e671", + "name": "Get acq_instrument", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.acq_instrument", + "tot": "msg" + }, + { + "t": "set", + "p": "topic", + "pt": "msg", + "to": "acq_instrument", + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 350, + "y": 640, + "wires": [ + [ + "bdc6718a.dd5d48" + ] + ] + }, + { + "id": "99725e1437cc390b", + "type": "file in", + "z": "1371dec5.76e671", + "name": "Versioning File", + "filename": "/usr/share/planktoscope/installer-versioning.yml", + "filenameType": "str", + "format": "utf8", + "chunk": false, + "sendError": false, + "encoding": "none", + "allProps": false, + "x": 240, + "y": 540, + "wires": [ + [ + "f4e21e28bd903f6d" + ] + ], + "info": "# PlanktoScope Help\nThis Node will read the content of the file named **config.txt** containing all the input placeholders.\n" + }, + { + "id": "6a0fa173874c3ddd", + "type": "inject", + "z": "1371dec5.76e671", + "name": "once", + "props": [ + { + "p": "payload" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": "", + "topic": "", + "payload": "start", + "payloadType": "str", + "x": 90, + "y": 540, + "wires": [ + [ + "99725e1437cc390b" + ] + ] + }, + { + "id": "f4e21e28bd903f6d", + "type": "yaml", + "z": "1371dec5.76e671", + "property": "payload", + "name": "", + "x": 390, + "y": 540, + "wires": [ + [ + "d6264e3e29b68c6e", + "aa84b912c996c69e", + "fba22dc2c16b3ec8" + ] + ] + }, + { + "id": "d6264e3e29b68c6e", + "type": "change", + "z": "1371dec5.76e671", + "name": "Get version", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.version", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 590, + "y": 540, + "wires": [ + [ + "3e64877a.9684b", + "8343fa69.49339" + ] + ] + }, + { + "id": "aa84b912c996c69e", + "type": "change", + "z": "1371dec5.76e671", + "name": "Get repo", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.repo", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 580, + "y": 500, + "wires": [ + [ + "fd55e7a43d9bdbbb" + ] + ] + }, + { + "id": "fd55e7a43d9bdbbb", + "type": "function", + "z": "1371dec5.76e671", + "name": "set global", + "func": "global.set(\"process_source\", msg.payload);\n", + "outputs": 1, + "timeout": "", + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 820, + "y": 480, + "wires": [ + [] + ] + }, + { + "id": "fba22dc2c16b3ec8", + "type": "change", + "z": "1371dec5.76e671", + "name": "Get commit", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.commit", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 590, + "y": 580, + "wires": [ + [ + "2ddc75a4ac38a17f" + ] + ] + }, + { + "id": "2ddc75a4ac38a17f", + "type": "function", + "z": "1371dec5.76e671", + "name": "set global", + "func": "global.set(\"process_commit\", msg.payload);\n", + "outputs": 1, + "timeout": "", + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 820, + "y": 600, + "wires": [ + [] + ] + }, + { + "id": "797675a937dc1629", + "type": "ui_template", + "z": "1371dec5.76e671", + "group": "3da7da8f.179606", + "name": "Metrics panel", + "order": 2, + "width": "0", + "height": "0", + "format": "
\n

\n The instrument's system time is different from your web browser's time by {{drift}}.\n As a result, timestamps in your datasets will be incorrect.\n Additionally, system metrics will not be recorded or shown correctly.\n Additionally, you will see incorrectly-aligned graphs in the metrics below.\n

\n

Please change the instrument's system time or your web browser's time to accurate values.

\n

\n \n

\n
\n\n
\n

Loading system metrics, please wait...

\n
\n\n
\n \n
\n\n\n", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "className": "", + "x": 330, + "y": 280, + "wires": [ + [] + ] + }, + { + "id": "aa2e4cd182dbc776", + "type": "function", + "z": "1371dec5.76e671", + "name": "Get system time", + "func": "var date = new Date();\ndate.setSeconds(0, 0);\nmsg.payload = (\n date.toISOString().replace('T', ' ').replace(/:\\d+\\.\\d+Z/,' UTC')\n);\nreturn msg", + "outputs": 1, + "timeout": "", + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 340, + "y": 240, + "wires": [ + [ + "7c9ee522f6dbd3b0" + ] + ] + }, + { + "id": "7c9ee522f6dbd3b0", + "type": "ui_text", + "z": "1371dec5.76e671", + "group": "ce9e278.781eed8", + "order": 5, + "width": 0, + "height": 0, + "name": "", + "label": "System Time", + "format": "{{msg.payload}}", + "layout": "row-spread", + "className": "", + "style": false, + "font": "", + "fontSize": "", + "color": "#000000", + "x": 590, + "y": 240, + "wires": [] + }, + { + "id": "6dc9862f2eebe935", + "type": "http in", + "z": "1371dec5.76e671", + "name": "POST /api/system-time", + "url": "/api/system-time", + "method": "post", + "upload": false, + "swaggerDoc": "", + "x": 120, + "y": 360, + "wires": [ + [ + "a7994a561866dc94", + "dea222e9a6553cac" + ] + ] + }, + { + "id": "1c4113d4c933fd4b", + "type": "ui_toast", + "z": "1371dec5.76e671", + "position": "top right", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 0, + "ok": "OK", + "cancel": "", + "raw": false, + "className": "", + "topic": "Setting system time", + "name": "", + "x": 610, + "y": 340, + "wires": [] + }, + { + "id": "a7994a561866dc94", + "type": "function", + "z": "1371dec5.76e671", + "name": "Get system time", + "func": "var date = new Date(msg.payload.timestamp);\nmsg.payload = (\n date.toISOString().replace('T', ' ').replace(/:\\d+\\.\\d+Z/,' UTC')\n);\nreturn msg", + "outputs": 1, + "timeout": "", + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 340, + "y": 340, + "wires": [ + [ + "1c4113d4c933fd4b", + "423659c62bae0524" + ] + ] + }, + { + "id": "814ce40bfc413777", + "type": "exec", + "z": "1371dec5.76e671", + "command": "sudo date -s", + "addpay": "payload", + "append": "", + "useSpawn": "", + "timer": "", + "winHide": false, + "name": "Set system time", + "x": 600, + "y": 380, + "wires": [ + [], + [], + [] + ] + }, + { + "id": "dea222e9a6553cac", + "type": "function", + "z": "1371dec5.76e671", + "name": "Prepare timestamp", + "func": "msg.payload = ('@' + msg.payload.timestamp).slice(0, -3);\nreturn msg;", + "outputs": 1, + "timeout": "", + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 350, + "y": 380, + "wires": [ + [ + "814ce40bfc413777" + ] + ] + }, + { + "id": "f6f570b10c675854", + "type": "ui_template", + "z": "1371dec5.76e671", + "group": "ce9e278.781eed8", + "name": "Browser time", + "order": 6, + "width": "6", + "height": "1", + "format": "
\n

Browser Time

\n

{{time}}

\n
\n\n", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": false, + "templateScope": "local", + "className": "", + "x": 330, + "y": 200, + "wires": [ + [] + ] + }, + { + "id": "3822b843fda94733", + "type": "http in", + "z": "1371dec5.76e671", + "name": "GET /api/system-time", + "url": "/api/system-time", + "method": "get", + "upload": false, + "swaggerDoc": "", + "x": 120, + "y": 420, + "wires": [ + [ + "5b0a65d3fe187424" + ] + ] + }, + { + "id": "5b0a65d3fe187424", + "type": "function", + "z": "1371dec5.76e671", + "name": "Get system time", + "func": "var date = new Date();\nmsg.payload = {'timestamp': date.getTime()};\nreturn msg", + "outputs": 1, + "timeout": "", + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 340, + "y": 420, + "wires": [ + [ + "312a15407574b38e" + ] + ] + }, + { + "id": "423659c62bae0524", + "type": "http response", + "z": "1371dec5.76e671", + "name": "Send POST response", + "statusCode": "", + "headers": {}, + "x": 620, + "y": 300, + "wires": [] + }, + { + "id": "312a15407574b38e", + "type": "http response", + "z": "1371dec5.76e671", + "name": "Send GET response", + "statusCode": "", + "headers": { + "Content-Type": "application/json; charset=UTF-8" + }, + "x": 620, + "y": 420, + "wires": [] + }, + { + "id": "1fdf77b5.24e4e", + "type": "mqtt in", + "z": "9a22e67a.378818", + "name": "", + "topic": "status/#", + "qos": "0", + "datatype": "json", + "broker": "8dc3722c.06efa8", + "nl": false, + "rap": false, + "inputs": 0, + "x": 290, + "y": 340, + "wires": [ + [ + "fa73983d.318188" + ] + ] + }, + { + "id": "4a1e9e3e.27506", + "type": "switch", + "z": "9a22e67a.378818", + "name": "Filter segmenter out", + "property": "topic", + "propertyType": "msg", + "rules": [ + { + "t": "else" + }, + { + "t": "cont", + "v": "status/segmenter", + "vt": "str" + } + ], + "checkall": "true", + "repair": false, + "outputs": 2, + "x": 620, + "y": 340, + "wires": [ + [ + "58f2e0f.4e8b12" + ], + [ + "dcf5bd45.16a8d" + ] + ] + }, + { + "id": "fa73983d.318188", + "type": "json", + "z": "9a22e67a.378818", + "name": "", + "property": "payload", + "action": "obj", + "pretty": true, + "x": 430, + "y": 340, + "wires": [ + [ + "4a1e9e3e.27506" + ] + ] + }, + { + "id": "58f2e0f.4e8b12", + "type": "link out", + "z": "9a22e67a.378818", + "name": "Fluidic module status", + "links": [ + "bb628f8d.98f108" + ], + "x": 795, + "y": 320, + "wires": [] + }, + { + "id": "dcf5bd45.16a8d", + "type": "link out", + "z": "9a22e67a.378818", + "name": "Segmenter module status", + "links": [ + "25867454.a8e334" + ], + "x": 795, + "y": 360, + "wires": [] + }, + { + "id": "e41870d7.300eb8", + "type": "link out", + "z": "1eaf21c8.f7a21e", + "name": "Stepper config change", + "mode": "link", + "links": [ + "438febd245a9f73c" + ], + "x": 1495, + "y": 380, + "wires": [] + }, + { + "id": "2068e7f.f4efb18", + "type": "delay", + "z": "1eaf21c8.f7a21e", + "name": "", + "pauseType": "delay", + "timeout": "1", + "timeoutUnits": "seconds", + "rate": "1", + "nbRateUnits": "1", + "rateUnits": "second", + "randomFirst": "1", + "randomLast": "5", + "randomUnits": "seconds", + "drop": false, + "outputs": 1, + "x": 1180, + "y": 380, + "wires": [ + [ + "e41870d7.300eb8" + ] + ] + }, + { + "id": "8e3b3d3c.955148", + "type": "subflow:4ed26b8b.253504", + "z": "1eaf21c8.f7a21e", + "name": "", + "env": [], + "x": 1220, + "y": 420, + "wires": [] + }, + { + "id": "54ba7f16.709ad8", + "type": "change", + "z": "1eaf21c8.f7a21e", + "name": "Get pump_steps_per_ml", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.pump_steps_per_ml", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 670, + "y": 400, + "wires": [ + [ + "ee58b91c.396108" + ] + ] + }, + { + "id": "ee58b91c.396108", + "type": "ui_text_input", + "z": "1eaf21c8.f7a21e", + "name": "pump_steps_per_ml", + "label": "Pump: steps per mL", + "tooltip": "", + "group": "6be36295.0ab324", + "order": 6, + "width": 0, + "height": 0, + "passthru": false, + "mode": "number", + "delay": "2000", + "topic": "pump_steps_per_ml", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 940, + "y": 400, + "wires": [ + [ + "2068e7f.f4efb18", + "8e3b3d3c.955148" + ] + ] + }, + { + "id": "7534dfd9.8cf3e8", + "type": "ui_template", + "z": "1eaf21c8.f7a21e", + "group": "6be36295.0ab324", + "name": "Information", + "order": 1, + "width": "8", + "height": "3", + "format": "
\n

\n Changing one of these values will cause the Python hardware controller to restart, to reload the new hardware configuration.\n

\n

\n Warning: selecting a hardware version from the dropdown menu below will also overwrite all of your hardware settings, including your camera white balance settings.\n

\n

\n If you are not sure, you probably should not be touching anything here!\n

\n
\n", + "storeOutMessages": true, + "fwdInMessages": true, + "resendOnRefresh": true, + "templateScope": "local", + "className": "", + "x": 610, + "y": 40, + "wires": [ + [] + ] + }, + { + "id": "a7e5c7f4.644678", + "type": "ui_dropdown", + "z": "1eaf21c8.f7a21e", + "name": "", + "label": "Hardware version", + "tooltip": "", + "place": "Select option", + "group": "6be36295.0ab324", + "order": 2, + "width": 0, + "height": 0, + "passthru": false, + "multiple": false, + "options": [ + { + "label": "", + "value": "PlanktoScope v2.1", + "type": "str" + }, + { + "label": "", + "value": "PlanktoScope v2.3", + "type": "str" + }, + { + "label": "", + "value": "PlanktoScope v2.5", + "type": "str" + }, + { + "label": "", + "value": "PlanktoScope v2.6", + "type": "str" + }, + { + "label": "", + "value": "PlanktoScope v3.0", + "type": "str" + } + ], + "payload": "", + "topic": "acq_instrument", + "topicType": "str", + "className": "", + "x": 670, + "y": 160, + "wires": [ + [ + "08d177136bd18281", + "56dd3f82c45717f0" + ] + ] + }, + { + "id": "1cfadc66.3cde8c", + "type": "subflow:1c24ad9c.bebec2", + "z": "1eaf21c8.f7a21e", + "name": "", + "env": [], + "x": 510, + "y": 300, + "wires": [ + [] + ] + }, + { + "id": "3e2c5c1c.4c57b4", + "type": "function", + "z": "1eaf21c8.f7a21e", + "name": "Save global", + "func": "global.set(msg.topic,msg.payload);\nreturn msg;", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 350, + "y": 300, + "wires": [ + [ + "1cfadc66.3cde8c" + ] + ] + }, + { + "id": "427c312.fc5e65", + "type": "subflow:1c24ad9c.bebec2", + "z": "1eaf21c8.f7a21e", + "name": "", + "env": [], + "x": 170, + "y": 140, + "wires": [ + [ + "c00c6732b9f36adb" + ] + ] + }, + { + "id": "c67c305004f87e39", + "type": "change", + "z": "1eaf21c8.f7a21e", + "name": "Get process_pixel_fixed", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.process_pixel_fixed", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 670, + "y": 480, + "wires": [ + [ + "244ca5dd62df2bcd" + ] + ] + }, + { + "id": "244ca5dd62df2bcd", + "type": "ui_text_input", + "z": "1eaf21c8.f7a21e", + "name": "process_pixel_fixed", + "label": "Pixel size calibration: um per pixel", + "tooltip": "Object size in µm / pixel. 0 will remove this calibration.", + "group": "6be36295.0ab324", + "order": 8, + "width": 0, + "height": 0, + "passthru": true, + "mode": "number", + "delay": "1000", + "topic": "process_pixel_fixed", + "sendOnBlur": true, + "className": "", + "topicType": "str", + "x": 940, + "y": 480, + "wires": [ + [ + "8e3b3d3c.955148", + "f9b47f4b1da15778" + ] + ] + }, + { + "id": "f9b47f4b1da15778", + "type": "function", + "z": "1eaf21c8.f7a21e", + "name": "Set or remove if null", + "func": "if (msg.payload == 0){\n global.set(msg.topic,undefined)\n}\nelse {\n global.set(msg.topic,msg.payload);\n}\n\nreturn msg", + "outputs": 1, + "noerr": 0, + "initialize": "", + "finalize": "", + "libs": [], + "x": 1220, + "y": 480, + "wires": [ + [ + "5d5ad36d2c50dcc2" + ] + ] + }, + { + "id": "5d5ad36d2c50dcc2", + "type": "link out", + "z": "1eaf21c8.f7a21e", + "name": "Process_pixel calibration", + "links": [], + "x": 1495, + "y": 500, + "wires": [] + }, + { + "id": "6146ba22df928516", + "type": "ui_dropdown", + "z": "1eaf21c8.f7a21e", + "name": "acq_fnumber_objective", + "label": "M12 Lens", + "tooltip": "", + "place": "Select option", + "group": "6be36295.0ab324", + "order": 7, + "width": 0, + "height": 0, + "passthru": true, + "multiple": false, + "options": [ + { + "label": "f 25mm 1/2\" 5MP IR", + "value": 25, + "type": "num" + }, + { + "label": "f 16mm 1/2.5\" 5MP IR", + "value": 16, + "type": "num" + }, + { + "label": "f 12mm 1/2.5\" 5MP IR", + "value": 12, + "type": "num" + }, + { + "label": "f 8mm 1/2.5\" 5MP IR", + "value": 8, + "type": "num" + }, + { + "label": "f 6mm 1/2.5\" 5MP IR", + "value": 6, + "type": "num" + } + ], + "payload": "", + "topic": "acq_fnumber_objective", + "topicType": "str", + "x": 930, + "y": 520, + "wires": [ + [ + "a6983d3232b570a7", + "8e3b3d3c.955148" + ] + ] + }, + { + "id": "a6983d3232b570a7", + "type": "change", + "z": "1eaf21c8.f7a21e", + "name": "", + "rules": [ + { + "t": "set", + "p": "acq_fnumber_objective", + "pt": "global", + "to": "payload", + "tot": "msg" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 1260, + "y": 520, + "wires": [ + [ + "5d5ad36d2c50dcc2" + ] + ] + }, + { + "id": "11955bbeefc29ab4", + "type": "change", + "z": "1eaf21c8.f7a21e", + "name": "Get acq_fnumber_objective", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.acq_fnumber_objective", + "tot": "msg" + }, + { + "t": "set", + "p": "topic", + "pt": "msg", + "to": "acq_fnumber_objective", + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 680, + "y": 520, + "wires": [ + [ + "6146ba22df928516" + ] + ] + }, + { + "id": "d276ce894f483bcf", + "type": "ui_toast", + "z": "1eaf21c8.f7a21e", + "position": "top right", + "displayTime": "3", + "highlight": "", + "sendall": true, + "outputs": 0, + "ok": "OK", + "cancel": "", + "raw": false, + "className": "", + "topic": "Resetting hardware configuration to version-specific default", + "name": "", + "x": 370, + "y": 260, + "wires": [] + }, + { + "id": "68703ef63da2f081", + "type": "change", + "z": "1eaf21c8.f7a21e", + "name": "Choose default hardware config", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "$join([\"/home/pi/PlanktoScope/device-backend/default-configs/\", $substringAfter(msg.payload, \"PlanktoScope \"), \".hardware.json\"])", + "tot": "jsonata" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 410, + "y": 220, + "wires": [ + [ + "e3ba6ac89221b17b" + ] + ] + }, + { + "id": "e3ba6ac89221b17b", + "type": "exec", + "z": "1eaf21c8.f7a21e", + "command": "cp", + "addpay": "payload", + "append": "/home/pi/PlanktoScope/hardware.json", + "useSpawn": "false", + "timer": "", + "winHide": false, + "oldrc": false, + "name": "Copy default hardware config", + "x": 700, + "y": 220, + "wires": [ + [ + "97e582080deae888" + ], + [], + [] + ] + }, + { + "id": "97e582080deae888", + "type": "delay", + "z": "1eaf21c8.f7a21e", + "name": "", + "pauseType": "delay", + "timeout": "500", + "timeoutUnits": "milliseconds", + "rate": "1", + "nbRateUnits": "1", + "rateUnits": "second", + "randomFirst": "1", + "randomLast": "5", + "randomUnits": "seconds", + "drop": false, + "allowrate": false, + "outputs": 1, + "x": 930, + "y": 220, + "wires": [ + [ + "3973b999ee7b3b1d" + ] + ] + }, + { + "id": "3973b999ee7b3b1d", + "type": "link out", + "z": "1eaf21c8.f7a21e", + "name": "Reload hardware config", + "mode": "link", + "links": [ + "438febd245a9f73c", + "4ebc0345e63a78e9", + "5984b086eddc9311", + "a2f2a4c7cbae4446" + ], + "x": 1095, + "y": 220, + "wires": [] + }, + { + "id": "3bcaf757cbc77fbe", + "type": "subflow:b7861ce703215a01", + "z": "1eaf21c8.f7a21e", + "name": "", + "x": 380, + "y": 440, + "wires": [ + [ + "54ba7f16.709ad8", + "c67c305004f87e39", + "11955bbeefc29ab4" + ] + ] + }, + { + "id": "862235d10aae5b83", + "type": "inject", + "z": "1eaf21c8.f7a21e", + "name": "Once", + "props": [], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "x": 170, + "y": 460, + "wires": [ + [ + "3bcaf757cbc77fbe" + ] + ] + }, + { + "id": "c00c6732b9f36adb", + "type": "change", + "z": "1eaf21c8.f7a21e", + "name": "Get acq_instrument", + "rules": [ + { + "t": "set", + "p": "payload", + "pt": "msg", + "to": "payload.acq_instrument", + "tot": "msg" + }, + { + "t": "set", + "p": "topic", + "pt": "msg", + "to": "acq_instrument", + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 370, + "y": 140, + "wires": [ + [ + "a7e5c7f4.644678", + "56dd3f82c45717f0" + ] + ] + }, + { + "id": "4ebc0345e63a78e9", + "type": "link in", + "z": "1eaf21c8.f7a21e", + "name": "Load hardware config", + "links": [ + "3973b999ee7b3b1d" + ], + "x": 205, + "y": 420, + "wires": [ + [ + "3bcaf757cbc77fbe" + ] + ] + }, + { + "id": "cb9009e8a49e93cc", + "type": "link in", + "z": "1eaf21c8.f7a21e", + "name": "Set hardware version", + "links": [ + "08d177136bd18281", + "9f34e4a2f33c4022" + ], + "x": 205, + "y": 260, + "wires": [ + [ + "68703ef63da2f081", + "d276ce894f483bcf", + "3e2c5c1c.4c57b4", + "a7e5c7f4.644678" + ] + ] + }, + { + "id": "08d177136bd18281", + "type": "link out", + "z": "1eaf21c8.f7a21e", + "name": "Set hardware version", + "mode": "link", + "links": [ + "cb9009e8a49e93cc" + ], + "x": 875, + "y": 160, + "wires": [] + }, + { + "id": "56dd3f82c45717f0", + "type": "link out", + "z": "1eaf21c8.f7a21e", + "name": "Hardware version loaded", + "mode": "link", + "links": [ + "a2f2a4c7cbae4446" + ], + "x": 875, + "y": 120, + "wires": [] + } ] From 891c2c74b9d471978ce551d23dd12afb152664ee Mon Sep 17 00:00:00 2001 From: Sonny Piers Date: Wed, 21 May 2025 11:10:56 +0200 Subject: [PATCH 3/3] f --- .editorconfig | 5 +++++ .prettierignore | 2 ++ 2 files changed, 7 insertions(+) create mode 100644 .prettierignore diff --git a/.editorconfig b/.editorconfig index 757efe4c3..90812fb5c 100644 --- a/.editorconfig +++ b/.editorconfig @@ -11,3 +11,8 @@ insert_final_newline = true # Tab indentation (no size specified) [Makefile] indent_style = tab + +# Formatting managed by Node-RED +[flows.json] +indent_style = unset +indent_size = unset diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 000000000..8b1eb44ac --- /dev/null +++ b/.prettierignore @@ -0,0 +1,2 @@ +# Formatting managed by Node-RED +flows.json