本文章为原创,转载请注明出处!

登录平台:IOTOS®爱投斯物联中台

账号:iotos_test    密码:iotos123

代码地址:IOTOSDK-Python: IOTOS Python版本SDK,自带原生接口和采集引擎 (gitee.com)

目录

前言

驱动目的

适用范围

使用示例

驱动代码

驱动解析


  • 前言

Modbus协议是应用于电子控制器上的一种通用语言。通过此协议,控制器相互之间、控制器经由网络例如以太网)和其它设备之间可以通信。它已经成为一通用工业标准。有了它,不同厂商生产的控制设备可以连成工业网络,进行集中监控此协议定义了一个控制器能认识使用的消息结构,而不管它们是经过何种网络进行通信的。它描述了一控制器请求访问其它设备的过程,如果回应来自其它设备的请求,以及怎样侦测错误并记录。它制定了消息域格局和内容的公共格式。

Modbus具有两种串行传输模式:分别为ASCII和RTU。Modbus是一种单主站的主从通信模式,Modbus网络上只能有一个主站存在,主站在Modbus网络上没有地址,每个从站必须有唯一的地址,从站的地址范围为0 - 247,其中0为广播地址,从站的实际地址范围为1 - 247。

Modbus RTU通信以主从的方式进行数据传输,在传输的过程中Modbus RTU主站是主动方,即主站发送数据请求报文到从站,Modbus RTU从站返回响应报文。

  • 驱动目的

驱动将以串口连接的易事特UPS电源EA660G3的数据拿到并上云(该型号的UPS电源为非标准的modbus协议)

  • 适用范围

易事特UPS电源EA660G3,以串口连接工控机或电脑

  • 使用示例

  • 首先,将易事特UPS电源的串口连接至工控机或者电脑上:
  • 进入爱投斯中台,账号为iotos_test,密码为iotos123,创建网关

  • 填好网关名称后点击确认

  • 创建设备示例点击【我的设备】 -> 【通信网关】 -> 【设备实例】->【创建设备】

  • 填写【设备名称】、选择刚刚创建的【模板驱动】和【通信网关】。参数topic为mqtt订阅的topic,用来拿去设备的数据,host和port为mqtt服务器的地址和端口号

  • 创建数据点,点击【我的设备】 -> 【通信网关】 -> 【设备实例】 -> 【数据点】,并在【设备实例】下拉列表选择刚刚创建的设备实例

  • 点击右边的创建数据点,填写名称

 并在高级配置中配置数据点的相关标志

第一个点配置"private"属性用于驱动识别表示第一点

其余的点配置point和index,point表示指向哪个点,index表示取第几个数据,下面示例为第二个数据点,这里point填第一个点的oid,index填1,后面的数据点一次,更改index获取不同位的数据即可

  • 在【我的设备】 -> 【通信网关】中找到刚才创建的网关,点击【高级】

  • 开启云网关,密码为账号密码

  • 点击 【我的设备】 -> 【通信网关】 -> 【设备实例】->【数据点】,选择刚才创建的设备实例

  • 即可查看数据已经上报成功

  • 驱动代码

  • 由于UPS电源与工控机或者电脑是串口连接,数据需要上报到线上的中台,但是工控机配置过低无法运行驱动文件,所以中间利用mqtt进行了数据的相关转移,若UPS电源连接的工控机或者电脑可以直接运行驱动则无需利用mqtt进行数据转移,可以直接上传至中台,这里的代码是包含了mqtt服务的。
  • 数据的获取和mqtt的发布(脚本)
