기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.
Docker와의 오픈 소스 통합 설정(Linux)
간소화된 배포 프로세스를 위해 Docker를 사용하여 Linux 환경에서 Node-RED®, InfluxDB® 및 Grafana®를 설정할 수 있습니다. 이 방법은 사전 구성된 컨테이너를 사용하므로 구성 요소를 신속하게 배포하고 더 쉽게 관리할 수 있습니다.
Docker 설정 사전 조건
시작하기 전에에 다음이 있는지 확인합니다.
-
MQTT 지원 V3 게이트웨이입니다. 자세한 내용은 MQTT 지원, AWS IoT SiteWise Edge용 V3 게이트웨이 단원을 참조하십시오.
-
Docker Compose 플러그인입니다. 설치 단계는 Docker 설명서의 Docker Compose 플러그인 설치를
참조하세요.
서비스 배포
이 배포는 동일한 호스트에서 SiteWise Edge, InfluxDB, Node-RED 및 Grafana를 실행합니다.
환경 설정
-
루트 액세스 권한 획득:
sudo -i
-
.env 파일을 생성하거나 다음 환경 변수를 내보냅니다.
export INFLUXDB_PASSWORD=
your-secure-influxdb-password
export INFLUXDB_TOKEN=your-secure-influxdb-token
export GRAFANA_PASSWORD=your-secure-grafana-password
Docker 네트워크 구성
-
이름을 사용하여 브리지 네트워크를 생성합니다
SiteWiseEdgeNodeRedDemoNetwork
.docker network create --driver=bridge SiteWiseEdgeNodeRedDemoNetwork
Docker Compose 파일 준비
다음 YAML 파일의 내용을 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 } } }
SiteWise Edge 배포 업데이트
-
AWS IoT 콘솔
로 이동합니다. -
왼쪽 탐색 메뉴의 관리 섹션에서 Greengrass 디바이스를 선택한 다음 코어 디바이스를 선택합니다.
-
SiteWise Edge Gateway에 연결된 코어 디바이스를 선택합니다.
-
배포 탭을 선택한 다음 배포 ID 값을 선택합니다.
-
작업을 선택한 다음 수정을 선택합니다.
-
팝업 메시지를 읽은 다음 배포 수정을 선택합니다.
-
2단계 - 구성 요소 선택에서 다음 구성 요소를 선택한 후 다음을 선택합니다.
-
aws.greengrass.clientdevices.mqtt.EMQX
-
aws.iot.SiteWiseEdgePublisher
-
-
3단계 - 구성 요소 구성에서
aws.greengrass.clientdevices.mqtt.EMQX
구성 요소 값을 선택하고 다음 네트워크 구성을 추가합니다.{ "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" }
-
다음을 선택합니다.
-
4단계 - 고급 설정 구성에서 다음을 선택합니다.
-
배포 선택
서비스 시작
-
Docker Compose 파일을 사용하여 서비스를 시작합니다.
compose.yaml
파일이 포함된 디렉터리에서 다음 명령을 실행합니다.docker compose up -d
-
SSH 터널을 생성하여 서비스에 액세스합니다.
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:8086username
@gateway_ip_address
이 배포는에서 SiteWiseEdgeNodeRedDemoNetwork network
다음 서비스를 생성합니다.
- InfluxDB v2(포트 8086)
-
사전 구성된 조직(iot-sitewise-edge), WindFarmData InfluxDB 버킷 및 관리자 자격 증명 포함
- Node-RED(포트 1880)
-
AWS IoT SiteWise 통합을 위해 InfluxDB 노드 및 사전 구성된 흐름 포함
- Grafana(포트 3000)
-
관리자 사용자, InfluxDB 데이터 소스 및 모니터링 대시보드 포함
서비스에 액세스
배포 후 다음 URLs.
참고
호스트 또는 게이트웨이 시스템에서 각 서비스에 액세스할 수 있습니다.
Service | URL | 보안 인증 정보 |
---|---|---|
Node-RED | http://127.0.0.1:1880 |
자격 증명 필요 없음 |
InfluxDB | http://127.0.0.1:8086 |
사용자 이름: admin 암호: $INFLUXDB_PASSWORD |
Grafana | http://127.0.0.1:3000 |
사용자 이름: admin 암호: $GRAFANA_PASSWORD |
배포 확인
배포에 성공하려면 다음 검사를 수행합니다.
-
Node-RED의 경우 미리 로드된 흐름이 두 개 있는지 확인합니다.
-
데이터 게시 흐름
-
데이터 보존 흐름
-
-
의 경우 AWS IoT SiteWise 콘솔 AWS IoT SiteWise에서 별칭이 인 데이터 스트림이 있는지 확인합니다
/Renton/WindFarm/Turbine/WindSpeed
. -
InfluxDB의 경우 Data Explorer를 사용하여
WindFarmData
버킷 내TurbineData
측정에서 데이터 스토리지를 확인합니다. -
Grafana의 경우 대시보드를 보고 Node-RED에서 생성된 시계열 데이터의 표시를 확인합니다.