hello world(Adapter Extension)¶
我们来写一个自定义插件(extension),实现hello world
。
一些唠叨¶
如果你不爱听唠叨,这部分可以跳过:)
在架构图中,可以看到一个完整的插件包含两个部分:
- Scratch 3.0 网页中的插件(内应)
- 在 CodeLab Adapter 中写一个插件,代理硬件设备、AI 或其他程序
关于第一部分,尽管 Scratch3 官方的 extensions 机制已经可用了,我们也在 Scratch 3.0 中写了很多插件,但社区里文档不多,不大建议大家来踩坑,如果愿意折腾,可以参考创建你的第一个 Scratch 3.0 Extension。
我们在 CodeLab Scratch3中构建了一些通用的消息积木(EIM),我们尽量将它做的通用,让开发者只需在 CodeLab Adapter 自定义插件,即可在 Scratch3 中使用。
这块的核心概念很简单,如 EIM 所代表的含义:Everything Is a Message
,消息是一种极其强大的概念,如 Alan Kay 说的:
The big idea is messaging.
如果你用过 Smalltalk / ZeroMQ / Erlang 大概深有体会。
自定义插件¶
我们来实现一个自定义插件:helloworld extension
我们构建这样一个自定义插件,它的功能为:
- 将 Scratch 发过来的字符串逆转,如果 Scratch 发过来的字符串为
hello world
,我们则向Scratch发送:dlrow olleh
该插件的源码为:
import time from codelab_adapter.core_extension import Extension class HelloWorldExtension(Extension): NODE_ID = "eim" def __init__(self): super().__init__() def send_message_to_scratch(self, content): message = self.message_template() message["payload"]["content"] = content self.publish(message) def extension_message_handle(self, topic, payload): self.logger.info(f'the message payload from scratch: {payload}') content = payload["content"] if type(content) == str: content_send_to_scratch = content[::-1] # 反转字符串 self.send_message_to_scratch(content_send_to_scratch) def run(self): while self._running: time.sleep(1) export = HelloWorldExtension
代码很简单,而且大部分是样板代码,有几点值得注意:
NODE_ID
默认为eim
,可以不写。extension_message_handle
是个回调函数,处理从 Scratch 过来的消息(一般由积木触发)run
是插件的主体代码,当你在 Web UI 中选择插件时,发生的事情是:- 首先实例化插件类(在此是
export = EIMExtension
) - 之后将
run
运行为线程。run 方法一般使用while self._running
来阻塞,run
方法一旦结束,该插件的生命周期就结束了。
- 首先实例化插件类(在此是
至于你要在extension_message_handle
和run
中写什么 Python 代码则是完全自由的。
将插件命名为extension_hello_world.py
,将其放到插件目录里,Mac/Linux 用户的插件目录在:~/codelab_adapter/extensions
,如果找不到插件目录(如 Windows 用户),可以通过 CodeLab Adapter 菜单栏上的 插件->查看目录
打开它。
刷新 Web UI,点击运行extension_hello_world.py
,接着你就可以在 Scratch 中与你的插件交互了。
恭喜你,已经能够让 Scratch 与 Python 对话了,你现在可以用你的 Python 技能来为 Scratch 写拓展啦!
提醒
你可以将自定义插件发布到插件市场, 用户点击即可下载使用。
调试技巧¶
建议你在写 Python 插件的时候,先做好单元测试,然后再作为插件放到插件目录里运行。
如果你喜欢在真实环境里开发,可以使用self.logger.info
来打日志(就像前头的代码里做的),你可以实时查看日志:tail -f ~/codelab_adapter/info.log
,日志目录可以通过菜单里的日志->目录
打开。
更多¶
你可以在插件中引用哪些 Python 库呢?
所有的 Python 内置库(json/re/math/……)以及这些第三方库:第三方模块。
如果你对 EIM 在 Scratch3 一侧的源码感兴趣,我们也开源出来了,可以自行阅读:scratch3_eim。
提醒
第三方模块中有几个采用异步模式(async): aiohttp、hbmqtt、pymata-express。
自定义插件默认以线程运行 run
方法, 配合异步库使用的时候需要注意.
参考extension_mqtt_broker.py和extension_arduino_uno.py
小结¶
从这个例子中,可以看出写一个自定义的插件是很简单的。而 CodeLab Adapter 对插件要做的事几乎没有任何限制,只要 Python 能做的事,插件系统都能做!就是说你可以自己写一个插件,让 Scratch3 来控制你的蓝牙设备、你的 ROS 机器人、你那跑着 OpenCV 的树莓派或者你童年那辆心爱的玩具四驱车。
enjoy it~