美文网首页edgexfoundry
EdgeX 2.0-Ireland 使用说明

EdgeX 2.0-Ireland 使用说明

作者: Mr_Michael | 来源:发表于2021-10-14 10:47 被阅读0次

    一、安装edgex 2.0

    1.使用docker-compose.yml启动[推荐]

    参考:https://docs.edgexfoundry.org/2.0/getting-started/quick-start/

    1)预装docker及docker-compose

    2)安装运行EdgeX

    下载非加密版本的edgex

    方法1

    # 86版本
    curl https://raw.githubusercontent.com/edgexfoundry/edgex-compose/ireland/docker-compose-no-secty.yml -o docker-compose.yml
    sudo docker-compose up -d
    
    # ARM64版本
    curl https://raw.githubusercontent.com/edgexfoundry/edgex-compose/ireland/docker-compose-no-secty-arm64.yml -o docker-compose.yml
    sudo docker-compose up -d
    

    方法2

    git clone -b ireland https://github.com/edgexfoundry/edgex-compose
    # X86运行
    make run
    # ARM64运行
    make run arm64
    

    验证安装

    docker-compose ps 
    
    image
    • 注意:如果需要edgex容器可以被外部设备访问,需要把docker-compose.yml中的"127.0.0.1:"去掉,然后重新启动。

    2.使用edgex-go 编译容器运行

    官方提供go和c两种开发方式,EdgeX Foundry 的开源微服务是用 Go 1.16 编写的,推荐使用golang进行开发。

    1)安装依赖

    • 安装Go环境

      • 推荐安装 Go 1.16 及其更新,较旧版本的 Go(尤其是 1.10 或更早版本),可能会导致问题。
    • 安装build-essential

      • 一般系统自带
    • ZeroMQ

      • 有几个edgex 服务默认使用zmq通信

      • 使用脚本[setup-zeromq.sh]安装(https://gist.github.com/katopz/8b766a5cb0ca96c816658e9407e83d00#file-setup-zeromq-sh),实测适用Ubuntu 16.04及18.04

        #!/bin/bash
        
        # Download zeromq
        # Ref http://zeromq.org/intro:get-the-software
        wget https://github.com/zeromq/libzmq/releases/download/v4.2.2/zeromq-4.2.2.tar.gz
        
        # Unpack tarball package
        tar xvzf zeromq-4.2.2.tar.gz
        
        # Install dependency
        sudo apt-get update && \
        sudo apt-get install -y libtool pkg-config build-essential autoconf automake uuid-dev
        
        # Create make file
        cd zeromq-4.2.2
        ./configure
        
        # Build and install(root permission only)
        sudo make install
        
        # Install zeromq driver on linux
        sudo ldconfig
        
        # Check installed
        ldconfig -p | grep zmq
        
        # Expected
        ############################################################
        # libzmq.so.5 (libc6,x86-64) => /usr/local/lib/libzmq.so.5
        # libzmq.so (libc6,x86-64) => /usr/local/lib/libzmq.so
        ############################################################
        
      • 命令安装,实测适用raspberry pi 4b ubuntu 20.10

        sudo apt-get update && \
        sudo apt-get install -y libtool pkg-config build-essential autoconf automake uuid-dev
        sudo apt-get install -y libzmq3-dev
        
        $ ldconfig -p | grep zmq
            libzmq.so.5 (libc6,AArch64) => /lib/aarch64-linux-gnu/libzmq.so.5
            libzmq.so (libc6,AArch64) => /lib/aarch64-linux-gnu/libzmq.so
        
    • 下载edgex-go仓库,作为设备微服务开发示例

      export GO111MODULE=on
      go get github.com/edgexfoundry/edgex-go
        # 代码下载到$GOPATH/pkg/mod/cache/download/github.com/edgexfoundry/edgex-go
      
      mkdir -p ~/go/src/github.com/edgexfoundry
      git clone https://github.com/edgexfoundry/edgex-go.git
      

    2)edgex-go目录说明

    ~/go/src/github.com/edgexfoundry/edgex-go$ tree -L 2
    .
    ├── ADOPTERS.md
    ├── Attribution.txt
    ├── bin
    │   └── test-attribution-txt.sh
    ├── CHANGELOG.md
    ├── cmd
    │   ├── core-command
    │   ├── core-data
    │   ├── core-metadata
    │   ├── secrets-config
    │   ├── security-bootstrapper
    │   ├── security-file-token-provider
    │   ├── security-proxy-setup
    │   ├── security-secretstore-setup
    │   ├── support-notifications
    │   ├── support-scheduler
    │   ├── sys-mgmt-agent
    │   └── sys-mgmt-executor
    ├── CONTRIBUTING.md
    ├── go.mod
    ├── GOVERNANCE.md
    ├── internal
    │   ├── constants.go
    │   ├── core
    │   ├── interface.go
    │   ├── io
    │   ├── pkg
    │   ├── security
    │   ├── support
    │   └── system
    ├── Jenkinsfile
    ├── LICENSE
    ├── Makefile
    ├── openapi
    │   └── v2
    ├── OWNERS.md
    ├── README.md
    ├── SECURITY.md
    ├── snap
    │   ├── hooks
    │   ├── local
    │   ├── README.md
    │   └── snapcraft.yaml
    ├── version.go
    └── ZMQWindows.md
    

    3)编译工程

    make docker 
    

    二、EdgeX服务组件

    https://docs.edgexfoundry.org/2.0/api/Ch-APIIntroduction/

    1.核心组件

    1)Core Command

    提供了一个 API 来获取可以为所有设备或单个设备发出的命令列表。

    • 向设备或传感器发出 GET 命令以获取设备上特定属性的当前值
    • 向设备或传感器发出 SET 命令以更改设备的当前状态或状态或其属性之一

    2)Core Data

    包含从设备/传感器收集的Events/Readings数据库 ,并将此数据库公开给其他服务。通过API可以对Add, Query 和 Delete Events/Readings的访问

    3)Core Metadata

    包含设备/传感器的元数据库 ,并将此数据库公开给其他服务。可以通过服务提供的API 存储和管理设备元数据。

    4)Configuration and Registry

    使用第三方的Consul 微服务作为配置和注册表的实现,RESTful API 由 Consul 直接提供。提供配置管理、服务注册、服务注销、服务发现、consul ui等功能

    2.支持组件

    1)Support Notifications

    2)Support Scheduler

    支持调度程序微服务提供一个内部 EdgeX“时钟”,可以启动任何 EdgeX 服务中的操作。在配置指定的时间,服务通过 REST 调用任何 EdgeX 服务 API URL 以触发操作。

    3.管理组件

    1)System Management Agent

    向第三方系统公开 EdgeX 管理服务 API。

    4.设备组件

    1)Device Services

    5.应用组件

    1)Application Services

    2)Rules Engine

    三、使用edgex 2.0

    1)EdgeX 服务的状态

    访问consul http://localhost:8500/

    2)本地读取设备微服务信息

    Edgex Foundry - Core Command API 2.0.0:59882端口

    Edgex Foundry - Core Metadata API 2.0.0:59881端口

    # 查询微服务是否正常运行
    curl http://localhost:[port]/api/v2/ping
    
    # 查询微服务当前configuration配置
    curl http://localhost:[port]/api/v2/config
    
    # 查询设备微服务的事件(deviceName、profileName、sourceName、valueType等)
    # Random-Integer-Device是预定义设备,在cmd/device-xxx/res/devices/xxx.toml中定义
    curl http://localhost:59880/api/v2/event/device/name/Random-Integer-Device
    
    # 查询所有设备
    curl http://localhost:59882/api/v2/device/all
    # 查询设备的coreCommands(name、url、path、parameters、get or set等)
    curl http://localhost:59882/api/v2/device/name/Random-Integer-Device
    # 读取deviceName的coreCommands的值
    curl -X GET http://localhost:59882/api/v2/device/name/Random-Integer-Device/Int16
    # 设置deviceName的coreCommands的值
    curl -X PUT -d '{"Int16":"42", "EnableRandomization_Int16":"false"}' http://localhost:59882/api/v2/device/name/Random-Integer-Device/WriteInt16Value
    
    # 删除设备
    curl -X DELETE http://localhost:59881/api/v2/device/name/Random-Integer-Device
    # 删除设备profile
    curl -X DELETE http://localhost:59881/api/v2/deviceprofile/name/Random-Integer-Device
    

    3)导出设备微服务的数据到MQTT broker

    社区提供的“可配置应用程序服务”将 EdgeX 数据发送到由 HiveMQ 托管的公共 MQTT 代理。然后可以通过 HiveMQ 提供的 MQTT 浏览器客户端查看 EdgeX 事件数据。

    将以下应用程序服务添加到 docker-compose.yml 文件中,紧跟在“app-service-rules”服务。

    app-service-mqtt:
        container_name: edgex-app-mqtt
        depends_on:
        - consul
        - data
        environment:
          CLIENTS_CORE_COMMAND_HOST: edgex-core-command
          CLIENTS_CORE_DATA_HOST: edgex-core-data
          CLIENTS_CORE_METADATA_HOST: edgex-core-metadata
          CLIENTS_SUPPORT_NOTIFICATIONS_HOST: edgex-support-notifications
          CLIENTS_SUPPORT_SCHEDULER_HOST: edgex-support-scheduler
          DATABASES_PRIMARY_HOST: edgex-redis
          EDGEX_PROFILE: mqtt-export
          EDGEX_SECURITY_SECRET_STORE: "false"
          MESSAGEQUEUE_HOST: edgex-redis
          REGISTRY_HOST: edgex-core-consul
          SERVICE_HOST: edgex-app-mqtt
          TRIGGER_EDGEXMESSAGEBUS_PUBLISHHOST_HOST: edgex-redis
          TRIGGER_EDGEXMESSAGEBUS_SUBSCRIBEHOST_HOST: edgex-redis
          WRITABLE_PIPELINE_FUNCTIONS_MQTTEXPORT_PARAMETERS_BROKERADDRESS: tcp://broker.mqttdashboard.com:1883
          WRITABLE_PIPELINE_FUNCTIONS_MQTTEXPORT_PARAMETERS_TOPIC: EdgeXEvents  # 可以修改主题
        hostname: edgex-app-mqtt
        image: edgexfoundry/app-service-configurable:2.0.0
        networks:
          edgex-network: {}
        ports:
        - 127.0.0.1:59702:59702/tcp
        read_only: true
        security_opt:
        - no-new-privileges:true
        user: 2002:2001
    

    公共MQTT代理接收到数据

    {"apiVersion":"v2","id":"83d86ea1-edfd-4c14-a69e-b8d7dfec3965","deviceName":"Random-UnsignedInteger-Device","profileName":"Random-UnsignedInteger-Device","sourceName":"Uint8","origin":1630311152846053399,"readings":[{"id":"891df7ab-7822-46e8-9cd8-8b8f8de8629d","origin":1630311152846053399,"deviceName":"Random-UnsignedInteger-Device","resourceName":"Uint8","profileName":"Random-UnsignedInteger-Device","valueType":"Uint8","binaryValue":null,"mediaType":"","value":"207"}]}
    

    四、Device Service开发

    https://docs.edgexfoundry.org/2.0/getting-started/Ch-GettingStartedSDK-Go/

    EdgeX Foundry - Device Service API 2.0.0

    1.基于device-sdk-go开发

    device-sdk-go is a set of Go packages that can be used to build Go-based device services for use within the EdgeX framework.

    device service主要依赖以下两个包来实现

    • github.com/edgexfoundry/device-sdk-go/v2 v2.0.0
    • github.com/edgexfoundry/go-mod-core-contracts/v2 v2.0.0

    1)获取device-sdk-go

    cd ~/go/src/github.com/edgexfoundry
    git clone --depth 1 --branch v2.0.0 https://github.com/edgexfoundry/device-sdk-go.git
    

    工程目录

    ├── bin
    │   ├── test-attribution-txt.sh
    │   └── test-go-mod-tidy.sh
    ├── CHANGELOG.md
    ├── Dockerfile.build
    ├── example     # device-simple
    │   ├── cmd
    │   │   └── device-simple
    │   ├── config
    │   │   └── configuration.go
    │   ├── driver
    │   │   └── simpledriver.go
    │   └── README.md
    ├── go.mod
    ├── internal
    │   ├── application
    │   │   ├── callback.go
    │   │   ├── command.go
    │   │   └── command_test.go
    │   ├── autodiscovery
    │   │   ├── autodiscovery.go
    │   │   └── discovery.go
    │   ├── autoevent
    │   │   ├── executor.go
    │   │   ├── executor_test.go
    │   │   └── manager.go
    │   ├── cache
    │   │   ├── const_test.go
    │   │   ├── devices.go
    │   │   ├── devices_test.go
    │   │   ├── init.go
    │   │   ├── profiles.go
    │   │   ├── profiles_test.go
    │   │   ├── provisionwatcher.go
    │   │   └── provisionwatcher_test.go
    │   ├── clients
    │   │   ├── clients.go
    │   │   ├── init.go
    │   │   └── init_test.go
    │   ├── common
    │   │   ├── consts.go
    │   │   └── utils.go
    │   ├── config
    │   │   ├── config.go
    │   │   └── types.go
    │   ├── container
    │   │   ├── client.go
    │   │   ├── config.go
    │   │   └── deviceservice.go
    │   ├── controller
    │   │   └── http
    │   ├── messaging
    │   │   ├── messaging.go
    │   │   └── messaging_test.go
    │   ├── provision
    │   │   ├── devices.go
    │   │   └── profiles.go
    │   ├── telemetry
    │   │   ├── linux_cpu.go
    │   │   ├── telemetry.go
    │   │   ├── unimplemented_cpu.go
    │   │   └── windows_cpu.go
    │   └── transformer
    │       ├── checkNaN.go
    │       ├── checkNaN_test.go
    │       ├── transform.go
    │       ├── transformparam.go
    │       ├── transformparam_test.go
    │       ├── transformresult.go
    │       ├── transformresult_test.go
    │       ├── transform_test.go
    │       ├── transformvaluechecker.go
    │       └── transformvaluechecker_test.go
    ├── Jenkinsfile
    ├── LICENSE
    ├── Makefile
    ├── openapi
    │   ├── v1
    │   │   └── device-sdk.yaml
    │   └── v2
    │       ├── changes.txt
    │       └── device-sdk.yaml
    ├── pkg     # golang依赖包
    │   ├── models      # driver相关
    │   │   ├── asyncvalues.go
    │   │   ├── commandrequest.go
    │   │   ├── commandvalue.go
    │   │   ├── commandvalue_test.go
    │   │   ├── manager.go
    │   │   ├── mocks
    │   │   ├── protocoldiscovery.go
    │   │   └── protocoldriver.go
    │   ├── service     # 服务管理相关
    │   │   ├── async.go
    │   │   ├── async_test.go
    │   │   ├── init.go
    │   │   ├── main.go
    │   │   ├── managedautoevents.go
    │   │   ├── manageddevices.go
    │   │   ├── managedprofiles.go
    │   │   ├── managedwatchers.go
    │   │   └── service.go
    │   └── startup # 启动相关
    │       └── bootstrap.go
    ├── README.md
    ├── snap
    │   ├── hooks
    │   │   └── install
    │   ├── local
    │   └── snapcraft.yaml
    └── version.go
    

    2)构建新的device-service工程

    cd ~/go/src/github.com/edgexfoundry
    mkdir device-simple
    cp -rf ./device-sdk-go/example/* ./device-simple/
    cp ./device-sdk-go/Makefile ./device-simple
    cp ./device-sdk-go/version.go ./device-simple/
    
    $ tree device-simple/
    device-simple/
    ├── cmd
    │   └── device-simple
    │       ├── Attribution.txt
    │       ├── Dockerfile
    │       ├── main.go
    │       └── res
    │           ├── configuration.toml      # 微服务配置文件
    │           ├── devices
    │           │   ├── simple-device.json.example
    │           │   └── simple-device.toml
    │           ├── off.jpg
    │           ├── on.png
    │           ├── profiles
    │           │   ├── Simple-Driver.json.example
    │           │   └── Simple-Driver.yaml
    │           └── provisionwatcher.json
    ├── config
    │   └── configuration.go
    ├── driver
    │   └── simpledriver.go
    ├── Makefile
    ├── README.md
    └── version.go
    

    修改device-simple/cmd/device-simple/main.go文件

     import (
    -       "github.com/edgexfoundry/device-sdk-go/v2"
    -       "github.com/edgexfoundry/device-sdk-go/v2/example/driver"
    +       "github.com/edgexfoundry/device-simple"
    +       "github.com/edgexfoundry/device-simple/driver"
            "github.com/edgexfoundry/device-sdk-go/v2/pkg/startup"
     )
    

    修改device-simple/Makefile文件

    @@ -3,13 +3,13 @@
    GO=CGO_ENABLED=0 GO111MODULE=on go
     GOCGO=CGO_ENABLED=1 GO111MODULE=on go
     
    -MICROSERVICES=example/cmd/device-simple/device-simple
    +MICROSERVICES=cmd/device-simple/device-simple
     .PHONY: $(MICROSERVICES)
     
     VERSION=$(shell cat ./VERSION 2>/dev/null || echo 0.0.0)
     DOCKER_TAG=$(VERSION)-dev
     
    -GOFLAGS=-ldflags "-X github.com/edgexfoundry/device-sdk-go/v2.Version=$(VERSION)"
    +GOFLAGS=-ldflags "-X github.com/edgexfoundry/device-simple.Version=$(VERSION)"
     GOTESTFLAGS?=-race
     
     GIT_SHA=$(shell git rev-parse HEAD)
    @@ -17,13 +17,13 @@ GIT_SHA=$(shell git rev-parse HEAD)
     build: $(MICROSERVICES)
            $(GOCGO) install -tags=safe
     
    -example/cmd/device-simple/device-simple:
    +cmd/device-simple/device-simple:
            go mod tidy
    -       $(GOCGO) build $(GOFLAGS) -o $@ ./example/cmd/device-simple
    +       $(GOCGO) build $(GOFLAGS) -o $@ ./cmd/device-simple
     
     docker:
            docker build \
    -               -f example/cmd/device-simple/Dockerfile \
    +               -f cmd/device-simple/Dockerfile \
                    --label "git_sha=$(GIT_SHA)" \
                    -t edgexfoundry/device-simple:$(GIT_SHA) \
                    -t edgexfoundry/device-simple:$(DOCKER_TAG) \
    

    初始化工程go module

    GO111MODULE=on go mod init github.com/edgexfoundry/device-simple
    # 为工程补齐module
    go mod tidy
    

    3)为微服务添加设备驱动

    修改driver/simpledriver.go,其导入device-sdk-go/v2/pkg/models包,xxxdriver.go需要基于驱动实现其函数。

    //github.com/edgexfoundry/device-sdk-go/pkg/models
    func (cv *CommandValue) ValueToString() string
    func (cv *CommandValue) String() string
    func (cv *CommandValue) BoolValue() (bool, error) 
    func (cv *CommandValue) BoolArrayValue() ([]bool, error) 
    func (cv *CommandValue) StringValue() (string, error) 
    func (cv *CommandValue) Uint8Value() (uint8, error) 
    func (cv *CommandValue) Uint8ArrayValue() ([]uint8, error) 
    func (cv *CommandValue) Uint16Value() (uint16, error) 
    func (cv *CommandValue) Uint16ArrayValue() ([]uint16, error) 
    func (cv *CommandValue) Uint32Value() (uint32, error) 
    func (cv *CommandValue) Uint32ArrayValue() ([]uint32, error) 
    func (cv *CommandValue) Uint64Value() (uint64, error) 
    func (cv *CommandValue) Uint64ArrayValue() ([]uint64, error) 
    func (cv *CommandValue) Int8Value() (int8, error) 
    func (cv *CommandValue) Int8ArrayValue() ([]int8, error) 
    func (cv *CommandValue) Int16Value() (int16, error) 
    func (cv *CommandValue) Int16ArrayValue() ([]int16, error) 
    func (cv *CommandValue) Int32Value() (int32, error) 
    func (cv *CommandValue) Int32ArrayValue() ([]int32, error) 
    func (cv *CommandValue) Int64Value() (int64, error) 
    func (cv *CommandValue) Int64ArrayValue() ([]int64, error) 
    func (cv *CommandValue) Float32Value() (float32, error) 
    func (cv *CommandValue) Float32ArrayValue() ([]float32, error) 
    func (cv *CommandValue) Float64Value() (float64, error) 
    func (cv *CommandValue) Float64ArrayValue() ([]float64, error) 
    func (cv *CommandValue) BinaryValue() ([]byte, error) 
    

    4)配置Device Profile

    Profile.yml是用来定义Device的数据类型以及EdgeX如何通过core-Command来对device发送命令。

    • deviceResources的值是定义Device上传到deviceService中数据的类型;
    • deviceCommands定义核心服务core-command能对设备进行的操作;

    device-profile参数说明

    type DeviceProfile struct {
        DBTimestamp
        Description     string
        Id              string
        Name            string
        Manufacturer    string
        Model           string
        Labels          []string
        DeviceResources []DeviceResource
        DeviceCommands  []DeviceCommand
    }
    
    type DeviceResource struct {
        Description string
        Name        string
        IsHidden    bool
        Tag         string
        Properties  ResourceProperties
        Attributes  map[string]interface{}
    }
    
    type DeviceCommand struct {
        Name               string
        IsHidden           bool
        ReadWrite          string
        ResourceOperations []ResourceOperation
    }
    
    // https://github.com/edgexfoundry/go-mod-core-contracts/blob/main/common/utils.go
    var valueTypes = []string{
        ValueTypeBool, ValueTypeString,
        ValueTypeUint8, ValueTypeUint16, ValueTypeUint32, ValueTypeUint64,
        ValueTypeInt8, ValueTypeInt16, ValueTypeInt32, ValueTypeInt64,
        ValueTypeFloat32, ValueTypeFloat64,
        ValueTypeBinary,
        ValueTypeBoolArray, ValueTypeStringArray,
        ValueTypeUint8Array, ValueTypeUint16Array, ValueTypeUint32Array, ValueTypeUint64Array,
        ValueTypeInt8Array, ValueTypeInt16Array, ValueTypeInt32Array, ValueTypeInt64Array,
        ValueTypeFloat32Array, ValueTypeFloat64Array,
    }
    

    路径:cmd/device-xxx/res/profiles/Simple-Driver.yaml,示例如下:

    # Identification部分
    apiVersion: "v2"
    name: "Simple-Device"       # 唯一的ProfileName
    manufacturer: "Simple Corp."
    model: "SP-01"
    labels:
      - "modbus"
    description: "Example of Simple Device"
    
    # deviceResources部分
    deviceResources:    # 资源属性
      -
        name: "SwitchButton"
        isHidden: false
        description: "Switch On/Off."
        properties:
            valueType: "Bool"
            readWrite: "RW"
            defaultValue: "true"
    
    # deviceCommands部分
    deviceCommands:     # restful api command
      -
        name: "Switch"
        isHidden: false
        readWrite: "RW"
        resourceOperations:
          - { deviceResource: "SwitchButton", defaultValue: "false" }
    

    5)添加预定义设备

    可以支持TOML或JSON格式的配置文件

    type Device struct {
        DBTimestamp
        Id             string
        Name           string
        Description    string
        AdminState     AdminState
        OperatingState OperatingState
        Protocols      map[string]ProtocolProperties
        LastConnected  int64
        LastReported   int64
        Labels         []string
        Location       interface{}
        ServiceName    string
        ProfileName    string
        AutoEvents     []AutoEvent
        Notify         bool
    }
    

    路径:cmd/device-xxx/res/devices/simple-device.toml

    [[DeviceList]]
      # 这里DeviceList的Name和Profile的值对应Simple-Driver.yaml的name: "Simple-Device"
      Name = "Simple-Device01"
      ProfileName = "Simple-Device"
      Description = "Example of Simple Device"
      Labels = [ "industrial" ]
      [DeviceList.Protocols]
      [DeviceList.Protocols.other]
        Address = "simple01"
        Port = "300"
      [[DeviceList.AutoEvents]]     # 自动请求事件
        Interval = "10s"        # 10秒发送一次
        OnChange = false
        SourceName = "Switch"   # 对应deviceCommands
    

    配置文件的处理代码:https://github.com/edgexfoundry/go-mod-core-contracts/tree/main/models

    6)修改device service配置文件

    路径:cmd/device-xxx/res/configuration.toml

    功能

    • 定义设备微服务的host、port等
    • 定义使用Registry的host、port
    • 定义edgex core-data和core-metadata等服务的host、port
    • 定义MessageQueue的配置,基于redis
    • 定义Device的ProfilesDir、DevicesDir和Discovery等
    [Writable]
    LogLevel = "INFO"
      # Example InsecureSecrets configuration that simulates SecretStore for when EDGEX_SECURITY_SECRET_STORE=false
      # InsecureSecrets are required for when Redis is used for message bus
      [Writable.InsecureSecrets]
        [Writable.InsecureSecrets.DB]
        path = "redisdb"
          [Writable.InsecureSecrets.DB.Secrets]
          username = ""
          password = ""
    
    [Service]
    HealthCheckInterval = "10s"
    Host = "localhost"
    Port = 59999 # Device serivce are assigned the 599xx range
    ServerBindAddr = ""  # blank value defaults to Service.Host value
    StartupMsg = "device simple started"
    # MaxRequestSize limit the request body size in byte of put command
    MaxRequestSize = 0 # value 0 unlimit the request size.
    RequestTimeout = "20s"
    
    [Registry]
    Host = "localhost"
    Port = 8500
    Type = "consul"
    
    [Clients]
      [Clients.core-data]
      Protocol = "http"
      Host = "localhost"
      Port = 59880
    
      [Clients.core-metadata]
      Protocol = "http"
      Host = "localhost"
      Port = 59881
    
    [MessageQueue]
    Protocol = "redis"
    Host = "localhost"
    Port = 6379
    Type = "redis"
    AuthMode = "usernamepassword"  # required for redis messagebus (secure or insecure).
    SecretName = "redisdb"
    PublishTopicPrefix = "edgex/events/device" # /<device-profile-name>/<device-name>/<source-name> will be added to this Publish Topic prefix
      [MessageQueue.Optional]
      # Default MQTT Specific options that need to be here to enable environment variable overrides of them
      # Client Identifiers
      ClientId = "device-simple"
      # Connection information
      Qos = "0" # Quality of Sevice values are 0 (At most once), 1 (At least once) or 2 (Exactly once)
      KeepAlive = "10" # Seconds (must be 2 or greater)
      Retained = "false"
      AutoReconnect = "true"
      ConnectTimeout = "5" # Seconds
      SkipCertVerify = "false" # Only used if Cert/Key file or Cert/Key PEMblock are specified
    
    # Example SecretStore configuration.
    # Only used when EDGEX_SECURITY_SECRET_STORE=true
    # Must also add `ADD_SECRETSTORE_TOKENS: "device-simple"` to vault-worker environment so it generates
    # the token and secret store in vault for "device-simple"
    [SecretStore]
    Type = "vault"
    Host = "localhost"
    Port = 8200
    Path = "device-simple/"
    Protocol = "http"
    RootCaCertPath = ""
    ServerName = ""
    TokenFile = "/tmp/edgex/secrets/device-simple/secrets-token.json"
      [SecretStore.Authentication]
      AuthType = "X-Vault-Token"
    
    [Device]
      DataTransform = true
      MaxCmdOps = 128
      MaxCmdValueLen = 256
      ProfilesDir = "./res/profiles"
      DevicesDir = "./res/devices"
      UpdateLastConnected = false
      AsyncBufferSize = 1
      EnableAsyncReadings = true
      Labels = []
      UseMessageBus = true
      [Device.Discovery]
        Enabled = false
        Interval = "30s"
    
    # Example structured custom configuration
    [SimpleCustom]
    OnImageLocation = "./res/on.png"
    OffImageLocation = "./res/off.jpg"
      [SimpleCustom.Writable]
      DiscoverSleepDurationSecs = 10
    

    7)编译及执行工程

    $ make build
    go mod tidy
    CGO_ENABLED=1 GO111MODULE=on go build -ldflags "-X github.com/edgexfoundry/device-simple.Version=0.0.0" -o cmd/device-simple/device-simple ./cmd/device-simple
    CGO_ENABLED=1 GO111MODULE=on go install -tags=safe
    # 执行文件为cmd/device-simple/device-simple
    

    运行可执行文件

    # 关闭安全模式
    $ export EDGEX_SECURITY_SECRET_STORE=false
    # 由于edgex服务组件使用容器以bridge网络启动,因此需要修改SERVICE_HOST为docker0 ip,否则会绑定127.0.0.1
    $ export SERVICE_HOST="172.17.0.1"
    $ cd ~/go/src/github.com/edgexfoundry/device-simple/cmd/device-simple
    
    $ ./device-simple 
    msg="Loaded service configuration from ./res/configuration.toml"    # 加载服务配置文件
    msg="Using local configuration from file (0 envVars overrides applied)"
    msg="Web server starting (localhost:59999)"     # 微服务开启webserver
    msg="Setting options for secure MessageBus with AuthMode='usernamepassword' and SecretName='redisdb"
    msg="Connected to redis Message Bus @ redis://localhost:6379 publishing on 'edgex/events/device' prefix topic with AuthMode='usernamepassword'" # 连接到redis
    msg="Check core-metadata service's status by ping..."
    msg="Service clients initialize successful."
    msg="Registering v2 routes..."
    msg="Skipping use of Configuration Provider for custom configuration: Provider not available"
    msg="Loaded custom configuration from ./res/configuration.toml"
    msg="Loaded custom configuration from file (0 envVars overrides applied)"
    msg="Custom config is: {./res/off.jpg ./res/on.png {10}}"
    msg="unable to watch custom configuration for changes: Configuration Provider not enabled"
    msg="device service device-simple doesn't exist, creating a new one"
    msg="Loading pre-defined profiles from /home/ubuntu/go/src/github.com/edgexfoundry/device-simple/cmd/device-simple/res/profiles"
    msg="Profile Simple-Device not found in Metadata, adding it ..."    # Metadata添加设备
    msg="Loading pre-defined devices from /home/ubuntu/go/src/github.com/edgexfoundry/device-simple/cmd/device-simple/res/devices"
    msg="Device Simple-Device01 not found in Metadata, adding it ..."
    msg="AutoDiscovery stopped: disabled by configuration"
    msg="Service dependencies resolved..."
    msg="Starting device-simple 0.0.0 "
    msg="device simple started"
    msg="Service started in: 19.572988ms"
    

    RESTFul API测试

    // curl http://localhost:59882/api/v2/device/name/Simple-Device01
    {
        "apiVersion": "v2",
        "statusCode": 200,
        "deviceCoreCommand": {
            "deviceName": "Simple-Device01",
            "profileName": "Simple-Device",
            "coreCommands": [
                {
                    "name": "SwitchButton",
                    "get": true,
                    "set": true,
                    "path": "/api/v2/device/name/Simple-Device01/SwitchButton",
                    "url": "http://edgex-core-command:59882",
                    "parameters": [
                        {
                            "resourceName": "SwitchButton",
                            "valueType": "Bool"
                        }
                    ]
                },
                ...
                {
                    "name": "Image",
                    "get": true,
                    "path": "/api/v2/device/name/Simple-Device01/Image",
                    "url": "http://edgex-core-command:59882",
                    "parameters": [
                        {
                            "resourceName": "Image",
                            "valueType": "Binary"
                        }
                    ]
                },
                ...
            ]
        }
    }
    

    8)构建镜像

    cd ~/edgexfoundry/device-simple
    make build
    make docker
    # 在docker-compose-no-secty.yml中添加微服务,并执行
    docker-compose -f docker-compose-no-secty.yml up -d
    

    docker-compose.yml样例

    • 添加到edgex核心服务的yml文件中
    ...
        device-xxx:
            container_name: edgex-device-xxx
            depends_on:
            - consul
            - data
            - metadata
            environment:
              CLIENTS_CORE_COMMAND_HOST: edgex-core-command
              CLIENTS_CORE_DATA_HOST: edgex-core-data
              CLIENTS_CORE_METADATA_HOST: edgex-core-metadata
              CLIENTS_SUPPORT_NOTIFICATIONS_HOST: edgex-support-notifications
              CLIENTS_SUPPORT_SCHEDULER_HOST: edgex-support-scheduler
              DATABASES_PRIMARY_HOST: edgex-redis
              EDGEX_SECURITY_SECRET_STORE: "false"
              MESSAGEQUEUE_HOST: edgex-redis
              REGISTRY_HOST: edgex-core-consul
              SERVICE_HOST: edgex-device-xxx
            hostname: edgex-device-xxx
            image: edgexfoundry/device-xxx:0.0.0-dev
            networks:
              edgex-network: {}
            ports:
            - 49994:49994/tcp
            read_only: false
            privileged: true
            volumes:
            - "/sys:/sys"
            - "/dev:/dev"
            security_opt:
            - no-new-privileges:false
            user: root:root
    ...
    

    2.device-sdk-go核心Package

    1)pkg/startup

    用于微服务的启动

    // bootstrap.go
    package startup
    
    import (
        "context"
    
        "github.com/edgexfoundry/device-sdk-go/v2/pkg/service"
        "github.com/gorilla/mux"
    )
    
    func Bootstrap(serviceName string, serviceVersion string, driver interface{}) {
        ctx, cancel := context.WithCancel(context.Background())
        service.Main(serviceName, serviceVersion, driver, ctx, cancel, mux.NewRouter()) // 调用pkg/service/main.go的Main函数
    }
    

    2)pkg/service

    // main.go
    func Main(serviceName string, serviceVersion string, proto interface{}, ctx context.Context, cancel context.CancelFunc, router *mux.Router) {
        ...
        bootstrap.Run(      // 执行github.com/edgexfoundry/go-mod-bootstrap/bootstrap/bootstrap.go的Run函数
            ctx,
            cancel,
            sdkFlags,
            ds.ServiceName,
            common.ConfigStemDevice,
            ds.config,
            startupTimer,
            ds.dic,
            true,
            []interfaces.BootstrapHandler{
                httpServer.BootstrapHandler,
                messaging.BootstrapHandler,
                clients.BootstrapHandler,
                autoevent.BootstrapHandler,
                NewBootstrap(router).BootstrapHandler,
                autodiscovery.BootstrapHandler,
                handlers.NewStartMessage(serviceName, serviceVersion).BootstrapHandler,
            })
        ...
    }
    
    // service.go
    type UpdatableConfig interface {
        interfaces.UpdatableConfig
    }
    
    type DeviceService struct {
        ServiceName     string
        LoggingClient   logger.LoggingClient
        RegistryClient  registry.Client
        SecretProvider  interfaces.SecretProvider
        edgexClients    clients.EdgeXClients
        controller      *restController.RestController
        config          *config.ConfigurationStruct
        deviceService   *models.DeviceService
        driver          sdkModels.ProtocolDriver
        discovery       sdkModels.ProtocolDiscovery
        manager         sdkModels.AutoEventManager
        asyncCh         chan *sdkModels.AsyncValues
        deviceCh        chan []sdkModels.DiscoveredDevice
        initialized     bool
        dic             *di.Container
        flags           flags.Common
        configProcessor *bootstrapConfig.Processor
        ctx             context.Context
        wg              *sync.WaitGroup
    }
    
    func (s *DeviceService) Initialize(serviceName, serviceVersion string, proto interface{}) 
    
    func (s *DeviceService) Name() string {
        return s.ServiceName
    }
    
    // Version returns the version number of this Device Service
    func (s *DeviceService) Version() string {
        return sdkCommon.ServiceVersion
    }
    
    // AsyncReadings returns a bool value to indicate whether the asynchronous reading is enabled.
    func (s *DeviceService) AsyncReadings() bool {
        return s.config.Device.EnableAsyncReadings
    }
    
    func (s *DeviceService) DeviceDiscovery() bool {
        return s.config.Device.Discovery.Enabled
    }
    
    // AddRoute allows leveraging the existing internal web server to add routes specific to Device Service.
    func (s *DeviceService) AddRoute(route string, handler func(http.ResponseWriter, *http.Request), methods ...string) error {
        return s.controller.AddRoute(route, handler, methods...)
    }
    
    // Stop shuts down the Service
    func (s *DeviceService) Stop(force bool) {
        if s.initialized {
            err := s.driver.Stop(force)
            if err != nil {
                s.LoggingClient.Error(err.Error())
            }
        }
    }
    
    // LoadCustomConfig uses the Config Processor from go-mod-bootstrap to attempt to load service's
    // custom configuration. It uses the same command line flags to process the custom config in the same manner
    // as the standard configuration.
    func (s *DeviceService) LoadCustomConfig(customConfig UpdatableConfig, sectionName string) error {
        if s.configProcessor == nil {
            s.configProcessor = bootstrapConfig.NewProcessorForCustomConfig(s.flags, s.ctx, s.wg, s.dic)
        }
        return s.configProcessor.LoadCustomConfigSection(customConfig, sectionName)
    }
    

    3)pkg/models

    实现coreCommand、protocoldriver与protocoldiscovery的相关接口,负责设备驱动与coreCommand的中间层交互。

    // protocoldriver.go
    package models
    
    import (
        "github.com/edgexfoundry/go-mod-core-contracts/v2/clients/logger"
        "github.com/edgexfoundry/go-mod-core-contracts/v2/models"
    )
    
    type ProtocolDriver interface {
        // Initialize performs protocol-specific initialization for the device service.
        // The given *AsyncValues channel can be used to push asynchronous events and
        // readings to Core Data. The given []DiscoveredDevice channel is used to send
        // discovered devices that will be filtered and added to Core Metadata asynchronously.
        Initialize(lc logger.LoggingClient, asyncCh chan<- *AsyncValues, deviceCh chan<- []DiscoveredDevice) error
    
        // HandleReadCommands passes a slice of CommandRequest struct each representing
        // a ResourceOperation for a specific device resource.
        HandleReadCommands(deviceName string, protocols map[string]models.ProtocolProperties, reqs []CommandRequest) ([]*CommandValue, error)
    
        // HandleWriteCommands passes a slice of CommandRequest struct each representing
        // a ResourceOperation for a specific device resource.
        // Since the commands are actuation commands, params provide parameters for the individual
        // command.
        HandleWriteCommands(deviceName string, protocols map[string]models.ProtocolProperties, reqs []CommandRequest, params []*CommandValue) error
    
        // Stop instructs the protocol-specific DS code to shutdown gracefully, or
        // if the force parameter is 'true', immediately. The driver is responsible
        // for closing any in-use channels, including the channel used to send async
        // readings (if supported).
        Stop(force bool) error
    
        // AddDevice is a callback function that is invoked
        // when a new Device associated with this Device Service is added
        AddDevice(deviceName string, protocols map[string]models.ProtocolProperties, adminState models.AdminState) error
    
        // UpdateDevice is a callback function that is invoked
        // when a Device associated with this Device Service is updated
        UpdateDevice(deviceName string, protocols map[string]models.ProtocolProperties, adminState models.AdminState) error
    
        // RemoveDevice is a callback function that is invoked
        // when a Device associated with this Device Service is removed
        RemoveDevice(deviceName string, protocols map[string]models.ProtocolProperties) error
    }
    
    // protocoldiscovery.go
    package models
    
    import (
        "github.com/edgexfoundry/go-mod-core-contracts/v2/models"
    )
    
    // ProtocolDiscovery is a low-level device-specific interface implemented
    // by device services that support dynamic device discovery.
    type ProtocolDiscovery interface {
        // Discover triggers protocol specific device discovery, asynchronously
        // writes the results to the channel which is passed to the implementation
        // via ProtocolDriver.Initialize(). The results may be added to the device service
        // based on a set of acceptance criteria (i.e. Provision Watchers).
        Discover()
    }
    
    // DiscoveredDevice defines the required information for a found device.
    type DiscoveredDevice struct {
        Name        string
        Protocols   map[string]models.ProtocolProperties
        Description string
        Labels      []string
    }
    

    相关文章

      网友评论

        本文标题:EdgeX 2.0-Ireland 使用说明

        本文链接:https://www.haomeiwen.com/subject/bvvsoltx.html