IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 易事特UPS电源(非标准modbus协议)对接 -> 正文阅读

[嵌入式]易事特UPS电源(非标准modbus协议)对接

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

登录平台: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,创建网关

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

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

createDevice1

  • 填写【设备名称】、选择刚刚创建的【模板驱动】和【通信网关】。参数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_rtu

class info():
    def __init__(self):
        self.broker = '***.***.***.***' #mqtt服务器地址,需要自行填写
        self.port = ***    #mqtt的端口,需要自行填写
        self.topic_airc = "/python/mqtt/ups"
        # generate client ID with pub prefix randomly
        self.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_connect
        client.connect(self.broker, self.port,60)
        return client


    def 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:
                pass

    def 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_data
            data = ''.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 += i

            U101 = int(data2[12: 16]) * 0.1
            U102 = int(data2[16: 20]) * 0.1
            U103 = int(data2[20: 24]) * 0.1
            U104 = int(data2[24: 28]) * 0.1
            U105 = int(data2[28: 32]) * 0.1
            U106 = int(data2[32: 36]) * 0.1
            U107 = int(data2[36: 40]) * 0.1
            U108 = int(data2[40: 44]) * 0.1
            U109 = int(data2[44: 48]) * 0.1
            U110 = int(data2[48: 52]) * 0.1
            U111 = int(data2[52: 56]) * 0.1
            U112 = 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 = 1
            else:
                U123 = 0

            # 逆变状态
            if U104 > 150:
                U124 = 1
            else:
                U124 = 0

            # 旁路输入状态
            if U107 > 150:
                U125 = 1
            else:
                U125 = 0

            # 电池供电状态
            if U101 > 100:
                U126 = 1
            else:
                U126 = 0

            # 整流器状态
            if U125 == 1 and U126 == 0:
                U127 = 1
            else:
                U127 = 0

            # 旁路供电状态
            if U125 == 1 and U110 > 0.1 and U124 == 0:
                U128 = 1
            else:
                U128 = 0

            # 输入C相过压
            if U103 > 250:
                U0113 = 1
            else:
                U0113 = 0

            # 输入C相欠压
            if U103 < 180:
                U0114 = 1
            else:
                U0114 = 0

            # 输入B相过压
            if U102 > 250:
            U0115 = 1
            else:
                U0115 = 0

            # 输入B相欠压
            if U102 < 180:
                U0116 = 1
            else:
                U0116 = 0

            # 输入A相过压
            if U101 > 250:
                U0117 = 1
            else:
                U0117 = 0
    
            # 输入A相欠压
            if U101 < 180:
                U0118 = 1
            else:
                U0118 = 0

            # 旁路C相过压
            if U109 > 250:
                U0123 = 1
            else:
                U0123 = 0

            # 旁路C相欠压
            if U109 < 180:
                U0124 = 1
            else:
                U0124 = 0

            # 旁路B相过压
            if U108 > 250:
                U0125 = 1
            else:
                U0125 = 0

            # 旁路B相欠压
            if U108 < 180:
                U0126 = 1
            else:
                U0126 = 0

            # 旁路A相过压
            if U107 > 250:
                U0127 = 1
            else:
                U0127 = 0

            # 旁路A相欠压
            if U107 < 180:
                U0128 = 1
            else:
                U0128 = 0

            # 逆变C相过压
            if U106 > 250:
                U0133 = 1
            else:
                U0133 = 0

            # 逆变C相欠压
            if U106 < 180:
                U0134 = 1
            else:
                U0134 = 0

            # 逆变B相过压
            if U105 > 250:
                U0135 = 1
            else:
                U0135 = 0

            # 逆变B相过压
            if U105 < 180:
                U0136 = 1
            else:
                U0136 = 0

            # 逆变A相过压
            if U104 > 250:
                U0137 = 1
            else:
                U0137 = 0

            # 逆变A相欠压
            if U104 < 180:
                U0138 = 1
            else:
                U0138 = 0

            data_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_false
        except Exception,e:
            pass


if __name__ == '__main__':
    info = info()
    self = info.run()

  • mqtt的订阅,并将获得的数据上传至中台(驱动文件)
#!coding:utf8
import sys

sys.path.append("..")
from driver import *
import json
import time
import random
import paho.mqtt.client as mqtt

