在 ubuntu22.04 中 安装 EdgeX 并运行 device-sdk-c sample
在 ubuntu22.04 中 安装 EdgeX 并运行 device-sdk-c sample 1.克隆源码-EdgeX 2.安装工具 3.编译运行-EdgeX 4.克隆源码-SDK-C 5.添加第三方依赖库 6.编译-C SDK 7.编译运行 random 设备服务示例 总结 在 ubuntu22.04 中 安装 EdgeX 并运行 device-sdk-c sample EdgeX Foundry 作为一个开源的边缘计算框架，为开发者提供了一个灵活、可扩展的平台，用于构建和管理边缘设备及服务。然而，对于初次接触 EdgeX 的用户来说，从零开始安装并运行其相关组件（如 device-sdk-c 示例）可能会面临不少挑战。 无论是环境的配置、依赖的安装，还是编译与调试的过程，每一步都需要细致的操作和清晰的思路。本文将以 Ubuntu 22.04 为基础平台，详细记录如何从克隆 EdgeX 源码到成功运行 device-sdk-c 的 sample 示例的全过程。希望通过这篇博客，不仅能为新手提供一份实用的操作指南，也能让有经验的开发者在遇到问题时找到解决思路。 1.克隆源码-EdgeX 在开始安装 EdgeX 之前，我们需要先获取其源码，而 GitHub 是获取最新版本的最佳途径。为了让后续操作更加有条理，我们首先在用户主目录下创建一个专属的工作目录，用于存放 EdgeX 相关的文件。以下是具体操作： 打开终端，输入以下命令创建一个名为 edgex 的文件夹，并进入该目录： mkdir edgex && cd edgex 接下来，我们需要从 GitHub 上克隆 EdgeX 的 Compose 文件仓库，这是运行 EdgeX 服务的核心配置文件集合。执行以下命令： git clone https://github.com/edgexfoundry/edgex-compose.git cd edgex-compose 结果显示如下： root@ubuntu:/home/ubuntu# mkdir edgex && cd edgex root@ubuntu:/home/ubuntu/edgex# git clone https://github.com/edgexfoundry/edgex-compose.git Cloning into 'edgex-compose'... remote: Enumerating objects: 5826, done. remote: Counting objects: 100% (3563/3563), done. remote: Compressing objects: 100% (319/319), done. remote: Total 5826 (delta 3504), reused 3250 (delta 3244), pack-reused 2263 (from 3) Receiving objects: 100% (5826/5826), 1.59 MiB | 1.76 MiB/s, done. Resolving deltas: 100% (4949/4949), done. root@ubuntu:/home/ubuntu/edgex# ls edgex-compose 输出信息显示了克隆进度，最终 ls 命令确认目录中已存在 edgex-compose 文件夹，说明这一步成功完成。 2.安装工具 EdgeX 的部署离不开 Docker，因为它通过容器化技术简化了服务的管理和运行。因此，我们需要先在 Ubuntu 系统中安装 Docker。以下是详细的安装步骤： 使用官方脚本安装 Docker，并指定阿里云镜像源以加速下载： curl -fsSL https://get.docker.com -o get-docker.sh sh get-docker.sh --mirror Aliyun docker -v 第一条命令通过 curl 下载安装脚本并保存为 get-docker.sh 文件；第二条命令执行脚本，--mirror Aliyun 参数指定使用阿里云镜像源，避免默认源下载缓慢；最后通过 docker -v 检查版本，确保安装成功。安装过程的输出类似： root@ubuntu:/home/ubuntu# curl -fsSL https://get.docker.com -o get-docker.sh root@ubuntu:/home/ubuntu# sh get-docker.sh --mirror Aliyun # Executing docker install script, commit: 4c94a56999e10efcf48c5b8e3f6afea464f9108e ... Client: Docker Engine - Community Version: 28.0.1 API version: 1.48 ... root@ubuntu:/home/ubuntu# docker -v Docker version 28.0.1, build 068a01e 如果下载速度过慢，可能是镜像源的问题。这时可以调整 Ubuntu 的软件源以提高效率。首先检查系统版本： root@ubuntu:/home/ubuntu# more /etc/os-release PRETTY_NAME="Ubuntu 22.04.5 LTS" NAME="Ubuntu" VERSION_ID="22.04" VERSION="22.04.5 LTS (Jammy Jellyfish)" VERSION_CODENAME=jammy ID=ubuntu ID_LIKE=debian HOME_URL="https://www.ubuntu.com/" SUPPORT_URL="https://help.ubuntu.com/" BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/" PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-poli cy" UBUNTU_CODENAME=jammy 确认版本为 jammy 后，访问南京大学镜像站（https://mirror.nju.edu.cn/mirrorz-help/ubuntu/）, 获取对应源配置并编辑 /etc/apt/sources.list： # vim /etc/apt/sources.list deb https://mirror.nju.edu.cn/ubuntu/ jammy main restricted universe multiverse deb https://mirror.nju.edu.cn/ubuntu/ jammy-updates main restricted universe multiverse deb https://mirror.nju.edu.cn/ubuntu/ jammy-backports main restricted universe multiverse deb http://security.ubuntu.com/ubuntu/ jammy-security main restricted universe multiverse 启动 docker 并查看状态： root@ubuntu:/home/ubuntu# systemctl restart docker root@ubuntu:/home/ubuntu# systemctl status docker ● docker.service - Docker Application Container Engine Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset> Active: active (running) since Thu 2025-03-13 12:21:05 CST; 6s ago TriggeredBy: ● docker.socket Docs: https://docs.docker.com Main PID: 28525 (dockerd) Tasks: 10 Memory: 22.1M CPU: 1.228s CGroup: /system.slice/docker.service └─28525 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/con> Active: active (running) 表示 Docker 已正常运行，为后续 EdgeX 部署奠定了基础。 3.编译运行-EdgeX 有了 Docker 支持后，我们可以开始部署 EdgeX 服务。EdgeX 使用 Docker Compose 管理多个容器，因此需要进入 compose-builder 目录执行构建和运行命令： 进入目录并运行无安全模式的 EdgeX： cd /home/ubuntu/edgex/edgex-compose/compose-builder/ make run no-secty echo MQTT_VERBOSE= MQTT_VERBOSE= docker compose -p edgex -f docker-compose-base.yml -f add-postgres.yml -f add-mqtt-messagebus.yml -f add-mqtt-broker-mosquitto.yml convert --output docker-compose.yml.gen if [ "0" = "0" ]; then rm -rf ./gen_ext_compose; fi echo "# Generated with: Docker Compose version v2.33.1" > docker-compose.yml cat docker-compose.yml.gen >> docker-compose.yml rm docker-compose.yml.gen docker compose -p edgex up -d [+] Running 12/12 ✔ Container edgex-ui-go Running 0.0s ✔ Container edgex-postgres Running 0.0s ✔ Container edgex-mqtt-broker Running 0.0s ✔ Container edgex-core-keeper Running 0.0s ✔ Container edgex-core-metadata Running 0.0s ✔ Container edgex-core-common-config-bootstrapper Running 0.0s ✔ Container edgex-app-rules-engine Running 0.0s ✔ Container edgex-support-scheduler Running 0.0s ✔ Container edgex-core-data Running 0.0s ✔ Container edgex-kuiper Running 0.0s ✔ Container edgex-support-notifications Running 0.0s ✔ Container edgex-core-command Started 0.4s 这表明所有容器已启动，包括 UI、数据库和核心服务等。 查看容器运行状态，显示如下，每个容器显示 Up 状态，说明 EdgeX 已成功运行： docker compose ps NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS edgex-app-rules-engine nexus3.edgexfoundry.org:10004/app-service-configurable:latest "/app-service-config…" app-rules-engine 7 minutes ago Up 7 minutes 48095/tcp, 127.0.0.1:59701->59701/tcp edgex-core-command nexus3.edgexfoundry.org:10004/core-command:latest "/core-command --reg…" core-command 7 minutes ago Up 5 minutes 127.0.0.1:59882->59882/tcp edgex-core-common-config-bootstrapper nexus3.edgexfoundry.org:10004/core-common-config-bootstrapper:latest "entrypoint.sh /core…" core-common-config-bootstrapper 7 minutes ago Up 7 minutes edgex-core-data nexus3.edgexfoundry.org:10004/core-data:latest "/core-data --regist…" core-data 7 minutes ago Up 7 minutes 127.0.0.1:59880->59880/tcp edgex-core-keeper nexus3.edgexfoundry.org:10004/core-keeper:latest "/core-keeper" core-keeper 7 minutes ago Up 7 minutes 127.0.0.1:59890->59890/tcp edgex-core-metadata nexus3.edgexfoundry.org:10004/core-metadata:latest "/core-metadata ... 4.克隆源码-SDK-C 为了运行 device-sdk-c 的示例，我们还需要获取其源码。device-sdk-c 包含了丰富的 C 语言示例，是开发自定义设备服务的好起点： 在 /edgex 目录下克隆仓库： git clone https://github.com/edgexfoundry/device-sdk-c.git root@ubuntu:/home/ubuntu/edgex/edgex-compose/compose-builder# cd ../.. root@ubuntu:/home/ubuntu/edgex# ls edgex-compose root@ubuntu:/home/ubuntu/edgex# git clone https://github.com/edgexfoundry/device-sdk-c.git Cloning into 'device-sdk-c'... remote: Enumerating objects: 5641, done. remote: Counting objects: 100% (527/527), done. remote: Compressing objects: 100% (213/213), done. remote: Total 5641 (delta 419), reused 337 (delta 307), pack-reused 5114 (from 4) Receiving objects: 100% (5641/5641), 1.93 MiB | 1.70 MiB/s, done. Resolving deltas: 100% (3210/3210), done. 5.添加第三方依赖库 编译 device-sdk-c 需要一系列依赖库，参考官方 README（https://github.com/edgexfoundry/device-sdk-c/blob/main/README.md） A Linux build host A version of GCC supporting C11. CMake version 3 or greater and make. Development libraries and headers for: curl (version 7.56 or later) microhttpd (version 0.9) libyaml (version 0.1.6 or later) libcbor (version 0.5) paho (version 1.3.x) libuuid (from util-linux v2.x) IOTech's C utilities package (version 1.5) apt-get install libcurl4-openssl-dev libmicrohttpd-dev libyaml-dev libcbor-dev libpaho-mqtt-dev apt-get install lsb-release apt-transport-https curl gnupg curl -fsSL https://iotech.jfrog.io/artifactory/api/gpg/key/public | gpg --dearmor -o /usr/share/keyrings/iotech.gpg echo "deb [signed-by=/usr/share/keyrings/iotech.gpg] https://iotech.jfrog.io/iotech/debian-release $(lsb_release -cs) main" | tee -a /etc/apt/sources.list.d/iotech.list apt-get update apt-get install iotech-iot-1.5-dev apt install uuid-dev 6.编译-C SDK 在C SDK 顶层目录下, 运行 make，最终结果显示如下： root@ubuntu:/home/ubuntu/edgex/device-sdk-c# make ... [100%] Built target device-file 7.编译运行 random 设备服务示例 编译前的准备工作，参考https://github.com/edgexfoundry/device-sdk-c/blob/main/src/c/examples/random/README.md 此示例设备服务模拟了一个具有两个随机数生成器和一个可读取和写入状态的开关的设备。先配置环境变量，注意自己的路径： export CSDK_DIR=/home/logan/edgex/device-sdk-c/build/release/_CPack_Packages/Linux/TGZ/csdk-0.0.0 export LD_LIBRARY_PATH=$CSDK_DIR/lib:/opt/iotech/iot/1.5/lib 涉及头文件和库文件的环境变量很重要，并且运行程序的时候也需要用到。 在/random 目录下执行编译命令： gcc -I$CSDK_DIR/include -I/opt/iotech/iot/1.5/include -L$CSDK_DIR/lib -L/opt/iotech/iot/1.5/lib -o device-random device-random.c -lcsdk -liot 将编译好的可执行文件 device-random 复制到以下源文件目录，因为源文件目录提供了/res 里面包含预设的配置文件： cp device-sdk-c/build/release/c/examples/random/device-random device-sdk-c/src/c/examples/random/ cd /home/ubuntu/edgex/device-sdk-c/src/c/examples/random/ 执行以下命令：-o 表示覆盖默认配置，-cp 指定配置提供者 ./device-random -o -cp=keeper.http://localhost:59890 如果遇到报错，按以下方法解决： 安全 Token 报错：设置环境变量禁用安全服务： root@ubuntu:/home/ubuntu/edgex/device-sdk-c/src/c/examples/random# ./device-random -o -cp=keeper.http://localhost:59890 level=INFO ts=2025-03-13T06:44:41Z app=device-random msg="iot_threadpool_alloc (threads: 8 max_jobs: 0 default_priority: -1 affinity: -1)" level=INFO ts=2025-03-13T06:44:41Z app=device-random msg="iot_scheduler_alloc (priority: -1 affinity: -1)" level=ERROR ts=2025-03-13T06:44:41Z app=device-random msg="vault: Token file /tmp/edgex/secrets/device-random/secrets-token.json doesn't parse as JSON" Error: 4: Configuration is invalid 解决：需要关闭Edges安全服务： 参考https://docs.edgexfoundry.org/4.0/microservices/configuration/CommonEnvironmentVariables/#edgex_security_secret_store export EDGEX_SECURITY_SECRET_STORE="false" Curl 解析失败：编辑 /etc/hosts： level=DEBUG ts=2025-03-13T06:45:41Z app=device-random msg="mqtt: subscribing to edgex/configs/edgex/v4/core-common-config-bootstrapper/all-services/#" level=DEBUG ts=2025-03-13T06:45:41Z app=device-random msg="mqtt: subscribing to edgex/configs/edgex/v4/core-common-config-bootstrapper/device-services/#" level=ERROR ts=2025-03-13T06:45:42Z app=device-random msg="Curl failed with code 6 (Couldn't resolve host name)" level=ERROR ts=2025-03-13T06:45:43Z app=device-random msg="Curl failed with code 6 (Couldn't resolve host name)" level=ERROR ts=2025-03-13T06:45:44Z app=device-random msg="Curl failed with code 6 (Couldn't resolve host name)" level=ERROR ts=2025-03-13T06:45:45Z app=device-random msg="Curl failed with code 6 (Couldn't resolve host name)" level=ERROR ts=2025-03-13T06:45:46Z app=device-random msg="Curl failed with code 6 (Couldn't resolve host name)" level=ERROR ts=2025-03-13T06:45:47Z app=device-random msg="Curl failed with code 6 (Couldn't resolve host name)" 解决：在/etc/hosts 中添加127.0.0.1 edgex-core-metadata： /etc/hosts 127.0.0.1 localhost 127.0.0.1 edgex-core-metadata # The following lines are desirable for IPv6 capable hosts ::1 ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters ff02::3 ip6-allhosts 健康检查间隔缺失：修改 res/configuration.yml： level=DEBUG ts=2025-03-13T06:50:39Z app=device-random msg="HTTP response: 404" level=DEBUG ts=2025-03-13T06:50:39Z app=device-random msg="HTTP response: 400" level=ERROR ts=2025-03-13T06:50:39Z app=device-random msg="Register service failed: {"apiVersion":"v3","message":"AddRegistrationRequest.Registration.HealthCheck.Interval field is required","statusCode":400} level=ERROR ts=2025-03-13T06:50:39Z app=device-random msg="Unable to register service in registry" Error: 21: HTTP request failed level=DEBUG ts=2025-03-13T06:50:39Z app=device-random msg="Scheduler thread stopping" 解决：在res/configration.yml 中添加 HealthCheckInterval: 10s： Writable: LogLevel: DEBUG Service: Host: localhost Port: 59999 StartupMsg: Example random device service started HealthCheckInterval: 10s ​ 或者在/etc/hosts 中添加127.0.0.1 edgex-mqtt-broker,然后在执行命令 ./device-random -o -cp=keeper.http://localhost:59890 中去掉 -o： /etc/hosts 127.0.0.1 localhost 127.0.0.1 edgex-core-metadata 127.0.0.1 edgex-mqtt-broker # The following lines are desirable for IPv6 capable hosts ::1 ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters ff02::3 ip6-allhosts 如果程序运行成功，将显示如下： ... level=INFO ts=2025-03-13T07:36:45Z app=device-random correlation-id=c26ef1f7-755c-4952-8091-5c7c436e039b msg="AutoEvent: RandomDevice1/SensorOne" level=INFO ts=2025-03-13T07:36:50Z app=device-random correlation-id=dc222997-3113-465b-9c5c-26829ce24901 msg="AutoEvent: RandomDevice1/SensorTwo" level=INFO ts=2025-03-13T07:36:55Z app=device-random correlation-id=049d560d-896a-4e5a-8101-f3364c2767f1 msg="AutoEvent: RandomDevice1/SensorOne" 打开浏览器进入：localhost:4000 可发现一个设备服务，可成功读取随机数，如下： 总结 通过以上步骤，我们成功地在 Ubuntu 22.04 上完成了 EdgeX 的安装，并运行了 device-sdk-c 的 random 设备服务示例。从源码的克隆到 Docker 环境的搭建，再到依赖库的安装和配置文件的调整，每一个环节都环环相扣，考验着我们的耐心和解决问题的能力。 过程中可能遇到的报错，如安全性 token 问题、Curl 解析失败或健康检查间隔配置缺失，也提醒我们在操作复杂系统时，细节的重要性不容忽视。 最终，当我们在浏览器中看到 localhost:4000 界面上显示的设备服务和随机数据时，那份成就感无疑是对所有努力的最好回报。这不仅是一个技术实现的过程，更是一次对 EdgeX 架构和边缘计算理念的深入学习之旅。未来，我们还可以基于此基础，进一步扩展功能、优化性能，让边缘计算的潜力在更多场景中得以释放！
准备工作 硬件 软件 基础配置 数据库配置 Docker 数据库 PostgreSQL MySQL 部署 K3S 管理集群 主机名 K3S 核心安装 自动安装(推荐) 手动二进制文件安装(不推荐) Master / Worker 手动加入(如有必要) 安装 Rancher 集群管理工具和 Harbor Registry 仓库 准备工作 安装 Kubernetes 包管理工具 Helm 安装证书管理器 cert-manager 安装 Rancher 安装 Harbor 使用 Ceph（推荐） 使用 NFS 部署 pv 和 pvc 部署 Harbor Helm 批量上传所需 image 到 Harbor 部署 K3S 业务集群 所有的 Master 和 Worker 都加入业务集群 Rancher 中创建一个新的集群 Master 加入集群(初始化业务集群) Worker 加入业务集群 (部署/更新) Harbor hub CA 证书到所有的 Master 和 Worker (手动操作)导出 Harbor hub HTTPS 证书 (自动部署)Harbor Hub CA 证书 新建一个 Secret 新建一个 DaemonSet 基于 K3S 部署业务应用(边缘计算框架) EdgeX Foundry Base 部署辅助应用：流媒体，推理服务器，NVR 部署 OpenVINO AI 应用 总结 准备工作 硬件 主 K3S Master 节点：3台, master101, master102, master103 业务 K3S Master 节点：3台，master151, master152, master153 Worker 节点：N台，随意, worker01, worker02, ... 软件 基础配置 操作系统：Ubuntu Server 22.04 最小化安装系统，包含：openssh-server, iputils-ping, net-tools, vim PRETTY_NAME="Ubuntu 22.04.5 LTS" NAME="Ubuntu" VERSION_ID="22.04" VERSION="22.04.5 LTS (Jammy Jellyfish)" 管理集群 主机名 IP 其他 database 192.168.198.100 数据库+NFS存储，如有需要做 HA master101 192.168.198.101 管理 K3S master master102 192.168.198.102 管理 K3S master master103 192.168.198.103 管理 K3S master 业务集群 主机名 IP 其他 master151 192.168.123.151 业务 K3S master + worker master152 192.168.123.152 业务 K3S master + worker master153 192.168.123.153 业务 K3S master + worker worker161 192.168.123.161 业务 worker worker162 192.168.123.162 业务 worker 数据库配置 Docker 准备 docker 环境 curl -fsSL https://get.docker.com | sh - 验证 docker docker images REPOSITORY TAG IMAGE ID CREATED SIZE 设置一个 Registry 镜像 cat /etc/docker/daemon.json { "insecure-registries" : [ "0.0.0.0/0" ], "registry-mirrors": [ "https://xxx.mirror.swr.myhuaweicloud.com" ] } 重启 docker systemctl restart docker 数据库 PostgreSQL 创建 compose.yml services: postgres: image: postgres:alpine container_name: postgres restart: unless-stopped environment: POSTGRES_USER: k3s POSTGRES_PASSWORD: talent POSTGRES_DB: k3s ports: - "5432:5432" volumes: - ./data:/var/lib/postgresql/data - ./init-db.sh:/docker-entrypoint-initdb.d/init-db.sh 创建脚本 init-db.sh #!/bin/bash set -e psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname=postgres <<-EOSQL CREATE DATABASE harbor; EOSQL 启动 PostgreSQL 数据库容器 docker compose up -d 验证数据库 docker exec -it postgres psql -U k3s -c '\l' List of databases Name | Owner | Encoding | Locale Provider | Collate | Ctype | Locale | ICU Rules | Access privileges -----------+-------+----------+-----------------+------------+------------+--------+-----------+------------------- harbor | k3s | UTF8 | libc | en_US.utf8 | en_US.utf8 | | | k3s | k3s | UTF8 | libc | en_US.utf8 | en_US.utf8 | | | ... (5 rows) MySQL 因为 Rancher 只支持 MySQL 不支持 PostgreSQL 创建 compose.yml services: mysql: image: mysql:latest container_name: mysql restart: unless-stopped environment: MYSQL_ROOT_PASSWORD: talent MYSQL_DATABASE: rancher MYSQL_USER: rancher MYSQL_PASSWORD: talent ports: - "3306:3306" volumes: - ./data:/var/lib/mysql - ./init:/docker-entrypoint-initdb.d 创建脚本 init/permissions.sql GRANT ALL PRIVILEGES ON *.* TO 'rancher'@'%' IDENTIFIED BY 'talent'; FLUSH PRIVILEGES; 启动 MySQL 数据库容器 docker compose up -d 验证数据库 docker exec -it mysql mysql -u rancher -p'talent' -e "SHOW DATABASES;" +--------------------+ | Database | +--------------------+ | rancher | +--------------------+ 部署 K3S 管理集群 本章节内容在管理 K3S 主机 上执行 主机名 所有的 Master 配置相同的 /etc/hosts127.0.0.1 localhost 127.0.1.1 master101 # CHAMGEME 192.168.198.100 database 192.168.198.101 master101 192.168.198.102 master102 192.168.198.103 master103 K3S 核心安装 自动安装(推荐) 可以连接互联网的情况下 默认安装最新版本，这里是: v1.30.5+k3s1，注意：k3s:talent 是你自己的数据库用户名密码，使用一样的 token curl -sfL https://get.k3s.io | sh -s - server \ --datastore-endpoint="postgres://k3s:talent@database:5432/k3s?sslmode=disable" --token K10c71232f051944de58ab058871ac7a85b42cbdee5c6df94deb6bb493c79b15a92::server:3d6c2d90cec2e63db66bde0e6f24013d 验证安装 kubectl get nodes NAME STATUS ROLES AGE VERSION master101 Ready control-plane,master 43s v1.30.5+k3s1 其他 Master 安装方式一样。在任何一台 Master 上确认安装完成 kubectl get nodes NAME STATUS ROLES AGE VERSION master101 Ready control-plane,master 117s v1.30.5+k3s1 master102 Ready control-plane,master 118s v1.30.5+k3s1 master103 Ready control-plane,master 29s v1.30.5+k3s1 手动二进制文件安装(不推荐) 下载二进制文件 wget https://github.com/k3s-io/k3s/releases/download/vX.X.X/k3s -O /usr/local/bin/k3s chmod +x /usr/local/bin/k3s 初始化 k3s server --cluster-init 设置自启动脚本 所有 Master 机器上一样的配置 cat <<EOF | sudo tee /etc/systemd/system/k3s.service [Unit] Description=Lightweight Kubernetes Documentation=https://k3s.io After=network.target [Service] ExecStart=/usr/local/bin/k3s server --datastore-endpoint="postgres://k3s:talent@database:5432/k3s?sslmode=disable" --token K10c71232f051944de58ab058871ac7a85b42cbdee5c6df94deb6bb493c79b15a92::server:3d6c2d90cec2e63db66bde0e6f24013d Restart=always RestartSec=5s [Install] WantedBy=multi-user.target EOF 更新自启动设置 systemctl daemon-reload systemctl enable k3s systemctl start k3s 查看集群状态 任何一台 Master 都可以 /usr/local/bin/k3s kubectl get nodes 结果 NAME STATUS ROLES AGE VERSION master101 Ready control-plane,master 10m v1.30.4+k3s1 master102 Ready control-plane,master 10m v1.30.4+k3s1 master103 Ready control-plane,master 81s v1.30.4+k3s1 Master / Worker 手动加入(如有必要) 获取集群 token cat /var/lib/rancher/k3s/server/node-token Master 直接加入集群（不建议） k3s server --server https://master101:6443 --token <token> 或修改 /etc/systemd/system/k3s.service Worker加入（可选） 替换<node-token> 为你的token cat <<EOF | sudo tee /etc/systemd/system/k3s-agent.service [Unit] Description=Lightweight Kubernetes Documentation=https://k3s.io After=network.target [Service] ExecStart=/usr/local/bin/k3s agent --server https://master101:6443 --token <node-token> Restart=always RestartSec=5s [Install] WantedBy=multi-user.target EOF 更新自启动设置 systemctl daemon-reload systemctl enable k3s-agent systemctl start k3s-agent 不管怎么操作，基础三个主机的 K3S 集群要跑起来，保证基础工作完成。 安装 Rancher 集群管理工具和 Harbor Registry 仓库 准备工作 安装 Kubernetes 包管理工具 Helm 选择一个 Master 或全部 Master，安装 Helm curl -fsSL https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash - 设置环境变量 加入到 /etc/profile 自启动 echo "export KUBECONFIG=/etc/rancher/k3s/k3s.yaml" >> /etc/profile && source /etc/profile 安装证书管理器 cert-manager helm 脚本安装 kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.15.3/cert-manager.crds.yaml helm repo add jetstack https://charts.jetstack.io helm repo update helm install cert-manager jetstack/cert-manager --namespace cert-manager \ --create-namespace --version v1.15.3 验证安装成功 kubectl get pods --namespace cert-manager NAME READY STATUS RESTARTS AGE cert-manager-9647b459d-9jwpj 1/1 Running 0 2m47s cert-manager-cainjector-5d8798687c-66r95 1/1 Running 0 2m47s cert-manager-webhook-c77744d75-k22h5 1/1 Running 0 2m47s 设置自签名 Issuer 创建 issuer-cert.yaml, 这里创建两个： rancher.yiqisoft.com hub.yiqisoft.com, 后面访问集群业务就是通过域名来通信 apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: selfsigned-issuer spec: selfSigned: {} --- apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: rancher-cert namespace: cattle-system spec: secretName: rancher-cert-secret issuerRef: name: selfsigned-issuer kind: ClusterIssuer commonName: rancher.yiqisoft.com duration: 315360000s renewBefore: 240h dnsNames: - rancher.yiqisoft.com --- apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: hub-cert namespace: harbor spec: secretName: hub-cert-secret issuerRef: name: selfsigned-issuer kind: ClusterIssuer commonName: hub.yiqisoft.com duration: 315360000s renewBefore: 240h dnsNames: - hub.yiqisoft.com 安装自定义 Certificate 先创建两个 namespace，再安装脚本 kubectl create namespace harbor kubectl create namespace cattle-system kubectl apply -f issuer-cert.yaml 结果输出 clusterissuer.cert-manager.io/selfsigned-issuer created certificate.cert-manager.io/rancher-cert created certificate.cert-manager.io/hub-cert created 安装 Rancher 增加 Rancher Helm 仓库 helm repo add rancher-latest https://releases.rancher.com/server-charts/latest helm repo update 安装 Rancher 这个过程比较漫长，需要从互联网下载 helm install rancher rancher-latest/rancher \ --namespace cattle-system \ --set hostname=rancher.yiqisoft.com \ --set replicas=3 \ --set extraEnv[0].name=CATTLE_DATABASE_ENDPOINT \ --set extraEnv[0].value=database:3306 \ --set extraEnv[1].name=CATTLE_DATABASE_USER \ --set extraEnv[1].value=rancher \ --set extraEnv[2].name=CATTLE_DATABASE_PASSWORD \ --set extraEnv[2].value=talent \ --set extraEnv[3].name=CATTLE_DATABASE_NAME \ --set extraEnv[3].value=rancher 验证安装成功 kubectl get pods --namespace cattle-system 结果 NAME READY STATUS RESTARTS AGE rancher-567cc5c6ff-bzx42 1/1 Running 0 65m rancher-567cc5c6ff-mgvns 1/1 Running 0 86m rancher-567cc5c6ff-rbgjn 1/1 Running 0 86m rancher-webhook-77b49b9ff9-mp2dm 1/1 Running 0 142m 安装 Harbor Harbor 作为内部 docker hub 使用 使用 Ceph（推荐） 准备一个 Ceph 集群用于存储（这里省略）。 使用 NFS 简单实用，但是效率不高，安全性一般。 在一个文件服务器上部署 NFS，这里用 database 主机apt update apt install nfs-kernel-server -y mkdir -p /opt/nfs_share chown nobody:nogroup /opt/nfs_share chmod 777 /opt/nfs_share echo "/opt/nfs_share *(rw,sync,no_subtree_check)" >> /etc/exports exportfs -ra systemctl restart nfs-kernel-server 部署 pv 和 pvc 编辑 pv-pvc.yaml apiVersion: v1 kind: PersistentVolume metadata: name: nfs-pv spec: capacity: storage: 30Gi accessModes: - ReadWriteMany nfs: path: /opt/nfs_share server: database --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: nfs-pvc spec: accessModes: - ReadWriteMany resources: requests: storage: 10Gi volumeName: nfs-pv storageClassName: "" 应用到 namespace harbor kubectl apply -f pv-pvc.yaml -n harbor 结果 persistentvolume/nfs-pv created persistentvolumeclaim/nfs-pvc created 查看结果，nfs-pvc 必须是 Bound kubectl get pvc -n harbor 结果 NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE nfs-pvc Bound nfs-pv 30Gi RWX <unset> 92s 查看 nfs-pv 必须是 Bound kubectl get pv -n harbor 结果 NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS VOLUMEATTRIBUTESCLASS REASON AGE nfs-pv 30Gi RWX Retain Bound harbor/nfs-pvc <unset> 97s 部署 Harbor Helm 安装 NFS 依赖 所有的 Master 上需要安装 nfs-common，并验证（可选），可以访问 /tmp/nfs 目录 apt install nfs-common -y mkdir /tmp/nfs mount -t nfs database:/opt/nfs_share /tmp/nfs ll /tmp/nfs 增加 Harbor Helm 仓库 helm repo add harbor https://helm.goharbor.io helm repo update 导出默认 values，修改 helm show values harbor/harbor > harbor-values.yml # 内容修改如下 expose: ingress: hosts: core: hub.yiqisoft.cn externalURL: https://hub.yiqisoft.cn persistentVolumeClaim: registry:/exter existingClaim: "nfs-pvc" storageClass: "-" database: type: external external: host: "192.168.198.100" port: "5432" username: "k3s" password: "talent" coreDatabase: "harbor" harborAdminPassword: "Harbor12345" 安装 Harbor，需要通过互联网下载所有的镜像，时间根据网络带宽决定 helm install harbor harbor/harbor -f harbor-values.yml -n harbor 确认 Harbor 是否安装成功 kubectl get pods -n harbor 都显示 READY 即可 NAME READY STATUS RESTARTS AGE harbor-core-666cf84bc6-vq8mp 1/1 Running 0 85s harbor-jobservice-c68bc669-6twbp 1/1 Running 0 85s harbor-portal-d6c99f896-cq9fx 1/1 Running 0 85s harbor-redis-0 1/1 Running 0 84s harbor-registry-5984c768c8-4xnrg 2/2 Running 0 84s harbor-trivy-0 1/1 Running 0 84s 验证 Harbor 工作状态 curl -k https://hub.yiqisoft.com/v2/ -u admin:Harbor12345 提示 {} 证明成功 {} 以下在 database 主机上运行 登录 Harbor docker login hub.yiqisoft.com -u admin -p Harbor12345 登录成功 Login Succeeded 上传已经存在的 PostgreSQL image 测试 docker tag postgres:alpine hub.yiqisoft.com/library/postgres:alpine docker push hub.yiqisoft.com/library/postgres:alpine 结果显示 The push refers to repository [hub.yiqisoft.com/library/postgres] 284f9fec9bcb: Pushed 07188499987f: Pushed ... 63ca1fbb43ae: Pushed alpine: digest: sha256:f0407919d966a86e9***c81641801e43c29b size: 2402 批量上传所需 image 到 Harbor 在准备好 docker image 的机器上运行 导出需要的 image docker images --format "{{.Repository}}:{{.Tag}}" |grep yiqisoft.com > images.txt 新建 /etc/docker/daemon.json，跳过安全证书 { "insecure-registries" : [ "0.0.0.0/0" ] } 重启 docker systemctl restart docker 新建一个脚本 push-images.sh #!/bin/bash # Check if the correct number of arguments is provided if [ $# -ne 1 ]; then echo "Usage: $0 <path_to_images_file>" exit 1 fi # Assign the first argument to the file variable file=$1 # Check if the file exists if [ ! -f "$file" ]; then echo "File not found: $file" exit 1 fi while read image; do echo "Pushing image: $image" docker push $image if [ $? -eq 0 ]; then echo "Successfully pushed $image" else echo "Failed to push $image" fi done < "$file" 登录 Harbor 并上传: push image docker login hub.yiqisoft.com -u admin -p Harbor12345 bash push-images.sh images.txt 查看 Harbor Registry 仓库结果 curl -k https://hub.yiqisoft.com/v2/_catalog -u admin:Harbor12345 |json_pp 结果显示 { "repositories" : [ "edgexfoundry/app-service-gateway", "edgexfoundry/consul", "edgexfoundry/core-command", "edgexfoundry/core-common-config-bootstrapper", "edgexfoundry/core-data", "edgexfoundry/core-metadata", "edgexfoundry/device-modbus", "edgexfoundry/device-onvif-camera", "edgexfoundry/device-openvino-face-recognition", "edgexfoundry/device-openvino-object-detection", "edgexfoundry/edgex-ui", "edgexfoundry/redis", "edgexfoundry/support-notifications", "edgexfoundry/support-scheduler", "library/hello-world", "library/postgres", "rancher/system-agent", "yiqisoft/media_server", "yiqisoft/model_server", "yiqisoft/nginx", "yiqisoft/nvr" ] } 部署 K3S 业务集群 以下操作注意：全部在新建的业务集群中操作 所有的 Master 和 Worker 都加入业务集群 Rancher 中创建一个新的集群 Rancher UI 操作（省略）, Cluster Name: yiqisoft, Kubernetes Version: 1.30.4+k3s1 Master 加入集群(初始化业务集群) 通过新集群的 Registration 加入，可以自定义一个 namespace。需要几个 Master 根据自己业务需要来定。 导入 hub CA echo | openssl s_client -showcerts -connect hub.yiqisoft.com:443 2>/dev/null | \ openssl x509 -outform PEM > /etc/ssl/certs/hub.yiqisoft.com.crt 分别在 master151-master153 主机上执行，主机名不能重复 curl --insecure -fL https://rancher.yiqisoft.com/system-agent-install.sh | \ sudo sh -s - --server https://rancher.yiqisoft.com --label 'cattle.io/os=linux' \ --token xft4fsrjgkn4rzqxrgrb4mztkcxtz4nhpwm58t84q54lvpsscdgd72 \ --ca-checksum 30d78ad0ece6355c40a4b3764ba02dfc96388a9c20f6b4e2bffb131cf7402c1f \ --etcd --controlplane --worker 查看业务集群 node kubectl get nodes 确认 Master 都在线 NAME STATUS ROLES AGE VERSION master151 Ready control-plane,etcd,master,worker 32m v1.30.4+k3s1 master152 Ready control-plane,etcd,master,worker 3h39m v1.30.4+k3s1 master153 Ready control-plane,etcd,master,worker 23m v1.30.4+k3s1 Worker 加入业务集群 首先通过 curl 直接输出 hub 证书到主机证书目录 containerd 拉取 image 时需要信任此证书 CA echo | openssl s_client -showcerts -connect hub.yiqisoft.com:443 2>/dev/null | \ openssl x509 -outform PEM > /etc/ssl/certs/hub.yiqisoft.com.crt 需要等 Master 加入成功后（至少一个成功注册），Worker 主机再次通过 Registration 加入，只需要选择 Worker 即可，需要定义一个 namespace label， 比如： namespace=worker01，以后可单独部署到独立应用 到 namespace 作为隔离使用。 在所有业务 Worker 上执行，同样注意主机名不能重复 curl --insecure -fL https://rancher.yiqisoft.com/system-agent-install.sh | \ sudo sh -s - \ --server https://rancher.yiqisoft.com \ --label 'cattle.io/os=linux' \ --token xft4fsrjgkn4rzqxrgrb4mztkcxtz4nhpwm58t84q54lvpsscdgd72 \ --ca-checksum 30d78ad0ece6355c40a4b3764ba02dfc96388a9c20f6b4e2bffb131cf7402c1f \ --worker \ --label namespace=worker161 验证 Worker 节点 kubectl get nodes -A 结果正常 NAME STATUS ROLES AGE VERSION master151 Ready control-plane,etcd,master,worker 74m v1.30.4+k3s1 master152 Ready control-plane,etcd,master,worker 4h21m v1.30.4+k3s1 master153 Ready control-plane,etcd,master,worker 65m v1.30.4+k3s1 worker161 Ready worker 25m v1.30.4+k3s1 (部署/更新) Harbor hub CA 证书到所有的 Master 和 Worker (手动操作)导出 Harbor hub HTTPS 证书 增加自签名证书到 ca-certificates 所有的 Master 和 Worker 上执行（不太可行）echo | openssl s_client -showcerts -connect hub.yiqisoft.com:443 2>/dev/null | \ openssl x509 -outform PEM > /etc/ssl/certs/hub.yiqisoft.com.crt (自动部署)Harbor Hub CA 证书 新建一个 Secret 在业务集群中，把 Harbor 证书导入集群 kube-system kubectl create secret generic hub-ca --from-file=ca.crt=/hub.yiqisoft.com.crt -n kube-system 查看 kubectl get secret -A |grep hub-ca 结果 NAMESPACE NAME TYPE DATA AGE kube-system hub-ca kubernetes.io/tls 2 101m 新建一个 DaemonSet 新建一个部署文件: ca-distributor.yaml，用于分发 hub 的证书，非常重要，否则无法从私有 Registry 拉取镜像。 apiVersion: apps/v1 kind: DaemonSet metadata: name: ca-distributor namespace: kube-system spec: selector: matchLabels: name: ca-distributor template: metadata: labels: name: ca-distributor spec: containers: - name: ca-distributor image: busybox:latest command: - /bin/sh - -c - "cp /etc/ca-certificates/tls.crt /etc/ssl/certs/hub.yiqisoft.cn.crt && echo 'Certificate Updated' && sleep 3600" volumeMounts: - name: ca-cert mountPath: /etc/ca-certificates - name: ssl-certs mountPath: /etc/ssl/certs volumes: - name: ca-cert secret: secretName: hub-ca - name: ssl-certs hostPath: path: /etc/ssl/certs type: Directory restartPolicy: Always 部署 yaml kubectl apply -f ca-distributor.yaml 验证结果,确保所有的节点都执行成功。 kubectl get pods -A |grep ca-distributor kube-system ca-distributor-ckhgh 1/1 Running 0 100s kube-system ca-distributor-hqzwt 1/1 Running 0 101s kube-system ca-distributor-lj72n. 1/1 Running 0 101s kube-system ca-distributor-mpp7m 1/1 Running 0 101s 在 Worker 上拉取镜像 image k3s ctr i pull hub.yiqisoft.com/library/hello-world:latest 验证结果 hub.yiqisoft.cn/library/hello-world:latest: resolved |++++++++++++++++++++++++++++++++++++++| manifest-sha256:d37ada95d47ad12224c205a938129df7a3e52345828b4fa27b03a98825d1e2e7: done |++++++++++++++++++++++++++++++++++++++| config-sha256:d2c94e258dcb3c5ac2798d32e1249e42ef01cba4841c2234249495f87264ac5a: done |++++++++++++++++++++++++++++++++++++++| layer-sha256:c1ec31eb59444d78df06a974d155e597c894ab4cda84f08294145e845394988e: done |++++++++++++++++++++++++++++++++++++++| elapsed: 0.6 s total: 524.0 (871.0 B/s) unpacking linux/amd64 sha256:d37ada95d47ad12224c205a938129df7a3e52345828b4fa27b03a98825d1e2e7... done: 54.873311ms 基于 K3S 部署业务应用(边缘计算框架) 以下所有部署都是通过 Helm Chart 工具进行，需要自行编写。 EdgeX Foundry Base 部署基本框架结果kubectl get pods -n worker161 NAME READY STATUS RESTARTS AGE edgex-core-command-tspw7 1/1 Running 0 5m41s edgex-core-common-config-bootstrapper-92q25 1/1 Running 0 5m25s edgex-core-consul-8lqxz 1/1 Running 0 6m4s edgex-core-data-nv26d 1/1 Running 0 6m23s edgex-core-metadata-l6c49 1/1 Running 0 5m3s edgex-device-onvif-camera-5tt4w 1/1 Running 0 3m26s edgex-mqtt-broker-j2jdr 1/1 Running 0 81s edgex-redis-rf4v7 1/1 Running 0 4m50s edgex-support-notifications-ws6l5 1/1 Running 0 4m28s edgex-support-scheduler-drx2p 1/1 Running 0 3m56s edgex-ui-v55vm 1/1 Running 0 3m45s 部署辅助应用：流媒体，推理服务器，NVR 部署辅助应用 业务 pod 之间有依赖关系，需等待其他 pod 起来才能工作，会不断的重试kubectl get pods -n worker161 |grep -v edgex 结果 NAME READY STATUS RESTARTS AGE media-server-wtjxk 1/1 Running 1 (5m29s ago) 13m model-server-9fpb2 1/1 Running 0 89s nvr-gqlst 1/1 Running 2 (5m29s ago) 11m 部署 OpenVINO AI 应用 部署基于 OpenVINO 推理框架的 AI 应用 podkubectl get pods -n worker161 |grep openvino 结果 NAME READY STATUS RESTARTS AGE edgex-device-openvino-face-recognition-bgch4 1/1 Running 0 5m43s edgex-device-openvino-object-detection-tbvwk 1/1 Running 0 7m21s 总结 通过本部署方案，可以管理基于 EdgeX 的边缘计算方案，EdgeX 具备边缘自治，即使脱离 K3S 集群，也照样能正常工作。 同时，此方案可以管理成千上万个边缘设备，之间互不干扰，适合大型项目部署。 云端配置相对较为复杂，但是边缘端就轻松很多，只需要手动注册到 K3S 集群，其他都可以通过 K8S API 进行部署和管理。 对比 K8S 而言，K3S 非常适合在边缘端工作，占用资源少，管理较为方便。 其实，最终结果就是：K3S 适合管理边缘容器分发。
喜报｜亿琪软件被认定为2023年高新技术企业
近日，根据科技部、财政部、国家税务总局《高新技术企业认定管理办法》（国科发火〔2016〕32号）、《高新技术企业认定管理工作指引》（国科发火〔2016〕195号）、《上海市高新技术企业认定管理实施办法》（沪科合〔2021〕21号）的有关规定，上海亿琪软件有限公司被认定为2023年度“高新技术企业”。 关于我们 上海亿琪软件有限公司，国家级高新技术企业，全球开放边缘计算和物联网领域的领导者，全球领先的工业物联网软件开发商和解决方案提供商，助力企业和组织实现数字化转型。公司专注于 5G 通信、AI 人工智能、边缘计算和大数据网络安全多项技术领域，致力于物联网领域前沿技术的创新，为用户提供全方位、智能化和安全的物联网解决方案。 2023 年，公司发布“ YiFUSION ｜工业边缘智能融合网关 ”产品，为工业客户提供一整套的边缘计算+AI 能力：高性能数据采集、多类型数据融合、AI 算法集成、云端业务对接。在边缘网关的基础上，集成了 IoT 平台的边缘协同能力、本地 Web SCADA 和 HMI 功能、本地数据存储、边缘 AI 视频分析、行业应用集成等。 2022 年，公司推出 “ YiCLOUD ｜亿琪云 ”一站式物联网应用解决方案。公司的业务涵盖了智慧城市、智慧农业、智能工厂和智慧园区等多个领域，公司软硬件产品和解决方案获得华为技术认证，得到中国移动 OCP 认证，公司还是边缘计算产业联盟 ECC 成员。 公司公众号 ThingsBoard中文社区 EdgeX爱好者社区 联系我们--商业服务 网站：http://yiqisoft.cn 邮件：support@yiqisoft.cn 电话：021-68863086 手机：186-1666-9123
文档｜EdgeX 设备微服务之 OPC-UA -- device-opcua 完整使用手册
EdgeX Foundry （以下统一简称：EdgeX）设备微服务 device-opcua 由我司根据已有代码优化后贡献给社区，文档也是必不可少的环节，社区要求英文，现翻译成中文，方便国内客户阅读和使用。 目的 入门 配置 协议属性 API 参考 源代码 目的 该服务的目的是将 OPC-UA 设备连接到 EdgeX。 入门 本页介绍如何将 OPC-UA 设备连接到 EdgeX。 在此示例中，我们使用模拟器来实现（OPC UA Simulation Server）。 这提供了一种测试设备服务功能的简单方法。 环境 您可以使用任何可以安装 docker 和 docker-compose 的操作系统。 在本例中，我们使用 Ubuntu 使用 docker 部署 EdgeX。 设置 Prosys OPC UA Simulation Server 设备 !!! warning "警告" 本页面并不是设置 OPC-UA 设备的完整指南，仅介绍了几个重要步骤供参考。 下载 Prosys OPC UA 模拟服务器 从 OPC UA 模拟服务器下载 下载最新版本的 OPC UA Simulation Server Download。 安装模拟服务器 启动模拟服务器 验证模拟服务器 Status 复制连接地址(UA TCP)值：opc.tcp://jiekemacbookpro14.lan:53530/OPCUA/SimulationServer Objects 启动微服务之前 以下部分介绍如何在启动服务之前完成设置。 使用预定义的配置进行测试 设置新配置 使用预定义的配置进行测试 文件夹中的预定义配置：cmd/res/ 预定义 Device Profile 设备配置 Device Profile profiles/Simple-Driver.yaml 描述了一个 OPC-UA 设备，它包含 3 个资源，如下所示： name: OPCUA-Server manufacturer: Prosys model: Simlulator labels: - OPCUA - TEST description: Simulation OPCUA Server deviceResources: - name: Constant description: generated constant number properties: valueType: Float64 readWrite: RW attributes: nodeId: ns=3;i=1001 - name: Counter description: generated counter number properties: valueType: Int32 readWrite: R attributes: nodeId: ns=3;i=1002 - name: Random description: generated random number properties: valueType: Float64 readWrite: R attributes: nodeId: ns=3;i=1003 deviceCommands: - name: ConstantNum isHidden: false readWrite: RW resourceOperations: - deviceResource: Constant defaultValue: 0.0 - name: CounterNum isHidden: false readWrite: R resourceOperations: - deviceResource: Counter defaultValue: 0 - name: RandomNum isHidden: false readWrite: R resourceOperations: - deviceResource: Random defaultValue: 0.0 该表描述了设备配置文件的每个资源： Resource Name valueType of EdgeX nodeId Description Constant Float64 ns=3;i=1001 generated constant number Counter Int32 ns=3;i=1002 generated counter number Random Float64 ns=3;i=1003 generated random number 预定义设备配置 Device Configuration 设备配置 Device Configuration devices/Simple-Devices.yaml 描述了如下所示的两种设备。 deviceList: - name: SimulationServer profileName: OPCUA-Server description: OPCUA device labels: - OPCUA - TEST protocols: opcua: Endpoint: 'opc.tcp://192.168.123.21:53530/OPCUA/SimulationServer' 设置一个新的配置 Configuration 创建自定义配置文件夹 运行以下命令： mkdir -p custom-config 设置新的设备配置 Device Profile 运行以下命令来创建您的设备配置文件： cd custom-config vi new-device-profile.yaml 插入您的设备配置文件定义，这取决于您的 OPC-UA 设备配置。 设置设备服务配置 Configuration cd custom-config vi new-device-config.yaml 填写 new-device-config.yaml 文件。 准备 docker-compose 文件 生成 docker compose 文件 Clone edgex-compose git clone https://github.com/edgexfoundry/edgex-compose.git 生成 docker-compose.yml 文件 cd edgex-compose make gen no-secty ds-opcua 将自定义配置添加到 docker-compose 文件 将准备好的配置文件添加到 docker-compose 文件中，您可以使用卷挂载它们并更改 device-opcua 内部使用的环境。 打开 docker-compose.yml 文件，然后添加卷路径和环境，如下所示： device-opcua: ... environment: ... DEVICE_PROFILESDIR: /custom-config DEVICE_DEVICESDIR: /custom-config volumes: ... - /path/to/custom-config:/custom-config 在 Docker 上启动 EdgeX Foundry 由于我们在上一步中生成了 docker-compose.yml 文件，因此我们可以部署 EdgeX，如下所示： cd edgex-compose/compose-builder docker compose -p edgex up -d [+] Running 12/12 ✔ Container edgex-core-consul Started 0.0s ✔ Container edgex-ui-go Started 0.0s ✔ Container edgex-redis Started 0.0s ✔ Container edgex-core-common-config-bootstrapper Started 0.1s ✔ Container edgex-support-scheduler Started 0.0s ✔ Container edgex-kuiper Started 0.0s ✔ Container edgex-support-notifications Started 0.1s ✔ Container edgex-core-metadata Started 0.1s ✔ Container edgex-core-command Started 0.0s ✔ Container edgex-core-data Started 0.0s ✔ Container edgex-app-rules-engine Started 0.0s ✔ Container edgex-device-opcua Started 0.0s 启动服务后设置 如果服务已在运行并且您想要添加设备，则可以使用本节中概述的“核心元数据 API”。 如果您按照启动服务之前的设置中的说明设置设备配置文件和服务，则可以跳过此部分。 要在启动服务后添加设备，请完成以下步骤： 使用 POST 将上面的设备配置文件上传到元数据：http://localhost:59881/api/v3/deviceprofile/uploadfile ，并以表单数据格式将文件作为密钥“文件”添加到正文，以及创建的 ID 将被退回。 以下示例命令使用 curl 发送请求： curl http://localhost:59881/api/v3/deviceprofile/uploadfile -F "file=@new-device-profile.yml" 确保 OPC-UA 设备服务正在运行，如有必要或使用其他设备服务，请调整下面的服务名称以匹配。 使用 POST 将设备添加到 http://localhost:59881/api/v3/device，正文将类似于： curl http://localhost:59881/api/v3/device -H "Content-Type:application/json" -X POST \ -d '[ { "apiVersion" : "{{api_version}}", "device" : { "adminState" : "UNLOCKED", "description" : "OPCUA device", "labels" : [ "OPCUA", "TEST" ], "name" : "SimulationServer1", "operatingState" : "UP", "profileName" : "OPCUA-Server", "protocols" : { "opcua" : { "Endpoint" : "opc.tcp://192.168.123.21:53530/OPCUA/SimulationServer" } }, "serviceName" : "device-opcua" } } ]' 服务名称必须匹配/引用目标设备服务（“device-opcua”），并且配置文件名称必须与前面步骤中的设备配置文件名称("OPCUA-Server") 执行命令 现在我们准备运行一些命令。 查找可执行命令 使用以下查询查找可执行命令： curl http://localhost:59882/api/v3/device/name/SimulationServer1 | json_pp { "apiVersion": "v3", "deviceCoreCommand": { "coreCommands": [ { "get": true, "name": "ConstantNum", "parameters": [ { "resourceName": "Constant", "valueType": "Float64" } ], "path": "/api/v3/device/name/SimulationServer1/ConstantNum", "set": true, "url": "http://edgex-core-command:59882" }, { "get": true, "name": "CounterNum", "parameters": [ { "resourceName": "Counter", "valueType": "Int32" } ], "path": "/api/v3/device/name/SimulationServer1/CounterNum", "url": "http://edgex-core-command:59882" }, { "get": true, "name": "RandomNum", "parameters": [ { "resourceName": "Random", "valueType": "Float64" } ], "path": "/api/v3/device/name/SimulationServer1/RandomNum", "url": "http://edgex-core-command:59882" }, { "get": true, "name": "Constant", "parameters": [ { "resourceName": "Constant", "valueType": "Float64" } ], "path": "/api/v3/device/name/SimulationServer1/Constant", "set": true, "url": "http://edgex-core-command:59882" }, { "get": true, "name": "Counter", "parameters": [ { "resourceName": "Counter", "valueType": "Int32" } ], "path": "/api/v3/device/name/SimulationServer1/Counter", "url": "http://edgex-core-command:59882" }, { "get": true, "name": "Random", "parameters": [ { "resourceName": "Random", "valueType": "Float64" } ], "path": "/api/v3/device/name/SimulationServer1/Random", "url": "http://edgex-core-command:59882" } ], "deviceName": "SimulationServer1", "profileName": "OPCUA-Server" }, "statusCode": 200 } 执行设置命令 根据url和parameterNames执行 SET 命令，运行 SET 命令时将localhost替换为服务器 IP。 这里我们使用“heartbeat”命令： curl http://localhost:59882/api/v3/device/name/SimulationServer1/Constant \ -H "Content-Type:application/json" -X PUT \ -d '{"Constant": "199.99"}' {"apiVersion":"v3","statusCode":200} 执行获取命令 运行 GET 命令时，将 localhost 替换为服务器 IP。 这里我们使用“heartbeat”命令： curl http://localhost:59882/api/v3/device/name/SimulationServer1/Constant { "apiVersion": "v3", "event": { "apiVersion": "v3", "deviceName": "SimulationServer1", "id": "cc8ea84d-0a5f-4d5b-b4db-9126368f4aa3", "origin": 1702613269923352589, "profileName": "OPCUA-Server", "readings": [ { "deviceName": "SimulationServer1", "id": "5c1ea763-bb50-4837-b78c-8ef1c2ed0035", "origin": 1702613269921, "profileName": "OPCUA-Server", "resourceName": "Constant", "value": "1.999900e+02", "valueType": "Float64" } ], "sourceName": "Constant" }, "statusCode": 200 } 自动事件 AutoEvent 在设备定义文件的 autoEvents 部分中定义： deviceList: autoEvents: interval: '30s' onChange: false sourceName: 'Constant' 服务启动后，查询 core-data API。 结果显示该服务每“30 秒”自动执行一次命令。 配置 OPC-UA 设备服务具有以下配置来实现 OPCUAServer 协议。 OPCUAServer 示例如下图： # configuration.yml OPCUAServer: DeviceName: SimulationServer Policy: None Mode: None CertFile: '' KeyFile: '' Writable: Resources: 'Counter,Random' Configuration Default Value Description DeviceName SimmulationServer Device name of OPC-UA Policy None Security Policy of OPC-UA- None- Basic128Rsa15- Basic256- Basic256Sha256- Aes128Sha256RsaOaep- Aes256Sha256RsaPss Mode None Security Mode of OPC-UA-None- Sign- SignAndEncrypt CertFile none Cert file of OPC-UA, path to cert.pem KeyFile none Key file of OPC-UA, path to private key.pem Writable.Resources none Subscritions of OPC-UA 协议属性 设备为 opcua 定义以下协议属性。 这些属性位于每个设备定义的协议部分中的“opcua”键下。 Property Description Endpoint The Connection Address(UA TCP) of OPC-UA server !!! example "opcua 协议属性示例" ```yaml ... protocols: opcua: Endpoint: "opc.tcp://jiekemacbookpro14.lan:53530/OPCUA/SimulationServer" ``` API 参考 该服务继承了 SDK 中的通用设备服务 API API。 源代码 Device Service OPC-UA 的源代码可以在 https://github.com/edgexfoundry/device-opcua 中找到（社区还未合并，目前在 https://github.com/yiqisoft/device-opcua-go/tree/refactor-v3 ）。 关于我们 !!! success "亿琪软件" 上海亿琪软件有限公司成立于 2016 年，专注于 5G 通信、AI 人工智能、边缘计算和大数据网络安全多项技术领域，致力于物联网领域前沿技术的创新，为用户提供全方位、智能化和安全的物联网解决方案。 2023 年，公司发布“YiFUSION ｜工业边缘智能融合一体机”产品，为工业客户提供一整套的边缘计算+AI 能力：高性能数据采集、多类型数据融合、AI 算法集成、云端业务对接。在边缘网关的基础上，集成了 IoT 平台的边缘协同能力、本地 Web SCADA 和 HMI 功能、本地数据存储、边缘 AI 视频分析、行业应用集成等。 2022 年，公司推出 “YiCLOUD ｜亿琪云”一站式物联网应用解决方案。公司的业务涵盖了智慧城市、智慧农业、智能工厂和智慧园区等多个领域，公司软硬件产品和解决方案获得华为技术认证，得到中国移动 OCP 认证，公司还是边缘计算产业联盟 ECC 成员。 !!! tip "关注我们" !!! warning "联系我们--商业服务" 网站：http://yiqisoft.cn 邮件：support@yiqisoft.cn 电话：021-68863086 手机：186-1666-9123
EdgeX Foundry 边缘计算框架的分层和服务为边缘设备/节点和云/企业应用之间提供了一个双向转换引擎。EdgeX 作为边缘计算平台是非常不错的选择。 OPC-UA Micro Service - 用于 OPC-UA 设备连接到 EdgeX 的设备服务。 01 介绍 EdgeX Foundry 边缘计算框架的分层和服务为边缘设备/节点和云/企业应用之间提供了一个双向转换引擎。EdgeX 作为边缘计算平台是非常不错的选择。 OPC-UA Micro Service - 用于 OPC-UA 设备连接到 EdgeX 的设备服务。 02 技术要点 工业互联网应用场景中，OPC-UA 是非常常见的工业控制设备，边缘计算框架 EdgeX 对于其驱动一直在 EdgeX Foundry 社区没有开源支持，我司经过项目的验证和长期的维护，在社区原有项目基础之上进行了 V3.2.0 版本驱动的移植和扩展。 本开源 EdgeX 设备驱动使用 github.com/goopcua/opcua 作为基础库，在基于 EdgeX device-sdk-go 的框架下，完成了驱动的开发和验证。 03 版本支持 本次开源的 EdgeX 驱动支持 EdgeX v3.x（最新版本，且持续更新和维护）。 开源代码：https://github.com/edgexfoundry-holding/device-opcua-go 04 使用文档 预计发布在：https://docs.edgexfoundry.org/3.1/microservices/device/services/device-opcua，敬请期待。 05 产品应用 EdgeX 框架应用于我司的边缘计算产品 YiEDGE（边缘计算软件） 和 YiFUSION（工业边缘智能融合网关）。 YiFUSION: 边缘融合智能网关是指具备边缘计算、智能分析、数据融合等功能的智能网关，能够在边缘侧实现数据采集、处理、分析、融合和应用，为用户提供更加智能、高效和低成本的服务。 简洁定义 英文名称：YiFUSION 中文名称：工业边缘智能融合网关 产品形态：软硬件一体机 硬件架构：X86/ARM/超融合/国产化 软件架构：全微服务化 关于我们 "亿琪软件" 上海亿琪软件有限公司成立于 2016 年，专注于 5G 通信、AI 人工智能、边缘计算和大数据网络安全多项技术领域，致力于物联网领域前沿技术的创新，为用户提供全方位、智能化和安全的物联网解决方案。 2023 年，公司发布“YiFUSION ｜工业边缘智能融合一体机”产品，为工业客户提供一整套的边缘计算+AI 能力：高性能数据采集、多类型数据融合、AI 算法集成、云端业务对接。在边缘网关的基础上，集成了 IoT 平台的边缘协同能力、本地 Web SCADA 和 HMI 功能、本地数据存储、边缘 AI 视频分析、行业应用集成等。 2022 年，公司推出 “YiCLOUD ｜亿琪云”一站式物联网应用解决方案。公司的业务涵盖了智慧城市、智慧农业、智能工厂和智慧园区等多个领域，公司软硬件产品和解决方案获得华为技术认证，得到中国移动 OCP 认证，公司还是边缘计算产业联盟 ECC 成员。 "联系我们--商业服务" 网站：http://yiqisoft.cn 邮件：support@yiqisoft.cn 电话：021-68863086 手机：186-1666-9123
文档｜EdgeX 设备微服务之西门子 S7 -- device-s7 完整使用手册
EdgeX Foundry （以下统一简称：EdgeX）设备微服务 device-s7 由我司贡献给社区，文档也是必不可少的环节，社区要求英文，现翻译成中文，方便国内客户阅读和使用。 目录 目的 入门 环境 设置 S7 设备 设置 ISO-on-TCP 访问 IP protocol 启用 S7 Communication 远程访问 (可选) 保留 S7 communication 设置数据块 Data Blocks 启动微服务之前 使用预定义的配置进行测试 预定义 Device Profile 预定义设备配置 Device Configuration 设置一个新的配置 Configuration 创建自定义配置文件夹 设置新的设备配置 Device Profile 设置设备服务配置 Configuration 准备 docker-compose 文件 生成 docker compose 文件 将自定义配置添加到 docker-compose 文件 在 Docker 上启动 EdgeX Foundry 启动服务后设置 执行命令 查找可执行命令 执行设置命令 执行获取命令 自动事件 配置 协议属性 API 参考 源代码 额外细节 读命令 Read Command 写命令 Write Command 何时转换数据 支持的转换 "亿琪软件" "联系我们--商业服务" 目的 该服务的目的是将西门子 S7 PLC 设备连接到 EdgeX。 入门 本页介绍如何将 S7 设备连接到 EdgeX。 在此示例中，我们使用真实设备（例如 S7-1200）。 这提供了一种测试设备服务功能的简单方法。 环境 您可以使用任何可以安装 docker 和 docker-compose 的操作系统。 在本例中，我们使用 Ubuntu 使用 docker 部署 EdgeX。 设置 S7 设备 !!! warning "警告" 本页面并不是设置 S7 设备的完整指南，仅介绍了几个重要步骤。 设置 ISO-on-TCP 访问 IP protocol 设置 Ethernet addresses -> IP protocol, 例如： 192.168.123.199/255.255.255.0 启用 S7 Communication 远程访问 启用 Permit access with PUT/GET communication from remote partner. (可选) 保留 S7 communication S7 Communication 保留和使用的资源数量，“Configured” 为 0，表示 EdgeX 最多可以建立 8 个连接。 !!! warning "提示" 重要提示：不要与单个 S7 设备创建超过“6”个连接！ 我们需要为 WINCC 保留 “2” 个连接。 设置数据块 Data Blocks Data Block 1 在本例子中，只需使用 Clcok 偏移量 160.0 中的进行测试即可。 Data Block 4 在本例子中, 使用 bool, byte, word, dword, int, dint, real 作为测试. 启动微服务之前 以下部分介绍如何在启动服务之前完成设置。 使用预定义的配置进行测试 设置新配置 使用预定义的配置进行测试 文件夹中的预定义配置：cmd/res/ 预定义 Device Profile 设备配置 Device Profile profiles/Simple-Driver.yaml 描述了一个 S7-1200 设备，它包含 8 个资源，如下所示： name: S7-Device manufacturer: YIQISOFT description: Example of S7 Device model: Siemens S7 labels: [ISO-on-TCP] deviceResources: - name: bool description: PLC bool isHidden: false properties: valueType: Bool readWrite: RW attributes: NodeName: DB4.DBX0.0 - name: byte description: PLC byte isHidden: false properties: valueType: Uint8 readWrite: RW attributes: NodeName: DB4.DBB1 - name: word description: PLC word isHidden: false properties: valueType: Int16 readWrite: RW attributes: NodeName: DB4.DBW2 - name: dword description: PLC dword isHidden: false properties: valueType: Int32 readWrite: RW attributes: NodeName: DB4.DBD4 - name: int description: PLC int isHidden: false properties: valueType: Int16 readWrite: RW attributes: NodeName: DB4.DBW8 - name: dint description: PLC dint isHidden: false properties: valueType: Int32 readWrite: RW attributes: NodeName: DB4.DBW10 - name: real description: PLC real isHidden: false properties: valueType: Float32 readWrite: RW attributes: NodeName: DB4.DBD14 - name: heartbeat description: PLC heartbeat isHidden: false properties: valueType: Int16 readWrite: RW attributes: NodeName: DB1.DBW160 deviceCommands: - name: AllResource isHidden: false readWrite: RW resourceOperations: - deviceResource: bool defaultValue: 'false' - deviceResource: byte defaultValue: '0' - deviceResource: word defaultValue: '0' - deviceResource: dword defaultValue: '0' - deviceResource: int defaultValue: '0' - deviceResource: dint defaultValue: '0' - deviceResource: real defaultValue: '0' - deviceResource: heartbeat defaultValue: '0' 该表描述了设备配置文件的每个资源： Resource Name valueType of EdgeX NodeName Note(DB: Data Block) bool Bool DB4.DBX0.0 DB4: DBX0.0: (BOOL) bit 0 of offset 0 byte Uint8 DB4.DBB1 DB4, DBB1: (BYTE) one byte of offset 1 word Int16 DB4.DBW2 DB4, DBW2: (WORD) two bytes of offset 2 dword Int32 DB4.DBD4 DB4, DBD4: (DWORD) four bytes of offset 4 int Int16 DB4.DBW8 DB4, DBW8: (WORD) two bytes of offset 8 dint Int32 DB4.DBW10 DB4, DBW10: (WORD) two bytes of offset 10 real Float32 DB4.DBD14 DB4, DBD14: (REAL) four bytes of offset 14 heartbeat Int16 DB1.DBW160 DB1, DBW160: (WORD) two bytes of offset 160 预定义设备配置 Device Configuration 设备配置 Device Configuration devices/Simple-Device.yaml 描述了如下所示的两种设备。 S7-Device01：自动事件“interval”值(10s) < IdleTimeout(30s)，只有一个 tcp 连接，直到连接失败。 S7-Device02：自动事件“interval”值（10s）> IdleTimeout（5s），因此每个读/写命令都会重新连接到 S7 设备。 deviceList: - name: S7-Device01 profileName: S7-Device description: Example of S7 Device labels: [industrial] protocols: s7: Host: 192.168.123.199 Port: 102 Rack: 0 Slot: 1 Timeout: 30 IdleTimeout: 30 autoEvents: - interval: 10s onChange: false sourceName: AllResource - name: S7-Device02 profileName: S7-Device description: Example of S7 Device labels: [industrial] protocols: s7: Host: 192.168.123.199 Port: 102 Rack: 0 Slot: 1 Timeout: 5 IdleTimeout: 5 autoEvents: - interval: 10s onChange: false sourceName: heartbeat 设置一个新的配置 Configuration 创建自定义配置文件夹 运行以下命令： mkdir -p custom-config 设置新的设备配置 Device Profile 运行以下命令来创建您的设备配置文件： cd custom-config vi new-device-profile.yaml 插入您的设备配置文件定义，这取决于您的 S7 设备配置。 设置设备服务配置 Configuration cd custom-config vi new-device-config.yaml 填写 new-device-config.yaml 文件。 准备 docker-compose 文件 生成 docker compose 文件 Clone edgex-compose git clone https://github.com/edgexfoundry/edgex-compose.git 生成 docker-compose.yml 文件 cd edgex-compose make gen ds-s7 将自定义配置添加到 docker-compose 文件 将准备好的配置文件添加到 docker-compose 文件中，您可以使用卷挂载它们并更改 device-s7 内部使用的环境。 打开 docker-compose.yml 文件，然后添加卷路径和环境，如下所示： device-s7: ... environment: ... DEVICE_PROFILESDIR: /custom-config DEVICE_DEVICESDIR: /custom-config volumes: ... - /path/to/custom-config:/custom-config 在 Docker 上启动 EdgeX Foundry 由于我们在上一步中生成了 docker-compose.yml 文件，因此我们可以部署 EdgeX，如下所示： cd edgex-compose/compose-builder docker compose -p edgex up -d [+] Running 12/12 ✔ Container edgex-core-consul Started 0.0s ✔ Container edgex-ui-go Started 0.0s ✔ Container edgex-redis Started 0.0s ✔ Container edgex-core-common-config-bootstrapper Started 0.1s ✔ Container edgex-support-scheduler Started 0.0s ✔ Container edgex-kuiper Started 0.0s ✔ Container edgex-support-notifications Started 0.1s ✔ Container edgex-core-metadata Started 0.1s ✔ Container edgex-core-command Started 0.0s ✔ Container edgex-core-data Started 0.0s ✔ Container edgex-app-rules-engine Started 0.0s ✔ Container edgex-device-s7 Started 0.0s 启动服务后设置 如果服务已在运行并且您想要添加设备，则可以使用本节中概述的“核心元数据 API”。 如果您按照启动服务之前的设置中的说明设置设备配置文件和服务，则可以跳过此部分。 要在启动服务后添加设备，请完成以下步骤： 使用 POST 将上面的设备配置文件上传到元数据：http://localhost:59881/api/v3/deviceprofile/uploadfile ，并以表单数据格式将文件作为密钥“文件”添加到正文，以及创建的 ID 将被退回。 以下示例命令使用 curl 发送请求： curl http://localhost:59881/api/v3/deviceprofile/uploadfile -F "file=@new-device-profile.yml" 确保 S7 设备服务正在运行，如有必要或使用其他设备服务，请调整下面的服务名称以匹配。 使用 POST 将设备添加到 http://localhost:59881/api/v3/device，正文将类似于： curl http://localhost:59881/api/v3/device -H "Content-Type:application/json" -X POST \ -d '[ { "apiVersion" : "v3", "device": { "name": "S7-Device03", "description": "Example of S7 Device", "adminState": "UNLOCKED", "operatingState": "UP", "serviceName": "device-s7", "profileName": "S7-Device", "protocols": { "s7": { "Host": "192.168.123.199", "Port": 102, "Rack": 0, "Slot": 1, "Timeout": 30, "IdleTimeout": 30 } }, "autoEvents": [ { "interval": "10s", "onChange": false, "sourceName": "AllResource" } ] } } ]' 服务名称必须匹配/引用目标设备服务（“device-s7”），并且配置文件名称必须与前面步骤中的设备配置文件名称（“S7-Device”）匹配。 执行命令 现在我们准备运行一些命令。 查找可执行命令 使用以下查询查找可执行命令： curl http://localhost:59882/api/v3/device/name/S7-Device03 | json_pp { "apiVersion": "v3", "deviceCoreCommand": { "coreCommands": [ { "get": true, "name": "word", "parameters": [ { "resourceName": "word", "valueType": "Int16" } ], "path": "/api/v3/device/name/S7-Device03/word", "set": true, "url": "http://edgex-core-command:59882" }, { "get": true, "name": "int", "parameters": [ { "resourceName": "int", "valueType": "Int16" } ], "path": "/api/v3/device/name/S7-Device03/int", "set": true, "url": "http://edgex-core-command:59882" }, { "get": true, "name": "real", "parameters": [ { "resourceName": "real", "valueType": "Float32" } ], "path": "/api/v3/device/name/S7-Device03/real", "set": true, "url": "http://edgex-core-command:59882" }, { "get": true, "name": "heartbeat", "parameters": [ { "resourceName": "heartbeat", "valueType": "Int16" } ], "path": "/api/v3/device/name/S7-Device03/heartbeat", "set": true, "url": "http://edgex-core-command:59882" }, { "get": true, "name": "AllResource", "parameters": [ { "resourceName": "bool", "valueType": "Bool" }, { "resourceName": "byte", "valueType": "Uint8" }, { "resourceName": "word", "valueType": "Int16" }, { "resourceName": "dword", "valueType": "Int32" }, { "resourceName": "int", "valueType": "Int16" }, { "resourceName": "dint", "valueType": "Int32" }, { "resourceName": "real", "valueType": "Float32" }, { "resourceName": "heartbeat", "valueType": "Int16" } ], "path": "/api/v3/device/name/S7-Device03/AllResource", "set": true, "url": "http://edgex-core-command:59882" }, { "get": true, "name": "bool", "parameters": [ { "resourceName": "bool", "valueType": "Bool" } ], "path": "/api/v3/device/name/S7-Device03/bool", "set": true, "url": "http://edgex-core-command:59882" }, { "get": true, "name": "byte", "parameters": [ { "resourceName": "byte", "valueType": "Uint8" } ], "path": "/api/v3/device/name/S7-Device03/byte", "set": true, "url": "http://edgex-core-command:59882" }, { "get": true, "name": "dword", "parameters": [ { "resourceName": "dword", "valueType": "Int32" } ], "path": "/api/v3/device/name/S7-Device03/dword", "set": true, "url": "http://edgex-core-command:59882" }, { "get": true, "name": "dint", "parameters": [ { "resourceName": "dint", "valueType": "Int32" } ], "path": "/api/v3/device/name/S7-Device03/dint", "set": true, "url": "http://edgex-core-command:59882" } ], "deviceName": "S7-Device03", "profileName": "S7-Device" }, "statusCode": 200 } 执行设置命令 根据url和parameterNames执行 SET 命令，运行 SET 命令时将localhost替换为服务器 IP。 这里我们使用“heartbeat”命令： curl http://localhost:59882/api/v3/device/name/S7-Device03/heartbeat \ -H "Content-Type:application/json" -X PUT \ -d '{"heartbeat": "1"}' {"apiVersion":"v3","statusCode":200} 执行获取命令 运行 GET 命令时，将 localhost 替换为服务器 IP。 这里我们使用“heartbeat”命令： curl http://localhost:59882/api/v3/device/name/S7-Device03/heartbeat { "apiVersion": "v3", "statusCode": 200, "event": { "apiVersion": "v3", "id": "dd56ed66-2874-4d78-af02-753783164b3c", "deviceName": "S7-Device03", "profileName": "S7-Device", "sourceName": "heartbeat", "origin": 1702103303160428120, "readings": [ { "id": "8324105a-1843-415d-bea7-b61e6d12142c", "origin": 1702103303159722671, "deviceName": "S7-Device03", "resourceName": "heartbeat", "profileName": "S7-Device", "valueType": "Int16", "value": "1" } ] } } 自动事件 AutoEvent 在设备定义文件的 autoEvents 部分中定义： deviceList: autoEvents: interval: '30s' onChange: false sourceName: 'heartbeat' 服务启动后，查询 core-data API。 结果显示该服务每“30 秒”自动执行一次命令。 配置 该服务没有设备 SDK 提供的附加配置。 常用设备服务配置请参见设备服务配置部分。 协议属性 设备 S7 为 ISO-on-TCP 定义以下协议属性。 这些属性位于每个设备定义的协议部分中的“s7”键下。 Properity Default value Note Host N/A S7 ip address, e.g. 192.168.123.199 Port N/A S7 port, e.g. 102 Rack N/A Rack number, e.g. 0 Slot N/A Slot number, e.g. 1 Timeout 30 connect to S7 timeout, seconds IdleTimeout 30 connection idle timeout, seconds !!! example "S7 协议属性示例" ```json ... "protocols": { "s7": { "Host": "192.168.123.199", "Port": 102, "Rack": 0, "Slot": 1, "Timeout": 30, "IdleTimeout": 30 } } ... ``` API 参考 该服务继承了 SDK 中的通用设备服务 API API。 源代码 Device S7 的源代码可以在 https://github.com/edgexfoundry/device-s7 中找到。 额外细节 在 S7 设备资源使用带有“Int16”数字的“WORD”数据类型的用例中，“WORD”有两个字节，应转换为整数。 以下来自设备配置文件的摘录将“NodeName”DB4.DBW2 定义为“valueType”Int16： !!! example "示例 - 设备配置文件" ```yaml name: S7-Device manufacturer: YIQISOFT description: Example of S7 Device model: Siemens S7 labels: [ISO-on-TCP] deviceResources: - name: word description: PLC word isHidden: false properties: valueType: Int16 readWrite: RW attributes: NodeName: DB4.DBW2 ``` 读命令 Read Command 读取命令执行如下： Client 执行 Read Command； 设备服务发送 Read Command 读取一个‘WORD’数据； S7 设备返回一个两字节数据； 设备服务解析数据； 设备服务将数据转换为 Int16 值； 设备服务返回 json 格式给 Client。 graph LR A[Client] -->|1. Execute Read Command| B[Device Service] B -->|2. Send Request - WORD| C[S7 Device] C -->|3. Return 2 bytes| B B -->|4. Parse bytes| B B -->|5. Cast to Int16| B B -->|6. Return json| A 写命令 Write Command 写入命令执行如下： Client 执行 Write Command 写入一个 In16 值； 设备服务将 Int16 值转换为两个字节； 设备服务转换为二进制； 设备服务向 S7 设备发送写请求； 设备服务返回结果 json 给 Client。 graph LR A[Client] -->|1. Execute Write Command| B[Device Service] B -->|2. Cast to Int16| B B -->|3. Convert to binary| B B -->|4. Send Request - WORD| C[S7 Device] B -->|5. Return json| A 何时转换数据 您通常需要随时转换数据，因为 S7 设备仅接收其特定的数据类型。 支持的转换 支持的转换如下： From NodeName Bit(s) To valueType Address Sample Bool 1 Bool DB1.DBX0.0 Byte 8 Uint DB1.DBB1 Word 16 Int16 DB1.DBW2 DWord 32 Int32 DB1.DBD4 Int 16 Int16 DB1.DBW6 DInt 32 Int32 DB1.DBD8 Real 32 Float32 DB1.DBD20 "亿琪软件" 上海亿琪软件有限公司成立于 2016 年，专注于 5G 通信、AI 人工智能、边缘计算和大数据网络安全多项技术领域，致力于物联网领域前沿技术的创新，为用户提供全方位、智能化和安全的物联网解决方案。 2023 年，公司发布“YiFUSION ｜工业边缘智能融合一体机”产品，为工业客户提供一整套的边缘计算+AI 能力：高性能数据采集、多类型数据融合、AI 算法集成、云端业务对接。在边缘网关的基础上，集成了 IoT 平台的边缘协同能力、本地 Web SCADA 和 HMI 功能、本地数据存储、边缘 AI 视频分析、行业应用集成等。 2022 年，公司推出 “YiCLOUD ｜亿琪云”一站式物联网应用解决方案。公司的业务涵盖了智慧城市、智慧农业、智能工厂和智慧园区等多个领域，公司软硬件产品和解决方案获得华为技术认证，得到中国移动 OCP 认证，公司还是边缘计算产业联盟 ECC 成员。 "联系我们--商业服务" 网站：http://yiqisoft.cn 邮件：support@yiqisoft.cn 电话：021-68863086 手机：186-1666-9123
分享｜EdgeX 案例之 BACnet 设备读取，并通过物联网平台展示分析
物联网边缘端协议很多，BACnet 就是一种比较常见的监控协议。今天，就来跟大家分享一下 BACnet 基于 EdgeX 框架数据采集、控制和分析。 目录 BACnet 是什么？ 准备工作 EdgeX 微服务 EdgeX 基本微服务 EdgeX BACnet 微服务 配置 Device Profile 和 Device 获取 BACnet 设备数据 了解 BACnet 工作机制，可采用多种方法来做 数据上传 亿琪软件物联网平台 YiCONNECT 物联网平台展示和分析数据 关于我们 "亿琪软件" "联系我们--商业服务" BACnet 是什么？ !!! info "BACnet 协议" BACnet是用于智能建筑的通信协议，是国际标准化组织（ISO）、美国国家标准协会（ANSI）及美国采暖、制冷与空调工程师学会（ASHRAE）定义的通信协议1。BACnet针对智能建筑及控制系统的应用所设计的通信，可用在暖通空调系统（HVAC，包括暖气、通风、空气调节），也可以用在照明控制、门禁系统、火警侦测系统及其相关的设备。优点在于能降低维护系统所需成本并且安装比一般工业通信协议更为简易，而且提供有五种业界常用的标准协议，此可防止设备供应商及系统业者的垄断，也因此未来系统扩展性与兼容性大为增加。 !!! tip "最常见的 BACnet 协议有两种" BACnet IP：网络层通讯，基于以太网，使用 IP 通信，==本案例使用此协议== BACnet MS/TP：主从站通讯，就是串口，比如RS-485 !!! warning "什么是 BACnet BBMD？" BACnet/IP 使用 UDP/IP 在现有的 IP 网络中进行通信，在多个IP子网中如果需要对 BACnet 的广播消息进行管理的时候就需要一种特殊的BBMD设备（Broadcast Management Device）。 更多信息，请查阅其他相关资源，非本案例的重点内容。 准备工作 !!! info "BACnet 模拟器" 本案例中，使用 Yabe (Yet Another Bacnet Explorer)，请自行通过互联网下载。 其中，我们会用到一个子工具：==Bacnet.Room.Simulator==，将作为 BACnet 模拟设备来获取数据和控制。 软件打开后，类似如下，请记住右下角的 Id: ==2179272== !!! info "BACnet 查询工具" 本案例中，使用两种查询工具，都可以从互联网下载来使用。 Yabe：新建一个 BACnet/IP over UDP，自动出现 Device BACnetSCAN：双击 ==BACnet IP== 条目，就会出现 Device。 !!! warning "注意" BACnetSCAN 既可以作为查询工具，也可以作为 到目前为止，都是 BACnet 相关的准备和设置。 EdgeX 微服务 EdgeX 基本微服务 !!! info "启动你的 EdgeX 核心模块" 下载 docker compose 运行环境 git clone -b v3.1.0 https://github.com/edgexfoundry/edgex-compose.git cd edgex-compose/compose-builder make run no-secty 保证你的 EdgeX 基本微服务启动成功 ✔ Container edgex-core-consul Running ✔ Container edgex-redis Running ✔ Container edgex-ui-go Running ✔ Container edgex-core-common-config-bootstrapper Running ✔ Container edgex-core-metadata Running ✔ Container edgex-kuiper Running ✔ Container edgex-support-notifications Running ✔ Container edgex-support-scheduler Running ✔ Container edgex-core-command Running ✔ Container edgex-core-data Running ✔ Container edgex-app-rules-engine Running EdgeX BACnet 微服务 !!! info "增加 BACnet 微服务" !!! warning "注意" 官方版本不能直接使用，拿不到 BACnet 设备信息，需要根据以下步骤执行 重新编译你的微服务，增加 ==ds-bacnet-ip== 即可 make run no-secty ds-bacnet-ip 修改 docker-compose.yml，保证 ==UDP:47808== 端口被映射到容器 device-bacnet-ip: ... ports: - mode: ingress host_ip: 127.0.0.1 target: 59980 published: "59980" protocol: tcp - mode: ingress host_ip: 0.0.0.0 target: 47808 published: "47808" protocol: udp ... 重启全部微服务 docker compose -p edgex up -d 确保 BACnet 微服务运行正常 curl -s http://localhost:59980/api/v3/ping|jq { "apiVersion": "v3", "requestId": "98059fe6-4b81-4d79-a851-4d0db85dbdf5", "statusCode": 200, "timestamp": "Fri, 01 Dec 2023 11:13:45 UTC", "serviceName": "device-bacnet-ip" } 配置 Device Profile 和 Device !!! info "Device Profile 配置信息" name: TemperatureSimple manufacturer: YIQISOFT description: BACnet device simulator provided with YIQISOFT model: BACnet Stack labels: [BACnet] deviceResources: - description: The current analog input value. name: Temperature.Indoor isHidden: false properties: valueType: Float32 readWrite: RW attributes: instance: 0 property: present-value type: analog-input - description: The current analog input value. name: Temperature.Water isHidden: false properties: valueType: Float32 readWrite: RW attributes: instance: 1 property: present-value type: analog-input - description: The current analog input value. name: Temperature.Outdoor isHidden: false properties: valueType: Float32 readWrite: RW attributes: instance: 2 property: present-value type: analog-input deviceCommands: - name: Query isHidden: false readWrite: R resourceOperations: - deviceResource: Temperature.Indoor - deviceResource: Temperature.Water - deviceResource: Temperature.Outdoor !!! info "Device 配置信息" 在 EdgeX UI 增加一个设备，以下信息必须保证一样，还记得前面的数字： ==2179272== 吗？就是填写在这里 至此，设备配置相关内容就完成了 获取 BACnet 设备数据 了解 BACnet 工作机制，可采用多种方法来做 !!! warning "是否采用 BBMD？" 前面说过 BBMD ，这个概念很重要，因为我们下面的方法用到了相关内容。 方法一：不采用 BBMD 方法二：采用外部 BBMD !!! info "方法一" 以上所有的配置，只是用 EdgeX BACnet 微服务本地来管理 BACnet 设备。前提是，你需要手动触发 ==BACnet who-Is== 请求，使用上述两个查询工具都可以完成这个操作。 Yabe：选中 Udp:47808 后，按键盘：F2 即可； BACnetSCAN：选中 BACnet IP 后，右键：搜索设备； 此时，在 EdgeX BACnet 微服务 log 下会出现如下信息，证明 BACnet 微服务已经收到 who-Is 广播包： level=DEBUG ts=2023-12-01T11:51:36Z app=device-bacnet-ip msg="Processing I-Am Request from 2179272" 查询 BACnet 设备 2179272 设备数据： curl http://localhost:59881/api/v3/device/name/hello/Query 结果如下： { "apiVersion": "v3", "statusCode": 200, "event": { "apiVersion": "v3", "id": "799292fc-565e-4b90-945c-18383dfafbcc", "deviceName": "hello", "profileName": "TemperatureSimple", "sourceName": "Query", "origin": 1701431871437505753, "readings": [ { "id": "6c0e2297-3b63-436e-b908-b6f9b563cc03", "origin": 1701431871437505753, "deviceName": "hello", "resourceName": "Temperature.Indoor", "profileName": "TemperatureSimple", "valueType": "Float32", "value": "2.07999992e+01" }, { "id": "8aef6bec-710f-4216-a1f6-1e7e4607599a", "origin": 1701431871437505753, "deviceName": "hello", "resourceName": "Temperature.Water", "profileName": "TemperatureSimple", "valueType": "Float32", "value": "3.87999992e+01" }, { "id": "8ef8d25b-c77f-44df-90cd-ec1e4e365e4c", "origin": 1701431871437505753, "deviceName": "hello", "resourceName": "Temperature.Outdoor", "profileName": "TemperatureSimple", "valueType": "Float32", "value": "1.20000000e+01" } ] } } !!! warning "这种方法的弊端就是需要 EdgeX BACnet 微服务来管理这些广播包" !!! info "方法二" 需要修改 EdgeX BACnet 微服务配置文件： configuration.yaml，启用外部 BBMD ... Driver: BBMD_ADDRESS: '192.168.123.11' BBMD_PORT: '47808' ... 重启微服务 make clean docker compose -p edgex up -d Docker 容器管理器可以看到 AutoEvents 日志，一切工作正常： level=INFO ts=2023-12-01T12:14:49Z app=device-bacnet-ip correlation-id=72a29f26-9d4c-4fee-a037-20827cf522c7 msg="AutoEvent: TemperatureDevice/Query" level=DEBUG ts=2023-12-01T12:14:49Z app=device-bacnet-ip correlation-id=72a29f26-9d4c-4fee-a037-20827cf522c7 msg="GET on device: TemperatureDevice" level=INFO ts=2023-12-01T12:14:50Z app=device-bacnet-ip correlation-id=1ca57207-8d0c-4094-a384-e48da5140e80 msg="AutoEvent: TemperatureDevice/Query" level=DEBUG ts=2023-12-01T12:14:50Z app=device-bacnet-ip correlation-id=1ca57207-8d0c-4094-a384-e48da5140e80 msg="GET on device: TemperatureDevice" level=INFO ts=2023-12-01T12:14:51Z app=device-bacnet-ip correlation-id=0a5ddc91-cc04-472b-b20a-64deaa16530d msg="AutoEvent: TemperatureDevice/Query" level=DEBUG ts=2023-12-01T12:14:51Z app=device-bacnet-ip correlation-id=0a5ddc91-cc04-472b-b20a-64deaa16530d msg="GET on device: TemperatureDevice" level=INFO ts=2023-12-01T12:14:52Z app=device-bacnet-ip correlation-id=e8a19615-2caa-4295-913b-aff37cdadbba msg="AutoEvent: TemperatureDevice/Query" level=DEBUG ts=2023-12-01T12:14:52Z app=device-bacnet-ip correlation-id=e8a19615-2caa-4295-913b-aff37cdadbba msg="GET on device: TemperatureDevice" level=INFO ts=2023-12-01T12:14:53Z app=device-bacnet-ip correlation-id=da1f321e-2780-40d9-af38-b4387a141b2f msg="AutoEvent: TemperatureDevice/Query" level=DEBUG ts=2023-12-01T12:14:53Z app=device-bacnet-ip correlation-id=da1f321e-2780-40d9-af38-b4387a141b2f msg="GET on device: TemperatureDevice" 数据上传 亿琪软件物联网平台 YiCONNECT !!! info "配置 eKuiper 规则引擎" 创建 Stream CREATE STREAM EdgeXStream () WITH (format = "json", type = "edgex", shared = "true") 创建 Rule { "triggered": true, "id": "RuleToYiCONNECT", "sql": "SELECT * , meta(deviceName) as deviceName, tstamp() as ts FROM EdgeXStream", "actions": [ { "mqtt": { "dataTemplate": "{\"{{.deviceName}}\":[{\"ts\":{{.ts}}, \"values\":{{json .}}}]}", "insecureSkipVerify": true, "protocolVersion": "3.1", "qos": 0, "retained": false, "sendSingle": true, "server": "tcp://demo.yiqisoft.cn:1883", "topic": "v1/gateway/telemetry", "username": "************" } } ], "options": { "debug": false, "logFilename": "", "isEventTime": false, "lateTolerance": 1000, "concurrency": 1, "bufferLength": 1024, "sendMetaToSink": false, "sendError": true, "qos": 0, "checkpointInterval": 300000, "restartStrategy": { "attempts": 0, "delay": 1000, "multiplier": 2, "maxDelay": 30000, "jitter": 0.1 }, "cron": "", "duration": "", "cronDatetimeRange": null } } 确保服务器连接正常，且数据传输正确。数据输入和输出数量一致，各方面的延迟都很正常。 { "status": "running", "source_EdgeXStream_0_records_in_total": 557, "source_EdgeXStream_0_records_out_total": 557, "source_EdgeXStream_0_process_latency_us": 138, "source_EdgeXStream_0_buffer_length": 0, "source_EdgeXStream_0_last_invocation": "2023-12-01T12:32:49.03012", "source_EdgeXStream_0_exceptions_total": 0, "source_EdgeXStream_0_last_exception": "", "source_EdgeXStream_0_last_exception_time": 0, "op_2_project_0_records_in_total": 557, "op_2_project_0_records_out_total": 557, "op_2_project_0_process_latency_us": 37, "op_2_project_0_buffer_length": 0, "op_2_project_0_last_invocation": "2023-12-01T12:32:49.03027", "op_2_project_0_exceptions_total": 0, "op_2_project_0_last_exception": "", "op_2_project_0_last_exception_time": 0, "sink_mqtt_0_0_records_in_total": 557, "sink_mqtt_0_0_records_out_total": 557, "sink_mqtt_0_0_process_latency_us": 262, "sink_mqtt_0_0_buffer_length": 0, "sink_mqtt_0_0_last_invocation": "2023-12-01T12:32:49.030321", "sink_mqtt_0_0_exceptions_total": 0, "sink_mqtt_0_0_last_exception": "", "sink_mqtt_0_0_last_exception_time": 0 } 物联网平台展示和分析数据 !!! info "Yabe 数据可视化效果" !!! info "物联网平台动态展示" 关于我们 "亿琪软件" 上海亿琪软件有限公司成立于 2016 年，专注于 5G 通信、AI 人工智能、边缘计算和大数据网络安全多项技术领域，致力于物联网领域前沿技术的创新，为用户提供全方位、智能化和安全的物联网解决方案。 2023 年，公司发布“YiFUSION ｜工业边缘智能融合一体机”产品，为工业客户提供一整套的边缘计算+AI 能力：高性能数据采集、多类型数据融合、AI 算法集成、云端业务对接。在边缘网关的基础上，集成了 IoT 平台的边缘协同能力、本地 Web SCADA 和 HMI 功能、本地数据存储、边缘 AI 视频分析、行业应用集成等。 2022 年，公司推出 “YiCLOUD ｜亿琪云”一站式物联网应用解决方案。公司的业务涵盖了智慧城市、智慧农业、智能工厂和智慧园区等多个领域，公司软硬件产品和解决方案获得华为技术认证，得到中国移动 OCP 认证，公司还是边缘计算产业联盟 ECC 成员。 "联系我们--商业服务" 网站：http://yiqisoft.cn 邮件：support@yiqisoft.cn 电话：021-68863086 手机：186-1666-9123
EdgeX 爱好者社区 在使用和开发过程中，收到很多使用者和开发者的提问和反馈，我们将在一系列文章中给大家分享出来。 EdgeX Foundry 在下面将统一简称为 EdgeX。 系列文章四： 如何集成 RBAC 到 EdgeX？ 如何一次获取多个数据测点？ EdgeX 有 API Gateway 吗？ 如何接入云或企业网络？ 常见问题(FAQ) "如何集成 RBAC 到 EdgeX？" 这个问题是由老外在 GitHub 社区 discussions 里面提出来，他希望 EdgeX 能够集成第三方认证软件，比如 Keycloak，以便完成权限对接。 RBAC，其实不适合 EdgeX，这只是一个边缘计算框架而已，不是一个完整的业务系统； EdgeX 本身有 token 机制来保证安全，控制中心与 EdgeX 交互是安全可靠的就好了，无需 RBAC； 当然，你也可以改造 EdgeX 使得其能够支持 RBAC，这个工作量社区无法作出评估； "如何一次获取多个数据测点？" 当然可以，而且数量不限制。主要的问题就是每次 core-command 能承受的数据量需要手工进行调整，以达到你的数量请求。 定义一个 command，包含你所需要的 resource，即可进行绑定，EdgeX 会一次性获取完所有的数据，返回到 message bus 中； 修改 Service - MaxResultCount ，以便容纳你的 command； "EdgeX 有 API Gateway 吗？" GitHub 社区里，经常有人问关于 API Gateway 的事情，总的来说，基本都是没有好好读官方文档的人，不了解 EdgeX 的机制，所以不清楚。 EdgeX API Gateway 使用 nginx 来实现，并且集成了 Secure 机制，从 v3 版本开始，微服务之间也需要 JWT 认证，这是为了防止有应用绕过 API Gateway； 也可以自行修改 API Gateway 配置，完成更多集成和扩展，就是 nginx 配置而已； kong 安全机制已经从 EdgeX 被移除，相对简单了很多； "如何接入云或企业网络？" 这个问题，也是 GitHub 社区问的比较多的，尤其是那些不需要接入公有云服务的客户，他们有自己的云或企业网络，要接入进去。 用 eKuiper 规则引擎，可以通过简单的配置和命令完成简单的云对接，而且 eKuiper 已经内置了很多云服务的对接； eKuiper 除了一些云资源对接，也需要接入企业网络，比如数据库，时序数据库等，都可以完美支持； 自己开发一个 Application Service 来对接，官方提供了很多例子可以参考，主要是修改对接协议的数据格式皆可完成。 关于我们 "亿琪软件" 上海亿琪软件有限公司成立于 2016 年，专注于 5G 通信、AI 人工智能、边缘计算和大数据网络安全多项技术领域，致力于物联网领域前沿技术的创新，为用户提供全方位、智能化和安全的物联网解决方案。 2023 年，公司发布“YiFUSION ｜工业边缘智能融合一体机”产品，为工业客户提供一整套的边缘计算+AI 能力：高性能数据采集、多类型数据融合、AI 算法集成、云端业务对接。在边缘网关的基础上，集成了 IoT 平台的边缘协同能力、本地 Web SCADA 和 HMI 功能、本地数据存储、边缘 AI 视频分析、行业应用集成等。 2022 年，公司推出 “YiCLOUD ｜亿琪云”一站式物联网应用解决方案。公司的业务涵盖了智慧城市、智慧农业、智能工厂和智慧园区等多个领域，公司软硬件产品和解决方案获得华为技术认证，得到中国移动 OCP 认证，公司还是边缘计算产业联盟 ECC 成员。 "联系我们--商业服务" 网站：http://yiqisoft.cn 邮件：support@yiqisoft.cn 电话：021-68863086 手机：186-1666-9123
EdgeX 爱好者社区 在使用和开发过程中，收到很多使用者和开发者的提问和反馈，我们将在一系列文章中给大家分享出来。 EdgeX Foundry 在下面将统一简称为 EdgeX。 系列文章三：主要介绍边缘计算框架对比相关的问答。 EdgeX 太占资源了，相比其他数据采集网关，硬件要求太高了，怎么竞争？ 在学习 EdgeX 开发过程中，出现各种稀奇古怪 或 古灵精怪 的问题，我该怎么处理？ 相比其他边缘计算或数据采集框架少则上百种多则几百种驱动，EdgeX 设备层驱动才二十种，完全不是一个量级，什么情况？ 打个不太恰当，又有一番道理的比喻，自己去体会：EdgeX 是一个航空母舰级别的产品，不能与那些小快艇、驱逐舰、巡洋舰相提并论。 常见问题(FAQ) 性能相关 "EdgeX 运行太占资源" 资源占用，跟业务要求有关系： 传感器数量：比如，接 10 个传感器和接1000个传感器，完全不一样的资源使用率； 采集频率：5秒采集一次数据比较正常，假如你调整到 500ms 一次采集，又是另一番景象； 设备类型：业务简单的话 1-2 种设备类型，复杂环境下几十上百种都可以，资源占用那是天壤之别； "软硬件要求高" 官方有最低资源要求，如果你的硬件低于这个要求，建议要么 ==别上== EdgeX，要么升级硬件： 硬件： 内存：最小 1GB，操作系统用掉一些，其他就是看你运行的容器数量，1GB 只适合测试验证，不适合商业用途； 存储：最小 3GB，操作系统占用多一些，docker image 占用不多，剩下的就是 container 运行过程中产生的日志，这个需要在 docker compose 中定义参数，回滚日志文件； CPU：没有特定限制（X86，ARM32需要自己编译 ，ARM64都可以），具体看业务处理量，做好观测，最大 CPU 负载不要超过 50%，保持一定的缓冲； 软件： 操作系统：宿主主机，虽然可以支持常见的 Windows、Linux、macOS，但是，生产环境还是应该以 Linux 为主（推荐 Ubuntu 系列）； 软件环境： 开发：采用开发工具包（包含：编译器，各种函数库），docker runtime； 生产：docker runtime 即可； "关于竞争" 这个问题比较宽泛，不能一概而论，可以从以下几个方面考虑： 摆正位置：要充分理解 EdgeX 在边缘计算领域所处的层次结构，你到底是做数据采集还是边缘计算？不要把传统的DTU和RTU称之为边缘计算就算是明白人了 竞争对象：如果用预装 EdgeX 的产品去跟其他单一功能的采集器相比，完全没必要，不是一个量级； 竞争场景：这个具体看你的市场策略和业务需要，你愿意用低价换取市场占有率，另当别论； 开发相关 社区经常出现一些奇怪又频繁的错误信息，贴出来问" 当然，你完全有这个权利和必要，毕竟遇到问题了，需要去解决它。 根据错误提示，去搜索引擎找找看，也许是一个通用的问题，或许并不是 EdgeX 本身； 可以到 GitHub issue 里面找，变换一些搜索关键字，也许被人也遇到过且已经被解决了； 各种开发基本能力，尤其是 docker，golang，物联网相关，保证能明白到底问题出在哪里，有时候并不是问题复杂，而是自己不熟悉整个过程； "提醒" 官方已经发布 v3 版本，最新版本 v3.1（LTS 长期支持版本） 刚刚在 2023年11月15日 发布，已经解决了 v3 以来的绝大部分问题。 理论上来说，官方社区已经不会提供更早版本的技术支持： 有 bug 不回修复； 新特性不会增加； 友善提醒更新到当前发布版本； 设备层驱动相关 "有人提问：这么少的驱动支持数量，如何成为一个官方应用的边缘计算框架？" 建议，还是先读一读 EdgeX 官方文档：a vendor-neutral open source project（供应商中立的开源项目） 以目前 EdgeX 应用情况来说，已经成为很多行业和领域的事实规范，不需要质疑，也无需考证，就冲着——供应商中立的开源项目，已经征服了很多开源边缘计算框架的使用者。 老外比较直接又比较委婉，以笔者的措辞：难道把开源软件拿来主义，换个皮，改一下项目名称，改一下程序接口名，顺便让社区把所有你需要的都做好，开放给你，免费给你技术支持，…… 参与开源，也可以奉献开源，你可以把你的驱动贡献给社区，也可以让社区帮你改改 bug 什么的； 可以提出你需要的驱动类型，参与社区讨论，帮助提高社区驱动支持的范围； 关于我们 "亿琪软件" 上海亿琪软件有限公司成立于 2016 年，专注于 5G 通信、AI 人工智能、边缘计算和大数据网络安全多项技术领域，致力于物联网领域前沿技术的创新，为用户提供全方位、智能化和安全的物联网解决方案。 2023 年，公司发布“YiFUSION ｜工业边缘智能融合一体机”产品，为工业客户提供一整套的边缘计算+AI 能力：高性能数据采集、多类型数据融合、AI 算法集成、云端业务对接。在边缘网关的基础上，集成了 IoT 平台的边缘协同能力、本地 Web SCADA 和 HMI 功能、本地数据存储、边缘 AI 视频分析、行业应用集成等。 2022 年，公司推出 “YiCLOUD ｜亿琪云”一站式物联网应用解决方案。公司的业务涵盖了智慧城市、智慧农业、智能工厂和智慧园区等多个领域，公司软硬件产品和解决方案获得华为技术认证，得到中国移动 OCP 认证，公司还是边缘计算产业联盟 ECC 成员。 "关注我们" "联系我们--商业服务" 网站：http://yiqisoft.cn 邮件：support@yiqisoft.cn 电话：021-68863086 手机：186-1666-9123
EdgeX Foundry 中文社区 在使用和开发过程中，收到很多使用者和开发者的提问和反馈，我们将在一系列文章中给大家分享出来。 系列文章二：主要介绍一些跟设备和驱动相关的问答。 EdgeX Foundry 性能如何？单个实例能承载多少设备？一次性能采集多少设备数据？ 如何开发一个新的 Device Service 设备驱动？ EdgeX 如何支持 I2C, SPI, UART 接口数据采集？ 官方支持通用协议情况如何？ ModBus，MQTT，REST，ONVIF 分别是什么情况？ 官方支持工业协议情况如何？ S7，OPC-UA，BACnet 分别是什么情况？ 常见问题(FAQ) 性能相关 !!! question "EdgeX Foundry 性能如何？" 这个问题由一位外国开发者在 GitHub 上提出来，坦率地说，这个问题范围太广了，不好完整的回答。 [x] 非要给个答案的话，那就是：EdgeX 性能完全取决于你的硬件配置。 !!! question "单个实例能承载多少设备？" 接着上一个大的问题，这是其中一个分支问题，假如计算资源足够的话，应该可以承受几十万设备。 [x] 笔者所在公司，采用 4核心，8G内存，可以跑 virtual device 50000-80000个，丝毫没有什么影响； [x] 把几万，几十万设备承载在一个实例中，其实并不是一个好的选择，要考虑到如果发生单点故障，应该如何应急处理； !!! question "一次性能采集多少设备数据？" 测试中有多少个命令以及命令间隔是多少？并且，您应该关注许多选项，例如：数据持久性、南向设备协议种类多少。 [x] 单协议采集，数量非常多的情况下，就看每个采集设备的测点数量，不会出现什么大问题，注意观察宿主机器上的资源利用率情况，及时作出调整； [x] 多协议采集，这样的情况下需要启动多个不同的设备服务微服务来运行，资源占用比单协议采集要多很多，需要更多的资源进行配合； 设备服务（驱动）开发 !!! question "如何开发一个新的 Device Service 设备驱动？" 其实，这个应该不是一个问答能解决的事情，需要一个章节或一个课题来解决。官方给出了很完整的[开发手册][3]，具备一些基础能力后，一步一步来，很容易开发出新的设备驱动。 [x] Golang SDK 符合官方的统一开发语言； 开发更简单； [x] C SDK 嵌入式设备上，或需要调用 C 库函数的情况下； 需要开启 C 编译环境，尤其是 docker 相关，生成 docker image 需要更多依赖； 总的来说，开发一个设备驱动，是一件很复杂且繁琐的工作，要测试的内容很多，稳定性/可靠性都是需要很多经验配合。 外设驱动开发 !!! question "EdgeX 如何支持 I2C, SPI, UART 接口数据采集？" 这个问题，是由一个国人在 GitHub 上提出来的，他的提法是否支持 I2C。 我的回答：不必要！ 原因有如下： EdgeX 更加偏向于计算，而不是针对一些串口协议进行解析； 这些传感器协议，也不适合接在边缘计算网关之上，太过于底层的协议，应该由 MCU + 实时操作系统来完成； 将这些协议转换成 ModBus RTU，我想这是更加合适的选择； 官方驱动支持情况 !!! question "通用协议：ModBus，MQTT，REST，ONVIF 分别是什么情况？" 这些协议，大部分都由社区开发完成，并且经过多轮迭代，稳定可靠，完全可以用在商业环境下。 ModBus: RTU/TCP 两个版本都支持的很好； MQTT: 跟随主版本一起发布，效果很好； REST: 跟随主版本一起发布，效果很好； ONVIF: 跟随主版本一起发布； v3.0 之前的版本隐性 bug 比较多，慢慢的完善了很多； 还需要一个流媒体服务器配合使用，毕竟 EdgeX 只是做了 ONVIF 协议适配； !!! question "工业场景协议：S7，OPC-UA，BACnet 分别是什么情况？" 工业场景下，稳定性要求高，性能要求也很高，那么，需要更多的时间来完成开发和测试。 Siemens S7: 官方还没有完整的开源子项目，笔者公司贡献了第一套代码，目前（11月12日）还在 review 中，详见：https://github.com/edgexfoundry-holding/device-s7 OPC-UA: 由社区完成了贡献，不过，也不是标准的 EdgeX 组件，需要自己编译和测试，并且用到项目中； BACnet: 官方有一个 C 版本的，也跟随主版本一起发布； 关于我们 !!! success "亿琪软件" 上海亿琪软件有限公司成立于 2016 年，专注于 5G 通信、AI 人工智能、边缘计算和大数据网络安全多项技术领域，致力于物联网领域前沿技术的创新，为用户提供全方位、智能化和安全的物联网解决方案。 2023 年，公司发布“YiFUSION ｜工业边缘智能融合一体机”产品，为工业客户提供一整套的边缘计算+AI 能力：高性能数据采集、多类型数据融合、AI 算法集成、云端业务对接。在边缘网关的基础上，集成了 IoT 平台的边缘协同能力、本地 Web SCADA 和 HMI 功能、本地数据存储、边缘 AI 视频分析、行业应用集成等。 2022 年，公司推出 “YiCLOUD ｜亿琪云”一站式物联网应用解决方案。公司的业务涵盖了智慧城市、智慧农业、智能工厂和智慧园区等多个领域，公司软硬件产品和解决方案获得华为技术认证，得到中国移动 OCP 认证，公司还是边缘计算产业联盟 ECC 成员。 !!! tip "关注我们" !!! warning "联系我们--商业服务" - 网站：http://yiqisoft.cn - 邮件：support@yiqisoft.cn - 电话：021-68863086 - 手机：186-1666-9123