吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4226|回复: 7
收起左侧

[Python 原创] 【python】OTA升级服务端程序,TCP连接,带文档

  [复制链接]
xuehu96 发表于 2019-7-13 10:37
本帖最后由 xuehu96 于 2019-7-13 20:05 编辑

OTA_Python_Server 指令

使用TCP与服务器建立链接,端口可自定义
固件为bin文件,每次发送1024字节,速率和发送方式可控  

升级流程

  1. 发送设备名字和本地版本
  2. 发送传输方式
  3. 发送控制指令

自动传输指令发送实例

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

发送数据:

  • auto
  • 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可以省略

正确返回:

  • 16进制固件数据

错误返回:

  • cmderr:1 未匹配到指令
  • cmderr:2 指令发送顺序错误
2.1.3发送完毕

发送结束,服务器主动断开连接

2.2控制传输

2.2.1发送control

发送数据:

  • control
  • control为小写

正确返回:

  • 固件的大小 例如16772

错误返回:

  • 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()


运行截图
2.png



免费评分

参与人数 6吾爱币 +10 热心值 +6 收起 理由
diopside + 1 + 1 我很赞同!
洲总 + 1 + 1 我很赞同!
wilder + 1 + 1 我很赞同!
苏紫方璇 + 5 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
yesit + 1 + 1 我很赞同!
1664593601 + 1 + 1 王工程师在不远等你

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

sgh2zlx 发表于 2019-7-13 12:03
这个有学习价值
yesit 发表于 2019-7-13 12:22
dimension4 发表于 2019-7-13 12:54
洲总 发表于 2019-7-15 23:42
好~~~~!!!支持狐狸~~~~
Noire 发表于 2019-7-22 10:45
写的挺好的,收藏了.......
s58046 发表于 2019-7-22 11:49
牛批。写的很好,感谢分享
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-16 11:44

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表