# encoding: utf-8
# python 2.7
import random
import time
import threading
from paho.mqtt import client as mqtt_client
import serial
from serial import Serial
import modbus_tk.modbus_rtu as modbus_rtuclass info():def __init__(self):self.broker = '***.***.***.***' #mqtt服务器地址,需要自行填写self.port = ***    #mqtt的端口,需要自行填写self.topic_airc = "/python/mqtt/ups"# generate client ID with pub prefix randomlyself.client_id = 'admin123'def connect_mqtt(self):def on_connect(client, userdata, flags, rc):if rc == 0:print("Connected to MQTT Broker!")else:print("Failed to connect, return code %d\n", rc)client = mqtt_client.Client(self.client_id)client.on_connect = on_connectclient.connect(self.broker, self.port,60)return clientdef publish(self,client):while True:try:time.sleep(3)data_rtu = com_get_info()msg1 = data_rtu.master()msg_1 = "{}".format(msg1)result1 = client.publish(self.topic_airc, msg_1)status1 = result1[0]if status1 == 0:print("Send {} to topic_airc {}".format(msg_1,self.topic_airc))else:print("Failed to send message to topic_airc {}".format(self.topic_airc))except Exception,e:passdef run(self):self.client = self.connect_mqtt()self.client.loop_start()self.publish(self.client)class com_get_info():def master(self):try:ser = serial.Serial("com3", 9600, timeout=0.5)ser.write(b'\xEA\x01\x01\xEA\x01\x81\x00\x82\xEF')pre_data = ser.readline()print pre_datadata = ''.join([hex(ord(c)) for c in pre_data])data1 = data.split('0x')data2 = ''for i in data1:if len(i) == 1:data2 += '0'data2 += iU101 = int(data2[12: 16]) * 0.1U102 = int(data2[16: 20]) * 0.1U103 = int(data2[20: 24]) * 0.1U104 = int(data2[24: 28]) * 0.1U105 = int(data2[28: 32]) * 0.1U106 = int(data2[32: 36]) * 0.1U107 = int(data2[36: 40]) * 0.1U108 = int(data2[40: 44]) * 0.1U109 = int(data2[44: 48]) * 0.1U110 = int(data2[48: 52]) * 0.1U111 = int(data2[52: 56]) * 0.1U112 = int(data2[56: 60]) * 0.1# 输出R相视在功率A = int(data2[84: 87])if int(data2[87]) > 0:U113 = A + 1# 输出S相视在功率B = int(data2[88: 91])if int(data2[91]) > 0:U114 = B + 1# 输出T相视在功率C = int(data2[92: 95])if int(data2[94]) > 0:U115 = C + 1# 1号电池组电压U116 = int(data2[60: 64]) * 0.1# 2号电池组电压U117 = int(data2[64: 68]) * 0.1# 逆变输出频率U120 = int(data2[76: 80]) * 0.1# 主输入状态if U101 > 150:U123 = 1else:U123 = 0# 逆变状态if U104 > 150:U124 = 1else:U124 = 0# 旁路输入状态if U107 > 150:U125 = 1else:U125 = 0# 电池供电状态if U101 > 100:U126 = 1else:U126 = 0# 整流器状态if U125 == 1 and U126 == 0:U127 = 1else:U127 = 0# 旁路供电状态if U125 == 1 and U110 > 0.1 and U124 == 0:U128 = 1else:U128 = 0# 输入C相过压if U103 > 250:U0113 = 1else:U0113 = 0# 输入C相欠压if U103 < 180:U0114 = 1else:U0114 = 0# 输入B相过压if U102 > 250:U0115 = 1else:U0115 = 0# 输入B相欠压if U102 < 180:U0116 = 1else:U0116 = 0# 输入A相过压if U101 > 250:U0117 = 1else:U0117 = 0# 输入A相欠压if U101 < 180:U0118 = 1else:U0118 = 0# 旁路C相过压if U109 > 250:U0123 = 1else:U0123 = 0# 旁路C相欠压if U109 < 180:U0124 = 1else:U0124 = 0# 旁路B相过压if U108 > 250:U0125 = 1else:U0125 = 0# 旁路B相欠压if U108 < 180:U0126 = 1else:U0126 = 0# 旁路A相过压if U107 > 250:U0127 = 1else:U0127 = 0# 旁路A相欠压if U107 < 180:U0128 = 1else:U0128 = 0# 逆变C相过压if U106 > 250:U0133 = 1else:U0133 = 0# 逆变C相欠压if U106 < 180:U0134 = 1else:U0134 = 0# 逆变B相过压if U105 > 250:U0135 = 1else:U0135 = 0# 逆变B相过压if U105 < 180:U0136 = 1else:U0136 = 0# 逆变A相过压if U104 > 250:U0137 = 1else:U0137 = 0# 逆变A相欠压if U104 < 180:U0138 = 1else:U0138 = 0data_code_false = (U101, U102, U103, U104, U105, U106, U107, U108, U109, U110, U111, U112, A, B, C, U116, U117, U120, U123, U124, U125, U126, U127, U128, U0113, U0114, U0115, U0116, U0117, U0118, U0123, U0124, U0125, U0126, U0127, U0128, U0133, U0134, U0135, U0136, U0137, U0138,)print len(data_code_false)return data_code_falseexcept Exception,e:passif __name__ == '__main__':info = info()self = info.run()
  • mqtt的订阅,并将获得的数据上传至中台(驱动文件)
