Configurer des intégrations open source avec Docker (Linux) - AWS IoT SiteWise

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

Configurer des intégrations open source avec Docker (Linux)

Pour un processus de déploiement rationalisé, vous pouvez utiliser Docker pour configurer Node-RED®, InfluxDB® et Grafana® dans un environnement Linux. Cette méthode utilise des conteneurs préconfigurés, ce qui permet un déploiement rapide et une gestion simplifiée des composants.

Conditions préalables à la configuration de Docker

Avant de commencer, vérifiez que vous disposez des éléments suivants :

Déployez les services

Ce déploiement exécute SiteWise Edge, InfluxDB, Node-RED et Grafana sur le même hôte.

Configuration de l'environnement

  1. Bénéficiez d'un accès root :

    sudo -i
  2. Créez un fichier .env ou exportez les variables d'environnement suivantes :

    export INFLUXDB_PASSWORD=your-secure-influxdb-password export INFLUXDB_TOKEN=your-secure-influxdb-token export GRAFANA_PASSWORD=your-secure-grafana-password

Configuration du réseau Docker

  • Créez un réseau de ponts en utilisant le nomSiteWiseEdgeNodeRedDemoNetwork.

    docker network create --driver=bridge SiteWiseEdgeNodeRedDemoNetwork

Préparez le Docker Compose fichier

Copiez le contenu du fichier YAML suivant sur votre périphérique de passerelle SiteWise Edge.

