在上篇中咱们分享了《如何利用Shifu接入公有驱动的设施》。Shifu内置了几个罕用的驱动,像是西门子S7系列的PLC,RTSP协定的摄像头等。物联网上的需要因人而异。在这次的文章中咱们将介绍如何扩大Shifu自带驱动的能力。

简介
本文是一个应用Shifu Framework的西门子PLC驱动的扩大指南,其中蕴含Linux, Python, Shifu Framework, Docker, Kubernetes的基本操作,任何开发者都能够浏览本文来学习Shifu Framework的开发方法。
本文中的Shifu Framework架构如下
北向通过"deviceshifu-http-http”容器向上凋谢HTTP API接口,南向通过"siemens-plc-driver”容器来和理论设施交互

指标

  1. 在本地运行K8s集群并装置Shifu Framework
  2. 批改西门子PLC的驱动增加一个性能
  3. 打包驱动,生成容器镜像
  4. 在Shifu中部署PLC的数字孪生
  5. 实现扩大西门子PLC的能力

本次分享中用到的设施

  1. 开发环境(本文中为运行在Windows 11 Pro上面的WSL子系统,零碎为Ubuntu 20.04)
  2. 西门子PLC(反对S7协定即可,本文中用到的型号为西门子S7-1200系列)

须要的基本知识
-根本的Python
-Linux命令行基本操作(创立文件,装置利用,运行程序)
-Docker/containerd基本操作
-K8s基本操作

步骤
第一步:在本地运行Kubernetes(如果已装置Shifu Framework,请间接跳到第三步)
为了运行Shifu,咱们须要一个Kubernetes的集群,这里不限度用户应用的版本,本文中应用的是利用kind建设的测试Kubernetes集群。如果资源受限的话也能够思考应用k3d或者microk8s。
kind的装置教程:
https://kind.sigs.k8s.io/docs...
具体装置步骤本文将不再赘述。
kind装置结束后能够通过“kind version”来查看以后版本,本文中的版本为”v0.12.0”:

$ kind version kind v0.12.0 go1.17.8 linux/amd64

接下来应用“kind create cluster”创立集群,整个过程会继续几分钟,因网速而异:

$ kind create cluster Creating cluster "kind" ...  ✓ Ensuring node image (kindest/node:v1.23.4)   ✓ Preparing nodes   ✓ Writing configuration   ✓ Starting control-plane ️  ✓ Installing CNI   ✓ Installing StorageClass  Set kubectl context to "kind-kind" You can now use your cluster with:  kubectl cluster-info --context kind-kind Not sure what to do next?   Check out https://kind.sigs.k8s.io/docs/user/quick-start/

创立实现后咱们能够通过“kubectl get nodes”查看集群状态,当显示“Ready”即可:

$ kubectl get nodes NAME                 STATUS   ROLES                  AGE    VERSION kind-control-plane   Ready    control-plane,master   119s   v1.23.4 

至此,运行K8s步骤结束。

第二步:装置Shifu
首先将Shifu我的项目克隆到本地,我的项目地址为:
https://github.com/Edgenesis/...
执行命令为:
git clone https://github.com/Edgenesis/shifu.git

上面通过“kubectl apply -f shifu/k8s/crd/install/shifu_install.yml”即可一键将Shifu部署到k3s集群中:

$ kubectl apply -f k8s/crd/install/shifu_install.yml namespace/shifu-crd-system created customresourcedefinition.apiextensions.k8s.io/edgedevices.shifu.edgenesis.io created serviceaccount/shifu-crd-controller-manager created role.rbac.authorization.k8s.io/shifu-crd-leader-election-role created clusterrole.rbac.authorization.k8s.io/shifu-crd-manager-role created clusterrole.rbac.authorization.k8s.io/shifu-crd-metrics-reader created clusterrole.rbac.authorization.k8s.io/shifu-crd-proxy-role created rolebinding.rbac.authorization.k8s.io/shifu-crd-leader-election-rolebinding created clusterrolebinding.rbac.authorization.k8s.io/shifu-crd-manager-rolebinding created clusterrolebinding.rbac.authorization.k8s.io/shifu-crd-proxy-rolebinding created configmap/shifu-crd-manager-config created service/shifu-crd-controller-manager-metrics-service created deployment.apps/shifu-crd-controller-manager created namespace/devices created serviceaccount/edgedevice-sa created clusterrole.rbac.authorization.k8s.io/edgedevice-clusterrole created clusterrolebinding.rbac.authorization.k8s.io/edgedevice-clusterrolebinding created