#!coding:utf8
import syssys.path.append("..")
from driver import *
import json
import time
import random
import paho.mqtt.client as mqttreload(sys)
sys.setdefaultencoding('utf8')def on_subscribe(client, userdata, mid, granted_qos):print("On Subscribed: qos = %d" % granted_qos)def on_disconnect(client, userdata, rc):if rc != 0:print("Unexpected disconnection %s" % rc)_msg=''
class XyDriver(IOTOSDriverI):def on_connect(self,client, userdata, flags, rc):print("Connected with result code " + str(rc))client.subscribe(self._topic)  # 订阅消息def on_message(self, client, userdata, msg):self.debug(msg.topic + " " + str(msg.qos) + " " + str(msg.payload))# a = msg.payloadglobal _msg_msg=tuple(eval(msg.payload))self.debug('data is collected')self.debug(_msg)def InitComm(self, attrs):self.online(True)self.setPauseCollect(False)self.setCollectingOneCircle(False)#获取中台填写的mqtt地址,端口以及需要订阅的topicself._topic = self.sysAttrs['config']['param']['topic']self._host = self.sysAttrs['config']['param']['host']self._port = self.sysAttrs['config']['param']['port']self.client=mqtt.Client()self.client.on_connect = self.on_connectself.client.on_message = self.on_messageself.client.on_subscribe = on_subscribeself.client.on_disconnect = on_disconnectself.client.username_pw_set(username='', password='')# 连接到服务器self.client.connect(host=self._host.encode('utf-8'), port=self._port, keepalive=60)self.client.loop_start()def Collecting(self, dataId):try:# self.debug('111111111111111111111111111')self.client.on_message=self.on_message# self.debug('22222222222222222222222222')self.debug(_msg)if 'private' in self.data2attrs[dataId]['config']['param'] and self.data2attrs[dataId]['config']['param']['private']=='first_point':if type(_msg)==tuple:return _msgelse:return ()except Exception as e:self.debug('error'+e)
  • 驱动解析

  • 编写环境为python2(python3也可以),首先需要导入modbus_tk和paho.mqtt等、数据解析和modbus通讯的相关包
# encoding: utf-8
# python 3.6
import random
import time
import threading
from paho.mqtt import client as mqtt_client
import serial
from serial import Serial
import modbus_tk.modbus_rtu as modbus_rtu
  • 利用modbus_tk里面的modbus_rtu打开服务器的串口并向其发送指令,其中serialObjTmp = serial.Serial(port='com11', baudrate=9600, timeout=0.5)中port表示串口号,baudrate表示波特率,timeout表示超时时间。打开串口后利用ser.write(b'\xEA\x01\x01\xEA\x01\x81\x00\x82\xEF')向串口发送数据,需要发送十六进制的bytes类型。读取数据后进行数据的处理
