Comments (18)
虽然这个插件能完美解决Scratch link的问题,可是scratch link的固件阉割掉了很多BLE的功能:
- IO 服务
- 磁力计服务
- UART 服务部分直接重写了
所以,我想研究codelab的固件,使得BLE 版 Microbit 更加强大
from codelab_adapter_extensions.
我已经成功通过MackCode开启Microbit的任意的BLE服务(总过有七个服务,可是最多同时开3到4个,不然内存会不够)并通过dongle来对其读写订阅等,算是有了比较好的进展。现在就需要一个adapter插件和Scratch插件了。
from codelab_adapter_extensions.
Hi,我的手上没有设备,暂时没办法测试,我观察到这个位置代码有些不一样,传参改成 List 试一下?
dongle.bled_write('6e400003-b5a3-f393-e0a9-e50e24dcca9e', [0x0a]) # 往tx写换行符
from codelab_adapter_extensions.
from codelab_adapter_extensions.
https://github.com/audetto/asi-link
I've written a super simple implementation in nodejs of a link for serial ports (USB or BT Classic), which should work on all platforms.
Not tested with any real device as I do not have a device to test it with. I am still writing the scratch-vm extension for an mBot, then I will do the full test.I might be completely off, but it looks super simple, with a few caveats
the whole device-manager.scratch.mit.edu + wss:// seems an over complication to me.
- I am running with ws://localhost and it works perfectly
- the certificates and the key are available in cleartext from the mac package, so it is hardly providing any security
- what is the rationale behind this solution? it makes it hard to recompile and reimplement scratch-link
about the protocol: using the gui I can load multiple BT extensions, but so far I have not found a way to detect which device each message belongs to. Have I missed something in the protocol?
社区里开始有人写link的nodejs版本,应该对我们后面的BLE的研究有启发
from codelab_adapter_extensions.
@wwj718 根据在 Scratch micro:bit extension与Scratch Link通信的细节 里分析的消息体的结构,我用dongle库编写了一下 adapter 的 Microbit ble 插件,由于库的限制无法呈现出 link 全部的功能,是一种单线程的实现方式。 还有个问题是,scratch 端主动断开之后,重新连接 Microbit,只能是通过重启插件的方式来连接。
'''
EIM: Everything Is Message
'''
import time
import threading
from codelab_adapter import settings
from codelab_adapter.core_extension import Extension
from codelab_adapter.utils import threaded
from codelab_adapter.dongle import Dongle
import time
import pygatt
import tenacity
import binascii
import base64
class BleMicrobit(Extension):
def __init__(self):
name = type(self).__name__ # class name
super().__init__(name)
self.TOPIC = "eim"
def read_cb(self, handle, value):
message = base64.b64encode(value)
self.publish({
"payload": {
"encoding": "base64",
"message": str(message)[2:-1] #处理字符
},
"method": "characteristicDidChange",
"topic": self.TOPIC,
})
@threaded
def message_monitor(self):
while self._running:
read_message = self.read()
topic = read_message.get("topic")
if topic == self.TOPIC:
self.logger.info("消息:{}".format(read_message))
method = read_message.get("method")
data = read_message.get("payload")
if method == 'discover':
try:
self.services = data.get('filters')[
0].get('services')[0]
except Exception as e:
self.publish({
"messageID": read_message.get("messageID"),
"error": str(e),
"topic": self.TOPIC,
})
else:
self.publish({
"messageID": read_message.get("messageID"),
"result": "",
"topic": self.TOPIC,
})
try:
self.logger.info("开始扫描BLE")
devices = self.dongle.bled_scan()
except Exception as e:
self.logger.info("BLE扫描错误:{}".format(e))
else:
for dev in devices:
try:
complete_list_16_bit_service_class_uuids = dev.get('packet_data').get(
'connectable_advertisement_packet').get('complete_list_16-bit_service_class_uuids')
except Exception as e:
pass
else:
if isinstance(complete_list_16_bit_service_class_uuids, bytearray):
if int.from_bytes(complete_list_16_bit_service_class_uuids, byteorder='little') == self.services:
self.publish({
"payload": {
"name": dev.get('name'),
"rssi": dev.get('rssi'),
"peripheralId": dev.get('address')
},
"method": "didDiscoverPeripheral",
"topic": self.TOPIC,
})
elif method == 'connect':
self.peripheralId = data.get("peripheralId")
try:
self.logger.info("开始连接")
self.dongle.bled_connect(self.peripheralId)
except Exception as e:
self.logger.info("连接错误:{}".format(str(e)))
self.publish({
"messageID": read_message.get("messageID"),
"error": str(e),
"topic": self.TOPIC
})
self.ble_connected = False
else:
self.publish({
"messageID": read_message.get("messageID"),
"result": "",
"topic": self.TOPIC
})
elif method == 'read':
characteristicId = data.get("characteristicId")
self.dongle.bled_subscribe(
characteristicId, callback=self.read_cb, indication=True) # 订阅传感器数据
self.publish(
{
"messageID": read_message.get("messageID"),
"result": {
"encoding": "base64",
"message": ""
},
"topic": self.TOPIC
}
)
elif method == 'write':
characteristicId = data.get("characteristicId")
text = data.get("message").encode('ascii')
self.logger.info("收到的消息为:{}".format(text))
try:
self.dongle.bled_write(
characteristicId, text)
except Exception as e:
self.logger.info("写消息错误:{}".format(e))
else:
self.publish(
{
"messageID": read_message.get("messageID"),
"topic": self.TOPIC,
"result": 6
}
)
def run(self):
self.dongle = Dongle()
try:
self.logger.info("启动BLE")
self.dongle.bled_start()
self.message_monitor()
while True:
time.sleep(1)
except Exception as e:
self.logger.info("BLE启动出错:{}".format(e))
finally:
self.dongle.bled_stop()
export = BleMicrobit
from codelab_adapter_extensions.
@wwj718 是个很不错的工具, 尤其是用树莓派来做python教学的时候,通过BLE设备开展教学工作的好方法,最重要的一点不需要再添加额外的蓝牙适配器。
from codelab_adapter_extensions.
@bilikyar 提到希望
读取模拟口的值
我的建议是利用makecode构建新的ble 固件,非常简单。
提醒
makecode默认的配置不会公开蓝牙,需要设置
ble服务细节: https://lancaster-university.github.io/microbit-docs/ble/profile/
from codelab_adapter_extensions.
这个库具体怎么用? 必须要配BLED 112这款USB Dongle吗? 我在华硕笔记本上运行这个代码报了下面的错误:
RetryError[<Future at 0x2ee1130 state=finished raised BGAPIError>]
from codelab_adapter_extensions.
@bilikyar 我目前是配合 BLED 112,对USB Dongle的要求,可以参考pygatt文档
from codelab_adapter_extensions.
最新的codelab-adapter内置了Dongle
测试插件: https://github.com/Scratch3Lab/codelab_adapter_extensions/blob/master/extension_dongle_scan_test.py
from codelab_adapter_extensions.
对microbit scratch官方固件的读取已经完成:
https://github.com/Scratch3Lab/codelab_adapter_extensions/blob/master/extension_dongle_read_test.py
对数据的解析 参考我之前的分析: https://blog.just4fun.site/scratch3-microbit-analysis.html
from codelab_adapter_extensions.
@wangshub dongle插件应该是支持Makeblock写的固件是吗?我用此文章的方法做实验的时候遇到了问题,Microbit固件代码如下:
1.运行如下代码时,无法检测UART通道上写入的值
dongle.bled_connect('E1:4C:E0:01:43:18') #这是我Microbit的Mac地址
dongle.bled_subscribe('6e400002-b5a3-f393-e0a9-e50e24dcca9e', callback=read_cb) #订阅rx
2.运行如下代码时,Microbit没有任何变化
dongle.bled_write('6e400003-b5a3-f393-e0a9-e50e24dcca9e',0x0a) # 往tx写换行符
3.此固件我已经通过其他各类BLE软件测试过了,运行没问题
from codelab_adapter_extensions.
@wangshub 恩,你帮到我了,最后确定了不是插件的问题,是我固件的问题:
1.写UART运行成功
2.订阅特征部分还是遇到困难,不能订阅直接写入UART的信息
from codelab_adapter_extensions.
经过一段时间的整理,我在dongle的基础上完成了一下内容,代码如下:
- 收集A和B按钮的数据
- 收集加速度,温度,磁力计传感器的数据
- 对于led发送文字和形状信息
- 对于引脚的输入数据的收集,其中包含模拟和数字信息
- 对于引脚的数字控制以及PWM控制
- 对于UART端的控制
import time
import pygatt
import tenacity
import binascii
# pygatt api doc : https://github.com/peplin/pygatt/blob/master/pygatt/device.py
class Dongle(object):
def __init__(self):
self.adapter = pygatt.BGAPIBackend()
self.device = None
self.is_running = True
@tenacity.retry(stop=tenacity.stop_after_attempt(3))
def bled_start(self):
self.adapter.start()
def bled_stop(self):
self.adapter.stop()
self.is_running = False
def bled_scan(self):
devices = self.adapter.scan()
return devices
def bled_rssi(self):
return self.device.get_rssi()
@tenacity.retry(stop=tenacity.stop_after_attempt(3))
def bled_connect(self, mac_addr):
self.device = self.adapter.connect(
mac_addr, address_type=pygatt.BLEAddressType.random)
print('connect to {}'.format(mac_addr))
print("rssi : " + str(self.device.get_rssi()))
# print("chars : " + str(self.device.discover_characteristics()))
# for i in self.device.discover_characteristics():
# print(i)
time.sleep(1)
def bled_subscribe(self, uuid, callback=None, indication=False):
try:
self.device.subscribe(uuid, callback=callback, indication=indication)
except Exception as e:
print(e)
def bled_write(self, uuid, data,length = 1):
if isinstance(data,int):
data = data.to_bytes(length, byteorder='little')
print("写入:", bytearray(data))
self.device.char_write(uuid, bytearray(data))
def bled_read(self, uuid):
data = self.device.char_read(uuid)
return data
@staticmethod
def _ascii_to_hex(rawhex):
return binascii.unhexlify(rawhex)
if __name__ == '__main__':
def read_cb(handle, value):
a = value
b = [bytes([a[i]])+ bytes([a[i+1]]) for i in range(0,len(a),2)]
c = [int.from_bytes(i, byteorder='little', signed=True) for i in b]
print(c)
# bytes_str = binascii.hexlify(value)
# print(bytes_str)
dongle = Dongle()
try:
dongle.bled_start()
devices = dongle.bled_scan()
for dev in devices:
print(dev.get('address'), dev.get('rssi'), dev.get('name'))
target_mac_address = 'DA:19:8A:61:AD:95'
microbit_uuid = {
'button_A' : 'e95dda90-251d-470a-a062-fa1922dfa9a8', #按钮A数据
'button_B' : 'e95dda91-251d-470a-a062-fa1922dfa9a8', #按钮B数据
'accelerometer' : 'e95dca4b-251d-470a-a062-fa1922dfa9a8', #加速度数据
'Temperature' : 'e95d9250-251d-470a-a062-fa1922dfa9a8', #温度计数据
'magnetometer' : 'e95dfb11-251d-470a-a062-fa1922dfa9a8', #磁力计数据
'led_char' : 'e95d93ee-251d-470a-a062-fa1922dfa9a8', #led文字
'led_matrix' : 'e95d7b77-251d-470a-a062-fa1922dfa9a8', #led矩阵
'pin_date' : 'e95d8d00-251d-470a-a062-fa1922dfa9a8', # pin读写服务
'pinMode_config' : 'e95d5899-251d-470a-a062-fa1922dfa9a8', # pin引脚配置
'ADC_config' : 'e95db9fe-251d-470a-a062-fa1922dfa9a8', # pinAD配置
'PWM_config' : 'e95dd822-251d-470a-a062-fa1922dfa9a8', # PWM设置
'tx': '6e400003-b5a3-f393-e0a9-e50e24dcca9e', # tx设置
'rx': '6e400002-b5a3-f393-e0a9-e50e24dcca9e', # rx设置
}
dongle.bled_connect(target_mac_address) # 这是我Microbit的Mac地址
dongle.bled_write(microbit_uuid['led_matrix'], [17, 27, 27, 27, 27]) #矩阵图标的显示方式
dongle.bled_subscribe(microbit_uuid['accelerometer'], callback=read_cb,indication=False) # 订阅传感器数据
while True:
time.sleep(1)
finally:
dongle.bled_stop()
from codelab_adapter_extensions.
目前待解决的问题如下:
- scratch连接特定的microbit(这个可以单独开一个issue讨论)
- adapter 收集数据逻辑(后端)
- scratch 具体的积木实现(前端)
from codelab_adapter_extensions.
@bilikyar 问题1 可以在这个issue里讨论: #27
这个issue试图跟进的问题是,如何将adapter作为像link一样的server,所有的交互在前端实现(link的策略是基于rpc消息)
from codelab_adapter_extensions.
@bilikyar 这是个不错的工具 https://github.com/ukBaz/python-bluezero
from codelab_adapter_extensions.
Related Issues (20)
- cmder下载后出问题,运行不成,文件坏了 HOT 6
- 证书更新 HOT 4
- pyinstaller 3.5 增加 jupyterlab的钩子 HOT 2
- 关于树莓派插件 HOT 3
- 除了EIM之外其他的scratch插件在哪能看到呢? HOT 4
- 更新codelab-adapter-mac-2_5_3之后使用cozmo插件出下面的提示 HOT 5
- 在windows下运行python-kernel-extension错误 HOT 4
- Extension_vector HOT 2
- Physical Blocks Scratch HOT 1
- 发现physical blocks 2.0中json列表是从右往左取的
- Extension中執行到while循環來執行攝像頭數據讀取后,疑似綫程阻塞導致插件無法响應後面的eim消息, 請教有沒有什麽辦法可以解決? HOT 2
- 请问下codelab可以打包成exe在本地运行吗? HOT 2
- 请教下 本项目和下载版本的区别 HOT 1
- 请问toio是通过什么方式连接的。 HOT 1
- 同时使用多个相同的MarkerID
- 希望把ESP32接入codelab,但是没有成功,能否给予一些例子。 HOT 4
- 请求大师adapter连接Arduino不成功总显示none type object HOT 6
- 老师,路过的好心人,能帮看看Arduino连接的nonetype错吗 HOT 1
- Scratch3 Alphamini extension and enabling other features HOT 9
- 可以看到Extension和Node具体实现差异么 HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from codelab_adapter_extensions.