至此,Shifu装置结束。

第三步:批改西门子PLC驱动来增加新的性能
在IDE中关上Shifu文件夹,本文应用的是VS Code。在"examples/siemensPLCDeviceShifu”目录下关上"siemens-plc.py”:

驱动内容如下(因长度问题只截取了一部分):

import os import sys import snap7 from flask import Flask, request client = snap7.client.Client() app = Flask(__name__) ip = os.environ.get("PLC_ADDRESS") port = os.environ.get("PLC_CONTAINER_PORT") rack = os.environ.get("PLC_RACK") slot = os.environ.get("PLC_SLOT") def edit_single_bit(originalbyte, digitvalue, isset):     if digitvalue > 7:         digitvalue -= 8         changebyte = originalbyte[1]         if isset == 0:             return bytes([originalbyte[0]]) + bytes([changebyte & ~(1 << digitvalue)])         else:             return bytes([originalbyte[0]]) + bytes([changebyte | (1 << digitvalue)])    else:         changebyte = originalbyte[0]         if isset == 0:             return bytes([changebyte & ~(1 << digitvalue)]) + bytes([originalbyte[1]])         else:             return bytes([changebyte | (1 << digitvalue)]) + bytes([originalbyte[1]]) @app.route('/sendsinglebit') def send_single_bit(): print("Changing single bit...") 

能够看到这个西门子PLC驱动是一个Python程序,通过调用”snap7”这个API来实现和西门子PLC的通信,向上通过Flask凋谢了若干个HTTP接口来供Shifu调用。

咱们次要看一下对于批改PLC内存值的“send_single_bit”这个函数,首先,是这个API接管的参数:

 rootaddress = request.args.get('rootaddress')  address = request.args.get('address', default=0, type=int)  start = request.args.get('start', default=0, type=int)  digit = request.args.get('digit', default=0, type=int)  value = request.args.get('value', default=0, type=int)

“rootaddress”定义了驱动写入的类型,目前承受的类型如下:

if rootaddress == 'M':         area = snap7.types.Areas.MK elif rootaddress == 'Q':         area = snap7.types.Areas.PA elif rootaddress == 'C':         area = snap7.types.Areas.CT elif rootaddress == 'T':         area = snap7.types.Areas.TM

能够看到目前反对的”M”, “Q”, “C”, “T”四种类型,除了这四种以外,S7还反对”PE”, “DB”这两种。明天咱们就来增加”DB”的反对。

首先增加一个新的”rootaddress”的查看,当值为”DB”的时候将”area”变量设为”snap7.types.Areas.DB”:

代码如下:

 elif rootaddress == 'DB':         area = snap7.types.Areas.DB

至此,驱动批改结束

第四步:打包驱动并运行PLC的数字孪生(deviceShifu)

接下来咱们对这个驱动进行打包,在“siemensPLCDeviceShifu”中有一个现成的Dockerfile,咱们间接利用它来对驱动进行打包,只需执行“docker build . -t edgenesis/plc-device:v0.0.1”即可:

