初识EdgeX,想理清楚设备接入及微服务间关系,最好的办法还是亲自动手部署,把数据交互功能实现出来,才能更清晰的理解EdgeX框架的各种微服务。
实践过程中,有几个坑要提前说明一下:
$curl -fsSL https://mirrors.ustc.edu.cn/docker-ce/linux/raspbian/gpg | sudo apt-key add -
获取docker-ce安装包
https://download.docker.com/linux/
因为arm64位,debian目录下找
https://download.docker.com/linux/debian/dists/buster/pool/edge/arm64/
$sudo dpkg -i containerd.io_1.3.7-1_arm64.deb
$sudo dpkg -i docker-ce-cli_19.03.13_3-0_debian-buster_arm64.deb
$sudo dpkg -i docker-ce_19.03.13_3-0_debian-buster_arm64.deb
设置docker镜像:
$sudo cat /etc/docker/daemon.json
{
"registry-mirrors": ["http://hub-mirror.c.163.com"]
}
$sudo systemctl daemon-reload
$sudo systemctl restart docker
$sudo apt-get install libffi-dev
$sudo apt-get install openssl
$pip3 install --default-timeout=100000 docker-compose
docker-compose安装过程中出现错误尝试upgrade参数解决
$pip3 install --upgrade --default-timeout=100000 docker-compose -i http://pypi.douban.com/simple
https://docs.edgexfoundry.org/1.2/getting-started/quick-start/
https://github.com/edgexfoundry/developer-scripts/tree/master/releases/geneva/compose-files
可选compose文件,跟据需求参考修改
$curl https://raw.githubusercontent.com/edgexfoundry/developer-scripts/master/releases/geneva/compose-files/docker-compose-geneva-redis-no-secty-arm64.yml -o docker-compose.yml
$docker-compose config --services
consul
redis
notifications
metadata
data
command
scheduler
system
app-service-rules
rulesengine
device-virtual
device-rest
device-random
device-mqtt
ui
$docker-compose up -d
$sudo docker-compose up -d device-random
$curl http://localhost:48080/api/v1/event/device/Random-Integer-Generator01/1
[{"id":"de7af9df-38ed-4900-b387-e1629d4f1472","device":"Random-Integer-Generator01","created":1613828304134,"origin":1613828304126888670,"readings":[{"id":"2f88dea3-15a6-44d6-980a-a1dfab38a113","created":1613828304134,"origin":1613828304126291278,"device":"Random-Integer-Generator01","name":"RandomValue_Int16","value":"-21446","valueType":"Int16"}]}]
$curl http://localhost:48082/api/v1/device/name/Random-Integer-Generator01
返回如下结果
{
"id": "edf4b3b2-9015-4ae6-afdb-f8b5e462d317",
"name": "Random-Integer-Generator01",
"adminState": "UNLOCKED",
"operatingState": "ENABLED",
"labels": ["device-random-example"],
"commands": [{
"created": 1613828283875,
"modified": 1613828283875,
"id": "025b1242-c66c-4d96-b470-70a93308eede",
"name": "GenerateRandomValue_Int32",
"get": {
"path": "/api/v1/device/{deviceId}/GenerateRandomValue_Int32",
"responses": [{
"code": "200",
"expectedValues": ["RandomValue_Int32"]
}, {
"code": "503",
"description": "service unavailable"
}],
"url": "http://edgex-core-command:48082/api/v1/device/edf4b3b2-9015-4ae6-afdb-f8b5e462d317/command/025b1242-c66c-4d96-b470-70a93308eede"
},
"put": {
"path": "/api/v1/device/{deviceId}/GenerateRandomValue_Int32",
"responses": [{
"code": "200"
}, {
"code": "503",
"description": "service unavailable"
}],
"url": "http://edgex-core-command:48082/api/v1/device/edf4b3b2-9015-4ae6-afdb-f8b5e462d317/command/025b1242-c66c-4d96-b470-70a93308eede",
"parameterNames": ["Min_Int32", "Max_Int32"]
}
}, {
"created": 1613828283874,
"modified": 1613828283874,
"id": "6943feba-f7eb-46f2-b120-d3c9890be1a1",
"name": "GenerateRandomValue_Int8",
"get": {
"path": "/api/v1/device/{deviceId}/GenerateRandomValue_Int8",
"responses": [{
"code": "200",
"expectedValues": ["RandomValue_Int8"]
}, {
"code": "503",
"description": "service unavailable"
}],
"url": "http://edgex-core-command:48082/api/v1/device/edf4b3b2-9015-4ae6-afdb-f8b5e462d317/command/6943feba-f7eb-46f2-b120-d3c9890be1a1"
},
"put": {
"path": "/api/v1/device/{deviceId}/GenerateRandomValue_Int8",
"responses": [{
"code": "200"
}, {
"code": "503",
"description": "service unavailable"
}],
"url": "http://edgex-core-command:48082/api/v1/device/edf4b3b2-9015-4ae6-afdb-f8b5e462d317/command/6943feba-f7eb-46f2-b120-d3c9890be1a1",
"parameterNames": ["Min_Int8", "Max_Int8"]
}
}, {
"created": 1613828283875,
"modified": 1613828283875,
"id": "b68cfcbf-7d3c-443d-ad38-113d22e29519",
"name": "GenerateRandomValue_Int16",
"get": {
"path": "/api/v1/device/{deviceId}/GenerateRandomValue_Int16",
"responses": [{
"code": "200",
"expectedValues": ["RandomValue_Int16"]
}, {
"code": "503",
"description": "service unavailable"
}],
"url": "http://edgex-core-command:48082/api/v1/device/edf4b3b2-9015-4ae6-afdb-f8b5e462d317/command/b68cfcbf-7d3c-443d-ad38-113d22e29519"
},
"put": {
"path": "/api/v1/device/{deviceId}/GenerateRandomValue_Int16",
"responses": [{
"code": "200"
}, {
"code": "503",
"description": "service unavailable"
}],
"url": "http://edgex-core-command:48082/api/v1/device/edf4b3b2-9015-4ae6-afdb-f8b5e462d317/command/b68cfcbf-7d3c-443d-ad38-113d22e29519",
"parameterNames": ["Min_Int16", "Max_Int16"]
}
}]
}
修改docker-compose.yml
如下代码:
ui:
image: edgexfoundry/docker-edgex-ui-go-arm64:1.2.1
ports:
- "127.0.0.1:4000:4000"
container_name: edgex-ui-go
hostname: edgex-ui-go
networks:
- edgex-network
启动UI服务
服务ui启动后,浏览器正常是可以打开UI页面了,如下图:
在这遇到问题,本机访问4000可以打开UI页面,局域网其它电脑浏览器无法访问,关闭了iptables还是没解决,后来发现是docker容器配置问题限定了访问IP,修改docker-compose.yml解决如下图:
为了方便测试,我在树莓派本机安装了mosquitto
$sudo apt-get install mosquitto
$sudo apt-get install mosquitto-clients
启动mqtt服务端log输出
$sudo mosquitto -v
app-service-mqtt:
image: edgexfoundry/docker-app-service-configurable-arm64:1.2.0
ports:
- "0.0.0.0:48101:48101"
container_name: edgex-app-service-configurable-mqtt
hostname: edgex-app-service-configurable-mqtt
networks:
- edgex-network
environment:
<<: *common-variables
edgex_profile: mqtt-export
Service_Host: edgex-app-service-configurable-mqtt
Service_Port: 48101
MessageBus_SubscribeHost_Host: edgex-core-data
Binding_PublishTopic: events
Writable_Pipeline_Functions_MQTTSend_Addressable_Address: 172.17.0.1
Writable_Pipeline_Functions_MQTTSend_Addressable_Port: 1883
Writable_Pipeline_Functions_MQTTSend_Addressable_Protocol: tcp
Writable_Pipeline_Functions_MQTTSend_Addressable_Publisher: edgex
Writable_Pipeline_Functions_MQTTSend_Addressable_Topic: EdgeXEvents
depends_on:
- consul
- data
注意 Writable_Pipeline_Functions_MQTTSend_Addressable_Address: 172.17.0.1
MQTT服务主机IP添写Docker网段所分配的主机IP。
$sudo docker-compose -f docker-compose-less.yml up app-service-mqtt
$sudo mosquitto_sub -h 127.0.0.1 -p 1883 -t EdgeXEvents
因为之前开启了device-random微服务,所以会定时收到数据。
pi@raspberrypi:~/edgex/script/device-service-demo $ sudo docker-compose ps
Name Command State Ports
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
edgex-app-service-configurable-mqtt /app-service-configurable ... Up 48095/tcp, 0.0.0.0:48101->48101/tcp
edgex-app-service-configurable-rules /app-service-configurable ... Up 48095/tcp, 0.0.0.0:48100->48100/tcp
edgex-core-command /core-command -cp=consul.h ... Up 0.0.0.0:48082->48082/tcp
edgex-core-consul edgex-consul-entrypoint.sh ... Up 8300/tcp, 8301/tcp, 8301/udp, 8302/tcp, 8302/udp, 0.0.0.0:8400->8400/tcp,
0.0.0.0:8500->8500/tcp, 8600/tcp, 8600/udp
edgex-core-data /core-data -cp=consul.http ... Up 0.0.0.0:48080->48080/tcp, 0.0.0.0:5563->5563/tcp
edgex-core-metadata /core-metadata -cp=consul. ... Up 0.0.0.0:48081->48081/tcp
edgex-device-mqtt /device-mqtt --cp=consul:/ ... Up 0.0.0.0:49982->49982/tcp
edgex-device-random /device-random --cp=consul ... Exit 0
edgex-kuiper /usr/bin/docker-entrypoint ... Up 127.0.0.1:20498->20498/tcp, 127.0.0.1:48075->48075/tcp, 9081/tcp
edgex-redis docker-entrypoint.sh redis ... Up 0.0.0.0:6379->6379/tcp
edgex-support-notifications /support-notifications -cp ... Up 127.0.0.1:48060->48060/tcp
edgex-support-scheduler /support-scheduler -cp=con ... Up 0.0.0.0:48085->48085/tcp
edgex-sys-mgmt-agent /sys-mgmt-agent -cp=consul ... Up 127.0.0.1:48090->48090/tcp
edgex-ui-go ./edgex-ui-server -conf=re ... Up 0.0.0.0:4000->4000/tcp
注意,edgex-device-random是我们之前测试生成随机数据服务,这里我们是要关闭的。
为了完整演示数据流,我开了两个MQTT Broker服务,1883端口用于处理设备侧消息流,1884用于处理EdgeX北向接口APP服务消息处理。
device-mqtt服务角色功能
device-demo程序的角色功能
这部份之前APP service讲述过了,这里没有其它变更,仅将1883改为1884端口,用于接收app-service-mqtt发布的事件并通过mqtt Broker订阅转出。
docker-compose.yml
device-mqtt:
image: edgexfoundry/docker-device-mqtt-go-arm64:1.2.1
ports:
- "0.0.0.0:49982:49982"
container_name: edgex-device-mqtt
hostname: edgex-device-mqtt
networks:
- edgex-network
environment:
<<: *common-variables
Service_Host: edgex-device-mqtt
depends_on:
- data
- command
pi@raspberrypi:~/edgex/script/device-service-demo $ sudo docker-compose up device-mqtt
Building with native build. Learn about native build in Compose here: https://docs.docker.com/go/compose-native-build/
edgex-core-consul is up-to-date
edgex-redis is up-to-date
edgex-support-notifications is up-to-date
edgex-core-metadata is up-to-date
edgex-core-data is up-to-date
edgex-core-command is up-to-date
Starting edgex-device-mqtt ... done
Device Profile用于描述设备信息结构。
mqtt.test.device.profile.yml
EdgeX 控制台UI界面:
Device Profile添加 mqtt.test.device.profile.yml 配置文件。
device-mqtt服务image是edgexfoundry/docker-device-mqtt-go-arm64:1.2.1,对于device-mqtt连接MQTT Broker地址和端口的配置可以通过consul UI界面完成。
打开Key/Value:
Key / Values -> edgex -> devices -> 1.0 -> edgex-device-mqtt
设置HOST:172.17.0.1 端口1883,device-mqtt服务连接设备侧mqtt broker。
$git clone https://github.com/edgexfoundry/device-mqtt-go
$vim device-mqtt-go-master/mock/device.go
下载地址:device-mqtt-go-master/mock/device.go
device.go编译运行,需要安装golang,并设置环境变量,这里就不说了,资料很多。
device.go主要有两部份工作,commandHandle和runDataSender两个主要函数。
commandHandle是用于处理接收下行请求,并回复数据完成上报。
runDataSender是实现定时上行数据功能。
注意,data[‘name’]设置必须与配置Device设置必须相同匹配。
这里Topic设置为DataTopic,而commandHandle处理对应的Topic是CommandTopic,也就是说需要建立两个Device信息。
下面看下效果截图
第一步,device demo启动注册mqtt Broker(1883)后发布数据
第二步,MQTT Broker收到数据,投给订阅者device-mqtt服务
第三步 device-mqtt服务收到mqtt Broker(1883)发布的数据,转发至EdgeCore
第四步,EdgeCore将事件发送给app-service-mqtt微服务
第五步,app-service-mqtt将消息发至mqtt Broker(1884)
第六步,app北向订阅者收到数据。
至此,EdgeX数据交互流程已经比较清楚了,后面附上docker-compose文件。
# /*******************************************************************************
# * Copyright 2020 Redis Labs Inc.
# * Copyright 2020 Intel Corporation.
# *
# * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
# * in compliance with the License. You may obtain a copy of the License at
# *
# * http://www.apache.org/licenses/LICENSE-2.0
# *
# * Unless required by applicable law or agreed to in writing, software distributed under the License
# * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
# * or implied. See the License for the specific language governing permissions and limitations under
# * the License.
# *
# * @author: Jim White, Dell
# * @author: Andre Srinivasan, Redis Labs
# * @author: Leonard Goodell, Intel
# * EdgeX Foundry, Geneva, version 1.2.0
# * added: May 14, 2020
# *******************************************************************************/
# NOTE: this Docker Compose file does not contain the security services - namely the API Gateway
# and Secret Store
version: '3.4'
# all common shared environment variables defined here:
x-common-env-variables: &common-variables
EDGEX_SECURITY_SECRET_STORE: "false"
Registry_Host: edgex-core-consul
Clients_CoreData_Host: edgex-core-data
Clients_Data_Host: edgex-core-data # For device Services
Clients_Notifications_Host: edgex-support-notifications
Clients_Metadata_Host: edgex-core-metadata
Clients_Command_Host: edgex-core-command
Clients_Scheduler_Host: edgex-support-scheduler
Clients_RulesEngine_Host: edgex-kuiper
Clients_VirtualDevice_Host: edgex-device-virtual
Databases_Primary_Host: edgex-redis
# Required in case old configuration from previous release used.
# Change to "true" if re-enabling logging service for remote logging
Logging_EnableRemote: "false"
# Clients_Logging_Host: edgex-support-logging # un-comment if re-enabling logging service for remote logging
volumes:
db-data:
log-data:
consul-config:
consul-data:
services:
consul:
image: edgexfoundry/docker-edgex-consul-arm64:1.2.0
ports:
- "0.0.0.0:8400:8400"
- "0.0.0.0:8500:8500"
container_name: edgex-core-consul
hostname: edgex-core-consul
networks:
- edgex-network
volumes:
- consul-config:/consul/config:z
- consul-data:/consul/data:z
environment:
- EDGEX_DB=redis
- EDGEX_SECURE=false
redis:
image: arm64v8/redis:5.0.8-alpine
ports:
- "127.0.0.1:6379:6379"
container_name: edgex-redis
hostname: edgex-redis
networks:
- edgex-network
environment:
<<: *common-variables
volumes:
- db-data:/data:z
# The logging service has been deprecated in Geneva release and will be removed in the Hanoi release.
# All services are configure to send logging to STDOUT, i.e. not remote which requires this logging service
# If you still must use remote logging, un-comment the block below, all the related depends that have been commented out
# and the related global override that are commented out at the top.
#
# logging:
# image: edgexfoundry/docker-support-logging-go-arm64:1.2.1
# ports:
# - "127.0.0.1:48061:48061"
# container_name: edgex-support-logging
# hostname: edgex-support-logging
# networks:
# - edgex-network
# environment:
# <<: *common-variables
# Service_Host: edgex-support-logging
# Writable_Persistence: file
# Databases_Primary_Type: file
# Logging_EnableRemote: "false"
# depends_on:
# - consul
system:
image: edgexfoundry/docker-sys-mgmt-agent-go-arm64:1.2.1
ports:
- "127.0.0.1:48090:48090"
container_name: edgex-sys-mgmt-agent
hostname: edgex-sys-mgmt-agent
networks:
- edgex-network
environment:
<<: *common-variables
Service_Host: edgex-sys-mgmt-agent
ExecutorPath: /sys-mgmt-executor
MetricsMechanism: executor
volumes:
- /var/run/docker.sock:/var/run/docker.sock:z
depends_on:
- consul
# - logging # uncomment if re-enabled remote logging
- scheduler
- notifications
- metadata
- data
- command
notifications:
image: edgexfoundry/docker-support-notifications-go-arm64:1.2.1
ports:
- "127.0.0.1:48060:48060"
container_name: edgex-support-notifications
hostname: edgex-support-notifications
networks:
- edgex-network
environment:
<<: *common-variables
Service_Host: edgex-support-notifications
depends_on:
- consul
# - logging # uncomment if re-enabled remote logging
- redis
metadata:
image: edgexfoundry/docker-core-metadata-go-arm64:1.2.1
ports:
- "0.0.0.0:48081:48081"
container_name: edgex-core-metadata
hostname: edgex-core-metadata
networks:
- edgex-network
environment:
<<: *common-variables
Service_Host: edgex-core-metadata
Service_Timeout: "20000"
Notifications_Sender: edgex-core-metadata
depends_on:
- consul
# - logging # uncomment if re-enabled remote logging
- redis
- notifications
data:
image: edgexfoundry/docker-core-data-go-arm64:1.2.1
ports:
- "0.0.0.0:48080:48080"
- "0.0.0.0:5563:5563"
container_name: edgex-core-data
hostname: edgex-core-data
networks:
- edgex-network
environment:
<<: *common-variables
Service_Host: edgex-core-data
depends_on:
- consul
# - logging # uncomment if re-enabled remote logging
- redis
- metadata
command:
image: edgexfoundry/docker-core-command-go-arm64:1.2.1
ports:
- "0.0.0.0:48082:48082"
container_name: edgex-core-command
hostname: edgex-core-command
networks:
- edgex-network
environment:
<<: *common-variables
Service_Host: edgex-core-command
depends_on:
- consul
# - logging # uncomment if re-enabled remote logging
- redis
- metadata
scheduler:
image: edgexfoundry/docker-support-scheduler-go-arm64:1.2.1
ports:
- "0.0.0.0:48085:48085"
container_name: edgex-support-scheduler
hostname: edgex-support-scheduler
networks:
- edgex-network
environment:
<<: *common-variables
Service_Host: edgex-support-scheduler
IntervalActions_ScrubPushed_Host: edgex-core-data
IntervalActions_ScrubAged_Host: edgex-core-data
depends_on:
- consul
# - logging # uncomment if re-enabled remote logging
- redis
app-service-mqtt:
image: edgexfoundry/docker-app-service-configurable-arm64:1.2.0
ports:
- "0.0.0.0:48101:48101"
container_name: edgex-app-service-configurable-mqtt
hostname: edgex-app-service-configurable-mqtt
networks:
- edgex-network
environment:
<<: *common-variables
edgex_profile: mqtt-export
Service_Host: edgex-app-service-configurable-mqtt
Service_Port: 48101
MessageBus_SubscribeHost_Host: edgex-core-data
Binding_PublishTopic: events
Writable_Pipeline_Functions_MQTTSend_Addressable_Address: 172.17.0.1
Writable_Pipeline_Functions_MQTTSend_Addressable_Port: 1884
Writable_Pipeline_Functions_MQTTSend_Addressable_Protocol: tcp
Writable_Pipeline_Functions_MQTTSend_Addressable_Publisher: edgex
Writable_Pipeline_Functions_MQTTSend_Addressable_Topic: EdgeXEvents
depends_on:
- consul
- data
# Support RulesEngine has been deprecated in the Geneva (1.2.0) release
# If still required, simply uncomment the block below and comment out the block above.
#
# rulesengine:
# image: edgexfoundry/docker-support-rulesengine-arm64:1.2.1
# ports:
# - "127.0.0.1:48075:48075"
# container_name: edgex-support-rulesengine
# hostname: edgex-support-rulesengine
# networks:
# - edgex-network
# depends_on:
# - app-service-rules
#################################################################
# Device Services
#################################################################
device-random:
image: edgexfoundry/docker-device-random-go-arm64:1.2.1
ports:
- "127.0.0.1:49988:49988"
container_name: edgex-device-random
hostname: edgex-device-random
networks:
- edgex-network
environment:
<<: *common-variables
Service_Host: edgex-device-random
depends_on:
- data
- command
ui:
image: edgexfoundry/docker-edgex-ui-go-arm64:1.2.1
ports:
- "0.0.0.0:4000:4000"
container_name: edgex-ui-go
hostname: edgex-ui-go
networks:
- edgex-network
networks:
edgex-network:
driver: "bridge"