class com_get_info():def master(self):try:ser = serial.Serial("com3", 9600, timeout=0.5)ser.write(b'\xEA\x01\x01\xEA\x01\x81\x00\x82\xEF')pre_data = ser.readline()print pre_datadata = ''.join([hex(ord(c)) for c in pre_data])data1 = data.split('0x')data2 = ''for i in data1:if len(i) == 1:data2 += '0'data2 += iU101 = int(data2[12: 16]) * 0.1U102 = int(data2[16: 20]) * 0.1U103 = int(data2[20: 24]) * 0.1U104 = int(data2[24: 28]) * 0.1U105 = int(data2[28: 32]) * 0.1U106 = int(data2[32: 36]) * 0.1U107 = int(data2[36: 40]) * 0.1U108 = int(data2[40: 44]) * 0.1U109 = int(data2[44: 48]) * 0.1U110 = int(data2[48: 52]) * 0.1U111 = int(data2[52: 56]) * 0.1U112 = int(data2[56: 60]) * 0.1# 输出R相视在功率A = int(data2[84: 87])if int(data2[87]) > 0:U113 = A + 1# 输出S相视在功率B = int(data2[88: 91])if int(data2[91]) > 0:U114 = B + 1# 输出T相视在功率C = int(data2[92: 95])if int(data2[94]) > 0:U115 = C + 1# 1号电池组电压U116 = int(data2[60: 64]) * 0.1# 2号电池组电压U117 = int(data2[64: 68]) * 0.1# 逆变输出频率U120 = int(data2[76: 80]) * 0.1# 主输入状态if U101 > 150:U123 = 1else:U123 = 0# 逆变状态if U104 > 150:U124 = 1else:U124 = 0# 旁路输入状态if U107 > 150:U125 = 1else:U125 = 0# 电池供电状态if U101 > 100:U126 = 1else:U126 = 0# 整流器状态if U125 == 1 and U126 == 0:U127 = 1else:U127 = 0# 旁路供电状态if U125 == 1 and U110 > 0.1 and U124 == 0:U128 = 1else:U128 = 0# 输入C相过压if U103 > 250:U0113 = 1else:U0113 = 0# 输入C相欠压if U103 < 180:U0114 = 1else:U0114 = 0# 输入B相过压if U102 > 250:U0115 = 1else:U0115 = 0# 输入B相欠压if U102 < 180:U0116 = 1else:U0116 = 0# 输入A相过压if U101 > 250:U0117 = 1else:U0117 = 0# 输入A相欠压if U101 < 180:U0118 = 1else:U0118 = 0# 旁路C相过压if U109 > 250:U0123 = 1else:U0123 = 0# 旁路C相欠压if U109 < 180:U0124 = 1else:U0124 = 0# 旁路B相过压if U108 > 250:U0125 = 1else:U0125 = 0# 旁路B相欠压if U108 < 180:U0126 = 1else:U0126 = 0# 旁路A相过压if U107 > 250:U0127 = 1else:U0127 = 0# 旁路A相欠压if U107 < 180:U0128 = 1else:U0128 = 0# 逆变C相过压if U106 > 250:U0133 = 1else:U0133 = 0# 逆变C相欠压if U106 < 180:U0134 = 1else:U0134 = 0# 逆变B相过压if U105 > 250:U0135 = 1else:U0135 = 0# 逆变B相过压if U105 < 180:U0136 = 1else:U0136 = 0# 逆变A相过压if U104 > 250:U0137 = 1else:U0137 = 0# 逆变A相欠压if U104 < 180:U0138 = 1else:U0138 = 0data_code_false = (U101, U102, U103, U104, U105, U106, U107, U108, U109, U110, U111, U112, A, B, C, U116, U117, U120, U123, U124, U125, U126, U127, U128, U0113, U0114, U0115, U0116, U0117, U0118, U0123, U0124, U0125, U0126, U0127, U0128, U0133, U0134, U0135, U0136, U0137, U0138,)print len(data_code_false)return data_code_falseexcept Exception,e:pass
  • 读取数据并处理后返回,利用mqtt将其发布到对应的topic
