前文我们已经介绍了基于串口的FreeD数据传输,可是我们写这个脚本的目的,主要是模拟FreeD设备发送设备数据。所以我们主要的要考虑设备的轻量化与简洁化,最好可以一台笔记本电脑解决所有问题。但是,我们都知道现在的移动端设备基本上都抛弃了串口,如果再去搞一个外接串口,属实有点画蛇添足,但是笔记本应该都不缺网卡(有线或者无线),如果我们能够将发送与接收设备接入一个局域网内,在局域网内传输数据,岂不美哉。恰好FreeD协议也可以通过Socket套接字传输,下面我们就通过Socket套接字来传输数据。
数据的采集,我们基本沿用serial串口的方式,重点在于生成协议数据后的发送与接收。网络的传输主要分为TCP与UDP,TCP是一种稳定和安全的传输方式,但是它在一个套接字下是一种一对一的传输方式,服务端与客户端要来回的状态转换。但是我们的Freed数据,就是单纯的发布freed设备的状态信息,基本不需要与接收端交互,所以UDP是一种更为理想的传输方式。
数据发送端与接收端,我们最好都绑定(s.bind())Ip 和 Port,做成UDP服务端,以避免客户端系统随机分配Port造成的一些问题。
示例:我们将接收端做成了一个死循环,不断的接受发送端的数据,可以在发送端发送“stop”字符串来停止接收端。
接收端代码:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
host = "your host IP"
port = "your port"
sourceAddr = (host,int(port))
s.bind(sourceAddr )
while True:
data,addr = s.recvfrom(1024)
data = data.decode()
print(data)
if data == 'stop':
break
发送端代码:
def generatePan(panvalue):
pan = float(panvalue)
#if the value of pan NOT in range [-180~180]
while abs(pan) > 180:
if pan < -180:
pan += 360
else:
pan -= 360
#print(pan)
return angleToByte(pan)
def generateTile(tilevalue):
tile = float(tilevalue)
#tile in [-90~90],now it's not a perfect solution
while abs(tile) > 90:
if tile < -90:
tile += 180
else:
tile -= 180
#print(tile)
return angleToByte(tile)
def generateRoll(rollvalue):
return generatePan(rollvalue)
def angleToByte(anglevalue):
value = float(anglevalue)
#to binary two's complement
vbinary = bin(int(value*32768) & 0xffffff)[2:]
#to hex
res = hex(int(vbinary,2))[2:]
#print(res)
res = "{:0>6}".format(res)
return res
def posToByte(posvalue):
value = float(posvalue)
#to binary two's complement
vbinary = bin(int(value*64) & 0xffffff)[2:]
#to hex
res = hex(int(vbinary,2))[2:]
#print(res)
res = "{:0>6}".format(res)
return res
def generatePos(pos_axis):
axis = float(pos_axis)
#if the value of position NOT in range (-131072~131072)mm
while abs(axis) > 131072:
if axis < -90:
axis = -131072
else:
axis = 131072
#print(axis)
return posToByte(axis)
def generateCoordiante(poslist):
pos_res = ""
#print(poslist)
if len(poslist) != 3:
print("position argument error.")
for i in poslist:
#print(i)
pos_res += str(generatePos(i))
#print(pos_res)
return pos_res
def intToByte(intvalue):
value = int(intvalue)
#to binary two's complement
vbinary = bin(value & 0xffffff)[2:]
#to hex
res = hex(int(vbinary,2))[2:]
#print(res)
res = "{:0>6}".format(res)
return res
# perfvalue is the range of focus [0~1]
# rvalue is max sample point of focus
def generateFocus(perfvalue,rvalue = 18723):
fvalue = perfvalue * rvalue
return intToByte(fvalue)
# perzvalue is the range of zoom [0~1]
# rvalue is max sample point of zoom
def generateZoom(perzvalue,rvalue = 13765):
zvalue = perzvalue * rvalue
return intToByte(zvalue)
# input:the string of all protocal info NOT include checksum
def generateCheckSum(proto_info):
prstr = proto_info
res = int('40',16)
for i in range(0,len(prstr),2):
subtrack_num = prstr[i:i+2]
res -= int(subtrack_num,16)
#print(res)
res %= 256
#print(res,"\n")
res = hex(res)[2:]
return res
def Delayms(delaytime):
delayT = int(delaytime * 1000)
startT = time.perf_counter() * 1000000
while True:
offset = round(time.perf_counter() * 1000000 - startT)
if offset >= delayT:
break
def hexascToChr(str_hex):
numDec = int(str(str_hex),16)
return chr(numDec)
def strshexToChrs(strs_hex):
res = []
for i in range(0,len(strs_hex),2):
str = strs_hex[i:i+2]
res.append(hexascToChr(str))
return ''.join(res)
def sampleToBytes(sampleList):
if len(sampleList) != 8:
raise Exception("sample sum error.")
return len(sampleList)
reslist = ['d1','ff']
reslist.append(generatePan(sampleList[0]))
reslist.append(generateTile(sampleList[1]))
reslist.append(generateRoll(sampleList[2]))
reslist.append(generatePos(sampleList[3]))
reslist.append(generatePos(sampleList[4]))
reslist.append(generatePos(sampleList[5]))
reslist.append(generateZoom(sampleList[6]))
reslist.append(generateFocus(sampleList[7]))
reslist.append('0000')
res_string = "".join(reslist)
return res_string
if __name__ =='__main__':
import time
import xlrd
import socket
data = xlrd.open_workbook_xls(r'.\axis_data.xls')
table = data.sheets()[0]
sourceAddr = ("hostIP",8888)
destAddr = ("remoteIP",8889)
#create udp server
udpServ = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
udpServ.bind(sourceAddr)
for rown in range(table.nrows):
#t1 = time.perf_counter()*1000000
lcam1 = []
for i in range(8):
lcam1.append(table.cell_value(rown,i))
#generate data bit
data_bits = sampleToBytes(lcam1)
CKSum = generateCheckSum(data_bits)
prres = data_bits + CKSum
#t2 = time.perf_counter()*1000000
#print("耗时:",str(int(round(t2 - t1))),"us" )
udpServ.sendto(prres.encode(),destAddr)
print(rown+1," transmit:",prres)
# time of the program runing is t2-t1 ~0.4ms
Delayms(19.6)
udpServ.sendto(b'stop',destAddr)
udpServ.close()
运行结果: