专栏首页嘘、小点声edgeXFoundry中modbus通信部署和测试(待续)

edgeXFoundry中modbus通信部署和测试(待续)

modbus协议分为基于tcp/ip的modbus tcp和和基于RS485接口的modbus rtu两种通信方式。

modbus方式虚拟设备部署测试

如下:参阅:https://docs.edgexfoundry.org/1.2/examples/Ch-ExamplesAddingModbusDevice/

1. 首先登录控制台edgex-ui-go页面,导入device profile文件,和mqtt导入相同。文件名为modbus.device.profile.yml。内容如下:

name: "Network Power Meter"
manufacturer: "Dent Instruments"
model: "PS3037"
description: "Power Scout Meter"
labels:
  - "modbus"
  - "powerscout"
deviceResources:
  -
    name: "Current"
    description: "Average current of all phases"
    attributes:
      { primaryTable: "HOLDING_REGISTERS", startingAddress: "9" }
    properties:
      value:
        { type: "UINT16", scale: "1"}
      units:
        { type: "String", readWrite: "R", defaultValue: "min"}
  -
    name: "Energy"
    description: "System Total True Energy"
    attributes:
      { primaryTable: "HOLDING_REGISTERS", startingAddress: "4001" }
    properties:
      value:
        { type: "FLOAT32", scale: "1"}
      units:
        { type: "String", readWrite: "R", defaultValue: "min"}
  -
    name: "Power"
    description: "System Total True Power "
    attributes:
      { primaryTable: "HOLDING_REGISTERS", startingAddress: "4003" }
    properties:
      value:
        { type: "UINT16", scale: "1"}
      units:
        { type: "String", readWrite: "R", defaultValue: "min"}
  -
    name: "Voltage"
    description: "Voltage Line to line (Volts) Average"
    attributes:
      { primaryTable: "HOLDING_REGISTERS", startingAddress: "4017" }
    properties:
      value:
        { type: "UINT16", scale: "1"}
      units:
        { type: "String", readWrite: "R", defaultValue: "min"}
  -
    name: "DemandWindowSize"
    description: "Demand window size in minutes; default is 15 min"
    attributes:
      { primaryTable: "HOLDING_REGISTERS", startingAddress: "4603" }
    properties:
      value:
        { type: "UINT16", readWrite: "R", scale: "1"}
      units:
        { type: "String", readWrite: "R", defaultValue: "min"}
  -
    name: "LineFrequency"
    description: "Line frequency setting for metering: 50=50 Hz, 60=60Hz"
    attributes:
      { primaryTable: "HOLDING_REGISTERS", startingAddress: "4609" }
    properties:
      value:
        { type: "UINT16", readWrite: "R", scale: "1"}
      units:
        { type: "String", readWrite: "R", defaultValue: "Hz"}
deviceCommands:
  -
    name: "Current"
    get:
      - { index: "1", operation: "get", deviceResource: "Current" }
  -
    name: "Values"
    get:
      - { index: "1", operation: "get", deviceResource: "Energy" }
      - { index: "2", operation: "get", deviceResource: "Power" }
      - { index: "3", operation: "get", deviceResource: "Voltage" }
  -
    name: "Configuration"
    set:
      - { index: "1", operation: "set", deviceResource: "DemandWindowSize" }
      - { index: "2", operation: "set", deviceResource: "LineFrequency" }
    get:
      - { index: "1", operation: "get", deviceResource: "DemandWindowSize" }
      - { index: "2", operation: "get", deviceResource: "LineFrequency" }
coreCommands:
  -
    name: "Current"
    get:
      path: "/api/v1/device/{deviceId}/Current"
      responses:
        -
          code: "200"
          description: "Get the Current"
          expectedValues: ["Current"]
        -
          code: "500"
          description: "internal server error"
          expectedValues: []
  -
    name: "Values"
    get:
      path: "/api/v1/device/{deviceId}/Values"
      responses:
        -
          code: "200"
          description: "Get the Values"
          expectedValues: ["Energy","Power","Voltage"]
        -
          code: "500"
          description: "internal server error"
          expectedValues: []
  -
    name: "Configuration"
    get:
      path: "/api/v1/device/{deviceId}/Configuration"
      responses:
        -
          code: "200"
          description: "Get the Configuration"
          expectedValues: ["DemandWindowSize","LineFrequency"]
        -
          code: "500"
          description: "internal server error"
          expectedValues: []
    put:
      path: "/api/v1/device/{deviceId}/Configuration"
      parameterNames: ["DemandWindowSize","LineFrequency"]
      responses:
        -
          code: "204"
          description: "Set the Configuration"
          expectedValues: []
        -
          code: "500"
          description: "internal server error"
          expectedValues: []

