本帖最后由 xuehu96 于 2019-7-13 20:05 编辑
OTA_Python_Server 指令
使用TCP与服务器建立链接,端口可自定义
固件为bin文件,每次发送1024字节,速率和发送方式可控
升级流程
- 发送设备名字和本地版本
- 发送传输方式
- 发送控制指令
自动传输指令发送实例
device#test12
auto
start#10kB/s
控制传输指令发送实例
device#test12
control
next
next
...(直到传完)
next
1.发送设备名字和本地版本
发送数据:device#[设备名][本地版本号]
示例数据:
device#test12
- device为关键字,不可修改,全部小写
-
test为设备名,只能为小写字母(不能有空格和数字)
-
12为版本号,全部为数字
固件命名为test13.bin 固件版本号大于设备版本号才会升级
新版本大于旧版本50个版本号则无法匹配到新固件
test13.bin test15.bin同时存在 则会升级为test15.bin
正确返回:
- newver:15 服务器有新版本v15(进入第二步)
- noupdates 没有新版本(没有新版本,服务器主动断开)
错误代码:
- cmderr:1 未匹配到指令
- cmderr:2 指令发送顺序错误
- cmderr:3 设备名不存在或版本号无法匹配
2.发送传送方式指令和接收固件
固件的传送分为两种方式1.自动传输(auto) 2.控制传输(control)
2.1自动传输
2.1.1发送auto
发送数据:
正确返回:
- 固件的大小
- 例如
16772
- 单位为字节,字符串,10进制,16772为16772字节
错误返回:
- cmderr:1 未匹配到指令
- cmderr:2 指令发送顺序错误
2.1.2发送start#[传输速率]kB/s
发送数据例子
start#10kB
start#50kB/s
注意:
- start为关键字 小写
-
10kB为传输速率 范围为1-99kB
-
必须写 k小写B大写
/s 可以省略
正确返回:
错误返回:
- cmderr:1 未匹配到指令
- cmderr:2 指令发送顺序错误
2.1.3发送完毕
发送结束,服务器主动断开连接
2.2控制传输
2.2.1发送control
发送数据:
正确返回:
错误返回:
- cmderr:1 未匹配到指令
- cmderr:2 指令发送顺序错误
2.2.2下一个数据包next
- 请求往后1024个字节的固件数据,如果传输结束,服务器会断开连接
2.2.3重发数据包resend
- 如果当前收到的数据有问题,可以重新请求发送当前数据包
2.2.4主动结束传输exit
- 发送exit退出传输
- 服务器最后一个数据包发完会发送endoffile并主动断开客户端
python代码,使用python3 socketserver模块
[Python] 纯文本查看 复制代码 import socketserver
import time
import os
import re
class MyTcpHandler(socketserver.BaseRequestHandler):
def handle(self):
step=0
filepath = 'null'
filesize = 0
files = None
conbuf = None
limit = None
cnt = 0
while True:
try:
data = self.request.recv(1024)
print(data)
if not data: break # 此行代码针对linux系统
recvstr = data.decode(encoding="utf-8")
if step == 0:#判断设备名
if recvstr.find('device')==-1:
self.request.send(b"cmderr:1")#未匹配到指令
else:
modestr = recvstr[recvstr.find('#')+1:]
oldver = re.sub(r'\D', "", modestr)
filename = re.sub(r'\d', "", modestr)
print ('ver'+oldver+' name='+filename)
print()
for i in range(50):
if os.path.exists(os.path.abspath('.')+'\\bin\\'+filename+str(int(oldver)+i+1)+'.bin')==True:
filepath = os.path.abspath('.')+'\\bin\\'+filename+str(int(oldver)+i+1)+'.bin'
print(os.path.abspath('.')+'\\bin\\'+filename+str(int(oldver)+i+1)+'.bin')
if filepath == 'null':
self.request.send(b"cmderr:3")#未匹配到指令
else:
step=1
newver = "newver:"+re.sub(r'\D', "", filepath)
self.request.send(newver.encode(encoding="utf-8"))
#打开文件
filesize = os.path.getsize(filepath)
files = open(filepath,'rb')
elif step ==1:#判断auto还是control
if recvstr.find('auto')!=-1:
step=10
filesizestr = str(filesize)
limit = int(filesize/1024) + 1
self.request.send(filesizestr.encode(encoding="utf-8"))
elif recvstr.find('control')!=-1:
step=20
filesizestr = str(filesize)
self.request.send(filesizestr.encode(encoding="utf-8"))
limit = int(filesize/1024) + 1
cnt = 0
else:
self.request.send(b"cmderr:1")#未匹配到指令
elif step ==10:#自动模式
if recvstr.find('start')==-1:
self.request.send(b"cmderr:1")#未匹配到指令
continue
delayms = 1000/ (int(re.sub(r'\D', "", recvstr)))
for i in range(limit):
buf = files.read(1024)
self.request.send(buf)
print('发送数据包:%d/%d' %(i+1,limit))
time.sleep(delayms/1000)
files.close()
print('传输结束')
break #传输结束
elif step ==20:#手动模式
if cnt >= limit:
self.request.send(b"endoffile")
files.close()
print('传输结束')
break
if recvstr.find('next')!=-1:
cnt = cnt + 1
conbuf = files.read(1024)
self.request.send(conbuf)
print('控制传输:%d/%d'%(cnt,limit))
time.sleep(0.03)
elif recvstr.find('resend')!=-1:
if cnt == 0:
conbuf = files.read(1024)
cnt = cnt + 1
self.request.send(conbuf)
print('重新传输:%d/%d'%(cnt,limit))
time.sleep(0.03)
elif recvstr.find('exit')!=-1:
files.close()
print('客户端断开')
break
else:
self.request.send(b"cmderr:1")#未匹配到指令
else:
self.request.send(b"cmderr:-1")#未知错误
except ConnectionResetError:
break
self.request.close()
if __name__ == '__main__':
server = socketserver.ThreadingTCPServer(('0.0.0.0', 6666), MyTcpHandler)
server.serve_forever()
运行截图
|