本文章为原创,转载请注明出处!
账号:iotos_test 密码:iotos123
代码地址:IOTOSDK-Python: IOTOS Python版本SDK,自带原生接口和采集引擎 (gitee.com)
目录
-
前言
精华隆周界可以连接多个设备并进行监控,作为主机,可以通过TCP/IP将数据包转发出来。
-
驱动目的
驱动将精华隆周界的数据解析并上传至中台以便于更好的进行可视化展示
-
适用范围
精华隆周界
-
使用示例
- 首先,连接好精华隆周界主机,在其下绑定相应的设备:
- 进入爱投斯中台,账号为iotos_test,密码为iotos123,创建网关
- 填好网关名称后点击确认
- 依次点击【系统设备】->【模板驱动】->【我的模板】,点击右上角创建模板。 填写模板名称和相关的参数,其中tcp为中台需要打开的端口,与精华隆主机的配置保持一致
- 创建设备实例,点击【系统设备】 -> 【通信网关】 -> 【设备实例】->【创建设备】
- 填写设备名称,选择刚才创建的网关和模板即可(检查一下驱动根配置的“driver”参数,若在创建模板时已按要求配置,则现在无需修改,否则则需要在此进行配置,配置标准见创建模板)。
- 创建数据点,点击【我的设备】 -> 【通信网关】 -> 【设备实例】 -> 【数据点】,并在【设备实例】下拉列表选择刚刚创建的设备实例
- 删除系统自带的四个数据点,然后点击右边的创建数据点,填写名称,名称为周界主机下面的设备的ID
- 开启云网关,密码为账号密码
- 在精华隆主机的操作界面配置数据转发的端口并且打开对外协议,url为中台的地址,端口号与中台tcp参数的值保持一致
- 点击 【我的设备】 -> 【通信网关】 -> 【设备实例】->【数据点】,选择刚才创建的设备实例
- 即可查看数据已经上报成功
在报警主机中进行布撤防,中台的数据也会发生相应的变化,报警状态也可以进行同步,放置物联组态上还可以做到报警提示或者其他联动效果
-
驱动代码
#!coding:utf8
import sys
import json
import base64
from Crypto.Cipher import AES
sys.path.append("..")
reload(sys)
sys.setdefaultencoding('gbk')
from driver import *
from jcomm import *
import threading
#打印日志
import logging
logger = logging.getLogger()
logging.basicConfig(level=logging.ERROR,
format='%(asctime)s %(threadName)s %(levelname)s %(filename)s:%(lineno)d %(funcName)s %(message)s')
logger.setLevel(logging.ERROR & logging.INFO)
#except,防止socket报error: [Errno 104] Connection reset by peer
from socket import error as SocketError
import errno
#AES的加解密类
class EncryptDate:
def __init__(self, rec_data):
self.key = self.create_key(rec_data) # 初始化密钥
self.length = AES.block_size # 初始化数据块大小
self.aes = AES.new(self.key, AES.MODE_ECB) # 初始化AES,ECB模式的实例
# 截断函数,去除填充的字符
self.unpad = lambda rec_data: rec_data[0:-ord(rec_data[-1])]
#根据传过来的数据 取出hostid 产生用于AES加密的密钥key
@staticmethod
def create_key(res):
newkey = ''
# print len(str(res['hostId']))
if len(str(res['hostId'])) != 12:
for i in range(0, (12 - len(str(res['hostId'])))):
newkey = newkey + '0'
newkey = newkey + str(res['hostId'])
else:
newkey = str(res['hostId'])
newkey = newkey + str(res['hostId'] + 12345)[-4:]
#logging.info (newkey)
return newkey
def pad(self, text):
"""
#填充函数,使被加密数据的字节码长度是block_size的整数倍
"""
count = len(text.encode('utf-8'))
add = self.length - (count % self.length)
entext = text + (chr(add) * add)
return entext
def encrypt(self, encrData): # 加密函数
res = self.aes.encrypt(self.pad(encrData).encode("utf8"))
msg = str(base64.b64encode(res))
return msg
def decrypt(self, decrData): # 解密函数
res = base64.decodestring(decrData.encode("utf8"))
msg = self.aes.decrypt(res).decode("utf8")
return self.unpad(msg)
"""
定义线程,防止在collecting里面两组数据上传时数据过慢
"""
#8023第一次的数据
class Set8023firstDataThreading(threading.Thread,JLib):
def __init__(self, driver):
threading.Thread.__init__(self)
JLib.__init__(self)
self.driver = driver
def run(self):
logging.info(u'8023 first data setvalue')
# logging.info(getattr(self.driver, __8023firstData))
# logging.info(self.driver._Alarm__8023firstData)
self.driver.__8023firstdataDict = eval(self.driver._Alarm__8023firstData)
data8023SetList = self.driver.__8023firstdataDict['deviceList']
for i in data8023SetList:
# 排除温湿度的设备
if str(i["deviceId"]).find('10007') != -1 or str(i["deviceId"]).find('10025') != -1:
continue
else:
try:
# logger.info(i["deviceName"].decode('utf-8'))
self.driver.setValue(unicode(str(i["deviceId"]), "utf-8"), (
i["deviceName"] + ',' + self.driver._Alarm__deviceStatus[i["deviceStatus"]] + ',' +
self.driver._Alarm__alarmStatus[i["armingStatus"]]))
except Exception as e:
if "deviceName" not in i:
self.driver.setValue(unicode(str(i["deviceId"]), "utf-8"), (
'未知' + ',' + self.driver._Alarm__deviceStatus[i["deviceStatus"]] + ',' +
self.driver._Alarm__alarmStatus[i["armingStatus"]]))
logging.info(str(i["deviceId"]))
continue
#8023第二次的数据
class Set8023DataThreading(threading.Thread,JLib):
def __init__(self, driver):
threading.Thread.__init__(self)
JLib.__init__(self)
self.driver = driver
def run(self):
logging.info(u'8023 data setvalue')
self.driver.__8023dataDict = eval(self.driver._Alarm__8023data)
data8023SetList = self.driver.__8023dataDict['deviceList']
for i in data8023SetList:
# 排除温湿度的设备
if str(i["deviceId"]).find('10007') != -1 or str(i["deviceId"]).find('10025') != -1:
continue
else:
try:
# logger.info(i["deviceName"].decode('utf-8'))
self.driver.setValue(unicode(str(i["deviceId"]), "utf-8"), (
i["deviceName"] + ',' + self.driver._Alarm__deviceStatus[i["deviceStatus"]] + ',' +
self.driver._Alarm__alarmStatus[i["armingStatus"]]))
except Exception as e:
if "deviceName" not in i:
self.driver.setValue(unicode(str(i["deviceId"]), "utf-8"), (
'未知' + ',' + self.driver._Alarm__deviceStatus[i["deviceStatus"]] + ',' +
self.driver._Alarm__alarmStatus[i["armingStatus"]]))
logging.info(str(i["deviceId"]))
continue
#8130的数据上传线程
class Set8130DataThreading(threading.Thread,JLib):
def __init__(self, driver):
threading.Thread.__init__(self)
JLib.__init__(self)
self.driver = driver
def run(self):
logging.info(u'8130 data setvalue')
self.driver.__8130dataDict = eval(self.driver._Alarm__8130data.replace('null', '""'))
data8130SetList = self.driver.__8130dataDict['data']
for i in data8130SetList:
# logging.info(unicode(str(i["deviceId"]), "utf-8"))
# logging.info(type(i["param"]["temperature"]))
try:
self.driver.setValue(unicode(str(i["deviceId"]), "utf-8"),
((i["deviceName"] + ',' + i["param"]["humidity"] + ',' + str(
int(i["param"]["temperature"]) * 0.01)) + ',' + self.driver._Alarm__deviceStatus[
i['deviceStatus']]))
except Exception as e:
#一些温湿度没有上线,没有param参数。
if i["param"]== "":
self.driver.setValue(unicode(str(i["deviceId"]), "utf-8"),
(i["deviceName"] + ',' + '' + ',' + '' + ',' +
self.driver._Alarm__deviceStatus[
i['deviceStatus']]))
else:
logging.info(e.message)
logging.info(str(i["deviceId"]))
continue
# 没有用到过
class Set8026dataThreading(threading.Thread,JLib):
def __init__(self, driver):
threading.Thread.__init__(self)
JLib.__init__(self)
self.driver = driver
def run(self):
logging.info(u'8026 data setvalue')
self.driver.__8026dataDict = eval(self.driver._Alarm__8026data.replace('null', '""'))
#判断8026是否有报警情况
for i in self.driver.__8026dataDict['zoneList']:
if i['zoneStatus']==1:
logging.info(33333333333333333333333333)
if self.driver._Alarm__8023firstData!='' and self.driver._Alarm__8023data=='':
self.driver.__8023firstdataDict = eval(self.driver._Alarm__8023firstData)
# data8023SetList = self.driver.__8023firstdataDict['deviceList']
for _8023i in self.driver.__8023firstdataDict['deviceList']:
if _8023i['deviceId'] == self.driver.__8026dataDict['deviceId']:
logging.info('99999999999999999999999999999999999999999')
_8023i['deviceStatus'] = 3
else:
pass
logging.info(self.driver.__8023firstdataDict['deviceList'])
elif self.driver._Alarm__8023firstData!='' and self.driver._Alarm__8023data!='':
self.driver.__8023dataDict = eval(self.driver._Alarm__8023data)
# data8023SetList = self.driver.__8023dataDict['deviceList']
for _8023i in self.driver.__8023dataDict['deviceList']:
if _8023i['deviceId'] == self.driver.__8026dataDict['deviceId']:
logging.info('99999999999999999999999999999999999999999')
_8023i['deviceStatus'] = 3
else:
pass
else:
pass
else:
continue
if self.driver.__8023dataDict:
return self.driver.__8023firstdataDict , self.driver.__8023dataDict
else:
return self.driver.__8023firstdataDict, ''
#驱动运行的类
class Alarm(IOTOSDriverI):
#初始化,获取设备实例中的tcp参数,开启中台的tcp端口
def InitComm(self, attrs=None):
self.__port = self.sysAttrs['config']['param']['tcp']
logging.info(str(self.__port))
self.__tcpServer = TcpServerThread(self, self.__port)
self.__tcpServer.setDaemon(True)
self.__tcpServer.start()
# self.__data='' #8026存储数据
self.__flat=0 #拼接的标识变量
self.__sumdata='' #第一种情况分包后拼接后的字符串
self.__sumdata2='' #第二种情况分包后拼接后的字符串
self.__8023flat = 1 #用于判断是否为第一次接收到8023
self.__8023firstData = '' #用于接收第一次收到的8023
self.__8023data = '' #保存8023的数据
self.__8030senddata = '' #保存从机发过来的一个命令用于8030发送数据的修改
self.__8130data='' #保存温湿度的数据
# self.__8016sendData_json = {} #保存主动询问设备的防区状态id和type
self.__deviceStatus = {
0:"未知状态",
1:"在线状态",
2:"离线状态",
3:"报警状态",
4:"故障状态"
} #设备状态
self.__alarmStatus = {
0:"未知状态",
1:"外出布防",
2:"在家布防",
3:"撤防状态",
4:"布防延时"
} #布防状态
logging.info(self.sysAttrs['name'] + u' TCP端口' + str(self.__port) + u"已启动监听!")
#设置tcp回调函数,接收主机传过来的数据
def tcpCallback(self,data):
# logging.info(data)
#一条cmd单独分包:判断是否分包,没有\n则分包了,进行合并,由于合并的最后一个包有\n,则通过判断__sumdata是否为空判断是否是需要合并的包,若此时的__sumdata不为空,说明正在合并,把最后一个包加上即可
if data.find('\n')==-1:
self.__sumdata = self.__sumdata+data
# logging.info(self.__sumdata)
else:
if self.__sumdata !='':
self.__sumdata = self.__sumdata+data
data = self.__sumdata
# logging.info(data)
self.__sumdata=''
dataList = data.split('\n')
# logging.info(dataList)
for i in dataList:
dataList_i = i
if dataList_i=='':
continue
#多条cmd,最后一个分包
elif dataList_i.find("{") == -1 or dataList_i.find("}") == -1:
# logging.info(dataList_i)
self.__sumdata2 = self.__sumdata2+dataList_i
self.__flat = self.__flat +1
# logging.info(self.__flat)
if self.__flat == 2:
self.__flat =0
dataList_i = self.__sumdata2
# logging.info(dataList_i)
self.__sumdata2=''
else:
continue
newdata = eval(dataList_i)
#报警主机发来请求登录信息
if newdata['cmd']==8001:
self.__8030senddata = newdata
# self.__8016senddata = newdata
"""
进行加解密
"""
obj_endata=EncryptDate(rec_data=newdata)
#响应登录请求
send_data = json.dumps({"code":0,"platformName":"aiotos"})
send_data = obj_endata.encrypt(send_data)
newdata["data"]=send_data
newdata["cmd"]=8101
data = json.dumps(newdata)
time.sleep(0.5)
self.__tcpServer.send(data + "\n")
time.sleep(0.5)
# #心跳包,直接跳过
# elif data["cmd"]==8000:
# logging.info(u"8000 rec , 心跳包")
#设备列表数据包
elif newdata['cmd']==8023:
time.sleep(1)
#拿去数据包并解密传至collecting
obj_endata = EncryptDate(rec_data=newdata)
if self.__8023flat == 1:
self.__8023firstData = obj_endata.decrypt(newdata["data"])
self.__8023flat = 0
logging.info(u'8023 : first data received is ' + str(self.__8023firstData))
else:
self.__8023data = obj_endata.decrypt(newdata["data"])
logging.info(u'8023 : data received is ' + str(self.__8023data))
#中台响应8123,加密
send_data = json.dumps({"code": 0})
send_data = obj_endata.encrypt(send_data)
# logging.info(send_data)
newdata["data"]=send_data
newdata["cmd"]=8123
data = json.dumps(newdata)
time.sleep(0.5)
self.__tcpServer.send(data + "\n")
# logging.info(u'8123 !deta send is' +str(data))
elif newdata['cmd']==8026:
pass
#中台响应8126
# obj_endata = EncryptDate(rec_data=newdata)
# self.__8026data = obj_endata.decrypt(newdata["data"])
#
# logging.info(u'8026 : data received is ' + str(self.__8026data))
# # if self.__8026data!='' and (self.__8023firstData!='' or self.__8023data!=''):
# # try:
# # self.__8023firstdataDict,self.__8023dataDict = Set8026dataThreading(self).start()
# # except Exception as e:
# # pass
# # else:
# # pass
# send_data = json.dumps({"code": 0})
# send_data = obj_endata.encrypt(send_data)
# # logging.info(send_data)
# newdata["data"] = send_data
# newdata["cmd"] = 8126
# data = json.dumps(newdata)
# time.sleep(0.5)
# self.__tcpServer.send(data + "\n")
# logging.info(u'8126 !deta send is' + str(data))
#8024为布撤防状态改变时发送,发送到来时将原有的8023数据修改掉
elif newdata['cmd']==8024:
obj_endata = EncryptDate(rec_data=newdata)
self.__8024data = obj_endata.decrypt(newdata["data"])
logging.info(u'8024 : data received is ' + str(self.__8024data))
self.__8024dataDict = eval(self.__8024data)
if self.__8023firstData != '':
__8023MidFirstData = eval(self.__8023firstData)
for i in self.__8024dataDict['deviceList']:
for j in __8023MidFirstData['deviceList']:
if i['deviceId'] == j['deviceId']:
# __8023MidFirstData['deviceList'].remove(j)
if 'armingStatus' in i:
j['armingStatus'] = i['armingStatus']
if 'deviceStatus' in i:
j['deviceStatus'] = i['deviceStatus']
logging.info(__8023MidFirstData)
# logging.info(j)
# __8023MidFirstData['deviceList'].append(j)
# logging.info(__8023MidFirstData)
self.__8023firstData = json.dumps(__8023MidFirstData,ensure_ascii=False,encoding="utf-8")
logging.info(self.__8023firstData)
else:
continue
if self.__8023data != '':
__8023MidData = eval(self.__8023data)
for i in self.__8024dataDict['deviceList']:
for j in __8023MidData['deviceList']:
if i['deviceId'] == j['deviceId']:
# __8023MidData['deviceList'].remove(j)
if 'armingStatus' in i:
j['armingStatus'] = i['armingStatus']
if 'deviceStatus' in i:
j['deviceStatus'] = i['deviceStatus']
logging.info(__8023MidFirstData)
self.__8023data = json.dumps(__8023MidData,ensure_ascii=False,encoding="utf-8")
else:
continue
# 报警事件传递过来,根据报警的id去8023数据中查找,若有则将deviceStatus改为3即可
elif newdata['cmd'] == 8011:
obj_endata = EncryptDate(rec_data=newdata)
self.__8011data = obj_endata.decrypt(newdata["data"])
logging.info(u'8011 : data received is ' + str(self.__8011data))
self.__8011dataDic = eval(self.__8011data.replace('null',''))
if self.__8023firstData != '':
__8023MidFirstData = eval(self.__8023firstData)
for i in __8023MidFirstData['deviceList']:
if i['deviceId'] == self.__8011dataDic['deviceId']:
i['deviceStatus'] = 3
logging.info(__8023MidFirstData)
self.__8023firstData = json.dumps(__8023MidFirstData, ensure_ascii=False, encoding="utf-8")
if self.__8023data != '':
__8023MidData = eval(self.__8023data)
for i in __8023MidData['deviceList']:
if i['deviceId'] == self.__8011dataDic['deviceId']:
i['deviceStatus'] = 3
logging.info(__8023MidData)
self.__8023data = json.dumps(__8023MidData, ensure_ascii=False, encoding="utf-8")
# 中台响应8111,加密
send_data = json.dumps({"code": 0})
send_data = obj_endata.encrypt(send_data)
# logging.info(send_data)
newdata["data"] = send_data
newdata["cmd"] = 8111
data = json.dumps(newdata)
time.sleep(0.5)
self.__tcpServer.send(data + "\n")
elif newdata['cmd']==8130:
# 拿去数据包并解密传至collecting
obj_endata = EncryptDate(rec_data=newdata)
self.__8130data = obj_endata.decrypt(newdata["data"])
logging.info(u'8130 : data received is ' + str(self.__8130data))
elif newdata['cmd']==8000:
logging.info(u'cmd' + str(newdata['cmd']))
logging.info(newdata["data"])
obj_endata = EncryptDate(rec_data=newdata)
send_data = json.dumps({"code": 0})
send_data = obj_endata.encrypt(send_data)
newdata["data"] = send_data
newdata["cmd"] = 8100
data = json.dumps(newdata)
time.sleep(1)
self.__tcpServer.send(data + "\n")
# 8023设备状态的数据上传成功后再发送8030请求温湿度的值
# logging.info('start')
if self.__8030senddata:
try:
obj_endata = EncryptDate(rec_data=self.__8030senddata)
send_data = json.dumps({"deviceType": 85})
send_data = obj_endata.encrypt(send_data)
self.__8030senddata["data"] = send_data
self.__8030senddata["cmd"] = 8030
data = json.dumps(self.__8030senddata)
# time.sleep(0.5)
self.__tcpServer.send(data + "\n")
# logging.info(u'8030 data send is' + str(data))
except SocketError as e:
logging.info(self.__8030senddata)
"""
断掉后再次开启端口进行重启
"""
self.__tcpServer = TcpServerThread(self, self.__port)
self.__tcpServer.setDaemon(True)
self.__tcpServer.start()
if e.errno != errno.ECONNRESET:
raise # Not error we are looking for
pass # Handle error here.
else:
logging.info(u'其他cmd' + str(newdata['cmd']))
logging.info(newdata["data"])
# 8023设备状态的数据上传成功后再发送8030请求温湿度的值
#logging.info('start')
if self.__8030senddata:
try:
obj_endata = EncryptDate(rec_data=self.__8030senddata)
send_data = json.dumps({"deviceType": 85})
send_data = obj_endata.encrypt(send_data)
self.__8030senddata["data"] = send_data
self.__8030senddata["cmd"] = 8030
data = json.dumps(self.__8030senddata)
time.sleep(0.5)
self.__tcpServer.send(data + "\n")
# logging.info(u'8030 data send is' + str(data))
except SocketError as e:
logging.info(self.__8030senddata)
"""
断掉后再次开启端口进行重启
"""
self.__tcpServer = TcpServerThread(self, self.__port)
self.__tcpServer.setDaemon(True)
self.__tcpServer.start()
if e.errno != errno.ECONNRESET:
raise # Not error we are looking for
pass # Handle error here.
# 连接状态回调
def connectEvent(self, state):
self.online(state)
try:
if state == True:
self.pauseCollect = False
else:
self.pauseCollect = True
except Exception, e:
logging.info(u'硬件心跳错误, ' + e.message)
def Collecting(self, dataId):
if self.__8023firstData !='' and self.__8023firstData != self.__8023data:
# logging.info(1234567890)
Set8023firstDataThreading(self).start()
else:
pass
if self.__8023data:
Set8023DataThreading(self).start()
time.sleep(1)
else:
pass
if self.__8130data:
Set8130DataThreading(self).start()
time.sleep(1)
else:
pass
# time.sleep(2)
return ()
-
驱动解析
- 编写环境为python2(python3也可以),首先需要导入加解密所需要的base64、AES包和中台通讯用的driver包以及其他数据解析所用的包
#!coding:utf8
import sys
import json
import base64
from Crypto.Cipher import AES
sys.path.append("..")
reload(sys)
sys.setdefaultencoding('gbk')
from driver import *
from jcomm import *
import threading
#打印日志
import logging
logger = logging.getLogger()
logging.basicConfig(level=logging.ERROR,
format='%(asctime)s %(threadName)s %(levelname)s %(filename)s:%(lineno)d %(funcName)s %(message)s')
logger.setLevel(logging.ERROR & logging.INFO)
#except,防止socket报error: [Errno 104] Connection reset by peer
from socket import error as SocketError
import errno
- 定义AES加解密的类
#AES的加解密类
class EncryptDate:
def __init__(self, rec_data):
self.key = self.create_key(rec_data) # 初始化密钥
self.length = AES.block_size # 初始化数据块大小
self.aes = AES.new(self.key, AES.MODE_ECB) # 初始化AES,ECB模式的实例
# 截断函数,去除填充的字符
self.unpad = lambda rec_data: rec_data[0:-ord(rec_data[-1])]
#根据传过来的数据 取出hostid 产生用于AES加密的密钥key
@staticmethod
def create_key(res):
newkey = ''
# print len(str(res['hostId']))
if len(str(res['hostId'])) != 12:
for i in range(0, (12 - len(str(res['hostId'])))):
newkey = newkey + '0'
newkey = newkey + str(res['hostId'])
else:
newkey = str(res['hostId'])
newkey = newkey + str(res['hostId'] + 12345)[-4:]
#logging.info (newkey)
return newkey
def pad(self, text):
"""
#填充函数,使被加密数据的字节码长度是block_size的整数倍
"""
count = len(text.encode('utf-8'))
add = self.length - (count % self.length)
entext = text + (chr(add) * add)
return entext
def encrypt(self, encrData): # 加密函数
res = self.aes.encrypt(self.pad(encrData).encode("utf8"))
msg = str(base64.b64encode(res))
return msg
def decrypt(self, decrData): # 解密函数
res = base64.decodestring(decrData.encode("utf8"))
msg = self.aes.decrypt(res).decode("utf8")
return self.unpad(msg)
- 定义数据上传的线程,防止全部留在collecting里面会出现延迟上传
#8023第一次的数据
class Set8023firstDataThreading(threading.Thread,JLib):
def __init__(self, driver):
threading.Thread.__init__(self)
JLib.__init__(self)
self.driver = driver
def run(self):
logging.info(u'8023 first data setvalue')
# logging.info(getattr(self.driver, __8023firstData))
# logging.info(self.driver._Alarm__8023firstData)
self.driver.__8023firstdataDict = eval(self.driver._Alarm__8023firstData)
data8023SetList = self.driver.__8023firstdataDict['deviceList']
for i in data8023SetList:
# 排除温湿度的设备
if str(i["deviceId"]).find('10007') != -1 or str(i["deviceId"]).find('10025') != -1:
continue
else:
try:
# logger.info(i["deviceName"].decode('utf-8'))
self.driver.setValue(unicode(str(i["deviceId"]), "utf-8"), (
i["deviceName"] + ',' + self.driver._Alarm__deviceStatus[i["deviceStatus"]] + ',' +
self.driver._Alarm__alarmStatus[i["armingStatus"]]))
except Exception as e:
if "deviceName" not in i:
self.driver.setValue(unicode(str(i["deviceId"]), "utf-8"), (
'未知' + ',' + self.driver._Alarm__deviceStatus[i["deviceStatus"]] + ',' +
self.driver._Alarm__alarmStatus[i["armingStatus"]]))
logging.info(str(i["deviceId"]))
continue
#8023第二次的数据
class Set8023DataThreading(threading.Thread,JLib):
def __init__(self, driver):
threading.Thread.__init__(self)
JLib.__init__(self)
self.driver = driver
def run(self):
logging.info(u'8023 data setvalue')
self.driver.__8023dataDict = eval(self.driver._Alarm__8023data)
data8023SetList = self.driver.__8023dataDict['deviceList']
for i in data8023SetList:
# 排除温湿度的设备
if str(i["deviceId"]).find('10007') != -1 or str(i["deviceId"]).find('10025') != -1:
continue
else:
try:
# logger.info(i["deviceName"].decode('utf-8'))
self.driver.setValue(unicode(str(i["deviceId"]), "utf-8"), (
i["deviceName"] + ',' + self.driver._Alarm__deviceStatus[i["deviceStatus"]] + ',' +
self.driver._Alarm__alarmStatus[i["armingStatus"]]))
except Exception as e:
if "deviceName" not in i:
self.driver.setValue(unicode(str(i["deviceId"]), "utf-8"), (
'未知' + ',' + self.driver._Alarm__deviceStatus[i["deviceStatus"]] + ',' +
self.driver._Alarm__alarmStatus[i["armingStatus"]]))
logging.info(str(i["deviceId"]))
continue
#8130的数据上传线程
class Set8130DataThreading(threading.Thread,JLib):
def __init__(self, driver):
threading.Thread.__init__(self)
JLib.__init__(self)
self.driver = driver
def run(self):
logging.info(u'8130 data setvalue')
self.driver.__8130dataDict = eval(self.driver._Alarm__8130data.replace('null', '""'))
data8130SetList = self.driver.__8130dataDict['data']
for i in data8130SetList:
# logging.info(unicode(str(i["deviceId"]), "utf-8"))
# logging.info(type(i["param"]["temperature"]))
try:
self.driver.setValue(unicode(str(i["deviceId"]), "utf-8"),
((i["deviceName"] + ',' + i["param"]["humidity"] + ',' + str(
int(i["param"]["temperature"]) * 0.01)) + ',' + self.driver._Alarm__deviceStatus[
i['deviceStatus']]))
except Exception as e:
#一些温湿度没有上线,没有param参数。
if i["param"]== "":
self.driver.setValue(unicode(str(i["deviceId"]), "utf-8"),
(i["deviceName"] + ',' + '' + ',' + '' + ',' +
self.driver._Alarm__deviceStatus[
i['deviceStatus']]))
else:
logging.info(e.message)
logging.info(str(i["deviceId"]))
continue
- 定义驱动运行的类,进行初始化和参数的获取,开启tcp监听的端口
#驱动运行的类
class Alarm(IOTOSDriverI):
#初始化,获取设备实例中的tcp参数,开启中台的tcp端口
def InitComm(self, attrs=None):
self.__port = self.sysAttrs['config']['param']['tcp']
logging.info(str(self.__port))
self.__tcpServer = TcpServerThread(self, self.__port)
self.__tcpServer.setDaemon(True)
self.__tcpServer.start()
# self.__data='' #8026存储数据
self.__flat=0 #拼接的标识变量
self.__sumdata='' #第一种情况分包后拼接后的字符串
self.__sumdata2='' #第二种情况分包后拼接后的字符串
self.__8023flat = 1 #用于判断是否为第一次接收到8023
self.__8023firstData = '' #用于接收第一次收到的8023
self.__8023data = '' #保存8023的数据
self.__8030senddata = '' #保存从机发过来的一个命令用于8030发送数据的修改
self.__8130data='' #保存温湿度的数据
# self.__8016sendData_json = {} #保存主动询问设备的防区状态id和type
self.__deviceStatus = {
0:"未知状态",
1:"在线状态",
2:"离线状态",
3:"报警状态",
4:"故障状态"
} #设备状态
self.__alarmStatus = {
0:"未知状态",
1:"外出布防",
2:"在家布防",
3:"撤防状态",
4:"布防延时"
} #布防状态
logging.info(self.sysAttrs['name'] + u' TCP端口' + str(self.__port) + u"已启动监听!")
- 定义回调函数,接收传过来的数据并进行相应的加解密处理和回应操作
#设置tcp回调函数,接收主机传过来的数据
def tcpCallback(self,data):
# logging.info(data)
#一条cmd单独分包:判断是否分包,没有\n则分包了,进行合并,由于合并的最后一个包有\n,则通过判断__sumdata是否为空判断是否是需要合并的包,若此时的__sumdata不为空,说明正在合并,把最后一个包加上即可
if data.find('\n')==-1:
self.__sumdata = self.__sumdata+data
# logging.info(self.__sumdata)
else:
if self.__sumdata !='':
self.__sumdata = self.__sumdata+data
data = self.__sumdata
# logging.info(data)
self.__sumdata=''
dataList = data.split('\n')
# logging.info(dataList)
for i in dataList:
dataList_i = i
if dataList_i=='':
continue
#多条cmd,最后一个分包
elif dataList_i.find("{") == -1 or dataList_i.find("}") == -1:
# logging.info(dataList_i)
self.__sumdata2 = self.__sumdata2+dataList_i
self.__flat = self.__flat +1
# logging.info(self.__flat)
if self.__flat == 2:
self.__flat =0
dataList_i = self.__sumdata2
# logging.info(dataList_i)
self.__sumdata2=''
else:
continue
newdata = eval(dataList_i)
#报警主机发来请求登录信息
if newdata['cmd']==8001:
self.__8030senddata = newdata
# self.__8016senddata = newdata
"""
进行加解密
"""
obj_endata=EncryptDate(rec_data=newdata)
#响应登录请求
send_data = json.dumps({"code":0,"platformName":"aiotos"})
send_data = obj_endata.encrypt(send_data)
newdata["data"]=send_data
newdata["cmd"]=8101
data = json.dumps(newdata)
time.sleep(0.5)
self.__tcpServer.send(data + "\n")
time.sleep(0.5)
# #心跳包,直接跳过
# elif data["cmd"]==8000:
# logging.info(u"8000 rec , 心跳包")
#设备列表数据包
elif newdata['cmd']==8023:
time.sleep(1)
#拿去数据包并解密传至collecting
obj_endata = EncryptDate(rec_data=newdata)
if self.__8023flat == 1:
self.__8023firstData = obj_endata.decrypt(newdata["data"])
self.__8023flat = 0
logging.info(u'8023 : first data received is ' + str(self.__8023firstData))
else:
self.__8023data = obj_endata.decrypt(newdata["data"])
logging.info(u'8023 : data received is ' + str(self.__8023data))
#中台响应8123,加密
send_data = json.dumps({"code": 0})
send_data = obj_endata.encrypt(send_data)
# logging.info(send_data)
newdata["data"]=send_data
newdata["cmd"]=8123
data = json.dumps(newdata)
time.sleep(0.5)
self.__tcpServer.send(data + "\n")
# logging.info(u'8123 !deta send is' +str(data))
elif newdata['cmd']==8026:
pass
#8024为布撤防状态改变时发送,发送到来时将原有的8023数据修改掉
elif newdata['cmd']==8024:
obj_endata = EncryptDate(rec_data=newdata)
self.__8024data = obj_endata.decrypt(newdata["data"])
logging.info(u'8024 : data received is ' + str(self.__8024data))
self.__8024dataDict = eval(self.__8024data)
if self.__8023firstData != '':
__8023MidFirstData = eval(self.__8023firstData)
for i in self.__8024dataDict['deviceList']:
for j in __8023MidFirstData['deviceList']:
if i['deviceId'] == j['deviceId']:
# __8023MidFirstData['deviceList'].remove(j)
if 'armingStatus' in i:
j['armingStatus'] = i['armingStatus']
if 'deviceStatus' in i:
j['deviceStatus'] = i['deviceStatus']
logging.info(__8023MidFirstData)
# logging.info(j)
# __8023MidFirstData['deviceList'].append(j)
# logging.info(__8023MidFirstData)
self.__8023firstData = json.dumps(__8023MidFirstData,ensure_ascii=False,encoding="utf-8")
logging.info(self.__8023firstData)
else:
continue
if self.__8023data != '':
__8023MidData = eval(self.__8023data)
for i in self.__8024dataDict['deviceList']:
for j in __8023MidData['deviceList']:
if i['deviceId'] == j['deviceId']:
# __8023MidData['deviceList'].remove(j)
if 'armingStatus' in i:
j['armingStatus'] = i['armingStatus']
if 'deviceStatus' in i:
j['deviceStatus'] = i['deviceStatus']
logging.info(__8023MidFirstData)
self.__8023data = json.dumps(__8023MidData,ensure_ascii=False,encoding="utf-8")
else:
continue
# 报警事件传递过来,根据报警的id去8023数据中查找,若有则将deviceStatus改为3即可
elif newdata['cmd'] == 8011:
obj_endata = EncryptDate(rec_data=newdata)
self.__8011data = obj_endata.decrypt(newdata["data"])
logging.info(u'8011 : data received is ' + str(self.__8011data))
self.__8011dataDic = eval(self.__8011data.replace('null',''))
if self.__8023firstData != '':
__8023MidFirstData = eval(self.__8023firstData)
for i in __8023MidFirstData['deviceList']:
if i['deviceId'] == self.__8011dataDic['deviceId']:
i['deviceStatus'] = 3
logging.info(__8023MidFirstData)
self.__8023firstData = json.dumps(__8023MidFirstData, ensure_ascii=False, encoding="utf-8")
if self.__8023data != '':
__8023MidData = eval(self.__8023data)
for i in __8023MidData['deviceList']:
if i['deviceId'] == self.__8011dataDic['deviceId']:
i['deviceStatus'] = 3
logging.info(__8023MidData)
self.__8023data = json.dumps(__8023MidData, ensure_ascii=False, encoding="utf-8")
# 中台响应8111,加密
send_data = json.dumps({"code": 0})
send_data = obj_endata.encrypt(send_data)
# logging.info(send_data)
newdata["data"] = send_data
newdata["cmd"] = 8111
data = json.dumps(newdata)
time.sleep(0.5)
self.__tcpServer.send(data + "\n")
elif newdata['cmd']==8130:
# 拿去数据包并解密传至collecting
obj_endata = EncryptDate(rec_data=newdata)
self.__8130data = obj_endata.decrypt(newdata["data"])
logging.info(u'8130 : data received is ' + str(self.__8130data))
elif newdata['cmd']==8000:
logging.info(u'cmd' + str(newdata['cmd']))
logging.info(newdata["data"])
obj_endata = EncryptDate(rec_data=newdata)
send_data = json.dumps({"code": 0})
send_data = obj_endata.encrypt(send_data)
newdata["data"] = send_data
newdata["cmd"] = 8100
data = json.dumps(newdata)
time.sleep(1)
self.__tcpServer.send(data + "\n")
# 8023设备状态的数据上传成功后再发送8030请求温湿度的值
# logging.info('start')
if self.__8030senddata:
try:
obj_endata = EncryptDate(rec_data=self.__8030senddata)
send_data = json.dumps({"deviceType": 85})
send_data = obj_endata.encrypt(send_data)
self.__8030senddata["data"] = send_data
self.__8030senddata["cmd"] = 8030
data = json.dumps(self.__8030senddata)
# time.sleep(0.5)
self.__tcpServer.send(data + "\n")
# logging.info(u'8030 data send is' + str(data))
except SocketError as e:
logging.info(self.__8030senddata)
"""
断掉后再次开启端口进行重启
"""
self.__tcpServer = TcpServerThread(self, self.__port)
self.__tcpServer.setDaemon(True)
self.__tcpServer.start()
if e.errno != errno.ECONNRESET:
raise # Not error we are looking for
pass # Handle error here.
else:
logging.info(u'其他cmd' + str(newdata['cmd']))
logging.info(newdata["data"])
# 8023设备状态的数据上传成功后再发送8030请求温湿度的值
#logging.info('start')
if self.__8030senddata:
try:
obj_endata = EncryptDate(rec_data=self.__8030senddata)
send_data = json.dumps({"deviceType": 85})
send_data = obj_endata.encrypt(send_data)
self.__8030senddata["data"] = send_data
self.__8030senddata["cmd"] = 8030
data = json.dumps(self.__8030senddata)
time.sleep(0.5)
self.__tcpServer.send(data + "\n")
# logging.info(u'8030 data send is' + str(data))
except SocketError as e:
logging.info(self.__8030senddata)
"""
断掉后再次开启端口进行重启
"""
self.__tcpServer = TcpServerThread(self, self.__port)
self.__tcpServer.setDaemon(True)
self.__tcpServer.start()
if e.errno != errno.ECONNRESET:
raise # Not error we are looking for
pass # Handle error here.
- 连接状态回调
# 连接状态回调
def connectEvent(self, state):
self.online(state)
try:
if state == True:
self.pauseCollect = False
else:
self.pauseCollect = True
except Exception, e:
logging.info(u'硬件心跳错误, ' + e.message)
- 循环采集函数,开启线程,将数据上传至中台
def Collecting(self, dataId):
if self.__8023firstData !='' and self.__8023firstData != self.__8023data:
# logging.info(1234567890)
Set8023firstDataThreading(self).start()
else:
pass
if self.__8023data:
Set8023DataThreading(self).start()
time.sleep(1)
else:
pass
if self.__8130data:
Set8130DataThreading(self).start()
time.sleep(1)
else:
pass
# time.sleep(2)
return ()
至此,精华隆周界的设备已经对接完成