services: influxdb: image: influxdb:latest container_name: influxdb ports: - "127.0.0.1:8086:8086" volumes: - influxdb-storage:/.influxdbv2 environment: - DOCKER_INFLUXDB_INIT_MODE=setup - DOCKER_INFLUXDB_INIT_USERNAME=admin - DOCKER_INFLUXDB_INIT_PASSWORD=${INFLUXDB_PASSWORD} - DOCKER_INFLUXDB_INIT_ORG=iot-sitewise-edge - DOCKER_INFLUXDB_INIT_BUCKET=WindFarmData - DOCKER_INFLUXDB_INIT_RETENTION=0 - DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=${INFLUXDB_TOKEN} networks: - SiteWiseEdgeNodeRedDemoNetwork restart: unless-stopped grafana: image: grafana/grafana:latest container_name: grafana ports: - "127.0.0.1:3000:3000" volumes: - grafana-storage:/var/lib/grafana - ./grafana/provisioning:/etc/grafana/provisioning environment: - GF_SECURITY_ADMIN_USER=admin - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD} - GF_INSTALL_PLUGINS=grafana-clock-panel,grafana-simple-json-datasource - GF_PATHS_PROVISIONING=/etc/grafana/provisioning - GF_PATHS_CONFIG=/etc/grafana/grafana.ini - GF_LOG_LEVEL=info configs: - source: grafana_datasource target: /etc/grafana/provisioning/datasources/influxdb.yaml - source: grafana_preload_dashboard_config target: /etc/grafana/provisioning/dashboards/dashboard.yml - source: grafana_preload_dashboard target: /etc/grafana/provisioning/dashboards/demo_dashboard.json depends_on: - influxdb networks: - SiteWiseEdgeNodeRedDemoNetwork restart: unless-stopped nodered: build: context: . dockerfile_inline: | FROM nodered/node-red:latest RUN npm install node-red-contrib-influxdb container_name: nodered ports: - "127.0.0.1:1880:1880" volumes: - node_red_data:/data environment: - NODE_RED_ENABLE_SAFE_MODE=false - NODE_RED_ENABLE_PALETTE_EDIT=true - NODE_RED_AUTO_INSTALL_MODULES=true configs: - source: nodered_flows target: /data/flows.json - source: nodered_settings target: /data/settings.js - source: nodered_flows_cred target: /data/flows_cred.json depends_on: - influxdb networks: - SiteWiseEdgeNodeRedDemoNetwork restart: unless-stopped volumes: influxdb-storage: grafana-storage: node_red_data: networks: SiteWiseEdgeNodeRedDemoNetwork: external: true configs: grafana_datasource: content: | apiVersion: 1 datasources: - name: windfarm-demo type: influxdb access: proxy url: http://influxdb:8086 jsonData: version: Flux organization: iot-sitewise-edge defaultBucket: WindFarmData tlsSkipVerify: true secureJsonData: token: ${INFLUXDB_TOKEN} editable: false grafana_preload_dashboard_config: content: | apiVersion: 1 providers: - name: "Dashboard provider" orgId: 1 type: file options: path: /etc/grafana/provisioning/dashboards grafana_preload_dashboard: content: | { "annotations": { "list": [ { "builtIn": 1, "datasource": { "type": "grafana", "uid": "-- Grafana --" }, "enable": true, "hide": true, "iconColor": "rgba(0, 211, 255, 1)", "name": "Annotations & Alerts", "type": "dashboard" } ] }, "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 0, "id": 1, "links": [], "panels": [ { "datasource": { "type": "influxdb", "uid": "PEB0DCBF338B3CEB2" }, "fieldConfig": { "defaults": { "color": { "mode": "palette-classic" }, "custom": { "axisBorderShow": false, "axisCenteredZero": false, "axisColorMode": "text", "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 0, "gradientMode": "none", "hideFrom": { "legend": false, "tooltip": false, "viz": false }, "insertNulls": false, "lineInterpolation": "linear", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { "type": "linear" }, "showPoints": "auto", "spanNulls": false, "stacking": { "group": "A", "mode": "none" }, "thresholdsStyle": { "mode": "off" } }, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green" }, { "color": "red", "value": 80 } ] } }, "overrides": [] }, "gridPos": { "h": 8, "w": 12, "x": 0, "y": 0 }, "id": 1, "options": { "legend": { "calcs": [], "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "hideZeros": false, "mode": "single", "sort": "none" } }, "pluginVersion": "11.6.0", "targets": [ { "datasource": { "type": "influxdb", "uid": "PEB0DCBF338B3CEB2" }, "query": "from(bucket: \"WindFarmData\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"TurbineData\")\n |> filter(fn: (r) => r[\"_field\"] == \"value\")\n |> filter(fn: (r) => r[\"name\"] == \"/Renton/WindFarm/Turbine/WindSpeed\")\n |> filter(fn: (r) => r[\"quality\"] == \"GOOD\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", "refId": "A" } ], "title": "Wind Speed", "type": "timeseries" } ], "preload": false, "schemaVersion": 41, "tags": [], "templating": { "list": [] }, "time": { "from": "now-6h", "to": "now" }, "timepicker": {}, "timezone": "browser", "title": "Demo Dashboard", "uid": "eejtureqjo9a8c", "version": 2 } nodered_flows: content: | [ { "id": "95fce448fdd43b47", "type": "tab", "label": "Demo Flow", "disabled": false, "info": "" }, { "id": "5f63740b66af3386", "type": "mqtt out", "z": "95fce448fdd43b47", "name": "Publish to MQTT broker", "topic": "/Renton/WindFarm/Turbine/WindSpeed", "qos": "1", "retain": "", "respTopic": "", "contentType": "", "userProps": "", "correl": "", "expiry": "", "broker": "5744207557fa19be", "x": 830, "y": 200, "wires": [] }, { "id": "8f2eb590d596679b", "type": "function", "z": "95fce448fdd43b47", "name": "Translate to SiteWise payload", "func": "let input = msg.payload;\nlet output = {};\n\noutput[\"propertyAlias\"] = input.name;\n\nlet propertyVal = {}\n\nlet timeInSeconds = Math.floor(input.timestamp / 1000);\nlet offsetInNanos = (input.timestamp % 1000) * 1000000;\n\npropertyVal[\"timestamp\"] = {\n \"timeInSeconds\": timeInSeconds,\n \"offsetInNanos\": offsetInNanos,\n};\n\npropertyVal[\"quality\"] = input.quality\n\nlet typeNameConverter = {\n \"number\": (x) => Number.isInteger(x) ? \"integerValue\" : \"doubleValue\",\n \"boolean\": (x) => \"booleanValue\",\n \"string\": (x) => \"stringValue\", \n}\nlet typeName = typeNameConverter[typeof input.value](input.value)\npropertyVal[\"value\"] = {}\npropertyVal[\"value\"][typeName] = input.value;\n\noutput[\"propertyValues\"] = [propertyVal]\n\nreturn {\n payload: JSON.stringify(output)\n};", "outputs": 1, "timeout": "", "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 530, "y": 200, "wires": [ [ "5f63740b66af3386" ] ] }, { "id": "4b78cbdea5e3258c", "type": "inject", "z": "95fce448fdd43b47", "name": "Turbine Simulator", "props": [ { "p": "payload.timestamp", "v": "", "vt": "date" }, { "p": "payload.quality", "v": "GOOD", "vt": "str" }, { "p": "payload.value", "v": "$$random()", "vt": "jsonata" }, { "p": "payload.name", "v": "/Renton/WindFarm/Turbine/WindSpeed", "vt": "str" } ], "repeat": "1", "crontab": "", "once": false, "onceDelay": "", "topic": "", "x": 270, "y": 200, "wires": [ [ "8f2eb590d596679b" ] ] }, { "id": "b658bf337ea2e316", "type": "influxdb out", "z": "95fce448fdd43b47", "influxdb": "2f1c38495035d2e4", "name": "Store data in InfluxDB", "measurement": "TurbineData", "precision": "", "retentionPolicy": "", "database": "", "retentionPolicyV18Flux": "", "org": "iot-sitewise-edge", "bucket": "WindFarmData", "x": 840, "y": 340, "wires": [] }, { "id": "9432d39af35b202f", "type": "function", "z": "95fce448fdd43b47", "name": "Translate to InfluxDB payload", "func": "let data = msg.payload;\n\nlet timeInSeconds = data.propertyValues[0].timestamp.timeInSeconds;\nlet offsetInNanos = data.propertyValues[0].timestamp.offsetInNanos;\nlet timestampInMilliseconds = (timeInSeconds * 1000) + (offsetInNanos / 1000000);\n\nmsg.payload = [\n {\n \"timestamp(milliseconds_since_epoch)\": timestampInMilliseconds,\n \"value\": data.propertyValues[0].value.doubleValue\n },\n {\n \"name\": data.propertyAlias,\n \"quality\": data.propertyValues[0].quality\n }\n]\n\nreturn msg", "outputs": 1, "timeout": "", "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 560, "y": 340, "wires": [ [ "b658bf337ea2e316" ] ] }, { "id": "b689403d2c80816b", "type": "mqtt in", "z": "95fce448fdd43b47", "name": "Subscribe to MQTT broker", "topic": "/Renton/WindFarm/Turbine/WindSpeed", "qos": "1", "datatype": "auto-detect", "broker": "5744207557fa19be", "nl": false, "rap": true, "rh": 0, "inputs": 0, "x": 290, "y": 340, "wires": [ [ "9432d39af35b202f" ] ] }, { "id": "4f59bed8e829fc35", "type": "comment", "z": "95fce448fdd43b47", "name": "Data Publish Flow", "info": "dfgh", "x": 270, "y": 160, "wires": [] }, { "id": "b218c7fc58c8b6e7", "type": "comment", "z": "95fce448fdd43b47", "name": "Data Retention flow", "info": "", "x": 270, "y": 300, "wires": [] }, { "id": "5744207557fa19be", "type": "mqtt-broker", "name": "emqx", "broker": "emqx", "port": "1883", "clientid": "", "autoConnect": true, "usetls": false, "protocolVersion": "5", "keepalive": 15, "cleansession": true, "autoUnsubscribe": true, "birthTopic": "", "birthQos": "0", "birthPayload": "", "birthMsg": {}, "closeTopic": "", "closePayload": "", "closeMsg": {}, "willTopic": "", "willQos": "0", "willPayload": "", "willMsg": {}, "userProps": "", "sessionExpiry": "" }, { "id": "2f1c38495035d2e4", "type": "influxdb", "hostname": "influxdb", "port": 8086, "protocol": "http", "database": "", "name": "InfluxDB", "usetls": false, "tls": "", "influxdbVersion": "2.0", "url": "http://influxdb:8086", "timeout": "", "rejectUnauthorized": false } ] nodered_flows_cred: content: | { "2f1c38495035d2e4": { "token": "${INFLUXDB_TOKEN}" } } nodered_settings: content: | module.exports = { flowFile: 'flows.json', credentialSecret: false, adminAuth: null, editorTheme: { projects: { enabled: false } } }

