# 振动边缘场景方案设计 ## 边缘场景 在结构物安全监测,包含物振动监测的场景中,将边缘网关将位于现场组网端(最接近“端”的位置)(一般会集成在采集箱内),通过边缘系统实现数据采集、计算和存储: ## 边缘场景 在结构物安全监测,包含**振动**监测的场景中,边缘网关将位于现场组网端(最接近“端”的位置)(一般会集成在采集箱内),通过边缘系统实现数据采集、计算和存储: > 对现场组网的理解可能存在偏差,大概示意如图 ![image-20211029141035589](imgs/振动边缘场景方案设计-GODAAS/image-20211029141035589.png) 可以看出,原来现场的配电箱内除了电源控制外,剩下的是采集控制(采集仪)和传输控制器(包含交换机、光纤收发器等),统一可以看作是对**信号量的调制过程**,即模拟信号->数字信号->光信号。 如果对应人体,就相当于一套**神经传输系统**。 边缘概念中,我们通常把边缘系统比做**章鱼**。章鱼有**40%**神经元在脑袋里,剩下的**60%**在它的8条腿上,所谓的**用“腿”思考**。 如集成箱②中描述,其中边缘服务器就类似这一区域内传感系统的“**大脑**”。 边缘计算的基本思想则是**功能缓存(function cache)**,是大脑功能的延生。 边缘计算是云计算的延生和补充。 边缘的大脑负责: + 收集和转发数据 (**信息传导**) + 数据存储(**记忆功能**) + 分析和反馈(**思考功能**) 这样的优势显而易见: :+1: 分布式和低延时计算 :+1: 效率更高、更加智能(AI)、更加节能 :+1: 缓解流量压力、云端存储压力 :+1: 隐私保护,更加安全 ## 振动边缘设计 拟在`linux`嵌入式板上实现`golang`开发的边缘服务,实现对振动F2采集仪的数据**采集控制、计算、存储和传输**功能。 ### 技术选型 硬件:跟硬件同事讨论后,选择了飞凌公司的OK1028A开发版,配置如下 软件:编程语言选择了目前以太DAC一致的Golang,开发Linux环境程序。 部署:考虑使用 `MicroK8S`在板子上部署采集程序和其他服务(数据库/消息组件) ## 整体设计 如上,框架在 《边缘网关的一些思考》中已经初步介绍,我们在开发板中,至少需要集成: + 数据采集和处理程序(T-DAC),这里主要是Go-DAAS负责采集振动数据 + 配置同步控制程序 + 数据库服务 + 规则引擎服务 需要安装的服务有: 数据库InfluxDB 消息中间件mosquitto 规则引起NodeRed 应用go-DAAS 应用go-DAC ### 数据流程 数据从采集开始,经过**ET**过程(图中滤波、校准、物理量计算 )之后, 主要分三个主流向: 1. 存储到数据库 2. 计算分析后存储和上报平台 3. 自动聚合(压缩)后的数据上报平台 ![image-20211029134533054](imgs/振动边缘场景方案设计-GODAAS/image-20211029134533054.png) 具体模块说明: 1. 滤波/校准 校准去直流、滤波算法 2. 物理量计算 输出电压值到监测物理量值转换 3. 分段 设置窗口大小、刷新时间,将数据进行分段 4. 窗口数据WEB 实现http服务提供实时窗口振动数据(类似DAAS实时采集展示)。并通过wobsocket实现实时更新 5. 计算分析 通过设置的算法,实现特征值(TMRS)、FFT、索力识别对计算 6. 触发判断 通过设置的触发条件(定时/信号量),对连续信号进行采样保存 (同DAAS采样生成.odb数据文件) 7. 存储 数据存储到边缘数据库。 8. 聚合 数据库中定时生成1s/10s等统计数据 9. 推送 通过规则引擎实现 关于边缘网关**提供数据**的形式,初步思考:可以通过DDNS或NAT内网穿透,通过端的WEB-API服务向外提供。 ## 采集模块 采集模块的设计稿如下,主要是设备连接控制的过程 。 Session: 管理TCP连接会话 VbServer:设备控制主服务,包括管理连接、配置读取、配置设置、启动采集和数据回调 VbController: 负责设备配置和处理流程控制 数据模型: ReceiveData: 参考C#DAAS,Session上的原始信号数据 VibData:转换后的振动数据 IotDbData: 待入库格式数据 ## 存储设计 在 《边缘数据库选型》中对比了几种数据库,初步拟定使用`InfluxDB`作为边缘端存储引擎。 目前仅考虑振动数据的存储。存储到数据格式如下: ```sql bucket : data measurement: vib tags: id (设备id) fields: phy (物理量值) ``` 通过配置持续聚集(CQ)实现数据的自动聚合 ```sql create database data_10sec_agg; -- 数据库 ${db} -- 10s持续聚集 每10s执行 (FOR 1min)允许数据晚到1min内 CREATE CONTINUOUS QUERY "cq_ten_sec" ON "vib" RESAMPLE EVERY 10s FOR 1m BEGIN SELECT mean(*),max(*),min(*),spread(*),stddev(*) INTO "data_10sec_agg"."autogen".:MEASUREMENT FROM /.*/ GROUP BY time(10s),* END; ``` ### 同步系统 TODO ### 推送系统 TODO ## 系统验证 #### MicroK8S安装出错 ```sh 开发版型号:FET3399-C核心板 系统:ForlinxDesktop 18.04 内核:Linux node37 4.15.0-136-generic #140-Ubuntu SMP Thu Jan 28 05:20:47 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux 按照官方安装MicroK8S步骤: 1. apt update 2. apt install snapd 3. snap install microk8s --classic --channel=1.21/edge 报错: error: system does not fully support snapd: cannot mount squashfs image using "squashfs": mount: /tmp/sanity-mountpoint-058597126: wrong fs type, bad option, bad superblock on /dev/loop0, missing codepage or helper program, or other error. ``` #### 裸运行程序 **问题1:无法通过网络远程** ```sh 通过串口连接后查看ip配置: ifconfig: eth0: flags=4163 mtu 1500 inet 10.8.30.195 netmask 255.255.255.0 broadcast 10.8.30.255 inet6 fe80::dd83:a430:5e3a:d947 prefixlen 64 scopeid 0x20 ether b6:a8:21:1d:72:0b txqueuelen 1000 (Ethernet) RX packets 46157 bytes 19908170 (19.9 MB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 31199 bytes 22566677 (22.5 MB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 device interrupt 24 lo: flags=73 mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 inet6 ::1 prefixlen 128 scopeid 0x10 loop txqueuelen 1 (Local Loopback) RX packets 42657 bytes 145116329 (145.1 MB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 42657 bytes 145116329 (145.1 MB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 需要ping一下外面的机器(10.8.30.117),然后117上才能访问它。 ``` 安装influxdb2. https://portal.influxdata.com/downloads/ ```sh #忘记密码了,重新安装,删除两个数据目录(k-v 数据和时序数据) sudo dpkg -r influxdb2 root@forlinx:/var/lib/influxdb/engine# rm -rf /var/lib/influxdb/influxd.bolt root@forlinx:/var/lib/influxdb/engine# rm -rf /var/lib/influxdb/.cache/ wget https://dl.influxdata.com/influxdb/releases/influxdb2-2.0.9-arm64.deb sudo dpkg -i influxdb2-2.0.9-arm64.deb # start influxd ``` 安装`mosquitto` ```sh apt install mosquitto ``` 安装Node-Red ```sh ``` 编译在arm上运行的edge程序: ```sh export PATH=$PATH:/usr/local/go/bin export GOPROXY=https://goproxy.io export GOPATH=${GOPATH}:"`pwd`" CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags "-extldflags -static " -ldflags "-X main.VERSION=1.0.0 -X 'main.SVN_REVISION=$SVN_REVISION_1' -X 'main.BUILD_NUMBER=$BUILD_NUMBER' -X 'main.BUILD_TIME=$BUILD_TIMESTAMP' -X 'main.GO_VERSION=`go version`'" -tags netgo -a -v -o ../../$BUILD_NUMBER/edge ``` 在本机构建: 启动WSL安装的ubuntu ```sh wget https://studygolang.com/dl/golang/go1.16.4.linux-amd64.tar.gz sudo rm -rf /usr/local/go sudo tar -C /usr/local -xzf go1.16.4.linux-amd64.tar.gz sudo sh -c "echo 'export PATH=\$PATH:/usr/local/go/bin'>> /etc/profile" source /etc/profile go version go env -w GO111MODULE=on go env -w GOPROXY=https://goproxy.io,direct #安装 gcc arm的交叉编译工具 sudo apt-get install -y gcc-aarch64-linux-gnu aarch64-linux-gnu-gcc -v yww@DESKTOP-5R6F0H1:/mnt/e/Iota/trunk/code/gowork/src/edge$ CGO_ENABLED=1 \ CC=aarch64-linux-gnu-gcc \ GOOS=linux \ GOARCH=arm64 \ go build -ldflags '-s -w --extldflags "-static -fpic"' -o ./edge ``` ## 串口服务器 开发linux上的串口服务器 虚拟串口VSPM软件。 串口服务器将串口转为Tcp连接,这里设定串口服务器作为TCP客户端。本工具是在PC机(边缘板)上启动tcp服务,将连接转到serial-port。 ![image-20211124170039516](imgs/振动边缘场景方案设计-GODAAS/image-20211124170039516.png) ![image-20211124170049666](imgs/振动边缘场景方案设计-GODAAS/image-20211124170049666.png) ## 云边协同设计 ![image-20211206102634500](imgs/振动边缘场景方案设计-GODAAS/image-20211206102634500.png) ### 工作序列 ![image-20220104133502998](imgs/振动边缘场景方案设计-GODAAS/image-20220104133502998.png) Ali: https://help.aliyun.com/document_detail/73731.html?spm=5176.11485173.help.7.380b59afFTM5xR#section-qej-6sd-o53 ### 原則 1. 配置至上而下 平臺執行下發指令。 無外網情況:平臺到處json 項目復用,MEC生產過程: 平臺生產連續json配置,下發or導出。 2. 數據至下而上 如字面意思. 3. 兼容第三方平臺??? 第三方平臺配置協議 very difficute!! 數據通過規則引擎轉發、任意格式 下發配置包 包含: > 產品包 > 協議、設備型號、能力、接口 > 部署包 > 鏈接關係、采集參數設置 > 公式包 > 公式選取和參數設置 邊緣特許場景: 1、問題排查 問題日志上傳。 工作日志上傳(跟蹤長期狀態) Can switch to off of cause 2、遠程升級 看其他平臺如何實現的? ### 协议选型 需要如下功能: 1. 配置下发 2. 心跳 3. 数据 4. 诊断 5. 固件OTA升级 选择iDAU MOP协议,通讯方式仅考虑MQTT(暂不考虑SoIP),进行改造。 参考《[整体方案-软件.docx](http://10.8.30.22/FS-iDAU/trunk/doc/iDAU 整体方案-软件.docx)》 ```json // 对象管理协议 // thing 下发 // /edge/thing/uuid { "M":"thing", "O":"set", "P":{ ... } } // 心跳 ANY // A { } // B { } // C { } // D { } // E { } ``` DAC中後處理接入位置: `src\iota\scheme\driverBase.go` ```sql SELECT id, name, "desc", version, impl, resource, "resType", "enableTime","updatedAt" FROM "ProtocolMeta" WHERE ("enableTime"<=$1 or "enableTime" is null) OnProtocolChanged --> updateProtocol 支持雲上協議動態應用。 “DeviceMeta” // cacheDeviceMeta 缓冲设备元型 SELECT id, name, model, "desc", "belongTo", category from "DeviceMeta" SELECT id, name, "desc", "deviceMetaId", "protocolMetaId" from "CapabilityMeta" where "deviceMetaId" in (%s) SELECT cp.name,cp."showName",cp.category,cp.enum,cp."defaultValue",cp."min",cp."max",cp."unit",cp."capabilityMetaId",cp."propertyTypeId" FROM "CapabilityProperty" cp %s WHERE cp."capabilityMetaId" in (select id from "CapabilityMeta" where "deviceMetaId" in (%s)) 獲取THING GetThingsByIds》 SELECT id,name,"desc","belongTo",enable, release FROM "Thing" WHERE TRUE AND enable=true getThinkLinksByID》 SELECT a.*, dstdi."deviceId", dc.id, dc."protocolMetaId" dcpmid, cm."protocolMetaId" cmpmid from ( SELECT t."belongTo", layout."thingId", lnk.id, lnk."parentLinkId", lnk."fromDeviceInterfaceId", it.key, im.name, di.properties, lnk."toDeviceInterfaceId", di."deviceId", dmi."deviceMetaId" FROM "LayoutLink" lnk, "LayoutNode" node ,"Layout" layout, "DeviceInterface" di, "DeviceMetaInterface" dmi, "InterfaceMeta" im , "InterfaceType" it, "Thing" t WHERE layout."thingId" = t.id AND lnk."fromDeviceInterfaceId" = di.id AND di."deviceMetaInterfaceId" = dmi.id AND dmi."interfaceMetaId" = im.id AND im."interfaceTypeId"=it.id AND lnk."fromLayoutNodeId" = node.id AND node."layoutId" = layout.id %s ) a LEFT JOIN "DeviceInterface" dstdi ON dstdi."id" = a."toDeviceInterfaceId" LEFT JOIN "DeviceCapability" dc on dc."deviceInterfaceId" = a."toDeviceInterfaceId" LEFT JOIN "CapabilityMeta" cm on cm.id = dc."capabilityMetaId AND t.enable=true AND layout."thingId" = '%s' getDimsOfThings》 SELECT id,name,"desc", "thingId" FROM "Dimension" where "thingId" in (%s) order by id getSchemes>> SELECT s.id,d."id" did, s.name, s.unit,s.mode, s.interval,s.repeats,s."notifyMode",s."capabilityNotifyMode", s."beginTime",s."endTime" FROM "Scheme" s, "Dimension" d WHERE s."dimensionId" = d.id and d."thingId" in (%s) getDimCaps>> fields := ` dc.id, dc."dimensionId", dc.repeats,dc.interval,dc.qos, dc.timeout, dc."errTimesToDrop",` + //DimensionCapability `cm.id, cm.name, ` + // CapabilityMeta=> Protocol/Interface/Device `c."id", c."protocolMetaId", c."capabilityMetaId", c."properties", ` + // DeviceCapability `d.id, d.name, d.properties, dm.id, dm.name,dm.category,` + //Device+DeviceMeta `di.id, di.properties, im.id, im.name, im."interfaceTypeId", ` + // DeviceInterface +InterfaceMeta `cm."protocolMetaId"` //DeviceProtocol +ProtocolMeta relation := ` "Dimension" dim, ` + `"DimensionCapability" dc, ` + // 主表 `"DeviceCapability" c, ` + // 使用的能力 `"Device" d, ` + // 设备 `"DeviceMeta" dm, ` + // 设备元型 `"DeviceInterface" di,` + // 设备接口 `"DeviceMetaInterface" dmi,` + // 设备元型接口 `"InterfaceMeta" im, ` + // 接口对应的接口元型 `"CapabilityMeta" cm ` // 能力元型 // ""ProtocolMeta" pm" // 协议元型 (协议信息) where := ` dc."deviceCapabilityId" = c.id ` + // 主引用: 能力元型 `AND d.id = c."deviceId" ` + // > 设备 `AND di.id = c."deviceInterfaceId" ` + // > 能力使用的接口 `AND cm.id = c."capabilityMetaId" ` + // > 能力使用的能力元型 `AND dm.id = d."deviceMetaId" ` + // Device => DeviceMeta : 设备-> 设备元型. `AND dmi.id = di."deviceMetaInterfaceId" ` + // DeviceInterface => DeviceMetaInterface `AND im.id = dmi."interfaceMetaId" ` + // DeviceMetaInterface => InterfaceMeta : 接口-> 接口元型. // "AND pm.id = cm."protocolMetaId" AND ` + // DeviceProtocol => ProtocolMeta : 协议-> 协议元型. fmt.Sprintf(` AND dc."dimensionId"=dim.id AND dim."thingId" in (%s) `, joinStr(thingIds)) // 限定 Thing scanRowAsDimCap>> ds.getSubDevices(dc.Device) (获得网关设备的子设备,并在子设备里添加链接实例) ds.GetFormula(dc.Capability.ID) SELECT id, "properties", "formulaId" FROM "CapabilityFormula" WHERE "capabilityId"=$1 ds.GetProtocol(dc, dc.Capability.PMID) // from cache ``` ## OTA升级 参考阿里云设计:https://help.aliyun.com/document_detail/85700.html ![image-20211206145612459](imgs/振动边缘场景方案设计-GODAAS/image-20211206145612459.png) + OTA deployment operator security. 操作权限足够安全 + Incremental roll-out of OTA updates. 作增量升级 + Securely downloading the update. 建立安全的下载通道 ## Nginx ON Windows windows上启动iota进行调试: download http://nginx.org/en/docs/windows.html ```sh cd /d E:\WorkSpace\nginx-1.13.10 .\nginx.exe ``` `nginx.conf` ```yaml server { listen 80; server_name 10.8.30.38; ssl off; client_max_body_size 10M; location /v1/api { proxy_pass http://10.8.30.38:19090/v1/api; proxy_cookie_domain localhost localhost; proxy_cookie_path / /; proxy_connect_timeout 300; proxy_send_timeout 1200; proxy_read_timeout 3000; proxy_set_header X-Real-Ip $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location / { proxy_pass http://10.8.30.38:9080; proxy_cookie_domain localhost localhost; proxy_cookie_path / /; proxy_connect_timeout 100; proxy_send_timeout 6000; proxy_read_timeout 600; } } ``` | nginx -s stop | fast shutdown | | --------------- | ------------------------------------------------------------ | | nginx -s quit | graceful shutdown | | nginx -s reload | changing configuration, starting new worker processes with a new configuration, graceful shutdown of old worker processes | | nginx -s reopen | re-opening log files | 通过docker启动 ```sh docker run -d --name nginx-server -p 8080:80 -p 443:443 -v E:\WorkSpace\nginx:/etc/nginx/conf.d:rw nginx ``` win10上安装micro-k8s https://ubuntu.com/tutorials/install-microk8s-on-windows#2-installation ## EMQX ### [规则引擎](https://docs.emqx.cn/broker/v4.3/rule/rule-engine.html) ![image-20190506171815028](imgs/振动边缘场景方案设计-GODAAS/image-20190506171815028.cc3c4ff2.jpg) 支持的事件: 消息发布、投递、确认、丢弃,客户端连接、订阅。 ![image-20220106151906800](imgs/振动边缘场景方案设计-GODAAS/image-20220106151906800.png) ![image-20220106152058560](imgs/振动边缘场景方案设计-GODAAS/image-20220106152058560.png)