前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >大疆特洛TELLO手柄盖世小鸡Gamesir-T1D蓝牙连接破解DIY

大疆特洛TELLO手柄盖世小鸡Gamesir-T1D蓝牙连接破解DIY

作者头像
云深无际
发布2020-12-03 14:48:35
5.9K0
发布2020-12-03 14:48:35
举报
文章被收录于专栏:云深之无迹

文章来源于以下博客

感谢大江的工作!!!

文章来源于转载,为了写一系列TT文章,故此加原创

代码语言:javascript
复制
https://www.hsli.top/%E5%A4%A7%E7%96%86%E7%89%B9%E6%B4%9BTELLO%E6%89%8B%E6%9F%84%E7%9B%96%E4%B8%96%E5%B0%8F%E9%B8%A1Gamesir-T1D%E8%93%9D%E7%89%99%E8%BF%9E%E6%8E%A5%E7%A0%B4%E8%A7%A3DIY.html

手头有个大疆TELLO并买了个盖世小鸡Gamesir-T1D遥控器,想着玩够了小飞机还可以用手柄来做DIY小车。。。万万没想到这个遥控器居然是定制的,只能遥控TELLO小飞机。。。电脑和手机都无法通过蓝牙直接连接。遂破解之。

先拆为敬

正面,做工还真是可以,本来手柄的手感就挺好的。可以看到单片机控制板和蓝牙板是单独的两个小板,可能不同遥控用的是同一套底板和不同的蓝牙以及单片机吧。

蓝牙板,芯片名称被磨掉了打上GS-T1d他们自家的标签。看起来像是CC2541方案。单片机和蓝牙之间预留有IIC的测试点。

单片机控制板,同样磨掉了芯片丝印。。

背后貌似预留了串口测试点?

硬件上看不出怎么破,手头没有设备,算了,拆开看一眼装回去。

用BLE调试软件连接,发现并不是用的设想的蓝牙串口方案来遥控,而是真的蓝牙协议。一共有3个Services,其中第三个Service接收的字节流一直不变,第二个变化没有什么规律。第一个UUID开头是00008651的Servie接收的字节流,变化比较有规律。

通过调试发现,在遥控器无动作的时候,第一个Service接收值一直都是C9-C6-86-A1-00-DB-B9-03-01-01-01-0B-01-E1-07-07-06-10-1E-56

有动作的时候,前两个Bytes一直是A1-C5。因此,前两个字节可以用来判断遥控状态。

以下的讨论都是在A1-C5状态下。

最后一个字节是一直自增的,按键按下,放开会使得该字节自增2,一直到0xFF又变回0x00,这个是用来记录按键按下次数的。

10-13字节是按键按下的状态,手柄上每个按键对应一位。实际上只要把这几个字节读取出来,就能和按键一一对应上了。

接下来是摇杆。3-7字节就是摇杆状态,一开始花了挺大劲去猜哪个摇杆对应哪些字节,后来发现其实很好猜的。一共5个字节,2个摇杆共4个方向,所以每个方向就是10bit。一般来说10bit的AD也是相当常见的。

所以只要把这些字节读取出来,然后每10位凑成整数,就可以还原出摇杆的读数了。

在linux上连接读取BLE可以用pyblue模块,可以在树莓派上用了。

下面给出读取的测试代码:

代码语言:javascript
复制
from __future__ import print_function
import struct
import time
from bluepy.btle import Peripheral

# 来自(https://www.hsli.top)

# 手柄的MAC地址可以通过蓝牙调试软件获得
my_gamesir = Peripheral('c6:xx:xx:xx:xx:b9', 'random')

services = my_gamesir.getServices()
for service in services:
    print(service)

    control_service = services[3]
    charac_dics = control_service.getCharacteristics()
    for charac in charac_dics:
        print(charac.uuid)


    while True:
        time.sleep(0.01)

        charac1, charac2, charac3 = [item.read() for item in charac_dics]

        status_code = struct.unpack('H', charac1[:2])[0]

        if status_code == 50593:
            on_press_key = struct.unpack('I', charac1[9:13])[0]
            press_counter = struct.unpack('B', charac1[-1])[0]

            bar_status = struct.unpack('5B', charac1[2:7])
            bar_status_bin = ''.join([bin(item).split('b')[1].rjust(8).replace(' ', '0') for item in bar_status])

            left_drag = int(bar_status_bin[0:10], 2)
            left_push = int(bar_status_bin[10:20], 2)
            right_drag = int(bar_status_bin[20:30], 2)
            right_push = int(bar_status_bin[30:40], 2)

            print("status %s" % status_code, end='  ')
            print("on_press %s" % on_press_key, end='  ')
            print("press_counter %s" % press_counter, end='  ')
            print("left_drag %s" % left_drag, end='  ')
            print("right_drag %s" % right_drag, end='  ')
            print("left_push %s" % left_push, end='  ')
            print("right_push %s" % right_push, end='\r')

        # break
代码语言:javascript
复制
from __future__ import print_function
import struct
import time
from bluepy.btle import Peripheral

# 来自(https://www.hsli.top)

# 手柄的MAC地址可以通过蓝牙调试软件获得
my_gamesir = Peripheral('c6:xx:xx:xx:xx:b9', 'random')

services = my_gamesir.getServices()
for service in services:
    print(service)

    control_service = services[3]
    charac_dics = control_service.getCharacteristics()
    for charac in charac_dics:
        print(charac.uuid)


    while True:
        time.sleep(0.01)

        charac1, charac2, charac3 = [item.read() for item in charac_dics]

        status_code = struct.unpack('H', charac1[:2])[0]

        if status_code == 50593:
            on_press_key = struct.unpack('I', charac1[9:13])[0]
            press_counter = struct.unpack('B', charac1[-1])[0]

            bar_status = struct.unpack('5B', charac1[2:7])
            bar_status_bin = ''.join([bin(item).split('b')[1].rjust(8).replace(' ', '0') for item in bar_status])

            left_drag = int(bar_status_bin[0:10], 2)
            left_push = int(bar_status_bin[10:20], 2)
            right_drag = int(bar_status_bin[20:30], 2)
            right_push = int(bar_status_bin[30:40], 2)

            print("status %s" % status_code, end='  ')
            print("on_press %s" % on_press_key, end='  ')
            print("press_counter %s" % press_counter, end='  ')
            print("left_drag %s" % left_drag, end='  ')
            print("right_drag %s" % right_drag, end='  ')
            print("left_push %s" % left_push, end='  ')
            print("right_push %s" % right_push, end='\r')

        # break

文章具有很大的指导型意见,注意文章的时间为2020年4月,所以应该是TT还是以前的版本呢?这个就不得为之了,现在属于没有硬件情况下最棒的文章了.

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-11-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 云深之无迹 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档