基于socket的FreeD数据收发

前文我们已经介绍了基于串口的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()

运行结果:

 

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值