Mind+ Python 积木模式扩展开发手册¶
本文档将指导开发者创建适用于 Mind+ Python 积木模式的扩展。
1. 扩展包文件结构¶
一个标准的扩展包目录结构如下:
extensionName/ # 扩展库根目录
├── func.js # 生成代码 (原 opcodeFunc.js)
├── index.js # 图形块定义主文件
├── public/ # 静态资源目录 (原 template/)
│ ├── cover.png # 扩展封面图
│ ├── config.json # 扩展配置文件(元数据)
│ ├── libraries/ # Python 扩展库文件目录 (可选)
│ │ └── df_xxx_lib.py # Python 库文件
│ └── requirements.txt # Python 项目依赖包 (可选)
├── icon/ # 图标资源目录
│ ├── blockIcon.svg # 积木图标
│ └── menuIcon.svg # 分类菜单图标
├── locales/ # 国际化语言包
│ ├── zh-cn.json # 简体中文翻译
│ ├── en.json # 英文翻译
│ └── index.js # 翻译入口文件
2. 配置文件 (public/config.json)¶
config.json 是扩展的核心配置文件。
示例配置¶
{
"id": "pinpongBase",
"version": "0.0.1",
"name": {
"zh-cn": "pinpong初始化",
"en": "pinpong initialize"
},
"description": {
"zh-cn": "pinpong库初始化选择主控板功能和gpio",
"en": "initialize pinpong library select board function and GPIO"
},
"author": "DFRobotTest",
"cover": "cover.png",
"main": "main.js",
"isDevice": false,
"mode": "python-block",
"meta": {
"runtimeVersion": "0.0.2"
}
}
关键字段说明¶
| 字段 | 类型 | 说明 |
|---|---|---|
id | string | 扩展唯一标识符。 |
author | string | 与id一起组成扩展唯一标识。 |
version | string | 版本号。 |
name | object | 多语言名称。 |
description | object | 多语言描述。 |
cover | string | 封面图片文件名,需位于 public 目录下。 |
mode | string | 模式,此处应为 python-block。 |
isDevice | boolean | Python模式均为 false。 |
meta.runtimeVersion | string | 扩展 runtime 接口版本(用于控制 API 兼容性)。 |
meta.runtimeVersion¶
runtimeVersion 表示开发扩展时依赖的 runtime API 最低版本。应按实际使用的 API 能力填写最小版本,避免随意填写过大导致扩展只能在高版本 Mind+ 中加载。
3. Python 依赖管理 (public/requirements.txt)¶
如果有配置,Mind+会在加载扩展时,在库管理中显示当前扩展的 Python 依赖库。
示例 requirements.txt:
4. 图形块描述文件 (index.js)¶
index.js 是扩展的入口文件。
类结构定义¶
import ArgumentType from '../utils/argument-type';
import BlockType from '../utils/block-type';
import blockIconURI from './icon/blockIcon.svg';
import menuIconURI from './icon/menuIcon.svg';
import Func from './func'; // 引入生成代码类
import { setLocaleData, formatMessage, setLocale } from '../utils/translation';
import LocaleData from "./locales";
setLocaleData(LocaleData);
class Extension {
constructor(runtime, extensionId) {
this.runtime = runtime;
// 初始化生成代码的实例
this.funcs = new Func(runtime, extensionId);
}
// 必须实现:切换语言的钩子
setLocale(locale) {
setLocale(locale);
}
// 必须实现:返回生成代码的实例
getCodePrimitives() {
return this.funcs;
}
// 必须实现:返回扩展的详细信息
getInfo() {
return {
name: "pinpong",
blockIconURI: blockIconURI,
menuIconURI: menuIconURI,
color1: "#FF6680",
color2: "#FF4D6A",
color3: "#FF3355",
blocks: [
{
opcode: 'pinpongInit',
blockType: BlockType.COMMAND,
text: formatMessage({id: 'gui.extension.pinpongBase.pinpongInit', default: 'pinpong初始化'}),
arguments: {}
}
],
menus: {},
};
}
}
export default Extension;
5. 代码生成文件 (func.js)¶
func.js 负责将图形块转换为 Python 代码。
核心结构¶
class Func {
constructor(runtime, extensionId) {
this.runtime = runtime;
}
pinpongInit(generator, block, parameter) {
// 生成 Python 代码逻辑
// 示例:导入库
generator.addImport('import time');
return `print("Hello Python Mode")`;
}
}
export default Func;
6. 翻译资源文件 (locales)¶
locales/zh-cn.json:
{
"gui.extension.pinpongBase.pinpongInit": "pinpong初始化",
"gui.extension.pinpongBase.pinpongUpdateFirmware": "pinpong更新固件 板型[Board]端口[Port]",
"gui.extension.pinpongBase.pinInit": "[Instance]pin初始化 引脚号[Pin] 模式[Mod]",
"gui.extension.pinpongBase.readPinValue": "[Instance]读数字值",
"gui.extension.pinpongBase.setPinValue": "[Instance]设置数字输出 值[Value]",
"gui.extension.pinpongBase.readAnalogValue": "[Instance]读模拟值",
"gui.extension.pinpongBase.setAnalogValue": "[Instance]设置模拟输出(PWM) 值[Value]"
}
7. Python 生成代码 API¶
1. 导入库模块 addImport¶
addImport(code: string) * 功能:导入 Python 库模块 * 参数: * code - 实际生成代码(code 去掉空格作为 id) * 覆盖规则:相同 id 时覆盖旧代码 * 示例:
2. 添加全局变量 addVariable¶
addVariable(id: string, code: string, coverage: boolean = false) * 功能:定义全局变量 * 参数: * id - 变量字符串标识符 * code - 实际生成代码 * coverage - 是否覆盖同 id 变量的生成代码(默认 false) * 示例:
3. 添加初始化区域代码 addInit¶
addInit(id: string, code: string, priority: number = 0, isCover: boolean = false) * 功能:添加初始化的代码(相当于 Arduino 的 addSetup) * 参数: * id - 字符串标识符 * code - 实际生成代码 * priority - 优先级(0-9,9最靠前,默认 0) * isCover - 是否覆盖同 id 的生成代码(默认 false) * 示例:
4. 添加全局函数 addFunction¶
addFunction(code: string, isCover: boolean = false) * 功能:添加全局函数 * 参数: * code - 函数内容生成代码(函数名作为 id) * isCover - 是否覆盖同 id 的生成代码(默认 false) * 示例:
let funcCode = [
`def send_to_serial(key, value):`,
` if myserial.isOpen():`,
` json_message = json.dumps({key: value})`,
` myserial.write(bytes(json_message, "utf-8"))`,
];
generator.addFunction(funcCode.join('\n'), true);
def send_to_serial(key, value):
if myserial.isOpen():
json_message = json.dumps({key: value})
myserial.write(bytes(json_message, "utf-8"))
while True:
pass
5. 创建事件回调函数¶
- 示例:
- 生成效果:
6. 在积木位置生成 code¶
- 位置:
while True:或积木当前位置 - 规则:
- 返回字符串直接插入代码
- 返回数组
[code, priority]处理优先级(如运算符顺序)
- 示例:
- 生成效果:
7. 进阶用法¶
- 添加注释
addComment(id: string, comment: any, position: number, isCover: boolean) - 添加错误提示
addErrorPrompt(message: string) - 获取资源路径
get_asset_path_by_name(全局函数)- 示例: