进入配置界面->设备配置->系统配置,在对话框中添加驱动。
其中驱动名称为用户自定义的英文驱动名。
或者在数据库eview.db中t_device_driver表增加一条记录,id自动生成(这里为:200001),name和modulename为xxxxdrv。
添加驱动配置后,可在设备中增加该驱动的一个设备.
在数据库t_device_list表中增加一条记录,id自动生成(这里为113),name为:xxxxdevice,driver_id:200001,conntype:tcpclient,connparam:ip=127.0.0.1;port=502;
添加设备配置后,可在设备中增加一个变量.
在数据库t_device_tag表中增加一条记录,id自动生成,name为:pytag2,device_id:113,address:AI:10;datatype:int16;pollrateMS:1000
驱动配置部署后,eview会自动启动你的驱动程序。调试前需要先关闭你的驱动程序,因为系统仅仅允许启动你的一个驱动进程,停止驱动的方法如下:任务管理器杀掉该驱动。
直接点击xxxxdrv.exe启动驱动。或者通过pkservermgr自动启动所有程序包括驱动。
驱动框架实现的主要功能如下:
代表每个变量,在pkDevice的vecTags中包含了所有该设备的tag点对象,可以用的属性如下:
name, 变量名称
address,变量地址
datatype,数据类型,整数
pollrate,轮训速度,整数
lenbits,占用长度,单位:bit
代表每个配置的设备,可以用的属性如下:
name, 设备名称
desc,设备描述
conntype,通讯连接类型,tcpclient,udp,tcpserver,other,serial
conntimeout,通讯连接超时时间
recvtimeout,接收超时时间
connparam,通讯连接参数内容,如ip=192.168.10.2;port=502
param1,设备参数1
param2,设备参数2
param3,设备参数3
param4,设备参数4
tags, 保存有tag点的各个名字的List
driver,设备对应driver对象,具体见下面
代表每个配置的设备驱动信息,可以用的属性如下:
name, 驱动名称
desc,驱动描述
param1,设备参数1
param2,设备参数2
param3,设备参数3
param4,设备参数4
示例代码(必须如下头部定义):
#! /usr/bin/python
# coding=utf-8
import sys
import struct
import os
sys.path.append(os.path.abspath('.') + '\\..\\..')
sys.path.append(os.path.abspath('.') + '\\..\\..\\python')
import pydriver
def InitDriver(pkDriver):
print "----InitDriver----"
print(pkDriver)
return 0
def UnInitDriver(pkDriver):
print "----UnInitDriver----"
print(pkDriver)
return 0
def InitDevice(pkDevice):
print "----InitDevice----"
print(pkDevice)
tags=[]
for tag in pkDevice['tags']:
tags.append(tag)
timerObj=pydriver.CreateTimer(pkDevice, 3000, tags)
return 0
def UnInitDevice(pkDevice):
print "UnInitDevice"
return 0
def OnTimer(pkDevice, timerObj, pkTimerParam):
print "----OnTimer----"
tags = pkTimerParam
print timerObj
print tags
id = 1
tag="100"
version = 2
count = 3
buffer = struct.pack("!H4s2I", id, tag, version, count)
print "before send..."
result = pydriver.Send(pkDevice, buffer, 2000)
print "SendToDevice:",result
if(result <= 0):
print "send to device return <-0"
print "send to device:", len(buffer) , "return :" , result
return
retCode, bufferRecv = pydriver.Recv(pkDevice, 10000, 200)
print "Recv,retcode:", retCode, ",length:",len(bufferRecv)
if(retCode != 0):
return
# 解析数据,得到值
tagValue =struct.unpack("!H", bufferRecv)
print "recv tagValue:",tagValue[0]
#print "recv,id:",id,",tag:",tag,",version:",version,",count:",count
tagAddr = "AI:10"
print tagAddr
tagList = pydriver.GetTagsByAddr(pkDevice, tagAddr)
pydriver.SetTagsValue(pkDevice,tagList, str(tagValue[0]))
pydriver.UpdateTagsData(pkDevice, tagList)
print "-OnTimer- end"
return 0
def OnControl(pkDevice, pkTag, strTagValue):
print "-!--OnControl--!-"
print pkDevice,pkTag
print "device name:",pkDevice['name'], "tagname:", pkTag['name'], "tagaddress:",pkTag['address'], "tagvalue:",strTagValue
return 0
#仅供调试使用,可以直接运行这个python文件进行调试
if __name__ == '__main__':
pkDriver={'name': '', '_InternalRef': 0, 'param4': '', 'param3': '', 'param2': '', 'param1': '', 'type': '', 'desc': ''}
pkDevice={'recvtimeout': 500, 'name': 'pytestdevice', 'tags': [{'_ctag': 7981384, 'name': 'CELL06_BLD1', 'lenbits': 16, 'datatype': 'uint16', 'address': 'AI:17023', 'pollrate': 3000}, {'_ctag': 7983144, 'name': 'CELL06_BLD2', 'lenbits': 16, 'datatype': 'uint16', 'address': 'AI:17023', 'pollrate': 3000}, {'_ctag': 7984904, 'name': 'CELL06_OKjishu', 'lenbits': 16, 'datatype': 'uint16', 'address': 'AI:17007', 'pollrate': 3000}, {'_ctag': 7986664, 'name': 'CELL06_NGjishu', 'lenbits': 16, 'datatype': 'uint16', 'address': 'AI:17036', 'pollrate': 3000}], '_InternalRef': 7947760, 'driver': {'name': '', '_InternalRef': 0, 'param4': '', 'param3': '', 'param2': '', 'param1': '', 'type': '', 'desc': ''}, 'conntype': 'tcpclient', 'param4': '', 'param3': '', 'param2': '', 'param1': '', 'conntimeout': 3000, 'connparam': 'ip=127.0.0.1;port=502', 'desc': ''}
InitDriver(pkDriver)
InitDevice(pkDevice)
主要有以下函数要实现:
def InitDriver(pkDriver):
print "----InitDriver----"
return 0
参数说明:驱动结构体
功能说明:初始化函数,驱动EXE启动时该函数被调用,可在该函数中实现用户自定义初始化操作(例如使用com接口时调用com初始化函数)。
注意:如无特别需要,可以不实现。
def UnInitDriver(pkDriver):
print "----UnInitDriver----"
return 0
参数说明:无
返回值:返回0代表成功,其余值为失败
功能:驱动退出时该函数被调用。在该函数中可以释放用户自定义资源、对于非TCP连接设备断开设备连接等操作。
注意:如无特别需要,可以不实现。
def InitDevice(pkDevice):
print "----InitDevice----"
pydriver.CreateTimer(pkDevice, 3000, '11aabb')
return 0
参数说明:设备结构体
功能说明:每个设备配置被加载后会调用该初始化函数,可在该函数中实现用户自定义的具体设备相关初始化操作。常用操作包括:创建定时器、自组块等。
注意:必须实现开启定时器的功能,否则无法执行OnTimer函数。
def UnInitDevice(pkDevice):
print "UnInitDevice"
return 0
参数说明:无
返回值:返回0代表成功,其余值为失败
功能:驱动退出时该函数被调用。在该函数中可以释放用户自定义资源、对于非TCP连接设备断开设备连接等操作。
注意:可以不实现。
def OnTimer(pkDevice, timerHandle,periodMS, pkTimerParam):
print "----OnTimer----"
参数说明:
pkDevice[输入参数]:设备句柄
timerHandle[输入参数]:定时器周期句柄
periodMS [输入参数]:定时器周期句柄
pkTimerParam[输入参数]:定时器周期句柄
返回值:返回0代表成功,其余值为失败
功能说明:该函数会在InitDevice时创建一定周期的定时器(CreateTimer(pDevice,periodMS,timeParam))后自动被调用。对于块设备,轮询周期往往是指块的轮询周期。对于一次读取所有状态的设备,轮询周期是指设备的轮询周期。通常该函数实现如下功能:
1、数据的发送和接收
2、更新变量实时数据的值、数据状态和时间戳
3、对于非tcp通信协议,通常需要在该接口检查连接状态
注意:该函数必须实现
def OnControl(pkDevice, tagName, tagValue):
print "OnControl"
return 0
参数说明:
pkDevice [输入参数]:设备指针
tagName [输入参数]:变量名称
tagValue [输入参数]:用字符串表示的变量值(如数字16这里传入”16”)
返回值:控制返回结果
功能说明:当有控制命令时该函数被调用,通过该函数向设备下发控制命令
注意:对于需要通过驱动实现控制功能的,该函数必须实现
pydriver.GetTagsByAddr(pkDevice, strTagAddr)
参数说明:
pkDevice [输入参数]:设备对象
strTagAddr[输入参数]:字符串类型的变量地址,如”AI:10”
返回值:返回该设备地址位strTagAddr的List
pydriver.SetTagsValue(pkDevice,tagList, strTagValue)
参数说明:
pkDevice [输入参数]:设备对象
tagList[输入参数]:变量列表,可能是pydriver.GetTagsByAddr返回的值
strTagValue[输入参数]:字符串类型的变量值,如”1000”
返回值:返回0表示成功
pydriver.UpdateTagsData(pkDevice, tagList)
pkDevice [输入参数]:设备对象
tagList[输入参数]:变量列表,可能是pkdriver.SetTagsValue之后的变量列表
返回值:返回0表示成功
pydriver.CreateTimer(pkDevice, periodMS, timerParam)
pkDevice [输入参数]:设备对象
periodMS[输入参数]:数值类型的定时周期,单位:毫秒。如:3000表示3秒
timerParam[输入参数]:自定义的定时器参数,可以是字符串、对象、数值等任意类型,在OnTimer中可以获取到这个参数
返回值:返回定时器句柄(int型)
pydriver.DestroyTimer(pkDevice,timerHandle);
pkDevice [输入参数]:设备对象
timerHandle[输入参数]:CreateTimer返回的定时器句柄
返回值:返回0表示成功
pydriver.Recv(pkDevice, maxBytes, recvTimeOutMS)
功能说明:当用户使用TCP、串口、UDP连接时可调用该接口接收设备数据
pkDevice [输入参数]:设备对象
maxBytes[输入参数]:该次接收最多接收的字符字节数
recvTimeOutMS[输入参数]:接收超时时间,单位是毫秒
返回值:二元元组(retcode, buffer)。这里的buffer必须用struct.unpack去解析。如:
retCode, bufferRecv = pydriver.Recv(pkDevice, 102400, 200)
pydriver.Send(pkDevice, buffer, sendTimeOutMS)
功能说明:当用户使用TCP、串口、UDP连接时可调用该接口发送数据到设备
参数说明:当前支持TCP作为客户端、服务端、UDP、串口的连接方式。
pkDevice [输入参数]:设备对象
buffer[输入参数]:待发送数据的缓冲区,二进制缓冲区,通过struct.pack 方法返回的二进制缓冲区。len(buffer)可以得到长度
sendTimeOutMS [输入参数]:发送超时时间,单位是毫秒
返回值:返回成功发送的字节数
参考:https://blog.csdn.net/w83761456/article/details/21171085
比如,存取文件,socket操作时.这时候,可以使用python的struct模块来完成.可以用 struct来处理c语言中的结构体.
struct模块中最重要的三个函数是pack(), unpack(), calcsize()
# 按照给定的格式(fmt),把数据封装成字符串(实际上是类似于c结构体的字节流)
pack(fmt, v1, v2, ...)
# 按照给定的格式(fmt)解析字节流string,返回解析出来的tuple
unpack(fmt, string)
# 计算给定的格式(fmt)占用多少字节的内存
calcsize(fmt)
参考:https://blog.csdn.net/w83761456/article/details/21171085
Result=1000
print("SendToDevice:",result)