Mettre à jour le déploiement d' SiteWise Edge

  1. Accédez à la AWS IoT console

  2. Choisissez Appareils Greengrass dans le menu de navigation de gauche sous la section Gérer, puis Appareils Core.

  3. Sélectionnez le périphérique principal connecté à votre SiteWise Edge Gateway.

  4. Choisissez l'onglet Déploiements, puis sélectionnez la valeur de l'ID de déploiement.

  5. Choisissez Actions, puis sélectionnez Réviser.

  6. Lisez le message contextuel, puis choisissez Revise le déploiement.

  7. À l'étape 2 - Sélection des composants, sélectionnez les composants suivants, puis cliquez sur Suivant.

    • aws.greengrass.clientdevices.mqtt.EMQX

    • aws.iot.SiteWiseEdgePublisher

  8. À l'étape 3 - Configuration des composants, sélectionnez la valeur du aws.greengrass.clientdevices.mqtt.EMQX composant et ajoutez la configuration réseau suivante :

    { "emqxConfig": { "authorization": { "no_match": "allow" }, "listeners": { "tcp": { "default": { "enabled": true, "enable_authn": false } } } }, "authMode": "bypass", "dockerOptions": "-p 127.0.0.1:1883:1883 --network=SiteWiseEdgeNodeRedDemoNetwork", "requiresPrivilege": "true" }
  9. Choisissez Suivant.

  10. À l'étape 4 - Configurer les paramètres avancés, choisissez Next.

  11. Choisissez Deploy