对要读取的modbus地址和存储的数据类型需要在profile中进行编辑。

2 修改modbus服务端的容器编排文件docker-compose.yml,将以下代码解注释:

然后重新启动:docker-compose up -d。

#  device-modbus:
#    image: edgexfoundry/docker-device-modbus-go:1.2.1
#    ports:
#      - "127.0.0.1:49991:49991"
#    container_name: edgex-device-modbus
#    hostname: edgex-device-modbus
#    networks:
#      - edgex-network
#    environment:
#      <<: *common-variables
#      Service_Host: edgex-device-modbus
#    depends_on:
#      - data
#      - command

3.和MQTT方式相同,在服务下添加设备,配置地址和端口,获得最终的控制台界面:

4.配置虚拟modebus设备。下载软件中的jar包,打开,点击Add,为方便测试,默认全选即可,其他不需要配置。然后点击Run。

http://modbuspal.sourceforge.net/

5.在控制台点击Send,获取结果,观察结果。另外,其中的Float32的Base64编码结果测试结果如下:

原始结果先解码,然后将byte数组所有表示为16进制,变成4个字节。其中高位两个字节表示为读取单位的值(INT),最大到0x7F7F,低位两个字节表示为读取位置的下一个位置的值。

当值超出范围或者仿真设置不正确时,Send返回结果会报错。

附上Python解码Base64并全体16进制显示的脚本:

import base64
bytes = base64.b64decode("f38AAA==")
l = [hex(int(i)) for i in bytes]
print(" ".join(l))

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 李宏毅的强化学习视频用于梳理翻阅(4)奖励、模仿

    curiosity模型中,在原来DQN的基础上,建立了Network1,用于在?_?和?_?的条件下预测输出的下一个状态,与实际在MDP的一个片段上输出的,下一...

    嘘、小点声
  • java学习与应用(4.2)--JavaScript、bootstrap

    JavaScript,弱类型脚本语言,增强交互和用户体验提高效率等。JavaScript=ECMAScript+JavaScript特有的内容(BOM对象+DO...

    嘘、小点声
  • java学习与应用(4.6)--过滤器、监听器、JQuery、AJAX、JSON等

    Filter过滤器:客户端在请求服务器资源前和返回响应,会通过过滤器,以拦截请求完成特殊功能。登录校验、统一编码校验等一些通用操作放置到过滤器。 定义类实现接口...

    嘘、小点声
  • appium+python自动化35-adb devices死活连不上

    启动adb 1.打开cmd首次使用adb devices,出现下面这两句,就是正在启动adb服务 C:\Users\admin>adb devices List...

    上海-悠悠
  • java instrument agent 原理小结

    java -cp classes:lib/byte-buddy-1.4.16.jar -javaagent:test-1.0-SNAPSHOT.jar com....

    小程故事多
  • 2018年7月26日python中面向对象中的封装

    武军超
  • 一张图看懂JVM之垃圾回收算法详解

    在之前的内容中,我们通过一张图的方式(图?),从总体上对JVM的结构特别是内存结构有了比较清晰的认识,虽然在JDK1.8+的版本中,JVM内存管理结构有了一定的...

    用户5927304
  • C++核心准则C.183: 不要使用联合体实现双关类型

    It is undefined behavior to read a union member with a different type from the o...

    面向对象思考
  • 计算机网络分层,会不会太多此一举了?

    最近很忙,写技术文章还是很花费时间的。但是,就在前几天出了一篇TCP粘包问题的文章 (TCP粘包,难道说这是一个伪命题???),反映不错。本来计划计算机网络文章...

    龙跃十二
  • gin框架之静态资源服务

    上传成功后,图片的访问地址http://127.0.0.1:8080/upload/2377654-3266b552b19aeb26.png

    大话swift

扫码关注云+社区

领取腾讯云代金券