reload(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.payload
        global _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地址,端口以及需要订阅的topic
        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_connect
        self.client.on_message = self.on_message
        self.client.on_subscribe = on_subscribe
        self.client.on_disconnect = on_disconnect
        self.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 _msg
            else:
                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_data
            data = ''.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 += i

            U101 = int(data2[12: 16]) * 0.1
            U102 = int(data2[16: 20]) * 0.1
            U103 = int(data2[20: 24]) * 0.1
            U104 = int(data2[24: 28]) * 0.1
            U105 = int(data2[28: 32]) * 0.1
            U106 = int(data2[32: 36]) * 0.1
            U107 = int(data2[36: 40]) * 0.1
            U108 = int(data2[40: 44]) * 0.1
            U109 = int(data2[44: 48]) * 0.1
            U110 = int(data2[48: 52]) * 0.1
            U111 = int(data2[52: 56]) * 0.1
            U112 = 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 = 1
            else:
                U123 = 0

            # 逆变状态
            if U104 > 150:
                U124 = 1
            else:
                U124 = 0

            # 旁路输入状态
            if U107 > 150:
                U125 = 1
            else:
                U125 = 0

            # 电池供电状态
            if U101 > 100:
                U126 = 1
            else:
                U126 = 0

            # 整流器状态
            if U125 == 1 and U126 == 0:
                U127 = 1
            else:
                U127 = 0

            # 旁路供电状态
            if U125 == 1 and U110 > 0.1 and U124 == 0:
                U128 = 1
            else:
                U128 = 0

            # 输入C相过压
            if U103 > 250:
                U0113 = 1
            else:
                U0113 = 0

            # 输入C相欠压
            if U103 < 180:
                U0114 = 1
            else:
                U0114 = 0

            # 输入B相过压
            if U102 > 250:
            U0115 = 1
            else:
                U0115 = 0

            # 输入B相欠压
            if U102 < 180:
                U0116 = 1
            else:
                U0116 = 0

            # 输入A相过压
            if U101 > 250:
                U0117 = 1
            else:
                U0117 = 0
    
            # 输入A相欠压
            if U101 < 180:
                U0118 = 1
            else:
                U0118 = 0

            # 旁路C相过压
            if U109 > 250:
                U0123 = 1
            else:
                U0123 = 0

            # 旁路C相欠压
            if U109 < 180:
                U0124 = 1
            else:
                U0124 = 0

            # 旁路B相过压
            if U108 > 250:
                U0125 = 1
            else:
                U0125 = 0

            # 旁路B相欠压
            if U108 < 180:
                U0126 = 1
            else:
                U0126 = 0

            # 旁路A相过压
            if U107 > 250:
                U0127 = 1
            else:
                U0127 = 0

            # 旁路A相欠压
            if U107 < 180:
                U0128 = 1
            else:
                U0128 = 0

            # 逆变C相过压
            if U106 > 250:
                U0133 = 1
            else:
                U0133 = 0

            # 逆变C相欠压
            if U106 < 180:
                U0134 = 1
            else:
                U0134 = 0

            # 逆变B相过压
            if U105 > 250:
                U0135 = 1
            else:
                U0135 = 0

            # 逆变B相过压
            if U105 < 180:
                U0136 = 1
            else:
                U0136 = 0

            # 逆变A相过压
            if U104 > 250:
                U0137 = 1
            else:
                U0137 = 0

            # 逆变A相欠压
            if U104 < 180:
                U0138 = 1
            else:
                U0138 = 0

            data_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_false
        except 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 randomly
        self.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_connect
        client.connect(self.broker, self.port,60)
        return client


    def 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发布到对应的topic
                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:
                pass

    def run(self):
        self.client = self.connect_mqtt()
        self.client.loop_start()
        self.publish(self.client)
  • 驱动文件(订阅并将数据上传至中台),首先先导入mqtt和驱动运行的依赖文件
#!coding:utf8
import sys

sys.path.append("..")
from driver import *
import json
import time
import random
import paho.mqtt.client as mqtt

reload(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.payload
        global _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_connect
        self.client.on_message = self.on_message
        self.client.on_subscribe = on_subscribe
        self.client.on_disconnect = on_disconnect
        self.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 _msg
            else:
                return ()
        except Exception as e:
            self.debug('error'+e)

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

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-09-27 14:15:39  更:2021-09-27 14:17:50 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 3:29:36-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码