shifu/examples/siemensPLCDeviceShifu$ docker build . -t edgenesis/plc-device:v0.0.1 [+] Building 65.0s (10/10) FINISHED                                                                                                                                                              => [internal] load build definition from Dockerfile                                                                                                                                      0.0s  => => transferring dockerfile: 298B                                                                                                                                                      0.0s  => [internal] load .dockerignore                                                                                                                                                         0.0s  => => transferring context: 2B                                                                                                                                                           0.0s  => [internal] load metadata for docker.io/library/python:3.9-slim-bullseye                                                                                                              11.4s  => [auth] library/python:pull token for registry-1.docker.io                                                                                                                             0.0s  => [1/4] FROM docker.io/library/python:3.9-slim-bullseye@sha256:dea558731860898a00ac0d004fcd67fff6a0a0d420af15d7ec4289fac5ab3df5                                                         8.5s  => => resolve docker.io/library/python:3.9-slim-bullseye@sha256:dea558731860898a00ac0d004fcd67fff6a0a0d420af15d7ec4289fac5ab3df5                                                         0.0s  => => sha256:1078a59cbb2c5273b0f18e6ad6b78aa01298be2b3a54365ed7ddf3b5d68f5c54 1.37kB / 1.37kB                                                                                            0.0s ……………………………………….  => => extracting sha256:8c7a905e65a9f4baafcf16861113440e68c6144d7c3a7e701482086992492f70                                                                                                 0.2s  => [internal] load build context                                                                                                                                                         0.0s  => => transferring context: 3.91kB                                                                                                                                                       0.0s  => [2/4] COPY requirements.txt .                                                                                                                                                         0.2s  => [3/4] RUN pip install --no-cache-dir -r requirements.txt                                                                                                                             44.5s  => [4/4] COPY siemens-plc.py .                                                                                                                                                           0.0s  => exporting to image                                                                                                                                                                    0.2s  => => exporting layers                                                                                                                                                                   0.2s  => => writing image sha256:9c5802b3e55e0b9b498dc05be642b4aff1c60098531156af747469cc795a7120                                                                                              0.0s  => => naming to docker.io/edgenesis/plc-device:v0.0.1 

因为是在本地执行的,所以让咱们将这个驱动的镜像载入到kind集群中,命令为“kind load docker-image edgenesis/plc-device:v0.0.1”:

$ kind load docker-image edgenesis/plc-device:v0.0.1 Image: "edgenesis/plc-device:v0.0.1" with ID "sha256:9c5802b3e55e0b9b498dc05be642b4aff1c60098531156af747469cc795a7120" not yet present on node "kind-control-plane", loading

在“examples/siemensPLCDeviceShifu/plc-deployment”文件夹中咱们提供了四个文件,能够将PLC的数字孪生一键部署到Kubernetes集群中:

├── plc-deviceshifu-configmap.yaml ├── plc-deviceshifu-deployment.yaml ├── plc-deviceshifu-service.yaml └── plc-edgedevice.yaml

首先咱们要批改PLC设施的地址,本教程中的PLC设施地址在“192.168.0.1”,咱们须要批改“plc-deviceshifu-deployment.yaml”中的”PLC_ADDR”环境变量来让咱们的容器应用这个IP来进行连贯:

- name: PLC_ADDR  value: "192.168.0.1" 

改好后,咱们就能够通过“Kubectl apply -f examples/siemensPLCDeviceShifu/plc-deployment”来部署

$ kubectl apply -f examples/siemensPLCDeviceShifu/plc-deployment/ configmap/plc-configmap-0.0.1 created deployment.apps/edgedevice-plc-deployment created service/edgedevice-plc created edgedevice.shifu.edgenesis.io/edgedevice-plc created

接下来让咱们运行一个nginx利用来演示如何与PLC进行交互,命令为:

curl "edgedevice-plc/sendsinglebit?rootaddress=DB&address=<address>&start=<start>&digit=<digit>&value=<0/1>" 

最初一步:运行成果

root@nginx:/# curl "edgedevice-plc/sendsinglebit?rootaddress=DB&address=0&start=0&digit=0&value=1";echo Changed from bytearray(b’\x00\x00’) to bytearray(b’\x01x00’) root@nginx:/# curl edgedevice-plc/getcontent?rootaddress=Q;echo 0b0000000000000001 

至此,教程完结

总结

在此篇文章中,咱们通过扩大Shifu的西门子PLC驱动的能力,实现了近程操纵改写PLC中DB的值。

能够看到,通过对驱动能力的减少也减少了Shifu的能力。

本文中的更改并没有提交到GitHub中,如果是您须要的需要,或者您刚好看到,无妨来咱们的GitHub提交一个PR第一个提交的人咱们将会给您筹备一份小礼物以示感激

十分感谢您看到了这里,咱们期待您的反馈,如果感觉文章写得不错或者有任何倡议请毫不犹豫地留言。

本文由博客群发一文多发等经营工具平台 OpenWrite 公布