class info():def __init__(self):self.broker = '***.***.***.***' #mqtt服务器地址,需要自行填写self.port = ***    #mqtt的端口,需要自行填写self.topic_airc = "/python/mqtt/ups"   #准备发布到mqtt的topic# generate client ID with pub prefix randomlyself.client_id = 'admin123'def connect_mqtt(self):def on_connect(client, userdata, flags, rc):if rc == 0:print("Connected to MQTT Broker!")else:print("Failed to connect, return code %d\n", rc)client = mqtt_client.Client(self.client_id)client.on_connect = on_connectclient.connect(self.broker, self.port,60)return clientdef publish(self,client):while True:try:time.sleep(3)#com_get_info()函数获取从串口拿到的数据data_rtu = com_get_info()msg1 = data_rtu.master()msg_1 = "{}".format(msg1)#将msg1发布到对应的topicresult1 = client.publish(self.topic_airc, msg_1)status1 = result1[0]if status1 == 0:print("Send {} to topic_airc {}".format(msg_1,self.topic_airc))else:print("Failed to send message to topic_airc {}".format(self.topic_airc))except Exception,e:passdef run(self):self.client = self.connect_mqtt()self.client.loop_start()self.publish(self.client)
  • 驱动文件(订阅并将数据上传至中台),首先先导入mqtt和驱动运行的依赖文件
#!coding:utf8
import syssys.path.append("..")
from driver import *
import json
import time
import random
import paho.mqtt.client as mqttreload(sys)
sys.setdefaultencoding('utf8')
  • 初始化mqtt和驱动,获取中台上设备示例的配置并且连接至mqtt
def on_subscribe(client, userdata, mid, granted_qos):print("On Subscribed: qos = %d" % granted_qos)def on_disconnect(client, userdata, rc):if rc != 0:print("Unexpected disconnection %s" % rc)_msg=''
class XyDriver(IOTOSDriverI):def on_connect(self,client, userdata, flags, rc):print("Connected with result code " + str(rc))client.subscribe(self._topic)  # 订阅消息def on_message(self, client, userdata, msg):self.debug(msg.topic + " " + str(msg.qos) + " " + str(msg.payload))# a = msg.payloadglobal _msg_msg=tuple(eval(msg.payload))self.debug('data is collected')self.debug(_msg)def InitComm(self, attrs):self.online(True)self.setPauseCollect(False)self.setCollectingOneCircle(False)self._topic = self.sysAttrs['config']['param']['topic']self._host = self.sysAttrs['config']['param']['host']self._port = self.sysAttrs['config']['param']['port']self.client=mqtt.Client()self.client.on_connect = self.on_connectself.client.on_message = self.on_messageself.client.on_subscribe = on_subscribeself.client.on_disconnect = on_disconnectself.client.username_pw_set(username='', password='')# 连接到服务器self.client.connect(host=self._host.encode('utf-8'), port=self._port, keepalive=60)self.client.loop_start()
  • 循环采集订阅拿到的数据并且上传至中台
def Collecting(self, dataId):try:# self.debug('111111111111111111111111111')self.client.on_message=self.on_message# self.debug('22222222222222222222222222')self.debug(_msg)#只采集第一个点并将订阅得到的数据返回if 'private' in self.data2attrs[dataId]['config']['param'] and self.data2attrs[dataId]['config']['param']['private']=='first_point':if type(_msg)==tuple:return _msgelse:return ()except Exception as e:self.debug('error'+e)

至此,易事特UPS电源驱动的开发完成,即可实现精密空调的数据上云

