KubeEdge分析-mapper的云端控制

問題描述

對KubeEdge整體框架了解之后,對于mapper有幾個細(xì)節(jié)上的問題還不清楚

  1. 對于多個同類型的device,是共用一個mapper還是會起多個mapper實例
  2. cloud如何下發(fā)device profile、更新profile到mapper

官方文檔說明

https://github.com/kubeedge/kubeedge/blob/master/docs/proposals/device-crd.md#device-model-type-definition

device-downstream-controller.png

The idea behind using config map to store device properties and visitors is that these metadata are only required by the mapper applications running on the edge node in order to connect to the device and collect data. Mappers if run as containers can load these properties as config maps . Any additions , deletions or updates to properties , visitors etc in the cloud are watched upon by the downstream controller and config maps are updated in etcd. The existing edge controller already has the mechanism to watch on config map updates and push them to the edge node. A mapper application can get these updates and then adjust the data collection process. A separate design proposal can be prepared to illustrate the details of how mappers can leverage these config maps.

If the mapper wants to discover what properties a device supports, it can get the model information from the device instance. Also , it can get the protocol information to connect to the device from the device instace. Once it has access to the device model , it can get the properties supported by the device. In order to access the property , the mapper needs to get the corresponding visitor information. This can be retrieved from the propertyVisitors list. Finally , using the visitorConfig, the mapper can read/write the data associated with the property.

下面是官方給的configMap的例子

apiVersion: v1
kind: ConfigMap
metadata:
  name: device-profile-config-01 // needs to be generated by device controller.
  namespace: foo
data:
  deviceProfile.json: |-
    {
      "deviceInstances": [
        {
          "id": "1",
          "name": "device1",
          "protocol": "modbus-rtu-01", // needs to be generated by device controller.
          "model": "SensorTagModel"
        }
      ],
      "deviceModels": [
        {
          "name": "SensorTagModel",
          "description": "TI Simplelink SensorTag Device Attributes Model",
          "properties": [
            {
              "name": "temperature",
              "datatype": "int",
              "accessMode": "r",
              "unit": "Degree Celsius",
              "maximum": "100",
            },
            {
              "name": "temperature-enable",
              "datatype": "string",
              "accessMode": "rw",
              "defaultValue": "OFF",
            }
          ]
        }
      ],
      "protocols": [
        {
          "name": "modbus-rtu-01",
          "protocol": "modbus-rtu",
          "protocolConfig": {
            "serialPort": "1",
            "baudRate": "115200",
            "dataBits": "8",
            "parity": "even",
            "stopBits": "1",
            "slaveID": "1"
          }
        }
      ],
      "propertyVisitors": [
        {
          "name": "temperature",
          "propertyName": "temperature",
          "modelName": "SensorTagModel",
          "protocol": "modbus-rtu",
          "visitorConfig": {
            "register": "CoilRegister",
            "offset": "2",
            "limit": "1",
            "scale": "1.0",
            "isSwap": "true",
            "isRegisterSwap": "true"
          }
        },
        {
          "name": "temperatureEnable",
          "propertyName": "temperature-enable",
          "modelName": "SensorTagModel",
          "protocol": "modbus-rtu",
          "visitorConfig": {
            "register": "DiscreteInputRegister",
            "offset": "3",
            "limit": "1",
            "scale": "1.0",
            "isSwap": "true",
            "isRegisterSwap": "true"
          }
        }
      ]
    }

從官方的說明看,cloud是通過config map將device profile傳遞給mapper的。

從官方給的config mapper的例子看,deviceInstances、deviceModels這些都是以List形式出現(xiàn)的,說明一個config map應(yīng)該是能描述多個device profile的。這一點在官方的Scability說明中其實也有提到

Currently, we have only one config map per node which stores all the device instances, device models, protocols and visitors for all the devices connected to the edge node. Mappers running on an edge node managing different devices now need to access one global configmap in order to extract information about the device properties and visitors. What should be the best way to partition a monolithic config map into smaller config maps ? Should the partitioning be based on the protocol type or based on device model ?

twin

這里注意下device instance中的twin沒有被放到configmap中,這就導(dǎo)致了mapper在report property的值的時候,不會考慮這個值是否在twin中。少了一個篩選的過程。

Mapper代碼分析

DockerFile

COPY src/ /opt/src
COPY conf/ /opt/src/conf
COPY scripts/ /opt/scripts

這里看到src目錄被放到了/opt/src下

deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: modbus-device-mapper-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: modbus-mapper
  template:
    metadata:
      labels:
        app: modbus-mapper
    spec:
      hostNetwork: true
      containers:
      - name: modbus-mapper-container
        image: <your_dockerhub_username>/modbus_mapper:v1.0
        env: 
        - name: CONNECTOR_MQTT_PORT
          value: "1883"
        - name: CONNECTOR_MQTT_IP
          value: 127.0.0.1
        - name: CONNECTOR_DPL_NAME
          value: dpl/deviceProfile.json
        imagePullPolicy: IfNotPresent
        securityContext:
          privileged: true
        volumeMounts:
        - name: dpl-config-volume
          mountPath: /opt/src/dpl
      nodeSelector:
        modbus: "true"      
      volumes:
      - name: dpl-config-volume
        configMap:
          name:  device-profile-config-<edge_node_name>
      restartPolicy: Always

這里注意下volumes和volumeMounts的配置,可以看出,dpl-config-volume這個config map會被掛載到/opt/src/dpl目錄,結(jié)合config profile中的key:deviceProfile.json,因此,edge core會在dpl目錄下生成并更新deviceProfile.json文件

src/index.js

    function(callback) {
        WatchFiles.loadDpl(options.dpl_name, (devInsMap, devModMap, devProMap, modVistrMap)=>{
            devIns = devInsMap;
            devMod = devModMap;
            devPro = devProMap;
            modVistr = modVistrMap;
            callback();
        });
    },

options.dpl_name配置的就是dpl/deviceProfile.json,因此,modbus_mapper初始化的時候,就加載了deviceProfile.json文件。

WatchFiles.watchChange(path.join(__dirname, 'dpl'), ()=>{
    async.series([
        function(callback) {
            WatchFiles.loadDpl(options.dpl_name, (devInsMap, devModMap, devProMap, modVistrMap)=>{
                devIns = devInsMap;
                devMod = devModMap;
                devPro = devProMap;
                modVistr = modVistrMap;
                callback();
            });
        },
...

除了啟動的時候,一次性讀取deviceProfile.json以外,還創(chuàng)建了一個線程用于監(jiān)測deviceProfile.json文件的更新(刪除并重新添加),如果檢測到更新,那么用新的config map來更新本地緩存,然后新建一個和mqtt broker的連接,監(jiān)聽并處理消息。

如何處理消息見《KubeEdge分析-mapper與deviceTwin交互流程》

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容