Shifu teaches you to easily add drivers and connect to any IoT device

Time:2022-11-24

Although Shifu is currently supporting more protocols, there are many connection protocols for IoT devices. In the process of using Shifu, it is inevitable to encounter protocols that are not currently supported. This article will introduce how to use third-party drivers to access devices in Shifu.

If you wish to contribute code to the Shifu project, adding a new driver, please seedeviceShifu Development Guide

Technical principle

You can findShifu Warehouseofpkg/deviceshifuView now under the folderShifusupporteddeviceShifu. can be seenpkg/deviceshifu/deviceshifuhttpwill convert an IoT device using the HTTP protocol todeviceShifu

In other words, we only need to convert the currently unsupported protocols to HTTP protocol interfaces.

Case realization

Take the device connected to RS485-Modbus protocol as an example.

RS485 is a hardware connection protocol, while Modbus is a software layer connection protocol.

read data

We need to find a third-party library that can read RS485-Modbus device data first. Here we use the Python programming language, and the third-party library used ispymodbus. Specifically, in this case, the RS485 physical device is connected to the computer through the RS485 to USB chip, so the Python class used isModbusSerialClient

from pymodbus.client.sync import ModbusSerialClient

Create a new device class, here we use an LED digital display as an example:

class MyRS485Device:
    def __init__(self, device_address: int = 0x01, port: str = '/dev/tty.usbserial-14420') -> None:
        self.device_address = device_address
        self.client = ModbusSerialClient(method='rtu', port=port,  stopbits=1, bytesize=8, parity='N', baudrate=9600, timeout=2.0)

You can see that here we need to follow the third-party libraryModbusSerialClientDocumentation forclientto initialize.

Next we can define the function of the RS485 device, here we choose to display a decimal on the LED:

class MyRs485Led:
    ......
    
    def setFloat(self, value: float):
        data = int(abs(value) * 10)

        self.client.connect()
        self.client.write_register(address=7, value=data, unit=self.device_address)

        self.client.close()

In this way, we have realized reading RS485-Modbus data through the above Python code.

Create an HTTP server

Next we usefastapiStart the HTTP server, for example, we expose asetfloatAPI for external access to display decimals on the LED display.

from fastapi import FastAPI

app = FastAPI()

device = ZhongshengLed()

@app.get("/setfloat")
def setTemperature(value: float = 0.0):
    device.setFloat(value=value)
    return { "OK": "OK" }

entered herefloatIt is a variable parameter; the return value is a json string, which is not important.

Next, we can deploy this HTTP service locally, and then accessShifu

uvicorn --host 0.0.0.0 --port 23330 main:app

This way we can access thelocalhost:23330/setfloat?value=123.4The corresponding numbers are displayed on the LED digital display.

Invasion Shifu

Next we connect this HTTP-rendered device toShifugeneratedeviceShifu

The complete configuration file is as follows:

---
# Source: shifu_chart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: deviceshifu-myled-configmap
  namespace: deviceshifu
data:
  driverProperties: |
    driverImage: "defaultImage"
    driverSku: "Hello"
  instructions: |
    instructionSettings:
      defaultTimeoutSeconds: 3
    instructions:
      "setfloat": # Here you need to add the API exposed by HTTP
  telemetries: |
    telemetrySettings:
      telemetryUpdateIntervalInMilliseconds: 6000
    telemetries:
---
# Source: shifu_chart/templates/service.yaml
apiVersion: v1
kind: Service
metadata:
  labels:
    app: deviceshifu-myled-deployment
  name: deviceshifu-myled-service
  namespace: deviceshifu
spec:
  ports:
    - port: 80
      protocol: TCP
      targetPort: 8080
  selector:
    app: deviceshifu-myled-deployment
  type: LoadBalancer
---
# Source: shifu_chart/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: deviceshifu-myled-deployment
  name: deviceshifu-myled-deployment
  namespace: deviceshifu
spec:
  replicas: 1
  selector:
    matchLabels:
      app: deviceshifu-myled-deployment
  template:
    metadata:
      labels:
       app: deviceshifu-myled-deployment
    spec:
      containers:
        - image: edgehub/deviceshifu-http-http:v0.1.0
          name: deviceimg
          ports:
            - containerPort: 8080
          volumeMounts:
            - name: deviceshifu-config
              mountPath: "/etc/edgedevice/config"
              readOnly: true
          env:
            - name: EDGEDEVICE_NAME
              value: edgedevice-myled
            - name: EDGEDEVICE_NAMESPACE
              value: devices
      volumes:
      - name: deviceshifu-config
        configMap:
          name: deviceshifu-myled-configmap
      serviceAccountName: edgedevice-sa
---
# Source: shifu_chart/templates/edgedevice.yaml
apiVersion: shifu.edgenesis.io/v1alpha1
kind: EdgeDevice
metadata:
  name: edgedevice-myled
  namespace: devices
spec:
  sku: "xxx"
  connection: Ethernet
  address: "192.168.0.123:23330" # Need to fill in the IP address of the machine
  protocol: HTTP
  customMetadata:
      "description" : "description"
      "paas_device_id" : "device_xxxx"
      "vendor" : "xxx"
status:
  edgedevicephase: "pending"

This completes our deployment.

WelcomeContribute code to the Shifu project, adding new drivers not yet supported!