IOTOS物联中台非标modbus驱动对接易事特UPS电源设备相关推荐

  1. IOTOS物联中台modbus驱动对接雅达电表设备

    本文章为原创,转载请注明出处! 登录平台:IOTOS®爱投斯物联中台 账号:iotos_test    密码:iotos123 代码地址:IOTOSDK-Python: IOTOS Python版本S ...

  2. IOTOS物联中台modbus驱动对接科士达精密空调设备

    本文章为原创,转载请注明出处! 登录平台:IOTOS®爱投斯物联中台 账号:iotos_test    密码:iotos123 代码地址:IOTOSDK-Python: IOTOS Python版本S ...

  3. IOTOS物联中台从0到1开发modbus_rtu驱动 实例详解

    本文章为原创,转载请注明出处! 登录平台:IOTOS®爱投斯物联中台 账号:iotos_test    密码:iotos123 代码地址:IOTOSDK-Python: IOTOS Python版本S ...

  4. IOTOS物联中台Bacnet驱动开发实例

    本文章为原创,转载请注明出处! 登录平台:IOTOS®爱投斯物联中台 账号:iotos_test    密码:iotos123 代码地址:IOTOSDK-Python: IOTOS Python版本S ...

  5. IOTOS物联中台开发驱动支持NB-IoT光电感烟火灾探测报警器设备

    本文章为原创,转载请注明出处! 登录平台:IOTOS®爱投斯物联中台 账号:iotos_test    密码:iotos123 代码地址:IOTOSDK-Python: IOTOS Python版本S ...

  6. IOTOS物联中台开发驱动支持中安易科智能门锁API 详解

    本文章为原创,转载请注明出处! 登录平台:IOTOS®爱投斯物联中台 账号:iotos_test    密码:iotos123 代码地址:IOTOSDK-Python: IOTOS Python版本S ...

  7. IOTOS物联中台Modbus_Tcp驱动对接Wheelers控制器设备

    目录 前言 驱动目的 适用范围 使用示例 驱动源码 驱动解析 前言 Modbus协议是一种已广泛应用于当今工业控制领域的通用通讯协议.通过此协议,控制器相互之间.或控制器经由网络(如以太网)可以和其它 ...

  8. 【杰神说说】物联大师2.0版本预告

    我的开源项目 物联大师,正式版本已经发行3个多月,获得了不少人关注,已经有多家公司在尝试和使用. 为了能够满足更多用户的需求,我们决定对物联大师进行一次重要升级,推出2.0版本,在自动控制和可视化功能 ...

  9. 玩游戏延迟高?太卡?对于物联卡你可能真的不了解!

    玩游戏延迟高?太卡?对于物联卡你可能真的不了解 随着各种APP的出现,有事没事看看新闻,刷刷抖音,流量快的一批,俗话说,哪里有需求,哪里就有市场,这时候大部分自然而然的就想到了各种流量卡,在种类繁多的 ...

最新文章

  1. 春天闻香食花——品尝一顿愉悦的花餐
  2. Event ID 5553 failure trying to synch sitexxxx for ContentDB xx WebApp xx. Exception message ...
  3. POJ2352 stars(树状数组)
  4. hal库开启中断关中断_stm32的HAL库开发学习笔记之外部中断
  5. java 泛型参数的类型_Java获得泛型参数类型
  6. 和搜狗输入法快捷键冲突_这款输入法被调教多年不输搜狗,爱了奥里给!
  7. springboot接收json参数_Springboot + Vue + shiro 实现前后端分离、权限控制
  8. 怎么让车辆gps定位失效_如何更有效地检测车辆gps定位器?
  9. Android必学之数据适配器BaseAdapter
  10. Jenkins 新版本及插件在Windows下的安装
  11. 【jQuery学习】—jQuery操作元素位置
  12. 红皮书--SQL语句
  13. vue iview组件表格 render函数的使用
  14. 《Effective Java 3rd》读书笔记——泛型
  15. 老外网络语言缩写总结
  16. android 视频预览,预览视频  |  Android 开发者  |  Android Developers
  17. c语言实现计算函数在某点的导数近似值
  18. mysql查找附近算法_附近地点搜索解决方案
  19. 为什么postgresql最大的单表只能是32TB
  20. 注意!吃蔬菜也有误区

热门文章

  1. JSP汽车维修服务管理系统myeclipse开发SqlServer数据库bs框架java编程web网页结构
  2. 安卓SlideMenu 仿QQ 主页侧滑菜单
  3. 有哪些可以投稿软件工程/系统软件/程序设计语言类外文期刊、会议?
  4. Java项目:台球室计费管理系统(java+SSM+JSP+HTML+JavaScript+mysql)
  5. 特朗普:美国尚未与中国就中兴事宜达成任何协议
  6. 壹药网科创板IPO辅导进度更新:公司名称发生变更,有高管已离职
  7. 工作中必备技能---思维导图你会吗???给我10分钟让你精通思维导图!!!
  8. 在读书郎G90s版本安装微信
  9. (持续学习)世界上最神奇的24堂课-----第二课 思维就是能量
  10. 【已解决】启动Python报错api-ms-win-crt-process-l1-1-0.dll缺失,windows7无法升级,升级补丁打不上的解决办法