Lancez les services

  1. Démarrez les services à l'aide du fichier Docker Compose. Exécutez la commande suivante dans le répertoire contenant le compose.yaml fichier.

    docker compose up -d
  2. Créez un tunnel SSH pour accéder aux services :

    ssh -i path_to_your_ssh_key -L 1880:127.0.0.1:1880 -L 3000:127.0.0.1:3000 -L 8086:127.0.0.1:8086 username@gateway_ip_address

Ce déploiement crée les services suivants dans SiteWiseEdgeNodeRedDemoNetwork network :

InfluxDB v2 (port 8086)

Inclut une organisation (iot-sitewise-edge) préconfigurée, un bucket WindFarmData InfluxDB et des informations d'identification d'administrateur

Node-rouge (port 1880)

Inclut des nœuds InfluxDB et des flux préconfigurés pour l'intégration AWS IoT SiteWise

Grafana (port 3000)

Comprend un utilisateur administrateur, une source de données InfluxDB et un tableau de bord de surveillance

Accédez aux services

Après le déploiement, accédez aux services à l'aide des informations suivantes URLs et des informations d'identification :

Note

Vous pouvez accéder à chaque service depuis votre hôte ou depuis la machine passerelle.

Détails d'accès au service
Service URL Informations d’identification
Nœud rouge http://127.0.0.1:1880 Aucune information d'identification requise
InfluxDB http://127.0.0.1:8086

Nom d'utilisateur : admin

Mot de passe : $INFLUXDB_PASSWORD

Grafana http://127.0.0.1:3000

Nom d'utilisateur : admin

Mot de passe : $GRAFANA_PASSWORD

Vérification du déploiement

Pour garantir le succès de votre déploiement, effectuez les vérifications suivantes :

  1. Pour Node-RED, vérifiez la présence de deux flux préchargés :

    • Flux de publication des données

    • Flux de conservation des données

  2. Car AWS IoT SiteWise, dans la AWS IoT SiteWise console, confirmez la présence d'un flux de données avec l'alias/Renton/WindFarm/Turbine/WindSpeed.

  3. Pour InfluxDB, utilisez l'explorateur de données pour vérifier le stockage des données dans la TurbineData mesure au sein du WindFarmData bucket.

  4. Pour Grafana, consultez le tableau de bord pour confirmer l'affichage des données de séries chronologiques générées par Node-RED.