本示例使用设备:实时网络双门双向门禁控制板可二次编程控制网络继电器远程开关-淘宝网 (taobao.com)
#python通过缩进来表示代码块,不可以随意更改每行前面的空白,否则程序会运行错误!!!如果缩进不一致,就会报错: IndentationError
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#python -m pdb xxx.py 调试程度 n命令单步执行,s命令单步执行 会进入函数内部 b xx ,c
#import pdb pdb.set_trace() 设断点
import sys
import os
import socket
import time
import datetime
import pdb
#接收到设备信息后,服务器向设备的反馈信息---------------------------------------------------------
def SendInfToIp(SendInfStr,addr):
sdata=bytes(SendInfStr, encoding='gbk') #将要发送的信息转为bytes
s.sendto(sdata,addr)
message = 'SendData To %s:%s' % (addr, sdata)
print(message+"\n")
#获取电脑系统日期时间---------------------------------------------------------------------------
def get_time():
st = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
st=st[0:16]
return st
#判断字符串是否为有效的日期时间-------------------------------------------------------------------
def isVaildDate(datestr):
try:
datetime.strptime(datestr,'%Y-%m-%d %H:%M:%S')
return 1
except:
return 0
#主程序-------------------------------------------------------------------------------------
IpList=[]
if sys.platform == 'linux' or sys.platform=='mac': # linux、mac系统获取电脑所有网卡IP
ips = [ip.split('/')[0] for ip in os.popen("ip addr | grep 'inet '|awk '{print $2}'").readlines()]
for i in ips:
IpList.append(i)
print('%d '%(len(IpList)) + i)
else:
addrs = socket.getaddrinfo(socket.gethostname(),None) #windows获取电脑所有网卡IP
for item in addrs:
if ':' not in item[4][0]:
IpList.append(item[4][0])
print('%d '%(len(IpList)) + item[4][0])
BUFSIZE = 1024
Bindip=IpList[0] #如果电脑有多个网卡IP,可以选择绑定不同的IP
Bindprot=39192
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
s.bind((Bindip, Bindprot))
print('\n系统绑定IP:'+Bindip+':%d'% (Bindprot)+'\n')
print('发送搜索在线设备的广播指令')
sdata=b'000'
s.sendto(sdata,('255.255.255.255',Bindprot)) #发送搜索同网段内所有在线设备的广播指令
print('Send To IP:255.255.255.255:'+str(Bindprot))
print('Send Data:000\n')
LastBuf='' #保存最后接收到的信息,用于比较是否重复接收的信息
while True:
data, addr = s.recvfrom(BUFSIZE)
message = 'Received from %s:%s \n' % (addr, data)
print(message)
GetInf=str(data, encoding = "gbk")
FieldsList=GetInf.split(',')
if(LastBuf==GetInf and len(FieldsList)>1): #对比当前接收到的数据是否重发的数据包
SendInfStr="001,"+FieldsList[1] #是已解析过的相同数据,确定接收,不用再分析处理
SendInfToIp(SendInfStr,addr)
else:
LastBuf=GetInf #将接收到的信息可存,用做下次接收到数据后
if(FieldsList[0]=='100'): #设备接收到000搜索指令后返回的设备信息
if(len(FieldsList)<9):
DevBufferIpAddrStr= FieldsList[1] #终端IP
DevBufferMaskStr= FieldsList[2] #掩码
DevBufferGatewayStr= FieldsList[3] #网关
DevBufferRemoteAddrStr= FieldsList[4] #远程服务器IP
DevBufferPort= FieldsList[5] #端口
DevBufferNumberDecStr= FieldsList[6] #设备序号
else:
DevBufferIpAddrStr= FieldsList[1] #终端IP
DevBufferMaskStr= FieldsList[2] #掩码
DevBufferGatewayStr= FieldsList[3] #网关
DevBufferGatewayStrMAC= FieldsList[4] #网关MAC
DevBufferRemoteAddrStr= FieldsList[5] #远程服务器IP
DevBufferRemoteAddrMACStr= FieldsList[6] #远程服务器IPMAC
DevBufferMACSearchStr= FieldsList[7] #MAC搜索标识
DevBufferPort= FieldsList[8] #端口
DevBufferNumberDecStr= FieldsList[9] #设备模块序号
if(len(FieldsList)>10):
DevBufferSerialNumStr= FieldsList[10] #设备唯一硬件序号
elif(FieldsList[0]=='101'): #接收到设备的开机信号
DevRecFramesStr = FieldsList[1] #包序列号
DevBufferIpAddrStr = FieldsList[2] #终端IP
DevBufferRemoteAddrStr = FieldsList[3] #远程电脑指机IP
DevBufferMachinStr = FieldsList[4] #机号
DevBufferDatetimeStr = FieldsList[5] #设备日期时间
if(len(FieldsList)>6): #2018年以后的设备有唯一硬件序号
DevBufferSerialNumStr=FieldsList[6]
SendInfStr="001,"+DevRecFramesStr #确定接收到信息,否则设备会连续发送三次
SendInfToIp(SendInfStr,addr)
GetDT=DevBufferDatetimeStr[0:16]
SysDT= get_time()
if (GetDT!=SysDT): #设备时钟与系统不符,更新设备时间
SendInfStr="003," + DevBufferMachinStr +"," + time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
SendInfToIp(SendInfStr,addr)
elif(FieldsList[0]=='150'): #接收到实时考勤门禁机的刷卡信息
DevRecFramesStr = FieldsList[1] #包序列号
DevBufferIpAddrStr = FieldsList[2] #终端IP
DevBufferRemoteAddrStr = FieldsList[3] #远程电脑指机IP
DevBufferMachinStr = FieldsList[4] #机号
DevBufferCardidStr = FieldsList[5] #卡号
DevBufferReaderStr= FieldsList[6] #读头号
DevBufferDoorNoStr= FieldsList[7] #门或继电器号
DevBufferDelayStr= FieldsList[8] #门磁未关秒数,0表示已关
DevBufferPasswPropStr= FieldsList[9] #密码属性(0密码无效,1刷卡后按密码,2补签密码,3开门密码,4防迫胁密码)
DevBufferPassWStr= FieldsList[10] #密码(最多8位数字)
DevBufferUseTimeStr= FieldsList[11] #刷卡时间
if(len(FieldsList)>12): #2018年以后的设备有唯一硬件序号
DevBufferSerialNumStr=FieldsList[12]
SendInfStr="001,"+DevRecFramesStr #确定接收到信息,否则设备会连续发送三次
SendInfToIp(SendInfStr,addr)
#可以在这里加上业务对数据库的查、增、删操作,要分析是否重复接收的信息
#用050指令返回开门成功
#用051指令返回开门失败,正式系统开发时要有重发机制
#SendInfStr="051," + DevBufferMachinStr + "," + DevBufferCardidStr + ",卡号:" + DevBufferCardidStr + "\\n姓名:张三丰 \\n状态:无效卡\\n,20,1,3"
SendInfStr="050," + DevBufferMachinStr + "," + DevBufferCardidStr + ",卡号:" + DevBufferCardidStr + "\\n姓名:张三丰 \\n状态:欢迎关临\\n,20,1,0," + DevBufferReaderStr + "," + DevBufferDoorNoStr + ",5,20"
SendInfToIp(SendInfStr,addr)
#更多的字段说明及回复方式,请仔细查看设备的通讯协议说明...